lpmp 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +3 -0
- data/README +3 -0
- data/Rakefile +45 -0
- data/bin/lpmp +107 -0
- data/config/help.yaml +1 -0
- data/config/hosts.yaml +2 -0
- data/config/log.yaml +1 -0
- data/config/memcache.yaml +5 -0
- data/erb/index.erb +62 -0
- data/lib/bg_pull/caichen.rb +199 -0
- data/lib/bg_pull/lpmp.rb +45 -0
- data/lib/exception.rb +8 -0
- data/lib/lpmp.rb +53 -0
- data/lib/pull/lpmp.rb +355 -0
- data/lib/remote_lmp.rb +129 -0
- data/lib/utils.rb +14 -0
- data/lib/xq_push/caichen.rb +174 -0
- data/lib/xq_push/lpmp.rb +96 -0
- data/log/lpmp1st.log +1 -0
- data/public/css/ext-portal.css +40 -0
- data/public/css/lpmp.css +6 -0
- data/public/designer/caichen.epj +1 -0
- data/public/designer/hostmonitor.epj +1 -0
- data/public/ext-3.0.0/INCLUDE_ORDER.txt +35 -0
- data/public/ext-3.0.0/adapter/ext/ext-base-debug.js +3589 -0
- data/public/ext-3.0.0/adapter/ext/ext-base.js +7 -0
- data/public/ext-3.0.0/adapter/jquery/ext-jquery-adapter-debug.js +2292 -0
- data/public/ext-3.0.0/adapter/jquery/ext-jquery-adapter.js +7 -0
- data/public/ext-3.0.0/adapter/prototype/ext-prototype-adapter-debug.js +2346 -0
- data/public/ext-3.0.0/adapter/prototype/ext-prototype-adapter.js +7 -0
- data/public/ext-3.0.0/adapter/yui/ext-yui-adapter-debug.js +2136 -0
- data/public/ext-3.0.0/adapter/yui/ext-yui-adapter.js +7 -0
- data/public/ext-3.0.0/ext-all-debug.js +65610 -0
- data/public/ext-3.0.0/ext-all.js +11 -0
- data/public/ext-3.0.0/license.txt +42 -0
- data/public/ext-3.0.0/pkgs/cmp-foundation-debug.js +11287 -0
- data/public/ext-3.0.0/pkgs/cmp-foundation.js +7 -0
- data/public/ext-3.0.0/pkgs/data-foundation-debug.js +3853 -0
- data/public/ext-3.0.0/pkgs/data-foundation.js +7 -0
- data/public/ext-3.0.0/pkgs/data-grouping-debug.js +139 -0
- data/public/ext-3.0.0/pkgs/data-grouping.js +7 -0
- data/public/ext-3.0.0/pkgs/data-json-debug.js +582 -0
- data/public/ext-3.0.0/pkgs/data-json.js +7 -0
- data/public/ext-3.0.0/pkgs/data-list-views-debug.js +1278 -0
- data/public/ext-3.0.0/pkgs/data-list-views.js +7 -0
- data/public/ext-3.0.0/pkgs/data-xml-debug.js +234 -0
- data/public/ext-3.0.0/pkgs/data-xml.js +7 -0
- data/public/ext-3.0.0/pkgs/direct-debug.js +1121 -0
- data/public/ext-3.0.0/pkgs/direct.js +7 -0
- data/public/ext-3.0.0/pkgs/ext-dd-debug.js +4567 -0
- data/public/ext-3.0.0/pkgs/ext-dd.js +7 -0
- data/public/ext-3.0.0/pkgs/ext-foundation-debug.js +13417 -0
- data/public/ext-3.0.0/pkgs/ext-foundation.js +7 -0
- data/public/ext-3.0.0/pkgs/pkg-buttons-debug.js +1060 -0
- data/public/ext-3.0.0/pkgs/pkg-buttons.js +7 -0
- data/public/ext-3.0.0/pkgs/pkg-charts-debug.js +1621 -0
- data/public/ext-3.0.0/pkgs/pkg-charts.js +10 -0
- data/public/ext-3.0.0/pkgs/pkg-forms-debug.js +7661 -0
- data/public/ext-3.0.0/pkgs/pkg-forms.js +7 -0
- data/public/ext-3.0.0/pkgs/pkg-grid-editor-debug.js +560 -0
- data/public/ext-3.0.0/pkgs/pkg-grid-editor.js +7 -0
- data/public/ext-3.0.0/pkgs/pkg-grid-foundation-debug.js +4765 -0
- data/public/ext-3.0.0/pkgs/pkg-grid-foundation.js +7 -0
- data/public/ext-3.0.0/pkgs/pkg-grid-grouping-debug.js +517 -0
- data/public/ext-3.0.0/pkgs/pkg-grid-grouping.js +7 -0
- data/public/ext-3.0.0/pkgs/pkg-grid-property-debug.js +370 -0
- data/public/ext-3.0.0/pkgs/pkg-grid-property.js +7 -0
- data/public/ext-3.0.0/pkgs/pkg-history-debug.js +203 -0
- data/public/ext-3.0.0/pkgs/pkg-history.js +7 -0
- data/public/ext-3.0.0/pkgs/pkg-menu-debug.js +1628 -0
- data/public/ext-3.0.0/pkgs/pkg-menu.js +7 -0
- data/public/ext-3.0.0/pkgs/pkg-tabs-debug.js +1100 -0
- data/public/ext-3.0.0/pkgs/pkg-tabs.js +7 -0
- data/public/ext-3.0.0/pkgs/pkg-tips-debug.js +994 -0
- data/public/ext-3.0.0/pkgs/pkg-tips.js +7 -0
- data/public/ext-3.0.0/pkgs/pkg-toolbars-debug.js +1374 -0
- data/public/ext-3.0.0/pkgs/pkg-toolbars.js +7 -0
- data/public/ext-3.0.0/pkgs/pkg-tree-debug.js +4522 -0
- data/public/ext-3.0.0/pkgs/pkg-tree.js +7 -0
- data/public/ext-3.0.0/pkgs/resizable-debug.js +760 -0
- data/public/ext-3.0.0/pkgs/resizable.js +7 -0
- data/public/ext-3.0.0/pkgs/state-debug.js +274 -0
- data/public/ext-3.0.0/pkgs/state.js +7 -0
- data/public/ext-3.0.0/pkgs/window-debug.js +1888 -0
- data/public/ext-3.0.0/pkgs/window.js +7 -0
- data/public/ext-3.0.0/resources/charts.swf +0 -0
- data/public/ext-3.0.0/resources/css/README.txt +3 -0
- data/public/ext-3.0.0/resources/css/ext-all-notheme.css +5345 -0
- data/public/ext-3.0.0/resources/css/ext-all.css +6990 -0
- data/public/ext-3.0.0/resources/css/reset-min.css +7 -0
- data/public/ext-3.0.0/resources/css/structure/borders.css +54 -0
- data/public/ext-3.0.0/resources/css/structure/box.css +80 -0
- data/public/ext-3.0.0/resources/css/structure/button.css +440 -0
- data/public/ext-3.0.0/resources/css/structure/combo.css +45 -0
- data/public/ext-3.0.0/resources/css/structure/core.css +326 -0
- data/public/ext-3.0.0/resources/css/structure/date-picker.css +265 -0
- data/public/ext-3.0.0/resources/css/structure/dd.css +61 -0
- data/public/ext-3.0.0/resources/css/structure/debug.css +26 -0
- data/public/ext-3.0.0/resources/css/structure/dialog.css +62 -0
- data/public/ext-3.0.0/resources/css/structure/editor.css +92 -0
- data/public/ext-3.0.0/resources/css/structure/form.css +562 -0
- data/public/ext-3.0.0/resources/css/structure/grid.css +552 -0
- data/public/ext-3.0.0/resources/css/structure/layout.css +296 -0
- data/public/ext-3.0.0/resources/css/structure/list-view.css +85 -0
- data/public/ext-3.0.0/resources/css/structure/menu.css +205 -0
- data/public/ext-3.0.0/resources/css/structure/panel-reset.css +130 -0
- data/public/ext-3.0.0/resources/css/structure/panel.css +468 -0
- data/public/ext-3.0.0/resources/css/structure/progress.css +42 -0
- data/public/ext-3.0.0/resources/css/structure/qtips.css +153 -0
- data/public/ext-3.0.0/resources/css/structure/reset.css +7 -0
- data/public/ext-3.0.0/resources/css/structure/resizable.css +149 -0
- data/public/ext-3.0.0/resources/css/structure/slider.css +103 -0
- data/public/ext-3.0.0/resources/css/structure/tabs.css +372 -0
- data/public/ext-3.0.0/resources/css/structure/toolbar.css +259 -0
- data/public/ext-3.0.0/resources/css/structure/tree.css +203 -0
- data/public/ext-3.0.0/resources/css/structure/window.css +222 -0
- data/public/ext-3.0.0/resources/css/visual/borders.css +25 -0
- data/public/ext-3.0.0/resources/css/visual/box.css +74 -0
- data/public/ext-3.0.0/resources/css/visual/button.css +94 -0
- data/public/ext-3.0.0/resources/css/visual/combo.css +43 -0
- data/public/ext-3.0.0/resources/css/visual/core.css +76 -0
- data/public/ext-3.0.0/resources/css/visual/date-picker.css +143 -0
- data/public/ext-3.0.0/resources/css/visual/dd.css +29 -0
- data/public/ext-3.0.0/resources/css/visual/debug.css +24 -0
- data/public/ext-3.0.0/resources/css/visual/dialog.css +34 -0
- data/public/ext-3.0.0/resources/css/visual/editor.css +13 -0
- data/public/ext-3.0.0/resources/css/visual/form.css +117 -0
- data/public/ext-3.0.0/resources/css/visual/grid.css +272 -0
- data/public/ext-3.0.0/resources/css/visual/layout.css +53 -0
- data/public/ext-3.0.0/resources/css/visual/list-view.css +37 -0
- data/public/ext-3.0.0/resources/css/visual/menu.css +82 -0
- data/public/ext-3.0.0/resources/css/visual/panel.css +87 -0
- data/public/ext-3.0.0/resources/css/visual/progress.css +32 -0
- data/public/ext-3.0.0/resources/css/visual/qtips.css +44 -0
- data/public/ext-3.0.0/resources/css/visual/resizable.css +43 -0
- data/public/ext-3.0.0/resources/css/visual/slider.css +21 -0
- data/public/ext-3.0.0/resources/css/visual/tabs.css +119 -0
- data/public/ext-3.0.0/resources/css/visual/toolbar.css +103 -0
- data/public/ext-3.0.0/resources/css/visual/tree.css +157 -0
- data/public/ext-3.0.0/resources/css/visual/window.css +86 -0
- data/public/ext-3.0.0/resources/css/xtheme-blue.css +1652 -0
- data/public/ext-3.0.0/resources/expressinstall.swf +0 -0
- data/public/ext-3.0.0/resources/images/default/box/corners-blue.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/box/corners.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/box/l-blue.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/box/l.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/box/r-blue.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/box/r.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/box/tb-blue.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/box/tb.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/button/arrow.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/button/btn.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/button/group-cs.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/button/group-lr.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/button/group-tb.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/button/s-arrow-b-noline.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/button/s-arrow-b.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/button/s-arrow-bo.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/button/s-arrow-noline.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/button/s-arrow-o.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/button/s-arrow.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/dd/drop-add.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/dd/drop-no.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/dd/drop-yes.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/editor/tb-sprite.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/form/checkbox.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/form/clear-trigger.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/form/clear-trigger.psd +0 -0
- data/public/ext-3.0.0/resources/images/default/form/date-trigger.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/form/date-trigger.psd +0 -0
- data/public/ext-3.0.0/resources/images/default/form/error-tip-corners.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/form/exclamation.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/form/radio.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/form/search-trigger.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/form/search-trigger.psd +0 -0
- data/public/ext-3.0.0/resources/images/default/form/text-bg.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/form/trigger-tpl.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/form/trigger.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/form/trigger.psd +0 -0
- data/public/ext-3.0.0/resources/images/default/gradient-bg.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/arrow-left-white.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/arrow-right-white.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/col-move-bottom.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/col-move-top.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/columns.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/dirty.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/done.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/drop-no.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/drop-yes.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/footer-bg.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/grid-blue-hd.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/grid-blue-split.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/grid-hrow.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/grid-loading.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/grid-split.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/grid-vista-hd.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/grid3-hd-btn.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/grid3-hrow-over.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/grid3-hrow.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/grid3-special-col-bg.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/grid3-special-col-sel-bg.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/group-by.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/group-collapse.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/group-expand-sprite.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/group-expand.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/hd-pop.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/hmenu-asc.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/hmenu-desc.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/hmenu-lock.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/hmenu-lock.png +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/hmenu-unlock.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/hmenu-unlock.png +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/invalid_line.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/loading.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/mso-hd.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/nowait.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/page-first-disabled.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/page-first.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/page-last-disabled.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/page-last.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/page-next-disabled.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/page-next.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/page-prev-disabled.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/page-prev.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/pick-button.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/refresh.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/row-check-sprite.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/row-expand-sprite.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/row-over.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/row-sel.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/sort-hd.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/sort_asc.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/sort_desc.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/grid/wait.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/layout/collapse.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/layout/expand.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/layout/gradient-bg.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/layout/mini-bottom.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/layout/mini-left.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/layout/mini-right.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/layout/mini-top.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/layout/ns-collapse.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/layout/ns-expand.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/layout/panel-close.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/layout/panel-title-bg.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/layout/panel-title-light-bg.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/layout/stick.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/layout/stuck.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/layout/tab-close-on.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/layout/tab-close.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/menu/checked.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/menu/group-checked.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/menu/item-over.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/menu/menu-parent.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/menu/menu.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/menu/unchecked.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/panel/corners-sprite.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/panel/left-right.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/panel/light-hd.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/panel/tool-sprite-tpl.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/panel/tool-sprites.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/panel/tools-sprites-trans.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/panel/top-bottom.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/panel/top-bottom.png +0 -0
- data/public/ext-3.0.0/resources/images/default/panel/white-corners-sprite.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/panel/white-left-right.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/panel/white-top-bottom.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/progress/progress-bg.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/qtip/bg.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/qtip/close.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/qtip/tip-anchor-sprite.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/qtip/tip-sprite.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/s.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/shadow-c.png +0 -0
- data/public/ext-3.0.0/resources/images/default/shadow-lr.png +0 -0
- data/public/ext-3.0.0/resources/images/default/shadow.png +0 -0
- data/public/ext-3.0.0/resources/images/default/shared/blue-loading.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/shared/calendar.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/shared/glass-bg.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/shared/hd-sprite.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/shared/large-loading.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/shared/left-btn.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/shared/loading-balls.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/shared/right-btn.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/shared/warning.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/sizer/e-handle-dark.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/sizer/e-handle.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/sizer/ne-handle-dark.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/sizer/ne-handle.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/sizer/nw-handle-dark.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/sizer/nw-handle.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/sizer/s-handle-dark.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/sizer/s-handle.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/sizer/se-handle-dark.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/sizer/se-handle.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/sizer/square.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/sizer/sw-handle-dark.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/sizer/sw-handle.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/slider/slider-bg.png +0 -0
- data/public/ext-3.0.0/resources/images/default/slider/slider-thumb.png +0 -0
- data/public/ext-3.0.0/resources/images/default/slider/slider-v-bg.png +0 -0
- data/public/ext-3.0.0/resources/images/default/slider/slider-v-thumb.png +0 -0
- data/public/ext-3.0.0/resources/images/default/tabs/scroll-left.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tabs/scroll-right.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tabs/scroller-bg.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tabs/tab-btm-inactive-left-bg.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tabs/tab-btm-inactive-right-bg.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tabs/tab-btm-left-bg.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tabs/tab-btm-right-bg.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tabs/tab-close.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tabs/tab-strip-bg.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tabs/tab-strip-bg.png +0 -0
- data/public/ext-3.0.0/resources/images/default/tabs/tab-strip-btm-bg.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tabs/tabs-sprite.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/toolbar/bg.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/toolbar/btn-arrow-light.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/toolbar/btn-arrow.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/toolbar/btn-over-bg.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/toolbar/gray-bg.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/toolbar/more.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/toolbar/tb-bg.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/toolbar/tb-btn-sprite.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/toolbar/tb-xl-btn-sprite.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/toolbar/tb-xl-sep.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tree/arrows.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tree/drop-add.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tree/drop-between.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tree/drop-no.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tree/drop-over.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tree/drop-under.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tree/drop-yes.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tree/elbow-end-minus-nl.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tree/elbow-end-minus.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tree/elbow-end-plus-nl.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tree/elbow-end-plus.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tree/elbow-end.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tree/elbow-line.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tree/elbow-minus-nl.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tree/elbow-minus.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tree/elbow-plus-nl.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tree/elbow-plus.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tree/elbow.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tree/folder-open.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tree/folder.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tree/leaf.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tree/loading.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/tree/s.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/window/icon-error.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/window/icon-info.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/window/icon-question.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/window/icon-warning.gif +0 -0
- data/public/ext-3.0.0/resources/images/default/window/left-corners.png +0 -0
- data/public/ext-3.0.0/resources/images/default/window/left-corners.psd +0 -0
- data/public/ext-3.0.0/resources/images/default/window/left-right.png +0 -0
- data/public/ext-3.0.0/resources/images/default/window/left-right.psd +0 -0
- data/public/ext-3.0.0/resources/images/default/window/right-corners.png +0 -0
- data/public/ext-3.0.0/resources/images/default/window/right-corners.psd +0 -0
- data/public/ext-3.0.0/resources/images/default/window/top-bottom.png +0 -0
- data/public/ext-3.0.0/resources/images/default/window/top-bottom.psd +0 -0
- data/public/ext-3.0.0/resources/images/icon/chart.gif +0 -0
- data/public/ext-3.0.0/src/adapter/core/ext-base-ajax.js +371 -0
- data/public/ext-3.0.0/src/adapter/core/ext-base-anim-extra.js +301 -0
- data/public/ext-3.0.0/src/adapter/core/ext-base-anim.js +477 -0
- data/public/ext-3.0.0/src/adapter/core/ext-base-begin.js +18 -0
- data/public/ext-3.0.0/src/adapter/core/ext-base-dom.js +157 -0
- data/public/ext-3.0.0/src/adapter/core/ext-base-end.js +21 -0
- data/public/ext-3.0.0/src/adapter/core/ext-base-event.js +453 -0
- data/public/ext-3.0.0/src/adapter/core/ext-base-point.js +17 -0
- data/public/ext-3.0.0/src/adapter/core/ext-base-region.js +81 -0
- data/public/ext-3.0.0/src/adapter/ext-base-dom-more.js +9 -0
- data/public/ext-3.0.0/src/adapter/jquery-bridge.js +546 -0
- data/public/ext-3.0.0/src/adapter/prototype-bridge.js +600 -0
- data/public/ext-3.0.0/src/adapter/yui-bridge.js +390 -0
- data/public/ext-3.0.0/src/core/CompositeElement.js +136 -0
- data/public/ext-3.0.0/src/core/CompositeElementLite-more.js +102 -0
- data/public/ext-3.0.0/src/core/DomHelper-more.js +179 -0
- data/public/ext-3.0.0/src/core/Element-more.js +192 -0
- data/public/ext-3.0.0/src/core/Element.alignment.js +370 -0
- data/public/ext-3.0.0/src/core/Element.dd.js +46 -0
- data/public/ext-3.0.0/src/core/Element.fx-more.js +152 -0
- data/public/ext-3.0.0/src/core/Element.insertion-more.js +52 -0
- data/public/ext-3.0.0/src/core/Element.keys.js +48 -0
- data/public/ext-3.0.0/src/core/Element.legacy.js +42 -0
- data/public/ext-3.0.0/src/core/Element.position-more.js +165 -0
- data/public/ext-3.0.0/src/core/Element.scroll-more.js +110 -0
- data/public/ext-3.0.0/src/core/Element.style-more.js +318 -0
- data/public/ext-3.0.0/src/core/Error.js +81 -0
- data/public/ext-3.0.0/src/core/EventManager-more.js +334 -0
- data/public/ext-3.0.0/src/core/Ext-more.js +669 -0
- data/public/ext-3.0.0/src/core/Template-more.js +115 -0
- data/public/ext-3.0.0/src/core/core/CompositeElementLite.js +197 -0
- data/public/ext-3.0.0/src/core/core/DomHelper.js +378 -0
- data/public/ext-3.0.0/src/core/core/DomQuery.js +826 -0
- data/public/ext-3.0.0/src/core/core/Element.fx.js +324 -0
- data/public/ext-3.0.0/src/core/core/Element.insertion.js +147 -0
- data/public/ext-3.0.0/src/core/core/Element.js +945 -0
- data/public/ext-3.0.0/src/core/core/Element.position.js +303 -0
- data/public/ext-3.0.0/src/core/core/Element.scroll.js +58 -0
- data/public/ext-3.0.0/src/core/core/Element.style.js +439 -0
- data/public/ext-3.0.0/src/core/core/Element.traversal.js +176 -0
- data/public/ext-3.0.0/src/core/core/EventManager.js +623 -0
- data/public/ext-3.0.0/src/core/core/Ext.js +922 -0
- data/public/ext-3.0.0/src/core/core/Fx.js +1115 -0
- data/public/ext-3.0.0/src/core/core/Template.js +185 -0
- data/public/ext-3.0.0/src/data/Api.js +210 -0
- data/public/ext-3.0.0/src/data/ArrayReader.js +102 -0
- data/public/ext-3.0.0/src/data/ArrayStore.js +70 -0
- data/public/ext-3.0.0/src/data/DataField.js +249 -0
- data/public/ext-3.0.0/src/data/DataProxy.js +427 -0
- data/public/ext-3.0.0/src/data/DataReader.js +160 -0
- data/public/ext-3.0.0/src/data/DataWriter.js +201 -0
- data/public/ext-3.0.0/src/data/DirectProxy.js +141 -0
- data/public/ext-3.0.0/src/data/DirectStore.js +52 -0
- data/public/ext-3.0.0/src/data/GroupingStore.js +139 -0
- data/public/ext-3.0.0/src/data/HttpProxy.js +276 -0
- data/public/ext-3.0.0/src/data/JsonReader.js +311 -0
- data/public/ext-3.0.0/src/data/JsonStore.js +49 -0
- data/public/ext-3.0.0/src/data/JsonWriter.js +77 -0
- data/public/ext-3.0.0/src/data/MemoryProxy.js +69 -0
- data/public/ext-3.0.0/src/data/Record.js +400 -0
- data/public/ext-3.0.0/src/data/ScriptTagProxy.js +279 -0
- data/public/ext-3.0.0/src/data/SortTypes.js +91 -0
- data/public/ext-3.0.0/src/data/Store.js +1492 -0
- data/public/ext-3.0.0/src/data/StoreMgr.js +72 -0
- data/public/ext-3.0.0/src/data/Tree.js +785 -0
- data/public/ext-3.0.0/src/data/XmlReader.js +128 -0
- data/public/ext-3.0.0/src/data/XmlStore.js +75 -0
- data/public/ext-3.0.0/src/data/XmlWriter.js +45 -0
- data/public/ext-3.0.0/src/data/core/Connection.js +575 -0
- data/public/ext-3.0.0/src/dd/DDCore.js +2992 -0
- data/public/ext-3.0.0/src/dd/DragSource.js +365 -0
- data/public/ext-3.0.0/src/dd/DragTracker.js +217 -0
- data/public/ext-3.0.0/src/dd/DragZone.js +133 -0
- data/public/ext-3.0.0/src/dd/DropTarget.js +115 -0
- data/public/ext-3.0.0/src/dd/DropZone.js +262 -0
- data/public/ext-3.0.0/src/dd/Registry.js +127 -0
- data/public/ext-3.0.0/src/dd/ScrollManager.js +201 -0
- data/public/ext-3.0.0/src/dd/StatusProxy.js +171 -0
- data/public/ext-3.0.0/src/debug.js +906 -0
- data/public/ext-3.0.0/src/direct/Direct.js +235 -0
- data/public/ext-3.0.0/src/direct/Event.js +34 -0
- data/public/ext-3.0.0/src/direct/JsonProvider.js +45 -0
- data/public/ext-3.0.0/src/direct/PollingProvider.js +151 -0
- data/public/ext-3.0.0/src/direct/Provider.js +110 -0
- data/public/ext-3.0.0/src/direct/RemotingProvider.js +373 -0
- data/public/ext-3.0.0/src/direct/Transaction.js +32 -0
- data/public/ext-3.0.0/src/locale/ext-lang-af.js +184 -0
- data/public/ext-3.0.0/src/locale/ext-lang-bg.js +278 -0
- data/public/ext-3.0.0/src/locale/ext-lang-ca.js +315 -0
- data/public/ext-3.0.0/src/locale/ext-lang-cs.js +293 -0
- data/public/ext-3.0.0/src/locale/ext-lang-da.js +296 -0
- data/public/ext-3.0.0/src/locale/ext-lang-de.js +326 -0
- data/public/ext-3.0.0/src/locale/ext-lang-el_GR.js +309 -0
- data/public/ext-3.0.0/src/locale/ext-lang-en.js +335 -0
- data/public/ext-3.0.0/src/locale/ext-lang-en_GB.js +315 -0
- data/public/ext-3.0.0/src/locale/ext-lang-es.js +318 -0
- data/public/ext-3.0.0/src/locale/ext-lang-fa.js +272 -0
- data/public/ext-3.0.0/src/locale/ext-lang-fi.js +302 -0
- data/public/ext-3.0.0/src/locale/ext-lang-fr.js +335 -0
- data/public/ext-3.0.0/src/locale/ext-lang-fr_CA.js +218 -0
- data/public/ext-3.0.0/src/locale/ext-lang-gr.js +175 -0
- data/public/ext-3.0.0/src/locale/ext-lang-he.js +292 -0
- data/public/ext-3.0.0/src/locale/ext-lang-hr.js +295 -0
- data/public/ext-3.0.0/src/locale/ext-lang-hu.js +296 -0
- data/public/ext-3.0.0/src/locale/ext-lang-id.js +302 -0
- data/public/ext-3.0.0/src/locale/ext-lang-it.js +295 -0
- data/public/ext-3.0.0/src/locale/ext-lang-ja.js +318 -0
- data/public/ext-3.0.0/src/locale/ext-lang-ko.js +267 -0
- data/public/ext-3.0.0/src/locale/ext-lang-lt.js +333 -0
- data/public/ext-3.0.0/src/locale/ext-lang-lv.js +176 -0
- data/public/ext-3.0.0/src/locale/ext-lang-mk.js +176 -0
- data/public/ext-3.0.0/src/locale/ext-lang-nl.js +323 -0
- data/public/ext-3.0.0/src/locale/ext-lang-no_NB.js +294 -0
- data/public/ext-3.0.0/src/locale/ext-lang-no_NN.js +294 -0
- data/public/ext-3.0.0/src/locale/ext-lang-pl.js +304 -0
- data/public/ext-3.0.0/src/locale/ext-lang-pt.js +260 -0
- data/public/ext-3.0.0/src/locale/ext-lang-pt_BR.js +302 -0
- data/public/ext-3.0.0/src/locale/ext-lang-pt_PT.js +298 -0
- data/public/ext-3.0.0/src/locale/ext-lang-ro.js +295 -0
- data/public/ext-3.0.0/src/locale/ext-lang-ru.js +319 -0
- data/public/ext-3.0.0/src/locale/ext-lang-sk.js +182 -0
- data/public/ext-3.0.0/src/locale/ext-lang-sl.js +176 -0
- data/public/ext-3.0.0/src/locale/ext-lang-sr.js +179 -0
- data/public/ext-3.0.0/src/locale/ext-lang-sr_RS.js +178 -0
- data/public/ext-3.0.0/src/locale/ext-lang-sv_SE.js +178 -0
- data/public/ext-3.0.0/src/locale/ext-lang-th.js +294 -0
- data/public/ext-3.0.0/src/locale/ext-lang-tr.js +306 -0
- data/public/ext-3.0.0/src/locale/ext-lang-ukr.js +258 -0
- data/public/ext-3.0.0/src/locale/ext-lang-vn.js +181 -0
- data/public/ext-3.0.0/src/locale/ext-lang-zh_CN.js +174 -0
- data/public/ext-3.0.0/src/locale/ext-lang-zh_TW.js +178 -0
- data/public/ext-3.0.0/src/state/CookieProvider.js +91 -0
- data/public/ext-3.0.0/src/state/Provider.js +127 -0
- data/public/ext-3.0.0/src/state/StateManager.js +69 -0
- data/public/ext-3.0.0/src/util/CSS.js +161 -0
- data/public/ext-3.0.0/src/util/ClickRepeater.js +200 -0
- data/public/ext-3.0.0/src/util/Cookies.js +96 -0
- data/public/ext-3.0.0/src/util/Date.js +1317 -0
- data/public/ext-3.0.0/src/util/Format.js +356 -0
- data/public/ext-3.0.0/src/util/History.js +203 -0
- data/public/ext-3.0.0/src/util/KeyMap.js +242 -0
- data/public/ext-3.0.0/src/util/KeyNav.js +161 -0
- data/public/ext-3.0.0/src/util/MixedCollection.js +576 -0
- data/public/ext-3.0.0/src/util/Observable-more.js +178 -0
- data/public/ext-3.0.0/src/util/TextMetrics.js +131 -0
- data/public/ext-3.0.0/src/util/UpdateManager.js +536 -0
- data/public/ext-3.0.0/src/util/XTemplate.js +379 -0
- data/public/ext-3.0.0/src/util/core/DelayedTask.js +68 -0
- data/public/ext-3.0.0/src/util/core/JSON.js +174 -0
- data/public/ext-3.0.0/src/util/core/Observable.js +483 -0
- data/public/ext-3.0.0/src/util/core/TaskMgr.js +174 -0
- data/public/ext-3.0.0/src/widgets/Action.js +252 -0
- data/public/ext-3.0.0/src/widgets/BoxComponent.js +519 -0
- data/public/ext-3.0.0/src/widgets/Button.js +762 -0
- data/public/ext-3.0.0/src/widgets/ButtonGroup.js +103 -0
- data/public/ext-3.0.0/src/widgets/ColorPalette.js +148 -0
- data/public/ext-3.0.0/src/widgets/Component.js +1540 -0
- data/public/ext-3.0.0/src/widgets/ComponentMgr.js +159 -0
- data/public/ext-3.0.0/src/widgets/Container.js +894 -0
- data/public/ext-3.0.0/src/widgets/CycleButton.js +188 -0
- data/public/ext-3.0.0/src/widgets/DataView.js +749 -0
- data/public/ext-3.0.0/src/widgets/DatePicker.js +771 -0
- data/public/ext-3.0.0/src/widgets/Editor.js +385 -0
- data/public/ext-3.0.0/src/widgets/Layer.js +466 -0
- data/public/ext-3.0.0/src/widgets/LoadMask.js +123 -0
- data/public/ext-3.0.0/src/widgets/MessageBox.js +626 -0
- data/public/ext-3.0.0/src/widgets/PagingToolbar.js +502 -0
- data/public/ext-3.0.0/src/widgets/Panel.js +1772 -0
- data/public/ext-3.0.0/src/widgets/PanelDD.js +154 -0
- data/public/ext-3.0.0/src/widgets/ProgressBar.js +289 -0
- data/public/ext-3.0.0/src/widgets/Resizable.js +760 -0
- data/public/ext-3.0.0/src/widgets/Shadow.js +192 -0
- data/public/ext-3.0.0/src/widgets/Slider.js +426 -0
- data/public/ext-3.0.0/src/widgets/SplitBar.js +436 -0
- data/public/ext-3.0.0/src/widgets/SplitButton.js +124 -0
- data/public/ext-3.0.0/src/widgets/TabPanel.js +1100 -0
- data/public/ext-3.0.0/src/widgets/Toolbar.js +781 -0
- data/public/ext-3.0.0/src/widgets/Viewport.js +124 -0
- data/public/ext-3.0.0/src/widgets/Window.js +941 -0
- data/public/ext-3.0.0/src/widgets/WindowManager.js +187 -0
- data/public/ext-3.0.0/src/widgets/chart/Chart.js +721 -0
- data/public/ext-3.0.0/src/widgets/chart/EventProxy.js +20 -0
- data/public/ext-3.0.0/src/widgets/chart/FlashComponent.js +117 -0
- data/public/ext-3.0.0/src/widgets/chart/swfobject.js +783 -0
- data/public/ext-3.0.0/src/widgets/form/Action.js +626 -0
- data/public/ext-3.0.0/src/widgets/form/BasicForm.js +735 -0
- data/public/ext-3.0.0/src/widgets/form/Checkbox.js +177 -0
- data/public/ext-3.0.0/src/widgets/form/CheckboxGroup.js +419 -0
- data/public/ext-3.0.0/src/widgets/form/Combo.js +1232 -0
- data/public/ext-3.0.0/src/widgets/form/DateField.js +389 -0
- data/public/ext-3.0.0/src/widgets/form/DisplayField.js +98 -0
- data/public/ext-3.0.0/src/widgets/form/Field.js +640 -0
- data/public/ext-3.0.0/src/widgets/form/FieldSet.js +305 -0
- data/public/ext-3.0.0/src/widgets/form/Form.js +335 -0
- data/public/ext-3.0.0/src/widgets/form/Hidden.js +39 -0
- data/public/ext-3.0.0/src/widgets/form/HtmlEditor.js +1179 -0
- data/public/ext-3.0.0/src/widgets/form/Label.js +64 -0
- data/public/ext-3.0.0/src/widgets/form/NumberField.js +139 -0
- data/public/ext-3.0.0/src/widgets/form/Radio.js +81 -0
- data/public/ext-3.0.0/src/widgets/form/RadioGroup.js +116 -0
- data/public/ext-3.0.0/src/widgets/form/TextArea.js +117 -0
- data/public/ext-3.0.0/src/widgets/form/TextField.js +491 -0
- data/public/ext-3.0.0/src/widgets/form/TimeField.js +146 -0
- data/public/ext-3.0.0/src/widgets/form/TriggerField.js +328 -0
- data/public/ext-3.0.0/src/widgets/form/VTypes.js +135 -0
- data/public/ext-3.0.0/src/widgets/grid/AbstractSelectionModel.js +57 -0
- data/public/ext-3.0.0/src/widgets/grid/CellSelectionModel.js +262 -0
- data/public/ext-3.0.0/src/widgets/grid/CheckboxSelectionModel.js +103 -0
- data/public/ext-3.0.0/src/widgets/grid/Column.js +406 -0
- data/public/ext-3.0.0/src/widgets/grid/ColumnDD.js +199 -0
- data/public/ext-3.0.0/src/widgets/grid/ColumnModel.js +592 -0
- data/public/ext-3.0.0/src/widgets/grid/ColumnSplitDD.js +62 -0
- data/public/ext-3.0.0/src/widgets/grid/EditorGrid.js +291 -0
- data/public/ext-3.0.0/src/widgets/grid/GridDD.js +95 -0
- data/public/ext-3.0.0/src/widgets/grid/GridEditor.js +21 -0
- data/public/ext-3.0.0/src/widgets/grid/GridPanel.js +952 -0
- data/public/ext-3.0.0/src/widgets/grid/GridView.js +1776 -0
- data/public/ext-3.0.0/src/widgets/grid/GroupingView.js +517 -0
- data/public/ext-3.0.0/src/widgets/grid/PropertyGrid.js +370 -0
- data/public/ext-3.0.0/src/widgets/grid/RowNumberer.js +61 -0
- data/public/ext-3.0.0/src/widgets/grid/RowSelectionModel.js +530 -0
- data/public/ext-3.0.0/src/widgets/layout/AbsoluteLayout.js +82 -0
- data/public/ext-3.0.0/src/widgets/layout/AccordionLayout.js +177 -0
- data/public/ext-3.0.0/src/widgets/layout/AnchorLayout.js +200 -0
- data/public/ext-3.0.0/src/widgets/layout/BorderLayout.js +1108 -0
- data/public/ext-3.0.0/src/widgets/layout/BoxLayout.js +417 -0
- data/public/ext-3.0.0/src/widgets/layout/CardLayout.js +127 -0
- data/public/ext-3.0.0/src/widgets/layout/ColumnLayout.js +130 -0
- data/public/ext-3.0.0/src/widgets/layout/ContainerLayout.js +215 -0
- data/public/ext-3.0.0/src/widgets/layout/FitLayout.js +48 -0
- data/public/ext-3.0.0/src/widgets/layout/FormLayout.js +266 -0
- data/public/ext-3.0.0/src/widgets/layout/TableLayout.js +194 -0
- data/public/ext-3.0.0/src/widgets/list/ColumnResizer.js +123 -0
- data/public/ext-3.0.0/src/widgets/list/ListView.js +357 -0
- data/public/ext-3.0.0/src/widgets/list/Sorter.js +70 -0
- data/public/ext-3.0.0/src/widgets/menu/BaseItem.js +160 -0
- data/public/ext-3.0.0/src/widgets/menu/CheckItem.js +114 -0
- data/public/ext-3.0.0/src/widgets/menu/ColorMenu.js +72 -0
- data/public/ext-3.0.0/src/widgets/menu/DateMenu.js +90 -0
- data/public/ext-3.0.0/src/widgets/menu/Item.js +211 -0
- data/public/ext-3.0.0/src/widgets/menu/Menu.js +733 -0
- data/public/ext-3.0.0/src/widgets/menu/MenuMgr.js +211 -0
- data/public/ext-3.0.0/src/widgets/menu/Separator.js +46 -0
- data/public/ext-3.0.0/src/widgets/menu/TextItem.js +46 -0
- data/public/ext-3.0.0/src/widgets/tips/QuickTip.js +207 -0
- data/public/ext-3.0.0/src/widgets/tips/QuickTips.js +159 -0
- data/public/ext-3.0.0/src/widgets/tips/Tip.js +157 -0
- data/public/ext-3.0.0/src/widgets/tips/ToolTip.js +492 -0
- data/public/ext-3.0.0/src/widgets/tree/AsyncTreeNode.js +114 -0
- data/public/ext-3.0.0/src/widgets/tree/TreeDragZone.js +82 -0
- data/public/ext-3.0.0/src/widgets/tree/TreeDropZone.js +321 -0
- data/public/ext-3.0.0/src/widgets/tree/TreeEditor.js +160 -0
- data/public/ext-3.0.0/src/widgets/tree/TreeEventModel.js +169 -0
- data/public/ext-3.0.0/src/widgets/tree/TreeFilter.js +114 -0
- data/public/ext-3.0.0/src/widgets/tree/TreeLoader.js +342 -0
- data/public/ext-3.0.0/src/widgets/tree/TreeNode.js +546 -0
- data/public/ext-3.0.0/src/widgets/tree/TreeNodeUI.js +633 -0
- data/public/ext-3.0.0/src/widgets/tree/TreePanel.js +918 -0
- data/public/ext-3.0.0/src/widgets/tree/TreeSelectionModel.js +315 -0
- data/public/ext-3.0.0/src/widgets/tree/TreeSorter.js +106 -0
- data/public/js/ext-portal.js +235 -0
- data/public/js/global.js +7 -0
- data/public/js/outerframe.js +47 -0
- data/public/js/portal.js +713 -0
- data/public/js/test_chart.js +152 -0
- data/test/config.rb +62 -0
- data/test/config/hosts.yaml +5 -0
- data/test/config/log.yaml +1 -0
- data/test/config/memcache.yaml +5 -0
- data/test/exception.rb +39 -0
- data/test/method_missing.rb +14 -0
- data/test/module.rb +39 -0
- data/test/remote_lmp.rb +126 -0
- data/test/sinatra.rb +29 -0
- data/test/sinatra_base.rb +16 -0
- metadata +690 -0
@@ -0,0 +1,7 @@
|
|
1
|
+
/*
|
2
|
+
* Ext JS Library 3.0.0
|
3
|
+
* Copyright(c) 2006-2009 Ext JS, LLC
|
4
|
+
* licensing@extjs.com
|
5
|
+
* http://www.extjs.com/license
|
6
|
+
*/
|
7
|
+
Ext.ComponentMgr=function(){var c=new Ext.util.MixedCollection();var b={};var a={};return{register:function(d){c.add(d)},unregister:function(d){c.remove(d)},get:function(d){return c.get(d)},onAvailable:function(f,e,d){c.on("add",function(g,h){if(h.id==f){e.call(d||h,h);c.un("add",e,d)}})},all:c,isRegistered:function(d){return b[d]!==undefined},registerType:function(e,d){b[e]=d;d.xtype=e},create:function(d,e){return d.render?d:new b[d.xtype||e](d)},registerPlugin:function(e,d){a[e]=d;d.ptype=e},createPlugin:function(d,e){return new a[d.ptype||e](d)}}}();Ext.reg=Ext.ComponentMgr.registerType;Ext.preg=Ext.ComponentMgr.registerPlugin;Ext.create=Ext.ComponentMgr.create;Ext.Component=function(b){b=b||{};if(b.initialConfig){if(b.isAction){this.baseAction=b}b=b.initialConfig}else{if(b.tagName||b.dom||Ext.isString(b)){b={applyTo:b,id:b.id||b}}}this.initialConfig=b;Ext.apply(this,b);this.addEvents("disable","enable","beforeshow","show","beforehide","hide","beforerender","render","afterrender","beforedestroy","destroy","beforestaterestore","staterestore","beforestatesave","statesave");this.getId();Ext.ComponentMgr.register(this);Ext.Component.superclass.constructor.call(this);if(this.baseAction){this.baseAction.addComponent(this)}this.initComponent();if(this.plugins){if(Ext.isArray(this.plugins)){for(var c=0,a=this.plugins.length;c<a;c++){this.plugins[c]=this.initPlugin(this.plugins[c])}}else{this.plugins=this.initPlugin(this.plugins)}}if(this.stateful!==false){this.initState(b)}if(this.applyTo){this.applyToMarkup(this.applyTo);delete this.applyTo}else{if(this.renderTo){this.render(this.renderTo);delete this.renderTo}}};Ext.Component.AUTO_ID=1000;Ext.extend(Ext.Component,Ext.util.Observable,{disabled:false,hidden:false,autoEl:"div",disabledClass:"x-item-disabled",allowDomMove:true,autoShow:false,hideMode:"display",hideParent:false,rendered:false,ctype:"Ext.Component",actionMode:"el",getActionEl:function(){return this[this.actionMode]},initPlugin:function(a){if(a.ptype&&!Ext.isFunction(a.init)){a=Ext.ComponentMgr.createPlugin(a)}else{if(Ext.isString(a)){a=Ext.ComponentMgr.createPlugin({ptype:a})}}a.init(this);return a},initComponent:Ext.emptyFn,render:function(b,a){if(!this.rendered&&this.fireEvent("beforerender",this)!==false){if(!b&&this.el){this.el=Ext.get(this.el);b=this.el.dom.parentNode;this.allowDomMove=false}this.container=Ext.get(b);if(this.ctCls){this.container.addClass(this.ctCls)}this.rendered=true;if(a!==undefined){if(Ext.isNumber(a)){a=this.container.dom.childNodes[a]}else{a=Ext.getDom(a)}}this.onRender(this.container,a||null);if(this.autoShow){this.el.removeClass(["x-hidden","x-hide-"+this.hideMode])}if(this.cls){this.el.addClass(this.cls);delete this.cls}if(this.style){this.el.applyStyles(this.style);delete this.style}if(this.overCls){this.el.addClassOnOver(this.overCls)}this.fireEvent("render",this);this.afterRender(this.container);if(this.hidden){this.doHide()}if(this.disabled){this.disable(true)}if(this.stateful!==false){this.initStateEvents()}this.initRef();this.fireEvent("afterrender",this)}return this},initRef:function(){if(this.ref){var d=this.ref.split("/");var c=d.length,b=0;var a=this;while(b<c){if(a.ownerCt){a=a.ownerCt}b++}a[d[--b]]=this}},initState:function(a){if(Ext.state.Manager){var c=this.getStateId();if(c){var b=Ext.state.Manager.get(c);if(b){if(this.fireEvent("beforestaterestore",this,b)!==false){this.applyState(b);this.fireEvent("staterestore",this,b)}}}}},getStateId:function(){return this.stateId||((this.id.indexOf("ext-comp-")==0||this.id.indexOf("ext-gen")==0)?null:this.id)},initStateEvents:function(){if(this.stateEvents){for(var a=0,b;b=this.stateEvents[a];a++){this.on(b,this.saveState,this,{delay:100})}}},applyState:function(b,a){if(b){Ext.apply(this,b)}},getState:function(){return null},saveState:function(){if(Ext.state.Manager&&this.stateful!==false){var b=this.getStateId();if(b){var a=this.getState();if(this.fireEvent("beforestatesave",this,a)!==false){Ext.state.Manager.set(b,a);this.fireEvent("statesave",this,a)}}}},applyToMarkup:function(a){this.allowDomMove=false;this.el=Ext.get(a);this.render(this.el.dom.parentNode)},addClass:function(a){if(this.el){this.el.addClass(a)}else{this.cls=this.cls?this.cls+" "+a:a}return this},removeClass:function(a){if(this.el){this.el.removeClass(a)}else{if(this.cls){this.cls=this.cls.split(" ").remove(a).join(" ")}}return this},onRender:function(b,a){if(!this.el&&this.autoEl){if(Ext.isString(this.autoEl)){this.el=document.createElement(this.autoEl)}else{var c=document.createElement("div");Ext.DomHelper.overwrite(c,this.autoEl);this.el=c.firstChild}if(!this.el.id){this.el.id=this.getId()}}if(this.el){this.el=Ext.get(this.el);if(this.allowDomMove!==false){b.dom.insertBefore(this.el.dom,a)}}},getAutoCreate:function(){var a=Ext.isObject(this.autoCreate)?this.autoCreate:Ext.apply({},this.defaultAutoCreate);if(this.id&&!a.id){a.id=this.id}return a},afterRender:Ext.emptyFn,destroy:function(){if(this.fireEvent("beforedestroy",this)!==false){this.beforeDestroy();if(this.rendered){this.el.removeAllListeners();this.el.remove();if(this.actionMode=="container"||this.removeMode=="container"){this.container.remove()}}this.onDestroy();Ext.ComponentMgr.unregister(this);this.fireEvent("destroy",this);this.purgeListeners()}},beforeDestroy:Ext.emptyFn,onDestroy:Ext.emptyFn,getEl:function(){return this.el},getId:function(){return this.id||(this.id="ext-comp-"+(++Ext.Component.AUTO_ID))},getItemId:function(){return this.itemId||this.getId()},focus:function(b,a){if(a){this.focus.defer(Ext.isNumber(a)?a:10,this,[b,false]);return}if(this.rendered){this.el.focus();if(b===true){this.el.dom.select()}}return this},blur:function(){if(this.rendered){this.el.blur()}return this},disable:function(a){if(this.rendered){this.onDisable()}this.disabled=true;if(a!==true){this.fireEvent("disable",this)}return this},onDisable:function(){this.getActionEl().addClass(this.disabledClass);this.el.dom.disabled=true},enable:function(){if(this.rendered){this.onEnable()}this.disabled=false;this.fireEvent("enable",this);return this},onEnable:function(){this.getActionEl().removeClass(this.disabledClass);this.el.dom.disabled=false},setDisabled:function(a){return this[a?"disable":"enable"]()},show:function(){if(this.fireEvent("beforeshow",this)!==false){this.hidden=false;if(this.autoRender){this.render(Ext.isBoolean(this.autoRender)?Ext.getBody():this.autoRender)}if(this.rendered){this.onShow()}this.fireEvent("show",this)}return this},onShow:function(){this.getVisibiltyEl().removeClass("x-hide-"+this.hideMode)},hide:function(){if(this.fireEvent("beforehide",this)!==false){this.doHide();this.fireEvent("hide",this)}return this},doHide:function(){this.hidden=true;if(this.rendered){this.onHide()}},onHide:function(){this.getVisibiltyEl().addClass("x-hide-"+this.hideMode)},getVisibiltyEl:function(){return this.hideParent?this.container:this.getActionEl()},setVisible:function(a){return this[a?"show":"hide"]()},isVisible:function(){return this.rendered&&this.getVisibiltyEl().isVisible()},cloneConfig:function(b){b=b||{};var c=b.id||Ext.id();var a=Ext.applyIf(b,this.initialConfig);a.id=c;return new this.constructor(a)},getXType:function(){return this.constructor.xtype},isXType:function(b,a){if(Ext.isFunction(b)){b=b.xtype}else{if(Ext.isObject(b)){b=b.constructor.xtype}}return !a?("/"+this.getXTypes()+"/").indexOf("/"+b+"/")!=-1:this.constructor.xtype==b},getXTypes:function(){var a=this.constructor;if(!a.xtypes){var d=[],b=this;while(b&&b.constructor.xtype){d.unshift(b.constructor.xtype);b=b.constructor.superclass}a.xtypeChain=d;a.xtypes=d.join("/")}return a.xtypes},findParentBy:function(a){for(var b=this.ownerCt;(b!=null)&&!a(b,this);b=b.ownerCt){}return b||null},findParentByType:function(a){return Ext.isFunction(a)?this.findParentBy(function(b){return b.constructor===a}):this.findParentBy(function(b){return b.constructor.xtype===a})},getDomPositionEl:function(){return this.getPositionEl?this.getPositionEl():this.getEl()},purgeListeners:function(){Ext.Component.superclass.purgeListeners.call(this);if(this.mons){this.on("beforedestroy",this.clearMons,this,{single:true})}},clearMons:function(){Ext.each(this.mons,function(a){a.item.un(a.ename,a.fn,a.scope)},this);this.mons=[]},mon:function(f,b,d,c,a){if(!this.mons){this.mons=[];this.on("beforedestroy",this.clearMons,this,{single:true})}if(Ext.isObject(b)){var i=/^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;var h=b;for(var g in h){if(i.test(g)){continue}if(Ext.isFunction(h[g])){this.mons.push({item:f,ename:g,fn:h[g],scope:h.scope});f.on(g,h[g],h.scope,h)}else{this.mons.push({item:f,ename:g,fn:h[g],scope:h.scope});f.on(g,h[g])}}return}this.mons.push({item:f,ename:b,fn:d,scope:c});f.on(b,d,c,a)},mun:function(g,c,f,e){var h,d;for(var b=0,a=this.mons.length;b<a;++b){d=this.mons[b];if(g===d.item&&c==d.ename&&f===d.fn&&e===d.scope){this.mons.splice(b,1);g.un(c,f,e);h=true;break}}return h},nextSibling:function(){if(this.ownerCt){var a=this.ownerCt.items.indexOf(this);if(a!=-1&&a+1<this.ownerCt.items.getCount()){return this.ownerCt.items.itemAt(a+1)}}return null},previousSibling:function(){if(this.ownerCt){var a=this.ownerCt.items.indexOf(this);if(a>0){return this.ownerCt.items.itemAt(a-1)}}return null},getBubbleTarget:function(){return this.ownerCt}});Ext.reg("component",Ext.Component);Ext.Action=function(a){this.initialConfig=a;this.itemId=a.itemId=(a.itemId||a.id||Ext.id());this.items=[]};Ext.Action.prototype={isAction:true,setText:function(a){this.initialConfig.text=a;this.callEach("setText",[a])},getText:function(){return this.initialConfig.text},setIconClass:function(a){this.initialConfig.iconCls=a;this.callEach("setIconClass",[a])},getIconClass:function(){return this.initialConfig.iconCls},setDisabled:function(a){this.initialConfig.disabled=a;this.callEach("setDisabled",[a])},enable:function(){this.setDisabled(false)},disable:function(){this.setDisabled(true)},isDisabled:function(){return this.initialConfig.disabled},setHidden:function(a){this.initialConfig.hidden=a;this.callEach("setVisible",[!a])},show:function(){this.setHidden(false)},hide:function(){this.setHidden(true)},isHidden:function(){return this.initialConfig.hidden},setHandler:function(b,a){this.initialConfig.handler=b;this.initialConfig.scope=a;this.callEach("setHandler",[b,a])},each:function(b,a){Ext.each(this.items,b,a)},callEach:function(e,b){var d=this.items;for(var c=0,a=d.length;c<a;c++){d[c][e].apply(d[c],b)}},addComponent:function(a){this.items.push(a);a.on("destroy",this.removeComponent,this)},removeComponent:function(a){this.items.remove(a)},execute:function(){this.initialConfig.handler.apply(this.initialConfig.scope||window,arguments)}};(function(){Ext.Layer=function(d,c){d=d||{};var e=Ext.DomHelper;var g=d.parentEl,f=g?Ext.getDom(g):document.body;if(c){this.dom=Ext.getDom(c)}if(!this.dom){var h=d.dh||{tag:"div",cls:"x-layer"};this.dom=e.append(f,h)}if(d.cls){this.addClass(d.cls)}this.constrain=d.constrain!==false;this.setVisibilityMode(Ext.Element.VISIBILITY);if(d.id){this.id=this.dom.id=d.id}else{this.id=Ext.id(this.dom)}this.zindex=d.zindex||this.getZIndex();this.position("absolute",this.zindex);if(d.shadow){this.shadowOffset=d.shadowOffset||4;this.shadow=new Ext.Shadow({offset:this.shadowOffset,mode:d.shadow})}else{this.shadowOffset=0}this.useShim=d.shim!==false&&Ext.useShims;this.useDisplay=d.useDisplay;this.hide()};var a=Ext.Element.prototype;var b=[];Ext.extend(Ext.Layer,Ext.Element,{getZIndex:function(){return this.zindex||parseInt((this.getShim()||this).getStyle("z-index"),10)||11000},getShim:function(){if(!this.useShim){return null}if(this.shim){return this.shim}var d=b.shift();if(!d){d=this.createShim();d.enableDisplayMode("block");d.dom.style.display="none";d.dom.style.visibility="visible"}var c=this.dom.parentNode;if(d.dom.parentNode!=c){c.insertBefore(d.dom,this.dom)}d.setStyle("z-index",this.getZIndex()-2);this.shim=d;return d},hideShim:function(){if(this.shim){this.shim.setDisplayed(false);b.push(this.shim);delete this.shim}},disableShadow:function(){if(this.shadow){this.shadowDisabled=true;this.shadow.hide();this.lastShadowOffset=this.shadowOffset;this.shadowOffset=0}},enableShadow:function(c){if(this.shadow){this.shadowDisabled=false;this.shadowOffset=this.lastShadowOffset;delete this.lastShadowOffset;if(c){this.sync(true)}}},sync:function(c){var j=this.shadow;if(!this.updating&&this.isVisible()&&(j||this.useShim)){var f=this.getShim();var i=this.getWidth(),e=this.getHeight();var d=this.getLeft(true),k=this.getTop(true);if(j&&!this.shadowDisabled){if(c&&!j.isVisible()){j.show(this)}else{j.realign(d,k,i,e)}if(f){if(c){f.show()}var g=j.adjusts,m=f.dom.style;m.left=(Math.min(d,d+g.l))+"px";m.top=(Math.min(k,k+g.t))+"px";m.width=(i+g.w)+"px";m.height=(e+g.h)+"px"}}else{if(f){if(c){f.show()}f.setSize(i,e);f.setLeftTop(d,k)}}}},destroy:function(){this.hideShim();if(this.shadow){this.shadow.hide()}this.removeAllListeners();Ext.removeNode(this.dom);Ext.Element.uncache(this.id)},remove:function(){this.destroy()},beginUpdate:function(){this.updating=true},endUpdate:function(){this.updating=false;this.sync(true)},hideUnders:function(c){if(this.shadow){this.shadow.hide()}this.hideShim()},constrainXY:function(){if(this.constrain){var i=Ext.lib.Dom.getViewWidth(),d=Ext.lib.Dom.getViewHeight();var n=Ext.getDoc().getScroll();var m=this.getXY();var j=m[0],g=m[1];var c=this.shadowOffset;var k=this.dom.offsetWidth+c,e=this.dom.offsetHeight+c;var f=false;if((j+k)>i+n.left){j=i-k-c;f=true}if((g+e)>d+n.top){g=d-e-c;f=true}if(j<n.left){j=n.left;f=true}if(g<n.top){g=n.top;f=true}if(f){if(this.avoidY){var l=this.avoidY;if(g<=l&&(g+e)>=l){g=l-e-5}}m=[j,g];this.storeXY(m);a.setXY.call(this,m);this.sync()}}return this},isVisible:function(){return this.visible},showAction:function(){this.visible=true;if(this.useDisplay===true){this.setDisplayed("")}else{if(this.lastXY){a.setXY.call(this,this.lastXY)}else{if(this.lastLT){a.setLeftTop.call(this,this.lastLT[0],this.lastLT[1])}}}},hideAction:function(){this.visible=false;if(this.useDisplay===true){this.setDisplayed(false)}else{this.setLeftTop(-10000,-10000)}},setVisible:function(h,g,j,k,i){if(h){this.showAction()}if(g&&h){var f=function(){this.sync(true);if(k){k()}}.createDelegate(this);a.setVisible.call(this,true,true,j,f,i)}else{if(!h){this.hideUnders(true)}var f=k;if(g){f=function(){this.hideAction();if(k){k()}}.createDelegate(this)}a.setVisible.call(this,h,g,j,f,i);if(h){this.sync(true)}else{if(!g){this.hideAction()}}}return this},storeXY:function(c){delete this.lastLT;this.lastXY=c},storeLeftTop:function(d,c){delete this.lastXY;this.lastLT=[d,c]},beforeFx:function(){this.beforeAction();return Ext.Layer.superclass.beforeFx.apply(this,arguments)},afterFx:function(){Ext.Layer.superclass.afterFx.apply(this,arguments);this.sync(this.isVisible())},beforeAction:function(){if(!this.updating&&this.shadow){this.shadow.hide()}},setLeft:function(c){this.storeLeftTop(c,this.getTop(true));a.setLeft.apply(this,arguments);this.sync();return this},setTop:function(c){this.storeLeftTop(this.getLeft(true),c);a.setTop.apply(this,arguments);this.sync();return this},setLeftTop:function(d,c){this.storeLeftTop(d,c);a.setLeftTop.apply(this,arguments);this.sync();return this},setXY:function(i,g,j,k,h){this.fixDisplay();this.beforeAction();this.storeXY(i);var f=this.createCB(k);a.setXY.call(this,i,g,j,f,h);if(!g){f()}return this},createCB:function(e){var d=this;return function(){d.constrainXY();d.sync(true);if(e){e()}}},setX:function(f,g,i,j,h){this.setXY([f,this.getY()],g,i,j,h);return this},setY:function(j,f,h,i,g){this.setXY([this.getX(),j],f,h,i,g);return this},setSize:function(i,j,g,l,m,k){this.beforeAction();var f=this.createCB(m);a.setSize.call(this,i,j,g,l,f,k);if(!g){f()}return this},setWidth:function(h,g,j,k,i){this.beforeAction();var f=this.createCB(k);a.setWidth.call(this,h,g,j,f,i);if(!g){f()}return this},setHeight:function(i,g,k,l,j){this.beforeAction();var f=this.createCB(l);a.setHeight.call(this,i,g,k,f,j);if(!g){f()}return this},setBounds:function(n,l,o,g,m,j,k,i){this.beforeAction();var f=this.createCB(k);if(!m){this.storeXY([n,l]);a.setXY.call(this,[n,l]);a.setSize.call(this,o,g,m,j,f,i);f()}else{a.setBounds.call(this,n,l,o,g,m,j,f,i)}return this},setZIndex:function(c){this.zindex=c;this.setStyle("z-index",c+2);if(this.shadow){this.shadow.setZIndex(c+1)}if(this.shim){this.shim.setStyle("z-index",c)}return this}})})();Ext.Shadow=function(d){Ext.apply(this,d);if(typeof this.mode!="string"){this.mode=this.defaultMode}var e=this.offset,c={h:0};var b=Math.floor(this.offset/2);switch(this.mode.toLowerCase()){case"drop":c.w=0;c.l=c.t=e;c.t-=1;if(Ext.isIE){c.l-=this.offset+b;c.t-=this.offset+b;c.w-=b;c.h-=b;c.t+=1}break;case"sides":c.w=(e*2);c.l=-e;c.t=e-1;if(Ext.isIE){c.l-=(this.offset-b);c.t-=this.offset+b;c.l+=1;c.w-=(this.offset-b)*2;c.w-=b+1;c.h-=1}break;case"frame":c.w=c.h=(e*2);c.l=c.t=-e;c.t+=1;c.h-=2;if(Ext.isIE){c.l-=(this.offset-b);c.t-=(this.offset-b);c.l+=1;c.w-=(this.offset+b+1);c.h-=(this.offset+b);c.h+=1}break}this.adjusts=c};Ext.Shadow.prototype={offset:4,defaultMode:"drop",show:function(a){a=Ext.get(a);if(!this.el){this.el=Ext.Shadow.Pool.pull();if(this.el.dom.nextSibling!=a.dom){this.el.insertBefore(a)}}this.el.setStyle("z-index",this.zIndex||parseInt(a.getStyle("z-index"),10)-1);if(Ext.isIE){this.el.dom.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius="+(this.offset)+")"}this.realign(a.getLeft(true),a.getTop(true),a.getWidth(),a.getHeight());this.el.dom.style.display="block"},isVisible:function(){return this.el?true:false},realign:function(b,q,p,f){if(!this.el){return}var m=this.adjusts,j=this.el.dom,r=j.style;var g=0;r.left=(b+m.l)+"px";r.top=(q+m.t)+"px";var o=(p+m.w),e=(f+m.h),i=o+"px",n=e+"px";if(r.width!=i||r.height!=n){r.width=i;r.height=n;if(!Ext.isIE){var k=j.childNodes;var c=Math.max(0,(o-12))+"px";k[0].childNodes[1].style.width=c;k[1].childNodes[1].style.width=c;k[2].childNodes[1].style.width=c;k[1].style.height=Math.max(0,(e-12))+"px"}}},hide:function(){if(this.el){this.el.dom.style.display="none";Ext.Shadow.Pool.push(this.el);delete this.el}},setZIndex:function(a){this.zIndex=a;if(this.el){this.el.setStyle("z-index",a)}}};Ext.Shadow.Pool=function(){var b=[];var a=Ext.isIE?'<div class="x-ie-shadow"></div>':'<div class="x-shadow"><div class="xst"><div class="xstl"></div><div class="xstc"></div><div class="xstr"></div></div><div class="xsc"><div class="xsml"></div><div class="xsmc"></div><div class="xsmr"></div></div><div class="xsb"><div class="xsbl"></div><div class="xsbc"></div><div class="xsbr"></div></div></div>';return{pull:function(){var c=b.shift();if(!c){c=Ext.get(Ext.DomHelper.insertHtml("beforeBegin",document.body.firstChild,a));c.autoBoxAdjust=false}return c},push:function(c){b.push(c)}}}();Ext.BoxComponent=Ext.extend(Ext.Component,{initComponent:function(){Ext.BoxComponent.superclass.initComponent.call(this);this.addEvents("resize","move")},boxReady:false,deferHeight:false,setSize:function(b,d){if(typeof b=="object"){d=b.height;b=b.width}if(!this.boxReady){this.width=b;this.height=d;return this}if(this.cacheSizes!==false&&this.lastSize&&this.lastSize.width==b&&this.lastSize.height==d){return this}this.lastSize={width:b,height:d};var c=this.adjustSize(b,d);var f=c.width,a=c.height;if(f!==undefined||a!==undefined){var e=this.getResizeEl();if(!this.deferHeight&&f!==undefined&&a!==undefined){e.setSize(f,a)}else{if(!this.deferHeight&&a!==undefined){e.setHeight(a)}else{if(f!==undefined){e.setWidth(f)}}}this.onResize(f,a,b,d);this.fireEvent("resize",this,f,a,b,d)}return this},setWidth:function(a){return this.setSize(a)},setHeight:function(a){return this.setSize(undefined,a)},getSize:function(){return this.getResizeEl().getSize()},getWidth:function(){return this.getResizeEl().getWidth()},getHeight:function(){return this.getResizeEl().getHeight()},getOuterSize:function(){var a=this.getResizeEl();return{width:a.getWidth()+a.getMargins("lr"),height:a.getHeight()+a.getMargins("tb")}},getPosition:function(a){var b=this.getPositionEl();if(a===true){return[b.getLeft(true),b.getTop(true)]}return this.xy||b.getXY()},getBox:function(a){var c=this.getPosition(a);var b=this.getSize();b.x=c[0];b.y=c[1];return b},updateBox:function(a){this.setSize(a.width,a.height);this.setPagePosition(a.x,a.y);return this},getResizeEl:function(){return this.resizeEl||this.el},getPositionEl:function(){return this.positionEl||this.el},setPosition:function(a,f){if(a&&typeof a[1]=="number"){f=a[1];a=a[0]}this.x=a;this.y=f;if(!this.boxReady){return this}var b=this.adjustPosition(a,f);var e=b.x,d=b.y;var c=this.getPositionEl();if(e!==undefined||d!==undefined){if(e!==undefined&&d!==undefined){c.setLeftTop(e,d)}else{if(e!==undefined){c.setLeft(e)}else{if(d!==undefined){c.setTop(d)}}}this.onPosition(e,d);this.fireEvent("move",this,e,d)}return this},setPagePosition:function(a,c){if(a&&typeof a[1]=="number"){c=a[1];a=a[0]}this.pageX=a;this.pageY=c;if(!this.boxReady){return}if(a===undefined||c===undefined){return}var b=this.getPositionEl().translatePoints(a,c);this.setPosition(b.left,b.top);return this},onRender:function(b,a){Ext.BoxComponent.superclass.onRender.call(this,b,a);if(this.resizeEl){this.resizeEl=Ext.get(this.resizeEl)}if(this.positionEl){this.positionEl=Ext.get(this.positionEl)}},afterRender:function(){Ext.BoxComponent.superclass.afterRender.call(this);this.boxReady=true;this.setSize(this.width,this.height);if(this.x||this.y){this.setPosition(this.x,this.y)}else{if(this.pageX||this.pageY){this.setPagePosition(this.pageX,this.pageY)}}},syncSize:function(){delete this.lastSize;this.setSize(this.autoWidth?undefined:this.getResizeEl().getWidth(),this.autoHeight?undefined:this.getResizeEl().getHeight());return this},onResize:function(d,b,a,c){},onPosition:function(a,b){},adjustSize:function(a,b){if(this.autoWidth){a="auto"}if(this.autoHeight){b="auto"}return{width:a,height:b}},adjustPosition:function(a,b){return{x:a,y:b}}});Ext.reg("box",Ext.BoxComponent);Ext.Spacer=Ext.extend(Ext.BoxComponent,{autoEl:"div"});Ext.reg("spacer",Ext.Spacer);Ext.SplitBar=function(c,e,b,d,a){this.el=Ext.get(c,true);this.el.dom.unselectable="on";this.resizingEl=Ext.get(e,true);this.orientation=b||Ext.SplitBar.HORIZONTAL;this.minSize=0;this.maxSize=2000;this.animate=false;this.useShim=false;this.shim=null;if(!a){this.proxy=Ext.SplitBar.createProxy(this.orientation)}else{this.proxy=Ext.get(a).dom}this.dd=new Ext.dd.DDProxy(this.el.dom.id,"XSplitBars",{dragElId:this.proxy.id});this.dd.b4StartDrag=this.onStartProxyDrag.createDelegate(this);this.dd.endDrag=this.onEndProxyDrag.createDelegate(this);this.dragSpecs={};this.adapter=new Ext.SplitBar.BasicLayoutAdapter();this.adapter.init(this);if(this.orientation==Ext.SplitBar.HORIZONTAL){this.placement=d||(this.el.getX()>this.resizingEl.getX()?Ext.SplitBar.LEFT:Ext.SplitBar.RIGHT);this.el.addClass("x-splitbar-h")}else{this.placement=d||(this.el.getY()>this.resizingEl.getY()?Ext.SplitBar.TOP:Ext.SplitBar.BOTTOM);this.el.addClass("x-splitbar-v")}this.addEvents("resize","moved","beforeresize","beforeapply");Ext.SplitBar.superclass.constructor.call(this)};Ext.extend(Ext.SplitBar,Ext.util.Observable,{onStartProxyDrag:function(a,e){this.fireEvent("beforeresize",this);this.overlay=Ext.DomHelper.append(document.body,{cls:"x-drag-overlay",html:" "},true);this.overlay.unselectable();this.overlay.setSize(Ext.lib.Dom.getViewWidth(true),Ext.lib.Dom.getViewHeight(true));this.overlay.show();Ext.get(this.proxy).setDisplayed("block");var c=this.adapter.getElementSize(this);this.activeMinSize=this.getMinimumSize();this.activeMaxSize=this.getMaximumSize();var d=c-this.activeMinSize;var b=Math.max(this.activeMaxSize-c,0);if(this.orientation==Ext.SplitBar.HORIZONTAL){this.dd.resetConstraints();this.dd.setXConstraint(this.placement==Ext.SplitBar.LEFT?d:b,this.placement==Ext.SplitBar.LEFT?b:d,this.tickSize);this.dd.setYConstraint(0,0)}else{this.dd.resetConstraints();this.dd.setXConstraint(0,0);this.dd.setYConstraint(this.placement==Ext.SplitBar.TOP?d:b,this.placement==Ext.SplitBar.TOP?b:d,this.tickSize)}this.dragSpecs.startSize=c;this.dragSpecs.startPoint=[a,e];Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd,a,e)},onEndProxyDrag:function(c){Ext.get(this.proxy).setDisplayed(false);var b=Ext.lib.Event.getXY(c);if(this.overlay){Ext.destroy(this.overlay);delete this.overlay}var a;if(this.orientation==Ext.SplitBar.HORIZONTAL){a=this.dragSpecs.startSize+(this.placement==Ext.SplitBar.LEFT?b[0]-this.dragSpecs.startPoint[0]:this.dragSpecs.startPoint[0]-b[0])}else{a=this.dragSpecs.startSize+(this.placement==Ext.SplitBar.TOP?b[1]-this.dragSpecs.startPoint[1]:this.dragSpecs.startPoint[1]-b[1])}a=Math.min(Math.max(a,this.activeMinSize),this.activeMaxSize);if(a!=this.dragSpecs.startSize){if(this.fireEvent("beforeapply",this,a)!==false){this.adapter.setElementSize(this,a);this.fireEvent("moved",this,a);this.fireEvent("resize",this,a)}}},getAdapter:function(){return this.adapter},setAdapter:function(a){this.adapter=a;this.adapter.init(this)},getMinimumSize:function(){return this.minSize},setMinimumSize:function(a){this.minSize=a},getMaximumSize:function(){return this.maxSize},setMaximumSize:function(a){this.maxSize=a},setCurrentSize:function(b){var a=this.animate;this.animate=false;this.adapter.setElementSize(this,b);this.animate=a},destroy:function(a){Ext.destroy(this.shim,Ext.get(this.proxy));this.dd.unreg();if(a){this.el.remove()}this.purgeListeners()}});Ext.SplitBar.createProxy=function(b){var c=new Ext.Element(document.createElement("div"));c.unselectable();var a="x-splitbar-proxy";c.addClass(a+" "+(b==Ext.SplitBar.HORIZONTAL?a+"-h":a+"-v"));document.body.appendChild(c.dom);return c.dom};Ext.SplitBar.BasicLayoutAdapter=function(){};Ext.SplitBar.BasicLayoutAdapter.prototype={init:function(a){},getElementSize:function(a){if(a.orientation==Ext.SplitBar.HORIZONTAL){return a.resizingEl.getWidth()}else{return a.resizingEl.getHeight()}},setElementSize:function(b,a,c){if(b.orientation==Ext.SplitBar.HORIZONTAL){if(!b.animate){b.resizingEl.setWidth(a);if(c){c(b,a)}}else{b.resizingEl.setWidth(a,true,0.1,c,"easeOut")}}else{if(!b.animate){b.resizingEl.setHeight(a);if(c){c(b,a)}}else{b.resizingEl.setHeight(a,true,0.1,c,"easeOut")}}}};Ext.SplitBar.AbsoluteLayoutAdapter=function(a){this.basic=new Ext.SplitBar.BasicLayoutAdapter();this.container=Ext.get(a)};Ext.SplitBar.AbsoluteLayoutAdapter.prototype={init:function(a){this.basic.init(a)},getElementSize:function(a){return this.basic.getElementSize(a)},setElementSize:function(b,a,c){this.basic.setElementSize(b,a,this.moveSplitter.createDelegate(this,[b]))},moveSplitter:function(a){var b=Ext.SplitBar;switch(a.placement){case b.LEFT:a.el.setX(a.resizingEl.getRight());break;case b.RIGHT:a.el.setStyle("right",(this.container.getWidth()-a.resizingEl.getLeft())+"px");break;case b.TOP:a.el.setY(a.resizingEl.getBottom());break;case b.BOTTOM:a.el.setY(a.resizingEl.getTop()-a.el.getHeight());break}}};Ext.SplitBar.VERTICAL=1;Ext.SplitBar.HORIZONTAL=2;Ext.SplitBar.LEFT=1;Ext.SplitBar.RIGHT=2;Ext.SplitBar.TOP=3;Ext.SplitBar.BOTTOM=4;Ext.Container=Ext.extend(Ext.BoxComponent,{bufferResize:100,autoDestroy:true,forceLayout:false,defaultType:"panel",initComponent:function(){Ext.Container.superclass.initComponent.call(this);this.addEvents("afterlayout","beforeadd","beforeremove","add","remove");this.enableBubble("add","remove");var a=this.items;if(a){delete this.items;if(Ext.isArray(a)&&a.length>0){this.add.apply(this,a)}else{this.add(a)}}},initItems:function(){if(!this.items){this.items=new Ext.util.MixedCollection(false,this.getComponentId);this.getLayout()}},setLayout:function(a){if(this.layout&&this.layout!=a){this.layout.setContainer(null)}this.initItems();this.layout=a;a.setContainer(this)},render:function(){Ext.Container.superclass.render.apply(this,arguments);if(this.layout){if(Ext.isObject(this.layout)&&!this.layout.layout){this.layoutConfig=this.layout;this.layout=this.layoutConfig.type}if(typeof this.layout=="string"){this.layout=new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig)}this.setLayout(this.layout);if(this.activeItem!==undefined){var a=this.activeItem;delete this.activeItem;this.layout.setActiveItem(a)}}if(!this.ownerCt){this.doLayout(false,true)}if(this.monitorResize===true){Ext.EventManager.onWindowResize(this.doLayout,this,[false])}},getLayoutTarget:function(){return this.el},getComponentId:function(a){return a.getItemId()},add:function(a){this.initItems();var b=arguments.length>1;if(b||Ext.isArray(a)){Ext.each(b?arguments:a,function(f){this.add(f)},this);return}var e=this.lookupComponent(this.applyDefaults(a));var d=this.items.length;if(this.fireEvent("beforeadd",this,e,d)!==false&&this.onBeforeAdd(e)!==false){this.items.add(e);e.ownerCt=this;this.fireEvent("add",this,e,d)}return e},insert:function(f,e){this.initItems();var d=arguments,b=d.length;if(b>2){for(var g=b-1;g>=1;--g){this.insert(f,d[g])}return}var h=this.lookupComponent(this.applyDefaults(e));if(h.ownerCt==this&&this.items.indexOf(h)<f){--f}if(this.fireEvent("beforeadd",this,h,f)!==false&&this.onBeforeAdd(h)!==false){this.items.insert(f,h);h.ownerCt=this;this.fireEvent("add",this,h,f)}return h},applyDefaults:function(a){if(this.defaults){if(typeof a=="string"){a=Ext.ComponentMgr.get(a);Ext.apply(a,this.defaults)}else{if(!a.events){Ext.applyIf(a,this.defaults)}else{Ext.apply(a,this.defaults)}}}return a},onBeforeAdd:function(a){if(a.ownerCt){a.ownerCt.remove(a,false)}if(this.hideBorders===true){a.border=(a.border===true)}},remove:function(a,b){this.initItems();var d=this.getComponent(a);if(d&&this.fireEvent("beforeremove",this,d)!==false){this.items.remove(d);delete d.ownerCt;if(b===true||(b!==false&&this.autoDestroy)){d.destroy()}if(this.layout&&this.layout.activeItem==d){delete this.layout.activeItem}this.fireEvent("remove",this,d)}return d},removeAll:function(c){this.initItems();var e,f=[],b=[];this.items.each(function(g){f.push(g)});for(var d=0,a=f.length;d<a;++d){e=f[d];this.remove(e,c);if(e.ownerCt!==this){b.push(e)}}return b},getComponent:function(a){if(Ext.isObject(a)){return a}return this.items.get(a)},lookupComponent:function(a){if(typeof a=="string"){return Ext.ComponentMgr.get(a)}else{if(!a.events){return this.createComponent(a)}}return a},createComponent:function(a){return Ext.create(a,this.defaultType)},doLayout:function(f,e){var j=this.rendered,h=this.forceLayout;if(!this.isVisible()||this.collapsed){this.deferLayout=this.deferLayout||!f;if(!(e||h)){return}f=f&&!this.deferLayout}else{delete this.deferLayout}if(j&&this.layout){this.layout.layout()}if(f!==true&&this.items){var d=this.items.items;for(var b=0,a=d.length;b<a;b++){var g=d[b];if(g.doLayout){g.forceLayout=h;g.doLayout()}}}if(j){this.onLayout(f,e)}delete this.forceLayout},onLayout:Ext.emptyFn,onShow:function(){Ext.Container.superclass.onShow.call(this);if(this.deferLayout!==undefined){this.doLayout(true)}},getLayout:function(){if(!this.layout){var a=new Ext.layout.ContainerLayout(this.layoutConfig);this.setLayout(a)}return this.layout},beforeDestroy:function(){if(this.items){Ext.destroy.apply(Ext,this.items.items)}if(this.monitorResize){Ext.EventManager.removeResizeListener(this.doLayout,this)}Ext.destroy(this.layout);Ext.Container.superclass.beforeDestroy.call(this)},bubble:function(c,b,a){var d=this;while(d){if(c.apply(b||d,a||[d])===false){break}d=d.ownerCt}return this},cascade:function(f,e,b){if(f.apply(e||this,b||[this])!==false){if(this.items){var d=this.items.items;for(var c=0,a=d.length;c<a;c++){if(d[c].cascade){d[c].cascade(f,e,b)}else{f.apply(e||d[c],b||[d[c]])}}}}return this},findById:function(c){var a,b=this;this.cascade(function(d){if(b!=d&&d.id===c){a=d;return false}});return a||null},findByType:function(b,a){return this.findBy(function(d){return d.isXType(b,a)})},find:function(b,a){return this.findBy(function(d){return d[b]===a})},findBy:function(d,c){var a=[],b=this;this.cascade(function(e){if(b!=e&&d.call(c||e,e,b)===true){a.push(e)}});return a},get:function(a){return this.items.get(a)}});Ext.Container.LAYOUTS={};Ext.reg("container",Ext.Container);Ext.layout.ContainerLayout=function(a){Ext.apply(this,a)};Ext.layout.ContainerLayout.prototype={monitorResize:false,activeItem:null,layout:function(){var a=this.container.getLayoutTarget();this.onLayout(this.container,a);this.container.fireEvent("afterlayout",this.container,this)},onLayout:function(a,b){this.renderAll(a,b)},isValidParent:function(b,a){return a&&b.getDomPositionEl().dom.parentNode==(a.dom||a)},renderAll:function(e,f){var b=e.items.items;for(var d=0,a=b.length;d<a;d++){var g=b[d];if(g&&(!g.rendered||!this.isValidParent(g,f))){this.renderItem(g,d,f)}}},renderItem:function(d,a,b){if(d&&!d.rendered){d.render(b,a);this.configureItem(d,a)}else{if(d&&!this.isValidParent(d,b)){if(typeof a=="number"){a=b.dom.childNodes[a]}b.dom.insertBefore(d.getDomPositionEl().dom,a||null);d.container=b;this.configureItem(d,a)}}},configureItem:function(d,a){if(this.extraCls){var b=d.getPositionEl?d.getPositionEl():d;b.addClass(this.extraCls)}if(this.renderHidden&&d!=this.activeItem){d.hide()}if(d.doLayout){d.doLayout(false,this.forceLayout)}},onResize:function(){if(this.container.collapsed){return}var a=this.container.bufferResize;if(a){if(!this.resizeTask){this.resizeTask=new Ext.util.DelayedTask(this.runLayout,this);this.resizeBuffer=typeof a=="number"?a:100}this.resizeTask.delay(this.resizeBuffer)}else{this.runLayout()}},runLayout:function(){this.layout();this.container.onLayout()},setContainer:function(a){if(this.monitorResize&&a!=this.container){if(this.container){this.container.un("resize",this.onResize,this);this.container.un("bodyresize",this.onResize,this)}if(a){a.on({scope:this,resize:this.onResize,bodyresize:this.onResize})}}this.container=a},parseMargins:function(b){if(typeof b=="number"){b=b.toString()}var c=b.split(" ");var a=c.length;if(a==1){c[1]=c[0];c[2]=c[0];c[3]=c[0]}if(a==2){c[2]=c[0];c[3]=c[1]}if(a==3){c[3]=c[1]}return{top:parseInt(c[0],10)||0,right:parseInt(c[1],10)||0,bottom:parseInt(c[2],10)||0,left:parseInt(c[3],10)||0}},fieldTpl:(function(){var a=new Ext.Template('<div class="x-form-item {itemCls}" tabIndex="-1">','<label for="{id}" style="{labelStyle}" class="x-form-item-label">{label}{labelSeparator}</label>','<div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">','</div><div class="{clearCls}"></div>',"</div>");a.disableFormats=true;return a.compile()})(),destroy:Ext.emptyFn};Ext.Container.LAYOUTS.auto=Ext.layout.ContainerLayout;Ext.layout.FitLayout=Ext.extend(Ext.layout.ContainerLayout,{monitorResize:true,onLayout:function(a,c){Ext.layout.FitLayout.superclass.onLayout.call(this,a,c);if(!this.container.collapsed){var b=(Ext.isIE6&&Ext.isStrict&&c.dom==document.body)?c.getViewSize():c.getStyleSize();this.setItemSize(this.activeItem||a.items.itemAt(0),b)}},setItemSize:function(b,a){if(b&&a.height>0){b.setSize(a)}}});Ext.Container.LAYOUTS.fit=Ext.layout.FitLayout;Ext.layout.CardLayout=Ext.extend(Ext.layout.FitLayout,{deferredRender:false,layoutOnCardChange:false,renderHidden:true,constructor:function(a){Ext.layout.CardLayout.superclass.constructor.call(this,a);this.forceLayout=(this.deferredRender===false)},setActiveItem:function(a){a=this.container.getComponent(a);if(this.activeItem!=a){if(this.activeItem){this.activeItem.hide()}this.activeItem=a;a.show();this.container.doLayout();if(this.layoutOnCardChange&&a.doLayout){a.doLayout()}}},renderAll:function(a,b){if(this.deferredRender){this.renderItem(this.activeItem,undefined,b)}else{Ext.layout.CardLayout.superclass.renderAll.call(this,a,b)}}});Ext.Container.LAYOUTS.card=Ext.layout.CardLayout;Ext.layout.AnchorLayout=Ext.extend(Ext.layout.ContainerLayout,{monitorResize:true,getAnchorViewSize:function(a,b){return b.dom==document.body?b.getViewSize():b.getStyleSize()},onLayout:function(j,m){Ext.layout.AnchorLayout.superclass.onLayout.call(this,j,m);var s=this.getAnchorViewSize(j,m);var q=s.width,g=s.height;if(q<20&&g<20){return}var d,o;if(j.anchorSize){if(typeof j.anchorSize=="number"){d=j.anchorSize}else{d=j.anchorSize.width;o=j.anchorSize.height}}else{d=j.initialConfig.width;o=j.initialConfig.height}var l=j.items.items,k=l.length,f,n,p,e,b;for(f=0;f<k;f++){n=l[f];if(n.anchor){p=n.anchorSpec;if(!p){var r=n.anchor.split(" ");n.anchorSpec=p={right:this.parseAnchor(r[0],n.initialConfig.width,d),bottom:this.parseAnchor(r[1],n.initialConfig.height,o)}}e=p.right?this.adjustWidthAnchor(p.right(q),n):undefined;b=p.bottom?this.adjustHeightAnchor(p.bottom(g),n):undefined;if(e||b){n.setSize(e||undefined,b||undefined)}}}},parseAnchor:function(c,g,b){if(c&&c!="none"){var e;if(/^(r|right|b|bottom)$/i.test(c)){var f=b-g;return function(a){if(a!==e){e=a;return a-f}}}else{if(c.indexOf("%")!=-1){var d=parseFloat(c.replace("%",""))*0.01;return function(a){if(a!==e){e=a;return Math.floor(a*d)}}}else{c=parseInt(c,10);if(!isNaN(c)){return function(a){if(a!==e){e=a;return a+c}}}}}}return false},adjustWidthAnchor:function(b,a){return b},adjustHeightAnchor:function(b,a){return b}});Ext.Container.LAYOUTS.anchor=Ext.layout.AnchorLayout;Ext.layout.ColumnLayout=Ext.extend(Ext.layout.ContainerLayout,{monitorResize:true,extraCls:"x-column",scrollOffset:0,isValidParent:function(b,a){return(b.getPositionEl?b.getPositionEl():b.getEl()).dom.parentNode==this.innerCt.dom},onLayout:function(d,g){var e=d.items.items,f=e.length,j,a;if(!this.innerCt){g.addClass("x-column-layout-ct");this.innerCt=g.createChild({cls:"x-column-inner"});this.innerCt.createChild({cls:"x-clear"})}this.renderAll(d,this.innerCt);var m=Ext.isIE&&g.dom!=Ext.getBody().dom?g.getStyleSize():g.getViewSize();if(m.width<1&&m.height<1){return}var k=m.width-g.getPadding("lr")-this.scrollOffset,b=m.height-g.getPadding("tb"),l=k;this.innerCt.setWidth(k);for(a=0;a<f;a++){j=e[a];if(!j.columnWidth){l-=(j.getSize().width+j.getEl().getMargins("lr"))}}l=l<0?0:l;for(a=0;a<f;a++){j=e[a];if(j.columnWidth){j.setSize(Math.floor(j.columnWidth*l)-j.getEl().getMargins("lr"))}}}});Ext.Container.LAYOUTS.column=Ext.layout.ColumnLayout;Ext.layout.BorderLayout=Ext.extend(Ext.layout.ContainerLayout,{monitorResize:true,rendered:false,onLayout:function(d,G){var f;if(!this.rendered){G.addClass("x-border-layout-ct");var u=d.items.items;f=[];for(var z=0,A=u.length;z<A;z++){var D=u[z];var k=D.region;if(D.collapsed){f.push(D)}D.collapsed=false;if(!D.rendered){D.cls=D.cls?D.cls+" x-border-panel":"x-border-panel";D.render(G,z)}this[k]=k!="center"&&D.split?new Ext.layout.BorderLayout.SplitRegion(this,D.initialConfig,k):new Ext.layout.BorderLayout.Region(this,D.initialConfig,k);this[k].render(G,D)}this.rendered=true}var t=G.getViewSize();if(t.width<20||t.height<20){if(f){this.restoreCollapsed=f}return}else{if(this.restoreCollapsed){f=this.restoreCollapsed;delete this.restoreCollapsed}}var q=t.width,B=t.height;var p=q,y=B,l=0,o=0;var v=this.north,r=this.south,j=this.west,C=this.east,D=this.center;if(!D&&Ext.layout.BorderLayout.WARN!==false){throw"No center region defined in BorderLayout "+d.id}if(v&&v.isVisible()){var F=v.getSize();var x=v.getMargins();F.width=q-(x.left+x.right);F.x=x.left;F.y=x.top;l=F.height+F.y+x.bottom;y-=l;v.applyLayout(F)}if(r&&r.isVisible()){var F=r.getSize();var x=r.getMargins();F.width=q-(x.left+x.right);F.x=x.left;var E=(F.height+x.top+x.bottom);F.y=B-E+x.top;y-=E;r.applyLayout(F)}if(j&&j.isVisible()){var F=j.getSize();var x=j.getMargins();F.height=y-(x.top+x.bottom);F.x=x.left;F.y=l+x.top;var a=(F.width+x.left+x.right);o+=a;p-=a;j.applyLayout(F)}if(C&&C.isVisible()){var F=C.getSize();var x=C.getMargins();F.height=y-(x.top+x.bottom);var a=(F.width+x.left+x.right);F.x=q-a+x.left;F.y=l+x.top;p-=a;C.applyLayout(F)}if(D){var x=D.getMargins();var g={x:o+x.left,y:l+x.top,width:p-(x.left+x.right),height:y-(x.top+x.bottom)};D.applyLayout(g)}if(f){for(var z=0,A=f.length;z<A;z++){f[z].collapse(false)}}if(Ext.isIE&&Ext.isStrict){G.repaint()}},destroy:function(){var b=["north","south","east","west"];for(var a=0;a<b.length;a++){var c=this[b[a]];if(c){if(c.destroy){c.destroy()}else{if(c.split){c.split.destroy(true)}}}}Ext.layout.BorderLayout.superclass.destroy.call(this)}});Ext.layout.BorderLayout.Region=function(b,a,c){Ext.apply(this,a);this.layout=b;this.position=c;this.state={};if(typeof this.margins=="string"){this.margins=this.layout.parseMargins(this.margins)}this.margins=Ext.applyIf(this.margins||{},this.defaultMargins);if(this.collapsible){if(typeof this.cmargins=="string"){this.cmargins=this.layout.parseMargins(this.cmargins)}if(this.collapseMode=="mini"&&!this.cmargins){this.cmargins={left:0,top:0,right:0,bottom:0}}else{this.cmargins=Ext.applyIf(this.cmargins||{},c=="north"||c=="south"?this.defaultNSCMargins:this.defaultEWCMargins)}}};Ext.layout.BorderLayout.Region.prototype={collapsible:false,split:false,floatable:true,minWidth:50,minHeight:50,defaultMargins:{left:0,top:0,right:0,bottom:0},defaultNSCMargins:{left:5,top:5,right:5,bottom:5},defaultEWCMargins:{left:5,top:0,right:5,bottom:0},floatingZIndex:100,isCollapsed:false,render:function(b,c){this.panel=c;c.el.enableDisplayMode();this.targetEl=b;this.el=c.el;var a=c.getState,d=this.position;c.getState=function(){return Ext.apply(a.call(c)||{},this.state)}.createDelegate(this);if(d!="center"){c.allowQueuedExpand=false;c.on({beforecollapse:this.beforeCollapse,collapse:this.onCollapse,beforeexpand:this.beforeExpand,expand:this.onExpand,hide:this.onHide,show:this.onShow,scope:this});if(this.collapsible||this.floatable){c.collapseEl="el";c.slideAnchor=this.getSlideAnchor()}if(c.tools&&c.tools.toggle){c.tools.toggle.addClass("x-tool-collapse-"+d);c.tools.toggle.addClassOnOver("x-tool-collapse-"+d+"-over")}}},getCollapsedEl:function(){if(!this.collapsedEl){if(!this.toolTemplate){var b=new Ext.Template('<div class="x-tool x-tool-{id}"> </div>');b.disableFormats=true;b.compile();Ext.layout.BorderLayout.Region.prototype.toolTemplate=b}this.collapsedEl=this.targetEl.createChild({cls:"x-layout-collapsed x-layout-collapsed-"+this.position,id:this.panel.id+"-xcollapsed"});this.collapsedEl.enableDisplayMode("block");if(this.collapseMode=="mini"){this.collapsedEl.addClass("x-layout-cmini-"+this.position);this.miniCollapsedEl=this.collapsedEl.createChild({cls:"x-layout-mini x-layout-mini-"+this.position,html:" "});this.miniCollapsedEl.addClassOnOver("x-layout-mini-over");this.collapsedEl.addClassOnOver("x-layout-collapsed-over");this.collapsedEl.on("click",this.onExpandClick,this,{stopEvent:true})}else{if(this.collapsible!==false&&!this.hideCollapseTool){var a=this.toolTemplate.append(this.collapsedEl.dom,{id:"expand-"+this.position},true);a.addClassOnOver("x-tool-expand-"+this.position+"-over");a.on("click",this.onExpandClick,this,{stopEvent:true})}if(this.floatable!==false||this.titleCollapse){this.collapsedEl.addClassOnOver("x-layout-collapsed-over");this.collapsedEl.on("click",this[this.floatable?"collapseClick":"onExpandClick"],this)}}}return this.collapsedEl},onExpandClick:function(a){if(this.isSlid){this.afterSlideIn();this.panel.expand(false)}else{this.panel.expand()}},onCollapseClick:function(a){this.panel.collapse()},beforeCollapse:function(b,a){this.lastAnim=a;if(this.splitEl){this.splitEl.hide()}this.getCollapsedEl().show();this.panel.el.setStyle("z-index",100);this.isCollapsed=true;this.layout.layout()},onCollapse:function(a){this.panel.el.setStyle("z-index",1);if(this.lastAnim===false||this.panel.animCollapse===false){this.getCollapsedEl().dom.style.visibility="visible"}else{this.getCollapsedEl().slideIn(this.panel.slideAnchor,{duration:0.2})}this.state.collapsed=true;this.panel.saveState()},beforeExpand:function(a){var b=this.getCollapsedEl();this.el.show();if(this.position=="east"||this.position=="west"){this.panel.setSize(undefined,b.getHeight())}else{this.panel.setSize(b.getWidth(),undefined)}b.hide();b.dom.style.visibility="hidden";this.panel.el.setStyle("z-index",this.floatingZIndex)},onExpand:function(){this.isCollapsed=false;if(this.splitEl){this.splitEl.show()}this.layout.layout();this.panel.el.setStyle("z-index",1);this.state.collapsed=false;this.panel.saveState()},collapseClick:function(a){if(this.isSlid){a.stopPropagation();this.slideIn()}else{a.stopPropagation();this.slideOut()}},onHide:function(){if(this.isCollapsed){this.getCollapsedEl().hide()}else{if(this.splitEl){this.splitEl.hide()}}},onShow:function(){if(this.isCollapsed){this.getCollapsedEl().show()}else{if(this.splitEl){this.splitEl.show()}}},isVisible:function(){return !this.panel.hidden},getMargins:function(){return this.isCollapsed&&this.cmargins?this.cmargins:this.margins},getSize:function(){return this.isCollapsed?this.getCollapsedEl().getSize():this.panel.getSize()},setPanel:function(a){this.panel=a},getMinWidth:function(){return this.minWidth},getMinHeight:function(){return this.minHeight},applyLayoutCollapsed:function(a){var b=this.getCollapsedEl();b.setLeftTop(a.x,a.y);b.setSize(a.width,a.height)},applyLayout:function(a){if(this.isCollapsed){this.applyLayoutCollapsed(a)}else{this.panel.setPosition(a.x,a.y);this.panel.setSize(a.width,a.height)}},beforeSlide:function(){this.panel.beforeEffect()},afterSlide:function(){this.panel.afterEffect()},initAutoHide:function(){if(this.autoHide!==false){if(!this.autoHideHd){var a=new Ext.util.DelayedTask(this.slideIn,this);this.autoHideHd={mouseout:function(b){if(!b.within(this.el,true)){a.delay(500)}},mouseover:function(b){a.cancel()},scope:this}}this.el.on(this.autoHideHd)}},clearAutoHide:function(){if(this.autoHide!==false){this.el.un("mouseout",this.autoHideHd.mouseout);this.el.un("mouseover",this.autoHideHd.mouseover)}},clearMonitor:function(){Ext.getDoc().un("click",this.slideInIf,this)},slideOut:function(){if(this.isSlid||this.el.hasActiveFx()){return}this.isSlid=true;var a=this.panel.tools;if(a&&a.toggle){a.toggle.hide()}this.el.show();if(this.position=="east"||this.position=="west"){this.panel.setSize(undefined,this.collapsedEl.getHeight())}else{this.panel.setSize(this.collapsedEl.getWidth(),undefined)}this.restoreLT=[this.el.dom.style.left,this.el.dom.style.top];this.el.alignTo(this.collapsedEl,this.getCollapseAnchor());this.el.setStyle("z-index",this.floatingZIndex+2);this.panel.el.replaceClass("x-panel-collapsed","x-panel-floating");if(this.animFloat!==false){this.beforeSlide();this.el.slideIn(this.getSlideAnchor(),{callback:function(){this.afterSlide();this.initAutoHide();Ext.getDoc().on("click",this.slideInIf,this)},scope:this,block:true})}else{this.initAutoHide();Ext.getDoc().on("click",this.slideInIf,this)}},afterSlideIn:function(){this.clearAutoHide();this.isSlid=false;this.clearMonitor();this.el.setStyle("z-index","");this.panel.el.replaceClass("x-panel-floating","x-panel-collapsed");this.el.dom.style.left=this.restoreLT[0];this.el.dom.style.top=this.restoreLT[1];var a=this.panel.tools;if(a&&a.toggle){a.toggle.show()}},slideIn:function(a){if(!this.isSlid||this.el.hasActiveFx()){Ext.callback(a);return}this.isSlid=false;if(this.animFloat!==false){this.beforeSlide();this.el.slideOut(this.getSlideAnchor(),{callback:function(){this.el.hide();this.afterSlide();this.afterSlideIn();Ext.callback(a)},scope:this,block:true})}else{this.el.hide();this.afterSlideIn()}},slideInIf:function(a){if(!a.within(this.el)){this.slideIn()}},anchors:{west:"left",east:"right",north:"top",south:"bottom"},sanchors:{west:"l",east:"r",north:"t",south:"b"},canchors:{west:"tl-tr",east:"tr-tl",north:"tl-bl",south:"bl-tl"},getAnchor:function(){return this.anchors[this.position]},getCollapseAnchor:function(){return this.canchors[this.position]},getSlideAnchor:function(){return this.sanchors[this.position]},getAlignAdj:function(){var a=this.cmargins;switch(this.position){case"west":return[0,0];break;case"east":return[0,0];break;case"north":return[0,0];break;case"south":return[0,0];break}},getExpandAdj:function(){var b=this.collapsedEl,a=this.cmargins;switch(this.position){case"west":return[-(a.right+b.getWidth()+a.left),0];break;case"east":return[a.right+b.getWidth()+a.left,0];break;case"north":return[0,-(a.top+a.bottom+b.getHeight())];break;case"south":return[0,a.top+a.bottom+b.getHeight()];break}}};Ext.layout.BorderLayout.SplitRegion=function(b,a,c){Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this,b,a,c);this.applyLayout=this.applyFns[c]};Ext.extend(Ext.layout.BorderLayout.SplitRegion,Ext.layout.BorderLayout.Region,{splitTip:"Drag to resize.",collapsibleSplitTip:"Drag to resize. Double click to hide.",useSplitTips:false,splitSettings:{north:{orientation:Ext.SplitBar.VERTICAL,placement:Ext.SplitBar.TOP,maxFn:"getVMaxSize",minProp:"minHeight",maxProp:"maxHeight"},south:{orientation:Ext.SplitBar.VERTICAL,placement:Ext.SplitBar.BOTTOM,maxFn:"getVMaxSize",minProp:"minHeight",maxProp:"maxHeight"},east:{orientation:Ext.SplitBar.HORIZONTAL,placement:Ext.SplitBar.RIGHT,maxFn:"getHMaxSize",minProp:"minWidth",maxProp:"maxWidth"},west:{orientation:Ext.SplitBar.HORIZONTAL,placement:Ext.SplitBar.LEFT,maxFn:"getHMaxSize",minProp:"minWidth",maxProp:"maxWidth"}},applyFns:{west:function(c){if(this.isCollapsed){return this.applyLayoutCollapsed(c)}var d=this.splitEl.dom,b=d.style;this.panel.setPosition(c.x,c.y);var a=d.offsetWidth;b.left=(c.x+c.width-a)+"px";b.top=(c.y)+"px";b.height=Math.max(0,c.height)+"px";this.panel.setSize(c.width-a,c.height)},east:function(c){if(this.isCollapsed){return this.applyLayoutCollapsed(c)}var d=this.splitEl.dom,b=d.style;var a=d.offsetWidth;this.panel.setPosition(c.x+a,c.y);b.left=(c.x)+"px";b.top=(c.y)+"px";b.height=Math.max(0,c.height)+"px";this.panel.setSize(c.width-a,c.height)},north:function(c){if(this.isCollapsed){return this.applyLayoutCollapsed(c)}var d=this.splitEl.dom,b=d.style;var a=d.offsetHeight;this.panel.setPosition(c.x,c.y);b.left=(c.x)+"px";b.top=(c.y+c.height-a)+"px";b.width=Math.max(0,c.width)+"px";this.panel.setSize(c.width,c.height-a)},south:function(c){if(this.isCollapsed){return this.applyLayoutCollapsed(c)}var d=this.splitEl.dom,b=d.style;var a=d.offsetHeight;this.panel.setPosition(c.x,c.y+a);b.left=(c.x)+"px";b.top=(c.y)+"px";b.width=Math.max(0,c.width)+"px";this.panel.setSize(c.width,c.height-a)}},render:function(a,c){Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this,a,c);var d=this.position;this.splitEl=a.createChild({cls:"x-layout-split x-layout-split-"+d,html:" ",id:this.panel.id+"-xsplit"});if(this.collapseMode=="mini"){this.miniSplitEl=this.splitEl.createChild({cls:"x-layout-mini x-layout-mini-"+d,html:" "});this.miniSplitEl.addClassOnOver("x-layout-mini-over");this.miniSplitEl.on("click",this.onCollapseClick,this,{stopEvent:true})}var b=this.splitSettings[d];this.split=new Ext.SplitBar(this.splitEl.dom,c.el,b.orientation);this.split.tickSize=this.tickSize;this.split.placement=b.placement;this.split.getMaximumSize=this[b.maxFn].createDelegate(this);this.split.minSize=this.minSize||this[b.minProp];this.split.on("beforeapply",this.onSplitMove,this);this.split.useShim=this.useShim===true;this.maxSize=this.maxSize||this[b.maxProp];if(c.hidden){this.splitEl.hide()}if(this.useSplitTips){this.splitEl.dom.title=this.collapsible?this.collapsibleSplitTip:this.splitTip}if(this.collapsible){this.splitEl.on("dblclick",this.onCollapseClick,this)}},getSize:function(){if(this.isCollapsed){return this.collapsedEl.getSize()}var a=this.panel.getSize();if(this.position=="north"||this.position=="south"){a.height+=this.splitEl.dom.offsetHeight}else{a.width+=this.splitEl.dom.offsetWidth}return a},getHMaxSize:function(){var b=this.maxSize||10000;var a=this.layout.center;return Math.min(b,(this.el.getWidth()+a.el.getWidth())-a.getMinWidth())},getVMaxSize:function(){var b=this.maxSize||10000;var a=this.layout.center;return Math.min(b,(this.el.getHeight()+a.el.getHeight())-a.getMinHeight())},onSplitMove:function(b,a){var c=this.panel.getSize();this.lastSplitSize=a;if(this.position=="north"||this.position=="south"){this.panel.setSize(c.width,a);this.state.height=a}else{this.panel.setSize(a,c.height);this.state.width=a}this.layout.layout();this.panel.saveState();return false},getSplitBar:function(){return this.split},destroy:function(){Ext.destroy(this.miniSplitEl,this.split,this.splitEl)}});Ext.Container.LAYOUTS.border=Ext.layout.BorderLayout;Ext.layout.FormLayout=Ext.extend(Ext.layout.AnchorLayout,{labelSeparator:":",setContainer:function(a){Ext.layout.FormLayout.superclass.setContainer.call(this,a);if(a.labelAlign){a.addClass("x-form-label-"+a.labelAlign)}if(a.hideLabels){this.labelStyle="display:none";this.elementStyle="padding-left:0;";this.labelAdjust=0}else{this.labelSeparator=a.labelSeparator||this.labelSeparator;a.labelWidth=a.labelWidth||100;if(typeof a.labelWidth=="number"){var b=(typeof a.labelPad=="number"?a.labelPad:5);this.labelAdjust=a.labelWidth+b;this.labelStyle="width:"+a.labelWidth+"px;";this.elementStyle="padding-left:"+(a.labelWidth+b)+"px"}if(a.labelAlign=="top"){this.labelStyle="width:auto;";this.labelAdjust=0;this.elementStyle="padding-left:0;"}}},getLabelStyle:function(e){var b="",c=[this.labelStyle,e];for(var d=0,a=c.length;d<a;++d){if(c[d]){b+=c[d];if(b.substr(-1,1)!=";"){b+=";"}}}return b},renderItem:function(e,a,d){if(e&&!e.rendered&&(e.isFormField||e.fieldLabel)&&e.inputType!="hidden"){var b=this.getTemplateArgs(e);if(typeof a=="number"){a=d.dom.childNodes[a]||null}if(a){this.fieldTpl.insertBefore(a,b)}else{this.fieldTpl.append(d,b)}e.render("x-form-el-"+e.id)}else{Ext.layout.FormLayout.superclass.renderItem.apply(this,arguments)}},getTemplateArgs:function(b){var a=!b.fieldLabel||b.hideLabel;return{id:b.id,label:b.fieldLabel,labelStyle:b.labelStyle||this.labelStyle||"",elementStyle:this.elementStyle||"",labelSeparator:a?"":(typeof b.labelSeparator=="undefined"?this.labelSeparator:b.labelSeparator),itemCls:(b.itemCls||this.container.itemCls||"")+(b.hideLabel?" x-hide-label":""),clearCls:b.clearCls||"x-form-clear-left"}},adjustWidthAnchor:function(b,a){return b-(a.isFormField||a.fieldLabel?(a.hideLabel?0:this.labelAdjust):0)},isValidParent:function(b,a){return true}});Ext.Container.LAYOUTS.form=Ext.layout.FormLayout;Ext.layout.AccordionLayout=Ext.extend(Ext.layout.FitLayout,{fill:true,autoWidth:true,titleCollapse:true,hideCollapseTool:false,collapseFirst:false,animate:false,sequence:false,activeOnTop:false,renderItem:function(a){if(this.animate===false){a.animCollapse=false}a.collapsible=true;if(this.autoWidth){a.autoWidth=true}if(this.titleCollapse){a.titleCollapse=true}if(this.hideCollapseTool){a.hideCollapseTool=true}if(this.collapseFirst!==undefined){a.collapseFirst=this.collapseFirst}if(!this.activeItem&&!a.collapsed){this.activeItem=a}else{if(this.activeItem&&this.activeItem!=a){a.collapsed=true}}Ext.layout.AccordionLayout.superclass.renderItem.apply(this,arguments);a.header.addClass("x-accordion-hd");a.on("beforeexpand",this.beforeExpand,this)},beforeExpand:function(c,b){var a=this.activeItem;if(a){if(this.sequence){delete this.activeItem;if(!a.collapsed){a.collapse({callback:function(){c.expand(b||true)},scope:this});return false}}else{a.collapse(this.animate)}}this.activeItem=c;if(this.activeOnTop){c.el.dom.parentNode.insertBefore(c.el.dom,c.el.dom.parentNode.firstChild)}this.layout()},setItemSize:function(c,b){if(this.fill&&c){var a=0;this.container.items.each(function(d){if(d!=c){a+=d.header.getHeight()}});b.height-=a;c.setSize(b)}},setActiveItem:function(a){a=this.container.getComponent(a);if(this.activeItem!=a){if(a.rendered&&a.collapsed){a.expand()}else{this.activeItem=a}}}});Ext.Container.LAYOUTS.accordion=Ext.layout.AccordionLayout;Ext.layout.Accordion=Ext.layout.AccordionLayout;Ext.layout.TableLayout=Ext.extend(Ext.layout.ContainerLayout,{monitorResize:false,tableAttrs:null,setContainer:function(a){Ext.layout.TableLayout.superclass.setContainer.call(this,a);this.currentRow=0;this.currentColumn=0;this.cells=[]},onLayout:function(d,f){var e=d.items.items,a=e.length,g,b;if(!this.table){f.addClass("x-table-layout-ct");this.table=f.createChild(Ext.apply({tag:"table",cls:"x-table-layout",cellspacing:0,cn:{tag:"tbody"}},this.tableAttrs),null,true)}this.renderAll(d,f)},getRow:function(a){var b=this.table.tBodies[0].childNodes[a];if(!b){b=document.createElement("tr");this.table.tBodies[0].appendChild(b)}return b},getNextCell:function(i){var a=this.getNextNonSpan(this.currentColumn,this.currentRow);var f=this.currentColumn=a[0],e=this.currentRow=a[1];for(var h=e;h<e+(i.rowspan||1);h++){if(!this.cells[h]){this.cells[h]=[]}for(var d=f;d<f+(i.colspan||1);d++){this.cells[h][d]=true}}var g=document.createElement("td");if(i.cellId){g.id=i.cellId}var b="x-table-layout-cell";if(i.cellCls){b+=" "+i.cellCls}g.className=b;if(i.colspan){g.colSpan=i.colspan}if(i.rowspan){g.rowSpan=i.rowspan}this.getRow(e).appendChild(g);return g},getNextNonSpan:function(a,c){var b=this.columns;while((b&&a>=b)||(this.cells[c]&&this.cells[c][a])){if(b&&a>=b){c++;a=0}else{a++}}return[a,c]},renderItem:function(e,a,d){if(e&&!e.rendered){e.render(this.getNextCell(e));if(this.extraCls){var b=e.getPositionEl?e.getPositionEl():e;b.addClass(this.extraCls)}}},isValidParent:function(b,a){return true}});Ext.Container.LAYOUTS.table=Ext.layout.TableLayout;Ext.layout.AbsoluteLayout=Ext.extend(Ext.layout.AnchorLayout,{extraCls:"x-abs-layout-item",onLayout:function(a,b){b.position();this.paddingLeft=b.getPadding("l");this.paddingTop=b.getPadding("t");Ext.layout.AbsoluteLayout.superclass.onLayout.call(this,a,b)},adjustWidthAnchor:function(b,a){return b?b-a.getPosition(true)[0]+this.paddingLeft:b},adjustHeightAnchor:function(b,a){return b?b-a.getPosition(true)[1]+this.paddingTop:b}});Ext.Container.LAYOUTS.absolute=Ext.layout.AbsoluteLayout;Ext.layout.BoxLayout=Ext.extend(Ext.layout.ContainerLayout,{defaultMargins:{left:0,top:0,right:0,bottom:0},padding:"0",pack:"start",monitorResize:true,scrollOffset:0,extraCls:"x-box-item",ctCls:"x-box-layout-ct",innerCls:"x-box-inner",isValidParent:function(b,a){return b.getEl().dom.parentNode==this.innerCt.dom},onLayout:function(e,h){var f=e.items.items,b=f.length,j,d,g=b-1,a;if(!this.innerCt){h.addClass(this.ctCls);this.innerCt=h.createChild({cls:this.innerCls});this.padding=this.parseMargins(this.padding)}this.renderAll(e,this.innerCt)},renderItem:function(a){if(typeof a.margins=="string"){a.margins=this.parseMargins(a.margins)}else{if(!a.margins){a.margins=this.defaultMargins}}Ext.layout.BoxLayout.superclass.renderItem.apply(this,arguments)},getTargetSize:function(a){return(Ext.isIE6&&Ext.isStrict&&a.dom==document.body)?a.getStyleSize():a.getViewSize()},getItems:function(b){var a=[];b.items.each(function(d){if(d.isVisible()){a.push(d)}});return a}});Ext.layout.VBoxLayout=Ext.extend(Ext.layout.BoxLayout,{align:"left",onLayout:function(e,D){Ext.layout.VBoxLayout.superclass.onLayout.call(this,e,D);var f=this.getItems(e),i,k,p,q=this.getTargetSize(D),j=q.width-D.getPadding("lr")-this.scrollOffset,x=q.height-D.getPadding("tb"),r=this.padding.left,m=this.padding.top,g=this.pack=="start",u=["stretch","stretchmax"].indexOf(this.align)==-1,A=j-(this.padding.left+this.padding.right),n=0,z=0,s=0,B=0,d=0;Ext.each(f,function(h){i=h.margins;s+=h.flex||0;k=h.getHeight();p=i.top+i.bottom;n+=k+p;B+=p+(h.flex?0:k);z=Math.max(z,h.getWidth()+i.left+i.right)});n=x-n-this.padding.top-this.padding.bottom;var a=z+this.padding.left+this.padding.right;switch(this.align){case"stretch":this.innerCt.setSize(j,x);break;case"stretchmax":case"left":this.innerCt.setSize(a,x);break;case"center":this.innerCt.setSize(j=Math.max(j,a),x);break}var c=Math.max(0,x-this.padding.top-this.padding.bottom-B),C=c,y=[],v=[],o=0,b=Math.max(0,j-this.padding.left-this.padding.right);Ext.each(f,function(h){if(g&&h.flex){k=Math.floor(c*(h.flex/s));C-=k;y.push(k)}});if(this.pack=="center"){m+=n?n/2:0}else{if(this.pack=="end"){m+=n}}Ext.each(f,function(h){i=h.margins;m+=i.top;h.setPosition(r+i.left,m);if(g&&h.flex){k=Math.max(0,y[o++]+(C-->0?1:0));if(u){v.push(h.getWidth())}h.setSize(b,k)}else{k=h.getHeight()}m+=k+i.bottom});o=0;Ext.each(f,function(l){i=l.margins;if(this.align=="stretch"){l.setWidth((A-(i.left+i.right)).constrain(l.minWidth||0,l.maxWidth||1000000))}else{if(this.align=="stretchmax"){l.setWidth((z-(i.left+i.right)).constrain(l.minWidth||0,l.maxWidth||1000000))}else{if(this.align=="center"){var h=b-(l.getWidth()+i.left+i.right);if(h>0){l.setPosition(r+i.left+(h/2),l.y)}}if(g&&l.flex){l.setWidth(v[o++])}}}},this)}});Ext.Container.LAYOUTS.vbox=Ext.layout.VBoxLayout;Ext.layout.HBoxLayout=Ext.extend(Ext.layout.BoxLayout,{align:"top",onLayout:function(d,D){Ext.layout.HBoxLayout.superclass.onLayout.call(this,d,D);var e=this.getItems(d),i,c,p,q=this.getTargetSize(D),k=q.width-D.getPadding("lr")-this.scrollOffset,A=q.height-D.getPadding("tb"),s=this.padding.left,n=this.padding.top,g=this.pack=="start",y=["stretch","stretchmax"].indexOf(this.align)==-1,m=A-(this.padding.top+this.padding.bottom),B=0,r=0,u=0,b=0,f=0;Ext.each(e,function(h){i=h.margins;u+=h.flex||0;c=h.getWidth();p=i.left+i.right;B+=c+p;b+=p+(h.flex?0:c);r=Math.max(r,h.getHeight()+i.top+i.bottom)});B=k-B-this.padding.left-this.padding.right;var x=r+this.padding.top+this.padding.bottom;switch(this.align){case"stretch":this.innerCt.setSize(k,A);break;case"stretchmax":case"top":this.innerCt.setSize(k,x);break;case"middle":this.innerCt.setSize(k,A=Math.max(A,x));break}var v=Math.max(0,k-this.padding.left-this.padding.right-b),C=v,j=[],z=[],o=0,a=Math.max(0,A-this.padding.top-this.padding.bottom);Ext.each(e,function(h){if(g&&h.flex){c=Math.floor(v*(h.flex/u));C-=c;j.push(c)}});if(this.pack=="center"){s+=B?B/2:0}else{if(this.pack=="end"){s+=B}}Ext.each(e,function(h){i=h.margins;s+=i.left;h.setPosition(s,n+i.top);if(g&&h.flex){c=Math.max(0,j[o++]+(C-->0?1:0));if(y){z.push(h.getHeight())}h.setSize(c,a)}else{c=h.getWidth()}s+=c+i.right});o=0;Ext.each(e,function(t){var h=t.margins;if(this.align=="stretch"){t.setHeight((m-(h.top+h.bottom)).constrain(t.minHeight||0,t.maxHeight||1000000))}else{if(this.align=="stretchmax"){t.setHeight((r-(h.top+h.bottom)).constrain(t.minHeight||0,t.maxHeight||1000000))}else{if(this.align=="middle"){var l=a-(t.getHeight()+h.top+h.bottom);if(l>0){t.setPosition(t.x,n+h.top+(l/2))}}if(g&&t.flex){t.setHeight(z[o++])}}}},this)}});Ext.Container.LAYOUTS.hbox=Ext.layout.HBoxLayout;Ext.Viewport=Ext.extend(Ext.Container,{initComponent:function(){Ext.Viewport.superclass.initComponent.call(this);document.getElementsByTagName("html")[0].className+=" x-viewport";this.el=Ext.getBody();this.el.setHeight=Ext.emptyFn;this.el.setWidth=Ext.emptyFn;this.el.setSize=Ext.emptyFn;this.el.dom.scroll="no";this.allowDomMove=false;this.autoWidth=true;this.autoHeight=true;Ext.EventManager.onWindowResize(this.fireResize,this);this.renderTo=this.el},fireResize:function(a,b){this.fireEvent("resize",this,a,b,a,b)}});Ext.reg("viewport",Ext.Viewport);Ext.Panel=Ext.extend(Ext.Container,{baseCls:"x-panel",collapsedCls:"x-panel-collapsed",maskDisabled:true,animCollapse:Ext.enableFx,headerAsText:true,buttonAlign:"right",collapsed:false,collapseFirst:true,minButtonWidth:75,elements:"body",preventBodyReset:false,toolTarget:"header",collapseEl:"bwrap",slideAnchor:"t",disabledClass:"",deferHeight:true,expandDefaults:{duration:0.25},collapseDefaults:{duration:0.25},initComponent:function(){Ext.Panel.superclass.initComponent.call(this);this.addEvents("bodyresize","titlechange","iconchange","collapse","expand","beforecollapse","beforeexpand","beforeclose","close","activate","deactivate");if(this.unstyled){this.baseCls="x-plain"}if(this.tbar){this.elements+=",tbar";if(Ext.isObject(this.tbar)){this.topToolbar=this.tbar}delete this.tbar}if(this.bbar){this.elements+=",bbar";if(Ext.isObject(this.bbar)){this.bottomToolbar=this.bbar}delete this.bbar}if(this.header===true){this.elements+=",header";delete this.header}else{if(this.headerCfg||(this.title&&this.header!==false)){this.elements+=",header"}}if(this.footerCfg||this.footer===true){this.elements+=",footer";delete this.footer}if(this.buttons){this.elements+=",footer";var c=this.buttons;this.buttons=[];for(var b=0,a=c.length;b<a;b++){if(c[b].render){this.buttons.push(c[b])}else{if(c[b].xtype){this.buttons.push(Ext.create(c[b],"button"))}else{this.addButton(c[b])}}}}if(this.fbar){this.elements+=",footer"}if(this.autoLoad){this.on("render",this.doAutoLoad,this,{delay:10})}},createElement:function(a,c){if(this[a]){c.appendChild(this[a].dom);return}if(a==="bwrap"||this.elements.indexOf(a)!=-1){if(this[a+"Cfg"]){this[a]=Ext.fly(c).createChild(this[a+"Cfg"])}else{var b=document.createElement("div");b.className=this[a+"Cls"];this[a]=Ext.get(c.appendChild(b))}if(this[a+"CssClass"]){this[a].addClass(this[a+"CssClass"])}if(this[a+"Style"]){this[a].applyStyles(this[a+"Style"])}}},onRender:function(f,e){Ext.Panel.superclass.onRender.call(this,f,e);this.createClasses();var a=this.el,h=a.dom,j;a.addClass(this.baseCls);if(h.firstChild){this.header=a.down("."+this.headerCls);this.bwrap=a.down("."+this.bwrapCls);var i=this.bwrap?this.bwrap:a;this.tbar=i.down("."+this.tbarCls);this.body=i.down("."+this.bodyCls);this.bbar=i.down("."+this.bbarCls);this.footer=i.down("."+this.footerCls);this.fromMarkup=true}if(this.preventBodyReset===true){a.addClass("x-panel-reset")}if(this.cls){a.addClass(this.cls)}if(this.buttons){this.elements+=",footer"}if(this.frame){a.insertHtml("afterBegin",String.format(Ext.Element.boxMarkup,this.baseCls));this.createElement("header",h.firstChild.firstChild.firstChild);this.createElement("bwrap",h);j=this.bwrap.dom;var c=h.childNodes[1],b=h.childNodes[2];j.appendChild(c);j.appendChild(b);var k=j.firstChild.firstChild.firstChild;this.createElement("tbar",k);this.createElement("body",k);this.createElement("bbar",k);this.createElement("footer",j.lastChild.firstChild.firstChild);if(!this.footer){this.bwrap.dom.lastChild.className+=" x-panel-nofooter"}}else{this.createElement("header",h);this.createElement("bwrap",h);j=this.bwrap.dom;this.createElement("tbar",j);this.createElement("body",j);this.createElement("bbar",j);this.createElement("footer",j);if(!this.header){this.body.addClass(this.bodyCls+"-noheader");if(this.tbar){this.tbar.addClass(this.tbarCls+"-noheader")}}}if(this.padding!==undefined){this.body.setStyle("padding",this.body.addUnits(this.padding))}if(this.border===false){this.el.addClass(this.baseCls+"-noborder");this.body.addClass(this.bodyCls+"-noborder");if(this.header){this.header.addClass(this.headerCls+"-noborder")}if(this.footer){this.footer.addClass(this.footerCls+"-noborder")}if(this.tbar){this.tbar.addClass(this.tbarCls+"-noborder")}if(this.bbar){this.bbar.addClass(this.bbarCls+"-noborder")}}if(this.bodyBorder===false){this.body.addClass(this.bodyCls+"-noborder")}this.bwrap.enableDisplayMode("block");if(this.header){this.header.unselectable();if(this.headerAsText){this.header.dom.innerHTML='<span class="'+this.headerTextCls+'">'+this.header.dom.innerHTML+"</span>";if(this.iconCls){this.setIconClass(this.iconCls)}}}if(this.floating){this.makeFloating(this.floating)}if(this.collapsible){this.tools=this.tools?this.tools.slice(0):[];if(!this.hideCollapseTool){this.tools[this.collapseFirst?"unshift":"push"]({id:"toggle",handler:this.toggleCollapse,scope:this})}if(this.titleCollapse&&this.header){this.mon(this.header,"click",this.toggleCollapse,this);this.header.setStyle("cursor","pointer")}}if(this.tools){var g=this.tools;this.tools={};this.addTool.apply(this,g)}else{this.tools={}}if(this.buttons&&this.buttons.length>0){this.fbar=new Ext.Toolbar({items:this.buttons,toolbarCls:"x-panel-fbar"})}this.toolbars=[];if(this.fbar){this.fbar=Ext.create(this.fbar,"toolbar");this.fbar.enableOverflow=false;if(this.fbar.items){this.fbar.items.each(function(d){d.minWidth=d.minWidth||this.minButtonWidth},this)}this.fbar.toolbarCls="x-panel-fbar";var l=this.footer.createChild({cls:"x-panel-btns x-panel-btns-"+this.buttonAlign});this.fbar.ownerCt=this;this.fbar.render(l);l.createChild({cls:"x-clear"});this.toolbars.push(this.fbar)}if(this.tbar&&this.topToolbar){if(Ext.isArray(this.topToolbar)){this.topToolbar=new Ext.Toolbar(this.topToolbar)}else{if(!this.topToolbar.events){this.topToolbar=Ext.create(this.topToolbar,"toolbar")}}this.topToolbar.ownerCt=this;this.topToolbar.render(this.tbar);this.toolbars.push(this.topToolbar)}if(this.bbar&&this.bottomToolbar){if(Ext.isArray(this.bottomToolbar)){this.bottomToolbar=new Ext.Toolbar(this.bottomToolbar)}else{if(!this.bottomToolbar.events){this.bottomToolbar=Ext.create(this.bottomToolbar,"toolbar")}}this.bottomToolbar.ownerCt=this;this.bottomToolbar.render(this.bbar);this.toolbars.push(this.bottomToolbar)}Ext.each(this.toolbars,function(d){d.on({scope:this,afterlayout:this.syncHeight,remove:this.syncHeight})},this)},setIconClass:function(b){var a=this.iconCls;this.iconCls=b;if(this.rendered&&this.header){if(this.frame){this.header.addClass("x-panel-icon");this.header.replaceClass(a,this.iconCls)}else{var d=this.header.dom;var c=d.firstChild&&String(d.firstChild.tagName).toLowerCase()=="img"?d.firstChild:null;if(c){Ext.fly(c).replaceClass(a,this.iconCls)}else{Ext.DomHelper.insertBefore(d.firstChild,{tag:"img",src:Ext.BLANK_IMAGE_URL,cls:"x-panel-inline-icon "+this.iconCls})}}}this.fireEvent("iconchange",this,b,a)},makeFloating:function(a){this.floating=true;this.el=new Ext.Layer(Ext.isObject(a)?a:{shadow:this.shadow!==undefined?this.shadow:"sides",shadowOffset:this.shadowOffset,constrain:false,shim:this.shim===false?false:undefined},this.el)},getTopToolbar:function(){return this.topToolbar},getBottomToolbar:function(){return this.bottomToolbar},addButton:function(a,d,c){var e={handler:d,scope:c,minWidth:this.minButtonWidth,hideParent:true};if(typeof a=="string"){e.text=a}else{Ext.apply(e,a)}var b=new Ext.Button(e);if(!this.buttons){this.buttons=[]}this.buttons.push(b);return b},addTool:function(){if(!this[this.toolTarget]){return}if(!this.toolTemplate){var g=new Ext.Template('<div class="x-tool x-tool-{id}"> </div>');g.disableFormats=true;g.compile();Ext.Panel.prototype.toolTemplate=g}for(var f=0,d=arguments,c=d.length;f<c;f++){var b=d[f];if(!this.tools[b.id]){var h="x-tool-"+b.id+"-over";var e=this.toolTemplate.insertFirst((b.align!=="left")?this[this.toolTarget]:this[this.toolTarget].child("span"),b,true);this.tools[b.id]=e;e.enableDisplayMode("block");this.mon(e,"click",this.createToolHandler(e,b,h,this));if(b.on){this.mon(e,b.on)}if(b.hidden){e.hide()}if(b.qtip){if(Ext.isObject(b.qtip)){Ext.QuickTips.register(Ext.apply({target:e.id},b.qtip))}else{e.dom.qtip=b.qtip}}e.addClassOnOver(h)}}},onLayout:function(){if(this.toolbars.length>0){this.duringLayout=true;Ext.each(this.toolbars,function(a){a.doLayout()});delete this.duringLayout;this.syncHeight()}},syncHeight:function(){if(!(this.autoHeight||this.duringLayout)){var d=this.lastSize;if(d&&!Ext.isEmpty(d.height)){var b=d.height,c=this.el.getHeight();if(b!="auto"&&b!=c){var e=this.body,a=e.getHeight();c=Math.max(a+b-c,0);if(a>0&&a!=c){e.setHeight(c);if(Ext.isIE&&c<=0){return}var f=e.getSize();this.fireEvent("bodyresize",f.width,f.height)}}}}},onShow:function(){if(this.floating){return this.el.show()}Ext.Panel.superclass.onShow.call(this)},onHide:function(){if(this.floating){return this.el.hide()}Ext.Panel.superclass.onHide.call(this)},createToolHandler:function(c,a,d,b){return function(f){c.removeClass(d);if(a.stopEvent!==false){f.stopEvent()}if(a.handler){a.handler.call(a.scope||c,f,c,b,a)}}},afterRender:function(){if(this.floating&&!this.hidden){this.el.show()}if(this.title){this.setTitle(this.title)}this.setAutoScroll();if(this.html){this.body.update(Ext.isObject(this.html)?Ext.DomHelper.markup(this.html):this.html);delete this.html}if(this.contentEl){var a=Ext.getDom(this.contentEl);Ext.fly(a).removeClass(["x-hidden","x-hide-display"]);this.body.dom.appendChild(a)}if(this.collapsed){this.collapsed=false;this.collapse(false)}Ext.Panel.superclass.afterRender.call(this);this.initEvents()},setAutoScroll:function(){if(this.rendered&&this.autoScroll){var a=this.body||this.el;if(a){a.setOverflow("auto")}}},getKeyMap:function(){if(!this.keyMap){this.keyMap=new Ext.KeyMap(this.el,this.keys)}return this.keyMap},initEvents:function(){if(this.keys){this.getKeyMap()}if(this.draggable){this.initDraggable()}},initDraggable:function(){this.dd=new Ext.Panel.DD(this,typeof this.draggable=="boolean"?null:this.draggable)},beforeEffect:function(){if(this.floating){this.el.beforeAction()}this.el.addClass("x-panel-animated")},afterEffect:function(){this.syncShadow();this.el.removeClass("x-panel-animated")},createEffect:function(c,b,d){var e={scope:d,block:true};if(c===true){e.callback=b;return e}else{if(!c.callback){e.callback=b}else{e.callback=function(){b.call(d);Ext.callback(c.callback,c.scope)}}}return Ext.applyIf(e,c)},collapse:function(b){if(this.collapsed||this.el.hasFxBlock()||this.fireEvent("beforecollapse",this,b)===false){return}var a=b===true||(b!==false&&this.animCollapse);this.beforeEffect();this.onCollapse(a,b);return this},onCollapse:function(a,b){if(a){this[this.collapseEl].slideOut(this.slideAnchor,Ext.apply(this.createEffect(b||true,this.afterCollapse,this),this.collapseDefaults))}else{this[this.collapseEl].hide();this.afterCollapse()}},afterCollapse:function(){this.collapsed=true;this.el.addClass(this.collapsedCls);this.afterEffect();this.fireEvent("collapse",this)},expand:function(b){if(!this.collapsed||this.el.hasFxBlock()||this.fireEvent("beforeexpand",this,b)===false){return}var a=b===true||(b!==false&&this.animCollapse);this.el.removeClass(this.collapsedCls);this.beforeEffect();this.onExpand(a,b);return this},onExpand:function(a,b){if(a){this[this.collapseEl].slideIn(this.slideAnchor,Ext.apply(this.createEffect(b||true,this.afterExpand,this),this.expandDefaults))}else{this[this.collapseEl].show();this.afterExpand()}},afterExpand:function(){this.collapsed=false;this.afterEffect();if(this.deferLayout!==undefined){this.doLayout(true)}this.fireEvent("expand",this)},toggleCollapse:function(a){this[this.collapsed?"expand":"collapse"](a);return this},onDisable:function(){if(this.rendered&&this.maskDisabled){this.el.mask()}Ext.Panel.superclass.onDisable.call(this)},onEnable:function(){if(this.rendered&&this.maskDisabled){this.el.unmask()}Ext.Panel.superclass.onEnable.call(this)},onResize:function(b,c){if(b!==undefined||c!==undefined){if(!this.collapsed){if(typeof b=="number"){b=this.adjustBodyWidth(b-this.getFrameWidth());if(this.tbar){this.tbar.setWidth(b);if(this.topToolbar){this.topToolbar.setSize(b)}}if(this.bbar){this.bbar.setWidth(b);if(this.bottomToolbar){this.bottomToolbar.setSize(b)}}if(this.fbar){var d=this.fbar,e=1,a=Ext.isStrict;if(this.buttonAlign=="left"){e=b-d.container.getFrameWidth("lr")}else{if(Ext.isIE||Ext.isWebKit){if(!(this.buttonAlign=="center"&&Ext.isWebKit)&&(!a||(!Ext.isIE8&&a))){(function(){d.setWidth(d.getEl().child(".x-toolbar-ct").getWidth())}).defer(1)}else{e="auto"}}else{e="auto"}}d.setWidth(e)}this.body.setWidth(b)}else{if(b=="auto"){this.body.setWidth(b)}}if(typeof c=="number"){c=Math.max(0,this.adjustBodyHeight(c-this.getFrameHeight()));this.body.setHeight(c)}else{if(c=="auto"){this.body.setHeight(c)}}if(this.disabled&&this.el._mask){this.el._mask.setSize(this.el.dom.clientWidth,this.el.getHeight())}}else{this.queuedBodySize={width:b,height:c};if(!this.queuedExpand&&this.allowQueuedExpand!==false){this.queuedExpand=true;this.on("expand",function(){delete this.queuedExpand;this.onResize(this.queuedBodySize.width,this.queuedBodySize.height);this.doLayout()},this,{single:true})}}this.fireEvent("bodyresize",this,b,c)}this.syncShadow()},adjustBodyHeight:function(a){return a},adjustBodyWidth:function(a){return a},onPosition:function(){this.syncShadow()},getFrameWidth:function(){var b=this.el.getFrameWidth("lr")+this.bwrap.getFrameWidth("lr");if(this.frame){var a=this.bwrap.dom.firstChild;b+=(Ext.fly(a).getFrameWidth("l")+Ext.fly(a.firstChild).getFrameWidth("r"));var c=this.bwrap.dom.firstChild.firstChild.firstChild;b+=Ext.fly(c).getFrameWidth("lr")}return b},getFrameHeight:function(){var a=this.el.getFrameWidth("tb")+this.bwrap.getFrameWidth("tb");a+=(this.tbar?this.tbar.getHeight():0)+(this.bbar?this.bbar.getHeight():0);if(this.frame){var c=this.el.dom.firstChild;var d=this.bwrap.dom.lastChild;a+=(c.offsetHeight+d.offsetHeight);var b=this.bwrap.dom.firstChild.firstChild.firstChild;a+=Ext.fly(b).getFrameWidth("tb")}else{a+=(this.header?this.header.getHeight():0)+(this.footer?this.footer.getHeight():0)}return a},getInnerWidth:function(){return this.getSize().width-this.getFrameWidth()},getInnerHeight:function(){return this.getSize().height-this.getFrameHeight()},syncShadow:function(){if(this.floating){this.el.sync(true)}},getLayoutTarget:function(){return this.body},setTitle:function(b,a){this.title=b;if(this.header&&this.headerAsText){this.header.child("span").update(b)}if(a){this.setIconClass(a)}this.fireEvent("titlechange",this,b);return this},getUpdater:function(){return this.body.getUpdater()},load:function(){var a=this.body.getUpdater();a.update.apply(a,arguments);return this},beforeDestroy:function(){if(this.header){this.header.removeAllListeners();if(this.headerAsText){Ext.Element.uncache(this.header.child("span"))}}Ext.Element.uncache(this.header,this.tbar,this.bbar,this.footer,this.body,this.bwrap);if(this.tools){for(var c in this.tools){Ext.destroy(this.tools[c])}}if(this.buttons){for(var a in this.buttons){Ext.destroy(this.buttons[a])}}Ext.destroy(this.toolbars);Ext.Panel.superclass.beforeDestroy.call(this)},createClasses:function(){this.headerCls=this.baseCls+"-header";this.headerTextCls=this.baseCls+"-header-text";this.bwrapCls=this.baseCls+"-bwrap";this.tbarCls=this.baseCls+"-tbar";this.bodyCls=this.baseCls+"-body";this.bbarCls=this.baseCls+"-bbar";this.footerCls=this.baseCls+"-footer"},createGhost:function(a,e,b){var d=document.createElement("div");d.className="x-panel-ghost "+(a?a:"");if(this.header){d.appendChild(this.el.dom.firstChild.cloneNode(true))}Ext.fly(d.appendChild(document.createElement("ul"))).setHeight(this.bwrap.getHeight());d.style.width=this.el.dom.offsetWidth+"px";if(!b){this.container.dom.appendChild(d)}else{Ext.getDom(b).appendChild(d)}if(e!==false&&this.el.useShim!==false){var c=new Ext.Layer({shadow:false,useDisplay:true,constrain:false},d);c.show();return c}else{return new Ext.Element(d)}},doAutoLoad:function(){var a=this.body.getUpdater();if(this.renderer){a.setRenderer(this.renderer)}a.update(Ext.isObject(this.autoLoad)?this.autoLoad:{url:this.autoLoad})},getTool:function(a){return this.tools[a]}});Ext.reg("panel",Ext.Panel);Ext.Editor=function(b,a){if(b.field){this.field=Ext.create(b.field,"textfield");a=Ext.apply({},b);delete a.field}else{this.field=b}Ext.Editor.superclass.constructor.call(this,a)};Ext.extend(Ext.Editor,Ext.Component,{value:"",alignment:"c-c?",shadow:"frame",constrain:false,swallowKeys:true,completeOnEnter:false,cancelOnEsc:false,updateEl:false,initComponent:function(){Ext.Editor.superclass.initComponent.call(this);this.addEvents("beforestartedit","startedit","beforecomplete","complete","canceledit","specialkey")},onRender:function(b,a){this.el=new Ext.Layer({shadow:this.shadow,cls:"x-editor",parentEl:b,shim:this.shim,shadowOffset:this.shadowOffset||4,id:this.id,constrain:this.constrain});if(this.zIndex){this.el.setZIndex(this.zIndex)}this.el.setStyle("overflow",Ext.isGecko?"auto":"hidden");if(this.field.msgTarget!="title"){this.field.msgTarget="qtip"}this.field.inEditor=true;this.field.render(this.el);if(Ext.isGecko){this.field.el.dom.setAttribute("autocomplete","off")}this.mon(this.field,"specialkey",this.onSpecialKey,this);if(this.swallowKeys){this.field.el.swallowEvent(["keydown","keypress"])}this.field.show();this.mon(this.field,"blur",this.onBlur,this);if(this.field.grow){this.mon(this.field,"autosize",this.el.sync,this.el,{delay:1})}},onSpecialKey:function(c,b){var a=b.getKey();if(this.completeOnEnter&&a==b.ENTER){b.stopEvent();this.completeEdit()}else{if(this.cancelOnEsc&&a==b.ESC){this.cancelEdit()}else{this.fireEvent("specialkey",c,b)}}if(this.field.triggerBlur&&(a==b.ENTER||a==b.ESC||a==b.TAB)){this.field.triggerBlur()}},startEdit:function(b,c){if(this.editing){this.completeEdit()}this.boundEl=Ext.get(b);var a=c!==undefined?c:this.boundEl.dom.innerHTML;if(!this.rendered){this.render(this.parentEl||document.body)}if(this.fireEvent("beforestartedit",this,this.boundEl,a)===false){return}this.startValue=a;this.field.setValue(a);this.doAutoSize();this.el.alignTo(this.boundEl,this.alignment);this.editing=true;this.show()},doAutoSize:function(){if(this.autoSize){var a=this.boundEl.getSize();switch(this.autoSize){case"width":this.setSize(a.width,"");break;case"height":this.setSize("",a.height);break;default:this.setSize(a.width,a.height)}}},setSize:function(a,b){delete this.field.lastSize;this.field.setSize(a,b);if(this.el){if(Ext.isGecko2||Ext.isOpera){this.el.setSize(a,b)}this.el.sync()}},realign:function(){this.el.alignTo(this.boundEl,this.alignment)},completeEdit:function(a){if(!this.editing){return}var b=this.getValue();if(!this.field.isValid()){if(this.revertInvalid!==false){this.cancelEdit(a)}return}if(String(b)===String(this.startValue)&&this.ignoreNoChange){this.hideEdit(a);return}if(this.fireEvent("beforecomplete",this,b,this.startValue)!==false){b=this.getValue();if(this.updateEl&&this.boundEl){this.boundEl.update(b)}this.hideEdit(a);this.fireEvent("complete",this,b,this.startValue)}},onShow:function(){this.el.show();if(this.hideEl!==false){this.boundEl.hide()}this.field.show();if(Ext.isIE&&!this.fixIEFocus){this.fixIEFocus=true;this.deferredFocus.defer(50,this)}else{this.field.focus()}this.fireEvent("startedit",this.boundEl,this.startValue)},deferredFocus:function(){if(this.editing){this.field.focus()}},cancelEdit:function(a){if(this.editing){var b=this.getValue();this.setValue(this.startValue);this.hideEdit(a);this.fireEvent("canceledit",this,b,this.startValue)}},hideEdit:function(a){if(a!==true){this.editing=false;this.hide()}},onBlur:function(){if(this.allowBlur!==true&&this.editing){this.completeEdit()}},onHide:function(){if(this.editing){this.completeEdit();return}this.field.blur();if(this.field.collapse){this.field.collapse()}this.el.hide();if(this.hideEl!==false){this.boundEl.show()}},setValue:function(a){this.field.setValue(a)},getValue:function(){return this.field.getValue()},beforeDestroy:function(){Ext.destroy(this.field);this.field=null}});Ext.reg("editor",Ext.Editor);Ext.ColorPalette=function(a){Ext.ColorPalette.superclass.constructor.call(this,a);this.addEvents("select");if(this.handler){this.on("select",this.handler,this.scope,true)}};Ext.extend(Ext.ColorPalette,Ext.Component,{itemCls:"x-color-palette",value:null,clickEvent:"click",ctype:"Ext.ColorPalette",allowReselect:false,colors:["000000","993300","333300","003300","003366","000080","333399","333333","800000","FF6600","808000","008000","008080","0000FF","666699","808080","FF0000","FF9900","99CC00","339966","33CCCC","3366FF","800080","969696","FF00FF","FFCC00","FFFF00","00FF00","00FFFF","00CCFF","993366","C0C0C0","FF99CC","FFCC99","FFFF99","CCFFCC","CCFFFF","99CCFF","CC99FF","FFFFFF"],onRender:function(b,a){var c=this.tpl||new Ext.XTemplate('<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on"> </span></em></a></tpl>');var d=document.createElement("div");d.id=this.getId();d.className=this.itemCls;c.overwrite(d,this.colors);b.dom.insertBefore(d,a);this.el=Ext.get(d);this.mon(this.el,this.clickEvent,this.handleClick,this,{delegate:"a"});if(this.clickEvent!="click"){this.mon(this.el,"click",Ext.emptyFn,this,{delegate:"a",preventDefault:true})}},afterRender:function(){Ext.ColorPalette.superclass.afterRender.call(this);if(this.value){var a=this.value;this.value=null;this.select(a)}},handleClick:function(b,a){b.preventDefault();if(!this.disabled){var d=a.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];this.select(d.toUpperCase())}},select:function(a){a=a.replace("#","");if(a!=this.value||this.allowReselect){var b=this.el;if(this.value){b.child("a.color-"+this.value).removeClass("x-color-palette-sel")}b.child("a.color-"+a).addClass("x-color-palette-sel");this.value=a;this.fireEvent("select",this,a)}}});Ext.reg("colorpalette",Ext.ColorPalette);Ext.DatePicker=Ext.extend(Ext.BoxComponent,{todayText:"Today",okText:" OK ",cancelText:"Cancel",todayTip:"{0} (Spacebar)",minText:"This date is before the minimum date",maxText:"This date is after the maximum date",format:"m/d/y",disabledDaysText:"Disabled",disabledDatesText:"Disabled",monthNames:Date.monthNames,dayNames:Date.dayNames,nextText:"Next Month (Control+Right)",prevText:"Previous Month (Control+Left)",monthYearText:"Choose a month (Control+Up/Down to move years)",startDay:0,showToday:true,initComponent:function(){Ext.DatePicker.superclass.initComponent.call(this);this.value=this.value?this.value.clearTime():new Date().clearTime();this.addEvents("select");if(this.handler){this.on("select",this.handler,this.scope||this)}this.initDisabledDays()},initDisabledDays:function(){if(!this.disabledDatesRE&&this.disabledDates){var b=this.disabledDates,a=b.length-1,c="(?:";Ext.each(b,function(f,e){c+=Ext.isDate(f)?"^"+Ext.escapeRe(f.dateFormat(this.format))+"$":b[e];if(e!=a){c+="|"}},this);this.disabledDatesRE=new RegExp(c+")")}},setDisabledDates:function(a){if(Ext.isArray(a)){this.disabledDates=a;this.disabledDatesRE=null}else{this.disabledDatesRE=a}this.initDisabledDays();this.update(this.value,true)},setDisabledDays:function(a){this.disabledDays=a;this.update(this.value,true)},setMinDate:function(a){this.minDate=a;this.update(this.value,true)},setMaxDate:function(a){this.maxDate=a;this.update(this.value,true)},setValue:function(b){var a=this.value;this.value=b.clearTime(true);if(this.el){this.update(this.value)}},getValue:function(){return this.value},focus:function(){if(this.el){this.update(this.activeDate)}},onEnable:function(a){Ext.DatePicker.superclass.onEnable.call(this);this.doDisabled(false);this.update(a?this.value:this.activeDate);if(Ext.isIE){this.el.repaint()}},onDisable:function(){Ext.DatePicker.superclass.onDisable.call(this);this.doDisabled(true);if(Ext.isIE&&!Ext.isIE8){Ext.each([].concat(this.textNodes,this.el.query("th span")),function(a){Ext.fly(a).repaint()})}},doDisabled:function(a){this.keyNav.setDisabled(a);this.prevRepeater.setDisabled(a);this.nextRepeater.setDisabled(a);if(this.showToday){this.todayKeyListener.setDisabled(a);this.todayBtn.setDisabled(a)}},onRender:function(e,b){var a=['<table cellspacing="0">','<tr><td class="x-date-left"><a href="#" title="',this.prevText,'"> </a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="',this.nextText,'"> </a></td></tr>','<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'],c=this.dayNames,g;for(g=0;g<7;g++){var j=this.startDay+g;if(j>6){j=j-7}a.push("<th><span>",c[j].substr(0,1),"</span></th>")}a[a.length]="</tr></thead><tbody><tr>";for(g=0;g<42;g++){if(g%7===0&&g!==0){a[a.length]="</tr><tr>"}a[a.length]='<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>'}a.push("</tr></tbody></table></td></tr>",this.showToday?'<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>':"",'</table><div class="x-date-mp"></div>');var h=document.createElement("div");h.className="x-date-picker";h.innerHTML=a.join("");e.dom.insertBefore(h,b);this.el=Ext.get(h);this.eventEl=Ext.get(h.firstChild);this.prevRepeater=new Ext.util.ClickRepeater(this.el.child("td.x-date-left a"),{handler:this.showPrevMonth,scope:this,preventDefault:true,stopDefault:true});this.nextRepeater=new Ext.util.ClickRepeater(this.el.child("td.x-date-right a"),{handler:this.showNextMonth,scope:this,preventDefault:true,stopDefault:true});this.monthPicker=this.el.down("div.x-date-mp");this.monthPicker.enableDisplayMode("block");this.keyNav=new Ext.KeyNav(this.eventEl,{left:function(d){if(d.ctrlKey){this.showPrevMonth()}else{this.update(this.activeDate.add("d",-1))}},right:function(d){if(d.ctrlKey){this.showNextMonth()}else{this.update(this.activeDate.add("d",1))}},up:function(d){if(d.ctrlKey){this.showNextYear()}else{this.update(this.activeDate.add("d",-7))}},down:function(d){if(d.ctrlKey){this.showPrevYear()}else{this.update(this.activeDate.add("d",7))}},pageUp:function(d){this.showNextMonth()},pageDown:function(d){this.showPrevMonth()},enter:function(d){d.stopPropagation();return true},scope:this});this.el.unselectable();this.cells=this.el.select("table.x-date-inner tbody td");this.textNodes=this.el.query("table.x-date-inner tbody span");this.mbtn=new Ext.Button({text:" ",tooltip:this.monthYearText,renderTo:this.el.child("td.x-date-middle",true)});this.mbtn.el.child("em").addClass("x-btn-arrow");if(this.showToday){this.todayKeyListener=this.eventEl.addKeyListener(Ext.EventObject.SPACE,this.selectToday,this);var f=(new Date()).dateFormat(this.format);this.todayBtn=new Ext.Button({renderTo:this.el.child("td.x-date-bottom",true),text:String.format(this.todayText,f),tooltip:String.format(this.todayTip,f),handler:this.selectToday,scope:this})}this.mon(this.eventEl,"mousewheel",this.handleMouseWheel,this);this.mon(this.eventEl,"click",this.handleDateClick,this,{delegate:"a.x-date-date"});this.mon(this.mbtn,"click",this.showMonthPicker,this);this.onEnable(true)},createMonthPicker:function(){if(!this.monthPicker.dom.firstChild){var a=['<table border="0" cellspacing="0">'];for(var b=0;b<6;b++){a.push('<tr><td class="x-date-mp-month"><a href="#">',Date.getShortMonthName(b),"</a></td>",'<td class="x-date-mp-month x-date-mp-sep"><a href="#">',Date.getShortMonthName(b+6),"</a></td>",b===0?'<td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-prev"></a></td><td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-next"></a></td></tr>':'<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>')}a.push('<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',this.okText,'</button><button type="button" class="x-date-mp-cancel">',this.cancelText,"</button></td></tr>","</table>");this.monthPicker.update(a.join(""));this.mon(this.monthPicker,"click",this.onMonthClick,this);this.mon(this.monthPicker,"dblclick",this.onMonthDblClick,this);this.mpMonths=this.monthPicker.select("td.x-date-mp-month");this.mpYears=this.monthPicker.select("td.x-date-mp-year");this.mpMonths.each(function(c,d,e){e+=1;if((e%2)===0){c.dom.xmonth=5+Math.round(e*0.5)}else{c.dom.xmonth=Math.round((e-1)*0.5)}})}},showMonthPicker:function(){if(!this.disabled){this.createMonthPicker();var a=this.el.getSize();this.monthPicker.setSize(a);this.monthPicker.child("table").setSize(a);this.mpSelMonth=(this.activeDate||this.value).getMonth();this.updateMPMonth(this.mpSelMonth);this.mpSelYear=(this.activeDate||this.value).getFullYear();this.updateMPYear(this.mpSelYear);this.monthPicker.slideIn("t",{duration:0.2})}},updateMPYear:function(e){this.mpyear=e;var c=this.mpYears.elements;for(var b=1;b<=10;b++){var d=c[b-1],a;if((b%2)===0){a=e+Math.round(b*0.5);d.firstChild.innerHTML=a;d.xyear=a}else{a=e-(5-Math.round(b*0.5));d.firstChild.innerHTML=a;d.xyear=a}this.mpYears.item(b-1)[a==this.mpSelYear?"addClass":"removeClass"]("x-date-mp-sel")}},updateMPMonth:function(a){this.mpMonths.each(function(b,c,d){b[b.dom.xmonth==a?"addClass":"removeClass"]("x-date-mp-sel")})},selectMPMonth:function(a){},onMonthClick:function(f,b){f.stopEvent();var c=new Ext.Element(b),a;if(c.is("button.x-date-mp-cancel")){this.hideMonthPicker()}else{if(c.is("button.x-date-mp-ok")){var g=new Date(this.mpSelYear,this.mpSelMonth,(this.activeDate||this.value).getDate());if(g.getMonth()!=this.mpSelMonth){g=new Date(this.mpSelYear,this.mpSelMonth,1).getLastDateOfMonth()}this.update(g);this.hideMonthPicker()}else{if((a=c.up("td.x-date-mp-month",2))){this.mpMonths.removeClass("x-date-mp-sel");a.addClass("x-date-mp-sel");this.mpSelMonth=a.dom.xmonth}else{if((a=c.up("td.x-date-mp-year",2))){this.mpYears.removeClass("x-date-mp-sel");a.addClass("x-date-mp-sel");this.mpSelYear=a.dom.xyear}else{if(c.is("a.x-date-mp-prev")){this.updateMPYear(this.mpyear-10)}else{if(c.is("a.x-date-mp-next")){this.updateMPYear(this.mpyear+10)}}}}}}},onMonthDblClick:function(d,b){d.stopEvent();var c=new Ext.Element(b),a;if((a=c.up("td.x-date-mp-month",2))){this.update(new Date(this.mpSelYear,a.dom.xmonth,(this.activeDate||this.value).getDate()));this.hideMonthPicker()}else{if((a=c.up("td.x-date-mp-year",2))){this.update(new Date(a.dom.xyear,this.mpSelMonth,(this.activeDate||this.value).getDate()));this.hideMonthPicker()}}},hideMonthPicker:function(a){if(this.monthPicker){if(a===true){this.monthPicker.hide()}else{this.monthPicker.slideOut("t",{duration:0.2})}}},showPrevMonth:function(a){this.update(this.activeDate.add("mo",-1))},showNextMonth:function(a){this.update(this.activeDate.add("mo",1))},showPrevYear:function(){this.update(this.activeDate.add("y",-1))},showNextYear:function(){this.update(this.activeDate.add("y",1))},handleMouseWheel:function(a){a.stopEvent();if(!this.disabled){var b=a.getWheelDelta();if(b>0){this.showPrevMonth()}else{if(b<0){this.showNextMonth()}}}},handleDateClick:function(b,a){b.stopEvent();if(!this.disabled&&a.dateValue&&!Ext.fly(a.parentNode).hasClass("x-date-disabled")){this.setValue(new Date(a.dateValue));this.fireEvent("select",this,this.value)}},selectToday:function(){if(this.todayBtn&&!this.todayBtn.disabled){this.setValue(new Date().clearTime());this.fireEvent("select",this,this.value)}},update:function(G,A){var a=this.activeDate,o=this.isVisible();this.activeDate=G;if(!A&&a&&this.el){var n=G.getTime();if(a.getMonth()==G.getMonth()&&a.getFullYear()==G.getFullYear()){this.cells.removeClass("x-date-selected");this.cells.each(function(d){if(d.dom.firstChild.dateValue==n){d.addClass("x-date-selected");if(o){Ext.fly(d.dom.firstChild).focus(50)}return false}});return}}var j=G.getDaysInMonth();var p=G.getFirstDateOfMonth();var f=p.getDay()-this.startDay;if(f<=this.startDay){f+=7}var B=G.add("mo",-1);var g=B.getDaysInMonth()-f;var e=this.cells.elements;var q=this.textNodes;j+=f;var y=86400000;var D=(new Date(B.getFullYear(),B.getMonth(),g)).clearTime();var C=new Date().clearTime().getTime();var u=G.clearTime().getTime();var s=this.minDate?this.minDate.clearTime():Number.NEGATIVE_INFINITY;var x=this.maxDate?this.maxDate.clearTime():Number.POSITIVE_INFINITY;var F=this.disabledDatesRE;var r=this.disabledDatesText;var I=this.disabledDays?this.disabledDays.join(""):false;var E=this.disabledDaysText;var z=this.format;if(this.showToday){var l=new Date().clearTime();var c=(l<s||l>x||(F&&z&&F.test(l.dateFormat(z)))||(I&&I.indexOf(l.getDay())!=-1));if(!this.disabled){this.todayBtn.setDisabled(c);this.todayKeyListener[c?"disable":"enable"]()}}var k=function(J,d){d.title="";var i=D.getTime();d.firstChild.dateValue=i;if(i==C){d.className+=" x-date-today";d.title=J.todayText}if(i==u){d.className+=" x-date-selected";if(o){Ext.fly(d.firstChild).focus(50)}}if(i<s){d.className=" x-date-disabled";d.title=J.minText;return}if(i>x){d.className=" x-date-disabled";d.title=J.maxText;return}if(I){if(I.indexOf(D.getDay())!=-1){d.title=E;d.className=" x-date-disabled"}}if(F&&z){var w=D.dateFormat(z);if(F.test(w)){d.title=r.replace("%0",w);d.className=" x-date-disabled"}}};var v=0;for(;v<f;v++){q[v].innerHTML=(++g);D.setDate(D.getDate()+1);e[v].className="x-date-prevday";k(this,e[v])}for(;v<j;v++){var b=v-f+1;q[v].innerHTML=(b);D.setDate(D.getDate()+1);e[v].className="x-date-active";k(this,e[v])}var H=0;for(;v<42;v++){q[v].innerHTML=(++H);D.setDate(D.getDate()+1);e[v].className="x-date-nextday";k(this,e[v])}this.mbtn.setText(this.monthNames[G.getMonth()]+" "+G.getFullYear());if(!this.internalRender){var h=this.el.dom.firstChild;var m=h.offsetWidth;this.el.setWidth(m+this.el.getBorderWidth("lr"));Ext.fly(h).setWidth(m);this.internalRender=true;if(Ext.isOpera&&!this.secondPass){h.rows[0].cells[1].style.width=(m-(h.rows[0].cells[0].offsetWidth+h.rows[0].cells[2].offsetWidth))+"px";this.secondPass=true;this.update.defer(10,this,[G])}}},beforeDestroy:function(){if(this.rendered){this.keyNav.disable();this.keyNav=null;Ext.destroy(this.leftClickRpt,this.rightClickRpt,this.monthPicker,this.eventEl,this.mbtn,this.todayBtn)}}});Ext.reg("datepicker",Ext.DatePicker);Ext.LoadMask=function(c,b){this.el=Ext.get(c);Ext.apply(this,b);if(this.store){this.store.on("beforeload",this.onBeforeLoad,this);this.store.on("load",this.onLoad,this);this.store.on("exception",this.onLoad,this);this.removeMask=Ext.value(this.removeMask,false)}else{var a=this.el.getUpdater();a.showLoadIndicator=false;a.on("beforeupdate",this.onBeforeLoad,this);a.on("update",this.onLoad,this);a.on("failure",this.onLoad,this);this.removeMask=Ext.value(this.removeMask,true)}};Ext.LoadMask.prototype={msg:"Loading...",msgCls:"x-mask-loading",disabled:false,disable:function(){this.disabled=true},enable:function(){this.disabled=false},onLoad:function(){this.el.unmask(this.removeMask)},onBeforeLoad:function(){if(!this.disabled){this.el.mask(this.msg,this.msgCls)}},show:function(){this.onBeforeLoad()},hide:function(){this.onLoad()},destroy:function(){if(this.store){this.store.un("beforeload",this.onBeforeLoad,this);this.store.un("load",this.onLoad,this);this.store.un("exception",this.onLoad,this)}else{var a=this.el.getUpdater();a.un("beforeupdate",this.onBeforeLoad,this);a.un("update",this.onLoad,this);a.un("failure",this.onLoad,this)}}};Ext.Slider=Ext.extend(Ext.BoxComponent,{vertical:false,minValue:0,maxValue:100,decimalPrecision:0,keyIncrement:1,increment:0,clickRange:[5,15],clickToChange:true,animate:true,dragging:false,initComponent:function(){if(!Ext.isDefined(this.value)){this.value=this.minValue}Ext.Slider.superclass.initComponent.call(this);this.keyIncrement=Math.max(this.increment,this.keyIncrement);this.addEvents("beforechange","change","changecomplete","dragstart","drag","dragend");if(this.vertical){Ext.apply(this,Ext.Slider.Vertical)}},onRender:function(){this.autoEl={cls:"x-slider "+(this.vertical?"x-slider-vert":"x-slider-horz"),cn:{cls:"x-slider-end",cn:{cls:"x-slider-inner",cn:[{cls:"x-slider-thumb"},{tag:"a",cls:"x-slider-focus",href:"#",tabIndex:"-1",hidefocus:"on"}]}}};Ext.Slider.superclass.onRender.apply(this,arguments);this.endEl=this.el.first();this.innerEl=this.endEl.first();this.thumb=this.innerEl.first();this.halfThumb=(this.vertical?this.thumb.getHeight():this.thumb.getWidth())/2;this.focusEl=this.thumb.next();this.initEvents()},initEvents:function(){this.thumb.addClassOnOver("x-slider-thumb-over");this.mon(this.el,{scope:this,mousedown:this.onMouseDown,keydown:this.onKeyDown});this.focusEl.swallowEvent("click",true);this.tracker=new Ext.dd.DragTracker({onBeforeStart:this.onBeforeDragStart.createDelegate(this),onStart:this.onDragStart.createDelegate(this),onDrag:this.onDrag.createDelegate(this),onEnd:this.onDragEnd.createDelegate(this),tolerance:3,autoStart:300});this.tracker.initEl(this.thumb);this.on("beforedestroy",this.tracker.destroy,this.tracker)},onMouseDown:function(b){if(this.disabled){return}if(this.clickToChange&&b.target!=this.thumb.dom){var a=this.innerEl.translatePoints(b.getXY());this.onClickChange(a)}this.focus()},onClickChange:function(a){if(a.top>this.clickRange[0]&&a.top<this.clickRange[1]){this.setValue(Ext.util.Format.round(this.reverseValue(a.left),this.decimalPrecision),undefined,true)}},onKeyDown:function(b){if(this.disabled){b.preventDefault();return}var a=b.getKey();switch(a){case b.UP:case b.RIGHT:b.stopEvent();if(b.ctrlKey){this.setValue(this.maxValue,undefined,true)}else{this.setValue(this.value+this.keyIncrement,undefined,true)}break;case b.DOWN:case b.LEFT:b.stopEvent();if(b.ctrlKey){this.setValue(this.minValue,undefined,true)}else{this.setValue(this.value-this.keyIncrement,undefined,true)}break;default:b.preventDefault()}},doSnap:function(b){if(!this.increment||this.increment==1||!b){return b}var d=b,c=this.increment;var a=b%c;if(a!=0){d-=a;if(a*2>c){d+=c}else{if(a*2<-c){d-=c}}}return d.constrain(this.minValue,this.maxValue)},afterRender:function(){Ext.Slider.superclass.afterRender.apply(this,arguments);if(this.value!==undefined){var a=this.normalizeValue(this.value);if(a!==this.value){delete this.value;this.setValue(a,false)}else{this.moveThumb(this.translateValue(a),false)}}},getRatio:function(){var a=this.innerEl.getWidth();var b=this.maxValue-this.minValue;return b==0?a:(a/b)},normalizeValue:function(a){a=this.doSnap(a);a=Ext.util.Format.round(a,this.decimalPrecision);a=a.constrain(this.minValue,this.maxValue);return a},setValue:function(b,a,c){b=this.normalizeValue(b);if(b!==this.value&&this.fireEvent("beforechange",this,b,this.value)!==false){this.value=b;this.moveThumb(this.translateValue(b),a!==false);this.fireEvent("change",this,b);if(c){this.fireEvent("changecomplete",this,b)}}},translateValue:function(a){var b=this.getRatio();return(a*b)-(this.minValue*b)-this.halfThumb},reverseValue:function(b){var a=this.getRatio();return(b+this.halfThumb+(this.minValue*a))/a},moveThumb:function(b,a){if(!a||this.animate===false){this.thumb.setLeft(b)}else{this.thumb.shift({left:b,stopFx:true,duration:0.35})}},focus:function(){this.focusEl.focus(10)},onBeforeDragStart:function(a){return !this.disabled},onDragStart:function(a){this.thumb.addClass("x-slider-thumb-drag");this.dragging=true;this.dragStartValue=this.value;this.fireEvent("dragstart",this,a)},onDrag:function(a){var b=this.innerEl.translatePoints(this.tracker.getXY());this.setValue(Ext.util.Format.round(this.reverseValue(b.left),this.decimalPrecision),false);this.fireEvent("drag",this,a)},onDragEnd:function(a){this.thumb.removeClass("x-slider-thumb-drag");this.dragging=false;this.fireEvent("dragend",this,a);if(this.dragStartValue!=this.value){this.fireEvent("changecomplete",this,this.value)}},onResize:function(a,b){this.innerEl.setWidth(a-(this.el.getPadding("l")+this.endEl.getPadding("r")));this.syncThumb()},onDisable:function(){Ext.Slider.superclass.onDisable.call(this);this.thumb.addClass(this.disabledClass);if(Ext.isIE){var a=this.thumb.getXY();this.thumb.hide();this.innerEl.addClass(this.disabledClass).dom.disabled=true;if(!this.thumbHolder){this.thumbHolder=this.endEl.createChild({cls:"x-slider-thumb "+this.disabledClass})}this.thumbHolder.show().setXY(a)}},onEnable:function(){Ext.Slider.superclass.onEnable.call(this);this.thumb.removeClass(this.disabledClass);if(Ext.isIE){this.innerEl.removeClass(this.disabledClass).dom.disabled=false;if(this.thumbHolder){this.thumbHolder.hide()}this.thumb.show();this.syncThumb()}},syncThumb:function(){if(this.rendered){this.moveThumb(this.translateValue(this.value))}},getValue:function(){return this.value}});Ext.reg("slider",Ext.Slider);Ext.Slider.Vertical={onResize:function(a,b){this.innerEl.setHeight(b-(this.el.getPadding("t")+this.endEl.getPadding("b")));this.syncThumb()},getRatio:function(){var b=this.innerEl.getHeight();var a=this.maxValue-this.minValue;return b/a},moveThumb:function(b,a){if(!a||this.animate===false){this.thumb.setBottom(b)}else{this.thumb.shift({bottom:b,stopFx:true,duration:0.35})}},onDrag:function(b){var c=this.innerEl.translatePoints(this.tracker.getXY());var a=this.innerEl.getHeight()-c.top;this.setValue(this.minValue+Ext.util.Format.round(a/this.getRatio(),this.decimalPrecision),false);this.fireEvent("drag",this,b)},onClickChange:function(b){if(b.left>this.clickRange[0]&&b.left<this.clickRange[1]){var a=this.innerEl.getHeight()-b.top;this.setValue(this.minValue+Ext.util.Format.round(a/this.getRatio(),this.decimalPrecision),undefined,true)}}};Ext.ProgressBar=Ext.extend(Ext.BoxComponent,{baseCls:"x-progress",animate:false,waitTimer:null,initComponent:function(){Ext.ProgressBar.superclass.initComponent.call(this);this.addEvents("update")},onRender:function(d,a){var c=new Ext.Template('<div class="{cls}-wrap">','<div class="{cls}-inner">','<div class="{cls}-bar">','<div class="{cls}-text">',"<div> </div>","</div>","</div>",'<div class="{cls}-text {cls}-text-back">',"<div> </div>","</div>","</div>","</div>");this.el=a?c.insertBefore(a,{cls:this.baseCls},true):c.append(d,{cls:this.baseCls},true);if(this.id){this.el.dom.id=this.id}var b=this.el.dom.firstChild;this.progressBar=Ext.get(b.firstChild);if(this.textEl){this.textEl=Ext.get(this.textEl);delete this.textTopEl}else{this.textTopEl=Ext.get(this.progressBar.dom.firstChild);var e=Ext.get(b.childNodes[1]);this.textTopEl.setStyle("z-index",99).addClass("x-hidden");this.textEl=new Ext.CompositeElement([this.textTopEl.dom.firstChild,e.dom.firstChild]);this.textEl.setWidth(b.offsetWidth)}this.progressBar.setHeight(b.offsetHeight)},afterRender:function(){Ext.ProgressBar.superclass.afterRender.call(this);if(this.value){this.updateProgress(this.value,this.text)}else{this.updateText(this.text)}},updateProgress:function(c,d,b){this.value=c||0;if(d){this.updateText(d)}if(this.rendered){var a=Math.floor(c*this.el.dom.firstChild.offsetWidth);this.progressBar.setWidth(a,b===true||(b!==false&&this.animate));if(this.textTopEl){this.textTopEl.removeClass("x-hidden").setWidth(a)}}this.fireEvent("update",this,c,d);return this},wait:function(b){if(!this.waitTimer){var a=this;b=b||{};this.updateText(b.text);this.waitTimer=Ext.TaskMgr.start({run:function(c){var d=b.increment||10;this.updateProgress(((((c+d)%d)+1)*(100/d))*0.01,null,b.animate)},interval:b.interval||1000,duration:b.duration,onStop:function(){if(b.fn){b.fn.apply(b.scope||this)}this.reset()},scope:a})}return this},isWaiting:function(){return this.waitTimer!==null},updateText:function(a){this.text=a||" ";if(this.rendered){this.textEl.update(this.text)}return this},syncProgressBar:function(){if(this.value){this.updateProgress(this.value,this.text)}return this},setSize:function(a,c){Ext.ProgressBar.superclass.setSize.call(this,a,c);if(this.textTopEl){var b=this.el.dom.firstChild;this.textEl.setSize(b.offsetWidth,b.offsetHeight)}this.syncProgressBar();return this},reset:function(a){this.updateProgress(0);if(this.textTopEl){this.textTopEl.addClass("x-hidden")}if(this.waitTimer){this.waitTimer.onStop=null;Ext.TaskMgr.stop(this.waitTimer);this.waitTimer=null}if(a===true){this.hide()}return this}});Ext.reg("progress",Ext.ProgressBar);
|
@@ -0,0 +1,3853 @@
|
|
1
|
+
/*!
|
2
|
+
* Ext JS Library 3.0.0
|
3
|
+
* Copyright(c) 2006-2009 Ext JS, LLC
|
4
|
+
* licensing@extjs.com
|
5
|
+
* http://www.extjs.com/license
|
6
|
+
*/
|
7
|
+
/**
|
8
|
+
* @class Ext.data.Api
|
9
|
+
* @extends Object
|
10
|
+
* Ext.data.Api is a singleton designed to manage the data API including methods
|
11
|
+
* for validating a developer's DataProxy API. Defines variables for CRUD actions
|
12
|
+
* create, read, update and destroy in addition to a mapping of RESTful HTTP methods
|
13
|
+
* GET, POST, PUT and DELETE to CRUD actions.
|
14
|
+
* @singleton
|
15
|
+
*/
|
16
|
+
Ext.data.Api = (function() {
|
17
|
+
|
18
|
+
// private validActions. validActions is essentially an inverted hash of Ext.data.Api.actions, where value becomes the key.
|
19
|
+
// Some methods in this singleton (e.g.: getActions, getVerb) will loop through actions with the code <code>for (var verb in this.actions)</code>
|
20
|
+
// For efficiency, some methods will first check this hash for a match. Those methods which do acces validActions will cache their result here.
|
21
|
+
// We cannot pre-define this hash since the developer may over-ride the actions at runtime.
|
22
|
+
var validActions = {};
|
23
|
+
|
24
|
+
return {
|
25
|
+
/**
|
26
|
+
* Defined actions corresponding to remote actions:
|
27
|
+
* <pre><code>
|
28
|
+
actions: {
|
29
|
+
create : 'create', // Text representing the remote-action to create records on server.
|
30
|
+
read : 'read', // Text representing the remote-action to read/load data from server.
|
31
|
+
update : 'update', // Text representing the remote-action to update records on server.
|
32
|
+
destroy : 'destroy' // Text representing the remote-action to destroy records on server.
|
33
|
+
}
|
34
|
+
* </code></pre>
|
35
|
+
* @property actions
|
36
|
+
* @type Object
|
37
|
+
*/
|
38
|
+
actions : {
|
39
|
+
create : 'create',
|
40
|
+
read : 'read',
|
41
|
+
update : 'update',
|
42
|
+
destroy : 'destroy'
|
43
|
+
},
|
44
|
+
|
45
|
+
/**
|
46
|
+
* Defined {CRUD action}:{HTTP method} pairs to associate HTTP methods with the
|
47
|
+
* corresponding actions for {@link Ext.data.DataProxy#restful RESTful proxies}.
|
48
|
+
* Defaults to:
|
49
|
+
* <pre><code>
|
50
|
+
restActions : {
|
51
|
+
create : 'POST',
|
52
|
+
read : 'GET',
|
53
|
+
update : 'PUT',
|
54
|
+
destroy : 'DELETE'
|
55
|
+
},
|
56
|
+
* </code></pre>
|
57
|
+
*/
|
58
|
+
restActions : {
|
59
|
+
create : 'POST',
|
60
|
+
read : 'GET',
|
61
|
+
update : 'PUT',
|
62
|
+
destroy : 'DELETE'
|
63
|
+
},
|
64
|
+
|
65
|
+
/**
|
66
|
+
* Returns true if supplied action-name is a valid API action defined in <code>{@link #actions}</code> constants
|
67
|
+
* @param {String} action
|
68
|
+
* @param {String[]}(Optional) List of available CRUD actions. Pass in list when executing multiple times for efficiency.
|
69
|
+
* @return {Boolean}
|
70
|
+
*/
|
71
|
+
isAction : function(action) {
|
72
|
+
return (Ext.data.Api.actions[action]) ? true : false;
|
73
|
+
},
|
74
|
+
|
75
|
+
/**
|
76
|
+
* Returns the actual CRUD action KEY "create", "read", "update" or "destroy" from the supplied action-name. This method is used internally and shouldn't generally
|
77
|
+
* need to be used directly. The key/value pair of Ext.data.Api.actions will often be identical but this is not necessarily true. A developer can override this naming
|
78
|
+
* convention if desired. However, the framework internally calls methods based upon the KEY so a way of retreiving the the words "create", "read", "update" and "destroy" is
|
79
|
+
* required. This method will cache discovered KEYS into the private validActions hash.
|
80
|
+
* @param {String} name The runtime name of the action.
|
81
|
+
* @return {String||null} returns the action-key, or verb of the user-action or null if invalid.
|
82
|
+
* @nodoc
|
83
|
+
*/
|
84
|
+
getVerb : function(name) {
|
85
|
+
if (validActions[name]) {
|
86
|
+
return validActions[name]; // <-- found in cache. return immediately.
|
87
|
+
}
|
88
|
+
for (var verb in this.actions) {
|
89
|
+
if (this.actions[verb] === name) {
|
90
|
+
validActions[name] = verb;
|
91
|
+
break;
|
92
|
+
}
|
93
|
+
}
|
94
|
+
return (validActions[name] !== undefined) ? validActions[name] : null;
|
95
|
+
},
|
96
|
+
|
97
|
+
/**
|
98
|
+
* Returns true if the supplied API is valid; that is, check that all keys match defined actions
|
99
|
+
* otherwise returns an array of mistakes.
|
100
|
+
* @return {String[]||true}
|
101
|
+
*/
|
102
|
+
isValid : function(api){
|
103
|
+
var invalid = [];
|
104
|
+
var crud = this.actions; // <-- cache a copy of the actions.
|
105
|
+
for (var action in api) {
|
106
|
+
if (!(action in crud)) {
|
107
|
+
invalid.push(action);
|
108
|
+
}
|
109
|
+
}
|
110
|
+
return (!invalid.length) ? true : invalid;
|
111
|
+
},
|
112
|
+
|
113
|
+
/**
|
114
|
+
* Returns true if the supplied verb upon the supplied proxy points to a unique url in that none of the other api-actions
|
115
|
+
* point to the same url. The question is important for deciding whether to insert the "xaction" HTTP parameter within an
|
116
|
+
* Ajax request. This method is used internally and shouldn't generally need to be called directly.
|
117
|
+
* @param {Ext.data.DataProxy} proxy
|
118
|
+
* @param {String} verb
|
119
|
+
* @return {Boolean}
|
120
|
+
*/
|
121
|
+
hasUniqueUrl : function(proxy, verb) {
|
122
|
+
var url = (proxy.api[verb]) ? proxy.api[verb].url : null;
|
123
|
+
var unique = true;
|
124
|
+
for (var action in proxy.api) {
|
125
|
+
if ((unique = (action === verb) ? true : (proxy.api[action].url != url) ? true : false) === false) {
|
126
|
+
break;
|
127
|
+
}
|
128
|
+
}
|
129
|
+
return unique;
|
130
|
+
},
|
131
|
+
|
132
|
+
/**
|
133
|
+
* This method is used internally by <tt>{@link Ext.data.DataProxy DataProxy}</tt> and should not generally need to be used directly.
|
134
|
+
* Each action of a DataProxy api can be initially defined as either a String or an Object. When specified as an object,
|
135
|
+
* one can explicitly define the HTTP method (GET|POST) to use for each CRUD action. This method will prepare the supplied API, setting
|
136
|
+
* each action to the Object form. If your API-actions do not explicitly define the HTTP method, the "method" configuration-parameter will
|
137
|
+
* be used. If the method configuration parameter is not specified, POST will be used.
|
138
|
+
<pre><code>
|
139
|
+
new Ext.data.HttpProxy({
|
140
|
+
method: "POST", // <-- default HTTP method when not specified.
|
141
|
+
api: {
|
142
|
+
create: 'create.php',
|
143
|
+
load: 'read.php',
|
144
|
+
save: 'save.php',
|
145
|
+
destroy: 'destroy.php'
|
146
|
+
}
|
147
|
+
});
|
148
|
+
|
149
|
+
// Alternatively, one can use the object-form to specify the API
|
150
|
+
new Ext.data.HttpProxy({
|
151
|
+
api: {
|
152
|
+
load: {url: 'read.php', method: 'GET'},
|
153
|
+
create: 'create.php',
|
154
|
+
destroy: 'destroy.php',
|
155
|
+
save: 'update.php'
|
156
|
+
}
|
157
|
+
});
|
158
|
+
</code></pre>
|
159
|
+
*
|
160
|
+
* @param {Ext.data.DataProxy} proxy
|
161
|
+
*/
|
162
|
+
prepare : function(proxy) {
|
163
|
+
if (!proxy.api) {
|
164
|
+
proxy.api = {}; // <-- No api? create a blank one.
|
165
|
+
}
|
166
|
+
for (var verb in this.actions) {
|
167
|
+
var action = this.actions[verb];
|
168
|
+
proxy.api[action] = proxy.api[action] || proxy.url || proxy.directFn;
|
169
|
+
if (typeof(proxy.api[action]) == 'string') {
|
170
|
+
proxy.api[action] = {
|
171
|
+
url: proxy.api[action]
|
172
|
+
};
|
173
|
+
}
|
174
|
+
}
|
175
|
+
},
|
176
|
+
|
177
|
+
/**
|
178
|
+
* Prepares a supplied Proxy to be RESTful. Sets the HTTP method for each api-action to be one of
|
179
|
+
* GET, POST, PUT, DELETE according to the defined {@link #restActions}.
|
180
|
+
* @param {Ext.data.DataProxy} proxy
|
181
|
+
*/
|
182
|
+
restify : function(proxy) {
|
183
|
+
proxy.restful = true;
|
184
|
+
for (var verb in this.restActions) {
|
185
|
+
proxy.api[this.actions[verb]].method = this.restActions[verb];
|
186
|
+
}
|
187
|
+
}
|
188
|
+
};
|
189
|
+
})();
|
190
|
+
|
191
|
+
/**
|
192
|
+
* @class Ext.data.Api.Error
|
193
|
+
* @extends Ext.Error
|
194
|
+
* Error class for Ext.data.Api errors
|
195
|
+
*/
|
196
|
+
Ext.data.Api.Error = Ext.extend(Ext.Error, {
|
197
|
+
constructor : function(message, arg) {
|
198
|
+
this.arg = arg;
|
199
|
+
Ext.Error.call(this, message);
|
200
|
+
},
|
201
|
+
name: 'Ext.data.Api'
|
202
|
+
});
|
203
|
+
Ext.apply(Ext.data.Api.Error.prototype, {
|
204
|
+
lang: {
|
205
|
+
'action-url-undefined': 'No fallback url defined for this action. When defining a DataProxy api, please be sure to define an url for each CRUD action in Ext.data.Api.actions or define a default url in addition to your api-configuration.',
|
206
|
+
'invalid': 'received an invalid API-configuration. Please ensure your proxy API-configuration contains only the actions defined in Ext.data.Api.actions',
|
207
|
+
'invalid-url': 'Invalid url. Please review your proxy configuration.',
|
208
|
+
'execute': 'Attempted to execute an unknown action. Valid API actions are defined in Ext.data.Api.actions"'
|
209
|
+
}
|
210
|
+
});
|
211
|
+
|
212
|
+
/**
|
213
|
+
* @class Ext.data.SortTypes
|
214
|
+
* @singleton
|
215
|
+
* Defines the default sorting (casting?) comparison functions used when sorting data.
|
216
|
+
*/
|
217
|
+
Ext.data.SortTypes = {
|
218
|
+
/**
|
219
|
+
* Default sort that does nothing
|
220
|
+
* @param {Mixed} s The value being converted
|
221
|
+
* @return {Mixed} The comparison value
|
222
|
+
*/
|
223
|
+
none : function(s){
|
224
|
+
return s;
|
225
|
+
},
|
226
|
+
|
227
|
+
/**
|
228
|
+
* The regular expression used to strip tags
|
229
|
+
* @type {RegExp}
|
230
|
+
* @property
|
231
|
+
*/
|
232
|
+
stripTagsRE : /<\/?[^>]+>/gi,
|
233
|
+
|
234
|
+
/**
|
235
|
+
* Strips all HTML tags to sort on text only
|
236
|
+
* @param {Mixed} s The value being converted
|
237
|
+
* @return {String} The comparison value
|
238
|
+
*/
|
239
|
+
asText : function(s){
|
240
|
+
return String(s).replace(this.stripTagsRE, "");
|
241
|
+
},
|
242
|
+
|
243
|
+
/**
|
244
|
+
* Strips all HTML tags to sort on text only - Case insensitive
|
245
|
+
* @param {Mixed} s The value being converted
|
246
|
+
* @return {String} The comparison value
|
247
|
+
*/
|
248
|
+
asUCText : function(s){
|
249
|
+
return String(s).toUpperCase().replace(this.stripTagsRE, "");
|
250
|
+
},
|
251
|
+
|
252
|
+
/**
|
253
|
+
* Case insensitive string
|
254
|
+
* @param {Mixed} s The value being converted
|
255
|
+
* @return {String} The comparison value
|
256
|
+
*/
|
257
|
+
asUCString : function(s) {
|
258
|
+
return String(s).toUpperCase();
|
259
|
+
},
|
260
|
+
|
261
|
+
/**
|
262
|
+
* Date sorting
|
263
|
+
* @param {Mixed} s The value being converted
|
264
|
+
* @return {Number} The comparison value
|
265
|
+
*/
|
266
|
+
asDate : function(s) {
|
267
|
+
if(!s){
|
268
|
+
return 0;
|
269
|
+
}
|
270
|
+
if(Ext.isDate(s)){
|
271
|
+
return s.getTime();
|
272
|
+
}
|
273
|
+
return Date.parse(String(s));
|
274
|
+
},
|
275
|
+
|
276
|
+
/**
|
277
|
+
* Float sorting
|
278
|
+
* @param {Mixed} s The value being converted
|
279
|
+
* @return {Float} The comparison value
|
280
|
+
*/
|
281
|
+
asFloat : function(s) {
|
282
|
+
var val = parseFloat(String(s).replace(/,/g, ""));
|
283
|
+
return isNaN(val) ? 0 : val;
|
284
|
+
},
|
285
|
+
|
286
|
+
/**
|
287
|
+
* Integer sorting
|
288
|
+
* @param {Mixed} s The value being converted
|
289
|
+
* @return {Number} The comparison value
|
290
|
+
*/
|
291
|
+
asInt : function(s) {
|
292
|
+
var val = parseInt(String(s).replace(/,/g, ""), 10);
|
293
|
+
return isNaN(val) ? 0 : val;
|
294
|
+
}
|
295
|
+
};/**
|
296
|
+
* @class Ext.data.Record
|
297
|
+
* <p>Instances of this class encapsulate both Record <em>definition</em> information, and Record
|
298
|
+
* <em>value</em> information for use in {@link Ext.data.Store} objects, or any code which needs
|
299
|
+
* to access Records cached in an {@link Ext.data.Store} object.</p>
|
300
|
+
* <p>Constructors for this class are generated by passing an Array of field definition objects to {@link #create}.
|
301
|
+
* Instances are usually only created by {@link Ext.data.Reader} implementations when processing unformatted data
|
302
|
+
* objects.</p>
|
303
|
+
* <p>Note that an instance of a Record class may only belong to one {@link Ext.data.Store Store} at a time.
|
304
|
+
* In order to copy data from one Store to another, use the {@link #copy} method to create an exact
|
305
|
+
* copy of the Record, and insert the new instance into the other Store.</p>
|
306
|
+
* <p>When serializing a Record for submission to the server, be aware that it contains many private
|
307
|
+
* properties, and also a reference to its owning Store which in turn holds references to its Records.
|
308
|
+
* This means that a whole Record may not be encoded using {@link Ext.util.JSON.encode}. Instead, use the
|
309
|
+
* <code>{@link #data}</code> and <code>{@link #id}</code> properties.</p>
|
310
|
+
* <p>Record objects generated by this constructor inherit all the methods of Ext.data.Record listed below.</p>
|
311
|
+
* @constructor
|
312
|
+
* This constructor should not be used to create Record objects. Instead, use {@link #create} to
|
313
|
+
* generate a subclass of Ext.data.Record configured with information about its constituent fields.
|
314
|
+
* @param {Object} data (Optional) An object, the properties of which provide values for the new Record's
|
315
|
+
* fields. If not specified the <code>{@link Ext.data.Field#defaultValue defaultValue}</code>
|
316
|
+
* for each field will be assigned.
|
317
|
+
* @param {Object} id (Optional) The id of the Record. This id should be unique, and is used by the
|
318
|
+
* {@link Ext.data.Store} object which owns the Record to index its collection of Records. If
|
319
|
+
* an <code>id</code> is not specified a <b><code>{@link #phantom}</code></b> Record will be created
|
320
|
+
* with an {@link #Record.id automatically generated id}.
|
321
|
+
*/
|
322
|
+
Ext.data.Record = function(data, id){
|
323
|
+
// if no id, call the auto id method
|
324
|
+
this.id = (id || id === 0) ? id : Ext.data.Record.id(this);
|
325
|
+
this.data = data || {};
|
326
|
+
};
|
327
|
+
|
328
|
+
/**
|
329
|
+
* Generate a constructor for a specific Record layout.
|
330
|
+
* @param {Array} o An Array of <b>{@link Ext.data.Field Field}</b> definition objects.
|
331
|
+
* The constructor generated by this method may be used to create new Record instances. The data
|
332
|
+
* object must contain properties named after the {@link Ext.data.Field field}
|
333
|
+
* <b><tt>{@link Ext.data.Field#name}s</tt></b>. Example usage:<pre><code>
|
334
|
+
// create a Record constructor from a description of the fields
|
335
|
+
var TopicRecord = Ext.data.Record.create([ // creates a subclass of Ext.data.Record
|
336
|
+
{{@link Ext.data.Field#name name}: 'title', {@link Ext.data.Field#mapping mapping}: 'topic_title'},
|
337
|
+
{name: 'author', mapping: 'username', allowBlank: false},
|
338
|
+
{name: 'totalPosts', mapping: 'topic_replies', type: 'int'},
|
339
|
+
{name: 'lastPost', mapping: 'post_time', type: 'date'},
|
340
|
+
{name: 'lastPoster', mapping: 'user2'},
|
341
|
+
{name: 'excerpt', mapping: 'post_text', allowBlank: false},
|
342
|
+
// In the simplest case, if no properties other than <tt>name</tt> are required,
|
343
|
+
// a field definition may consist of just a String for the field name.
|
344
|
+
'signature'
|
345
|
+
]);
|
346
|
+
|
347
|
+
// create Record instance
|
348
|
+
var myNewRecord = new TopicRecord(
|
349
|
+
{
|
350
|
+
title: 'Do my job please',
|
351
|
+
author: 'noobie',
|
352
|
+
totalPosts: 1,
|
353
|
+
lastPost: new Date(),
|
354
|
+
lastPoster: 'Animal',
|
355
|
+
excerpt: 'No way dude!',
|
356
|
+
signature: ''
|
357
|
+
},
|
358
|
+
id // optionally specify the id of the record otherwise {@link #Record.id one is auto-assigned}
|
359
|
+
);
|
360
|
+
myStore.{@link Ext.data.Store#add add}(myNewRecord);
|
361
|
+
</code></pre>
|
362
|
+
* @method create
|
363
|
+
* @return {function} A constructor which is used to create new Records according
|
364
|
+
* to the definition. The constructor has the same signature as {@link #Ext.data.Record}.
|
365
|
+
* @static
|
366
|
+
*/
|
367
|
+
Ext.data.Record.create = function(o){
|
368
|
+
var f = Ext.extend(Ext.data.Record, {});
|
369
|
+
var p = f.prototype;
|
370
|
+
p.fields = new Ext.util.MixedCollection(false, function(field){
|
371
|
+
return field.name;
|
372
|
+
});
|
373
|
+
for(var i = 0, len = o.length; i < len; i++){
|
374
|
+
p.fields.add(new Ext.data.Field(o[i]));
|
375
|
+
}
|
376
|
+
f.getField = function(name){
|
377
|
+
return p.fields.get(name);
|
378
|
+
};
|
379
|
+
return f;
|
380
|
+
};
|
381
|
+
|
382
|
+
Ext.data.Record.PREFIX = 'ext-record';
|
383
|
+
Ext.data.Record.AUTO_ID = 1;
|
384
|
+
Ext.data.Record.EDIT = 'edit';
|
385
|
+
Ext.data.Record.REJECT = 'reject';
|
386
|
+
Ext.data.Record.COMMIT = 'commit';
|
387
|
+
|
388
|
+
|
389
|
+
/**
|
390
|
+
* Generates a sequential id. This method is typically called when a record is {@link #create}d
|
391
|
+
* and {@link #Record no id has been specified}. The returned id takes the form:
|
392
|
+
* <tt>{PREFIX}-{AUTO_ID}</tt>.<div class="mdetail-params"><ul>
|
393
|
+
* <li><b><tt>PREFIX</tt></b> : String<p class="sub-desc"><tt>Ext.data.Record.PREFIX</tt>
|
394
|
+
* (defaults to <tt>'ext-record'</tt>)</p></li>
|
395
|
+
* <li><b><tt>AUTO_ID</tt></b> : String<p class="sub-desc"><tt>Ext.data.Record.AUTO_ID</tt>
|
396
|
+
* (defaults to <tt>1</tt> initially)</p></li>
|
397
|
+
* </ul></div>
|
398
|
+
* @param {Record} rec The record being created. The record does not exist, it's a {@link #phantom}.
|
399
|
+
* @return {String} auto-generated string id, <tt>"ext-record-i++'</tt>;
|
400
|
+
*/
|
401
|
+
Ext.data.Record.id = function(rec) {
|
402
|
+
rec.phantom = true;
|
403
|
+
return [Ext.data.Record.PREFIX, '-', Ext.data.Record.AUTO_ID++].join('');
|
404
|
+
};
|
405
|
+
|
406
|
+
Ext.data.Record.prototype = {
|
407
|
+
/**
|
408
|
+
* <p><b>This property is stored in the Record definition's <u>prototype</u></b></p>
|
409
|
+
* A MixedCollection containing the defined {@link Ext.data.Field Field}s for this Record. Read-only.
|
410
|
+
* @property fields
|
411
|
+
* @type Ext.util.MixedCollection
|
412
|
+
*/
|
413
|
+
/**
|
414
|
+
* An object hash representing the data for this Record. Every field name in the Record definition
|
415
|
+
* is represented by a property of that name in this object. Note that unless you specified a field
|
416
|
+
* with {@link Ext.data.Field#name name} "id" in the Record definition, this will <b>not</b> contain
|
417
|
+
* an <tt>id</tt> property.
|
418
|
+
* @property data
|
419
|
+
* @type {Object}
|
420
|
+
*/
|
421
|
+
/**
|
422
|
+
* The unique ID of the Record {@link #Record as specified at construction time}.
|
423
|
+
* @property id
|
424
|
+
* @type {Object}
|
425
|
+
*/
|
426
|
+
/**
|
427
|
+
* Readonly flag - true if this Record has been modified.
|
428
|
+
* @type Boolean
|
429
|
+
*/
|
430
|
+
dirty : false,
|
431
|
+
editing : false,
|
432
|
+
error: null,
|
433
|
+
/**
|
434
|
+
* This object contains a key and value storing the original values of all modified
|
435
|
+
* fields or is null if no fields have been modified.
|
436
|
+
* @property modified
|
437
|
+
* @type {Object}
|
438
|
+
*/
|
439
|
+
modified: null,
|
440
|
+
/**
|
441
|
+
* <tt>false</tt> when the record does not yet exist in a server-side database (see
|
442
|
+
* {@link #markDirty}). Any record which has a real database pk set as its id property
|
443
|
+
* is NOT a phantom -- it's real.
|
444
|
+
* @property phantom
|
445
|
+
* @type {Boolean}
|
446
|
+
*/
|
447
|
+
phantom : false,
|
448
|
+
|
449
|
+
// private
|
450
|
+
join : function(store){
|
451
|
+
/**
|
452
|
+
* The {@link Ext.data.Store} to which this Record belongs.
|
453
|
+
* @property store
|
454
|
+
* @type {Ext.data.Store}
|
455
|
+
*/
|
456
|
+
this.store = store;
|
457
|
+
},
|
458
|
+
|
459
|
+
/**
|
460
|
+
* Set the {@link Ext.data.Field#name named field} to the specified value. For example:
|
461
|
+
* <pre><code>
|
462
|
+
// record has a field named 'firstname'
|
463
|
+
var Employee = Ext.data.Record.{@link #create}([
|
464
|
+
{name: 'firstname'},
|
465
|
+
...
|
466
|
+
]);
|
467
|
+
|
468
|
+
// update the 2nd record in the store:
|
469
|
+
var rec = myStore.{@link Ext.data.Store#getAt getAt}(1);
|
470
|
+
|
471
|
+
// set the value (shows dirty flag):
|
472
|
+
rec.set('firstname', 'Betty');
|
473
|
+
|
474
|
+
// commit the change (removes dirty flag):
|
475
|
+
rec.{@link #commit}();
|
476
|
+
|
477
|
+
// update the record in the store, bypass setting dirty flag,
|
478
|
+
// and do not store the change in the {@link Ext.data.Store#getModifiedRecords modified records}
|
479
|
+
rec.{@link #data}['firstname'] = 'Wilma'); // updates record, but not the view
|
480
|
+
rec.{@link #commit}(); // updates the view
|
481
|
+
* </code></pre>
|
482
|
+
* <b>Notes</b>:<div class="mdetail-params"><ul>
|
483
|
+
* <li>If the store has a writer and <code>autoSave=true</code>, each set()
|
484
|
+
* will execute an XHR to the server.</li>
|
485
|
+
* <li>Use <code>{@link #beginEdit}</code> to prevent the store's <code>update</code>
|
486
|
+
* event firing while using set().</li>
|
487
|
+
* <li>Use <code>{@link #endEdit}</code> to have the store's <code>update</code>
|
488
|
+
* event fire.</li>
|
489
|
+
* </ul></div>
|
490
|
+
* @param {String} name The {@link Ext.data.Field#name name of the field} to set.
|
491
|
+
* @param {Object} value The value to set the field to.
|
492
|
+
*/
|
493
|
+
set : function(name, value){
|
494
|
+
var isObj = (typeof value === 'object');
|
495
|
+
if(!isObj && String(this.data[name]) === String(value)){
|
496
|
+
return;
|
497
|
+
} else if (isObj && Ext.encode(this.data[name]) === Ext.encode(value)) {
|
498
|
+
return;
|
499
|
+
}
|
500
|
+
this.dirty = true;
|
501
|
+
if(!this.modified){
|
502
|
+
this.modified = {};
|
503
|
+
}
|
504
|
+
if(typeof this.modified[name] == 'undefined'){
|
505
|
+
this.modified[name] = this.data[name];
|
506
|
+
}
|
507
|
+
this.data[name] = value;
|
508
|
+
if(!this.editing){
|
509
|
+
this.afterEdit();
|
510
|
+
}
|
511
|
+
},
|
512
|
+
|
513
|
+
// private
|
514
|
+
afterEdit: function(){
|
515
|
+
if(this.store){
|
516
|
+
this.store.afterEdit(this);
|
517
|
+
}
|
518
|
+
},
|
519
|
+
|
520
|
+
// private
|
521
|
+
afterReject: function(){
|
522
|
+
if(this.store){
|
523
|
+
this.store.afterReject(this);
|
524
|
+
}
|
525
|
+
},
|
526
|
+
|
527
|
+
// private
|
528
|
+
afterCommit: function(){
|
529
|
+
if(this.store){
|
530
|
+
this.store.afterCommit(this);
|
531
|
+
}
|
532
|
+
},
|
533
|
+
|
534
|
+
/**
|
535
|
+
* Get the value of the {@link Ext.data.Field#name named field}.
|
536
|
+
* @param {String} name The {@link Ext.data.Field#name name of the field} to get the value of.
|
537
|
+
* @return {Object} The value of the field.
|
538
|
+
*/
|
539
|
+
get : function(name){
|
540
|
+
return this.data[name];
|
541
|
+
},
|
542
|
+
|
543
|
+
/**
|
544
|
+
* Begin an edit. While in edit mode, no events (e.g.. the <code>update</code> event)
|
545
|
+
* are relayed to the containing store.
|
546
|
+
* See also: <code>{@link #endEdit}</code> and <code>{@link #cancelEdit}</code>.
|
547
|
+
*/
|
548
|
+
beginEdit : function(){
|
549
|
+
this.editing = true;
|
550
|
+
this.modified = this.modified || {};
|
551
|
+
},
|
552
|
+
|
553
|
+
/**
|
554
|
+
* Cancels all changes made in the current edit operation.
|
555
|
+
*/
|
556
|
+
cancelEdit : function(){
|
557
|
+
this.editing = false;
|
558
|
+
delete this.modified;
|
559
|
+
},
|
560
|
+
|
561
|
+
/**
|
562
|
+
* End an edit. If any data was modified, the containing store is notified
|
563
|
+
* (ie, the store's <code>update</code> event will fire).
|
564
|
+
*/
|
565
|
+
endEdit : function(){
|
566
|
+
this.editing = false;
|
567
|
+
if(this.dirty){
|
568
|
+
this.afterEdit();
|
569
|
+
}
|
570
|
+
},
|
571
|
+
|
572
|
+
/**
|
573
|
+
* Usually called by the {@link Ext.data.Store} which owns the Record.
|
574
|
+
* Rejects all changes made to the Record since either creation, or the last commit operation.
|
575
|
+
* Modified fields are reverted to their original values.
|
576
|
+
* <p>Developers should subscribe to the {@link Ext.data.Store#update} event
|
577
|
+
* to have their code notified of reject operations.</p>
|
578
|
+
* @param {Boolean} silent (optional) True to skip notification of the owning
|
579
|
+
* store of the change (defaults to false)
|
580
|
+
*/
|
581
|
+
reject : function(silent){
|
582
|
+
var m = this.modified;
|
583
|
+
for(var n in m){
|
584
|
+
if(typeof m[n] != "function"){
|
585
|
+
this.data[n] = m[n];
|
586
|
+
}
|
587
|
+
}
|
588
|
+
this.dirty = false;
|
589
|
+
delete this.modified;
|
590
|
+
this.editing = false;
|
591
|
+
if(silent !== true){
|
592
|
+
this.afterReject();
|
593
|
+
}
|
594
|
+
},
|
595
|
+
|
596
|
+
/**
|
597
|
+
* Usually called by the {@link Ext.data.Store} which owns the Record.
|
598
|
+
* Commits all changes made to the Record since either creation, or the last commit operation.
|
599
|
+
* <p>Developers should subscribe to the {@link Ext.data.Store#update} event
|
600
|
+
* to have their code notified of commit operations.</p>
|
601
|
+
* @param {Boolean} silent (optional) True to skip notification of the owning
|
602
|
+
* store of the change (defaults to false)
|
603
|
+
*/
|
604
|
+
commit : function(silent){
|
605
|
+
this.dirty = false;
|
606
|
+
delete this.modified;
|
607
|
+
this.editing = false;
|
608
|
+
if(silent !== true){
|
609
|
+
this.afterCommit();
|
610
|
+
}
|
611
|
+
},
|
612
|
+
|
613
|
+
/**
|
614
|
+
* Gets a hash of only the fields that have been modified since this Record was created or commited.
|
615
|
+
* @return Object
|
616
|
+
*/
|
617
|
+
getChanges : function(){
|
618
|
+
var m = this.modified, cs = {};
|
619
|
+
for(var n in m){
|
620
|
+
if(m.hasOwnProperty(n)){
|
621
|
+
cs[n] = this.data[n];
|
622
|
+
}
|
623
|
+
}
|
624
|
+
return cs;
|
625
|
+
},
|
626
|
+
|
627
|
+
// private
|
628
|
+
hasError : function(){
|
629
|
+
return this.error !== null;
|
630
|
+
},
|
631
|
+
|
632
|
+
// private
|
633
|
+
clearError : function(){
|
634
|
+
this.error = null;
|
635
|
+
},
|
636
|
+
|
637
|
+
/**
|
638
|
+
* Creates a copy of this Record.
|
639
|
+
* @param {String} id (optional) A new Record id, defaults to {@link #Record.id autogenerating an id}.
|
640
|
+
* Note: if an <code>id</code> is not specified the copy created will be a
|
641
|
+
* <code>{@link #phantom}</code> Record.
|
642
|
+
* @return {Record}
|
643
|
+
*/
|
644
|
+
copy : function(newId) {
|
645
|
+
return new this.constructor(Ext.apply({}, this.data), newId || this.id);
|
646
|
+
},
|
647
|
+
|
648
|
+
/**
|
649
|
+
* Returns <tt>true</tt> if the passed field name has been <code>{@link #modified}</code>
|
650
|
+
* since the load or last commit.
|
651
|
+
* @param {String} fieldName {@link Ext.data.Field.{@link Ext.data.Field#name}
|
652
|
+
* @return {Boolean}
|
653
|
+
*/
|
654
|
+
isModified : function(fieldName){
|
655
|
+
return !!(this.modified && this.modified.hasOwnProperty(fieldName));
|
656
|
+
},
|
657
|
+
|
658
|
+
/**
|
659
|
+
* By default returns <tt>false</tt> if any {@link Ext.data.Field field} within the
|
660
|
+
* record configured with <tt>{@link Ext.data.Field#allowBlank} = false</tt> returns
|
661
|
+
* <tt>true</tt> from an {@link Ext}.{@link Ext#isEmpty isempty} test.
|
662
|
+
* @return {Boolean}
|
663
|
+
*/
|
664
|
+
isValid : function() {
|
665
|
+
return this.fields.find(function(f) {
|
666
|
+
return (f.allowBlank === false && Ext.isEmpty(this.data[f.name])) ? true : false;
|
667
|
+
},this) ? false : true;
|
668
|
+
},
|
669
|
+
|
670
|
+
/**
|
671
|
+
* <p>Marks this <b>Record</b> as <code>{@link #dirty}</code>. This method
|
672
|
+
* is used interally when adding <code>{@link #phantom}</code> records to a
|
673
|
+
* {@link Ext.data.Store#writer writer enabled store}.</p>
|
674
|
+
* <br><p>Marking a record <code>{@link #dirty}</code> causes the phantom to
|
675
|
+
* be returned by {@link Ext.data.Store#getModifiedRecords} where it will
|
676
|
+
* have a create action composed for it during {@link Ext.data.Store#save store save}
|
677
|
+
* operations.</p>
|
678
|
+
*/
|
679
|
+
markDirty : function(){
|
680
|
+
this.dirty = true;
|
681
|
+
if(!this.modified){
|
682
|
+
this.modified = {};
|
683
|
+
}
|
684
|
+
this.fields.each(function(f) {
|
685
|
+
this.modified[f.name] = this.data[f.name];
|
686
|
+
},this);
|
687
|
+
}
|
688
|
+
};/**
|
689
|
+
* @class Ext.StoreMgr
|
690
|
+
* @extends Ext.util.MixedCollection
|
691
|
+
* The default global group of stores.
|
692
|
+
* @singleton
|
693
|
+
*/
|
694
|
+
Ext.StoreMgr = Ext.apply(new Ext.util.MixedCollection(), {
|
695
|
+
/**
|
696
|
+
* @cfg {Object} listeners @hide
|
697
|
+
*/
|
698
|
+
|
699
|
+
/**
|
700
|
+
* Registers one or more Stores with the StoreMgr. You do not normally need to register stores
|
701
|
+
* manually. Any store initialized with a {@link Ext.data.Store#storeId} will be auto-registered.
|
702
|
+
* @param {Ext.data.Store} store1 A Store instance
|
703
|
+
* @param {Ext.data.Store} store2 (optional)
|
704
|
+
* @param {Ext.data.Store} etc... (optional)
|
705
|
+
*/
|
706
|
+
register : function(){
|
707
|
+
for(var i = 0, s; (s = arguments[i]); i++){
|
708
|
+
this.add(s);
|
709
|
+
}
|
710
|
+
},
|
711
|
+
|
712
|
+
/**
|
713
|
+
* Unregisters one or more Stores with the StoreMgr
|
714
|
+
* @param {String/Object} id1 The id of the Store, or a Store instance
|
715
|
+
* @param {String/Object} id2 (optional)
|
716
|
+
* @param {String/Object} etc... (optional)
|
717
|
+
*/
|
718
|
+
unregister : function(){
|
719
|
+
for(var i = 0, s; (s = arguments[i]); i++){
|
720
|
+
this.remove(this.lookup(s));
|
721
|
+
}
|
722
|
+
},
|
723
|
+
|
724
|
+
/**
|
725
|
+
* Gets a registered Store by id
|
726
|
+
* @param {String/Object} id The id of the Store, or a Store instance
|
727
|
+
* @return {Ext.data.Store}
|
728
|
+
*/
|
729
|
+
lookup : function(id){
|
730
|
+
if(Ext.isArray(id)){
|
731
|
+
var fields = ['field1'], expand = !Ext.isArray(id[0]);
|
732
|
+
if(!expand){
|
733
|
+
for(var i = 2, len = id[0].length; i <= len; ++i){
|
734
|
+
fields.push('field' + i);
|
735
|
+
}
|
736
|
+
}
|
737
|
+
return new Ext.data.ArrayStore({
|
738
|
+
fields: fields,
|
739
|
+
data: id,
|
740
|
+
expandData: expand,
|
741
|
+
autoDestroy: true,
|
742
|
+
autoCreated: true
|
743
|
+
|
744
|
+
});
|
745
|
+
}
|
746
|
+
return Ext.isObject(id) ? (id.events ? id : Ext.create(id, 'store')) : this.get(id);
|
747
|
+
},
|
748
|
+
|
749
|
+
// getKey implementation for MixedCollection
|
750
|
+
getKey : function(o){
|
751
|
+
return o.storeId;
|
752
|
+
}
|
753
|
+
});/**
|
754
|
+
* @class Ext.data.Store
|
755
|
+
* @extends Ext.util.Observable
|
756
|
+
* <p>The Store class encapsulates a client side cache of {@link Ext.data.Record Record}
|
757
|
+
* objects which provide input data for Components such as the {@link Ext.grid.GridPanel GridPanel},
|
758
|
+
* the {@link Ext.form.ComboBox ComboBox}, or the {@link Ext.DataView DataView}.</p>
|
759
|
+
* <p><u>Retrieving Data</u></p>
|
760
|
+
* <p>A Store object may access a data object using:<div class="mdetail-params"><ul>
|
761
|
+
* <li>{@link #proxy configured implementation} of {@link Ext.data.DataProxy DataProxy}</li>
|
762
|
+
* <li>{@link #data} to automatically pass in data</li>
|
763
|
+
* <li>{@link #loadData} to manually pass in data</li>
|
764
|
+
* </ul></div></p>
|
765
|
+
* <p><u>Reading Data</u></p>
|
766
|
+
* <p>A Store object has no inherent knowledge of the format of the data object (it could be
|
767
|
+
* an Array, XML, or JSON). A Store object uses an appropriate {@link #reader configured implementation}
|
768
|
+
* of a {@link Ext.data.DataReader DataReader} to create {@link Ext.data.Record Record} instances from the data
|
769
|
+
* object.</p>
|
770
|
+
* <p><u>Store Types</u></p>
|
771
|
+
* <p>There are several implementations of Store available which are customized for use with
|
772
|
+
* a specific DataReader implementation. Here is an example using an ArrayStore which implicitly
|
773
|
+
* creates a reader commensurate to an Array data object.</p>
|
774
|
+
* <pre><code>
|
775
|
+
var myStore = new Ext.data.ArrayStore({
|
776
|
+
fields: ['fullname', 'first'],
|
777
|
+
idIndex: 0 // id for each record will be the first element
|
778
|
+
});
|
779
|
+
* </code></pre>
|
780
|
+
* <p>For custom implementations create a basic {@link Ext.data.Store} configured as needed:</p>
|
781
|
+
* <pre><code>
|
782
|
+
// create a {@link Ext.data.Record Record} constructor:
|
783
|
+
var rt = Ext.data.Record.create([
|
784
|
+
{name: 'fullname'},
|
785
|
+
{name: 'first'}
|
786
|
+
]);
|
787
|
+
var myStore = new Ext.data.Store({
|
788
|
+
// explicitly create reader
|
789
|
+
reader: new Ext.data.ArrayReader(
|
790
|
+
{
|
791
|
+
idIndex: 0 // id for each record will be the first element
|
792
|
+
},
|
793
|
+
rt // recordType
|
794
|
+
)
|
795
|
+
});
|
796
|
+
* </code></pre>
|
797
|
+
* <p>Load some data into store (note the data object is an array which corresponds to the reader):</p>
|
798
|
+
* <pre><code>
|
799
|
+
var myData = [
|
800
|
+
[1, 'Fred Flintstone', 'Fred'], // note that id for the record is the first element
|
801
|
+
[2, 'Barney Rubble', 'Barney']
|
802
|
+
];
|
803
|
+
myStore.loadData(myData);
|
804
|
+
* </code></pre>
|
805
|
+
* <p>Records are cached and made available through accessor functions. An example of adding
|
806
|
+
* a record to the store:</p>
|
807
|
+
* <pre><code>
|
808
|
+
var defaultData = {
|
809
|
+
fullname: 'Full Name',
|
810
|
+
first: 'First Name'
|
811
|
+
};
|
812
|
+
var recId = 100; // provide unique id for the record
|
813
|
+
var r = new myStore.recordType(defaultData, ++recId); // create new record
|
814
|
+
myStore.{@link #insert}(0, r); // insert a new record into the store (also see {@link #add})
|
815
|
+
* </code></pre>
|
816
|
+
* @constructor
|
817
|
+
* Creates a new Store.
|
818
|
+
* @param {Object} config A config object containing the objects needed for the Store to access data,
|
819
|
+
* and read the data into Records.
|
820
|
+
* @xtype store
|
821
|
+
*/
|
822
|
+
Ext.data.Store = function(config){
|
823
|
+
this.data = new Ext.util.MixedCollection(false);
|
824
|
+
this.data.getKey = function(o){
|
825
|
+
return o.id;
|
826
|
+
};
|
827
|
+
/**
|
828
|
+
* See the <code>{@link #baseParams corresponding configuration option}</code>
|
829
|
+
* for a description of this property.
|
830
|
+
* To modify this property see <code>{@link #setBaseParam}</code>.
|
831
|
+
* @property
|
832
|
+
*/
|
833
|
+
this.baseParams = {};
|
834
|
+
|
835
|
+
// temporary removed-records cache
|
836
|
+
this.removed = [];
|
837
|
+
|
838
|
+
if(config && config.data){
|
839
|
+
this.inlineData = config.data;
|
840
|
+
delete config.data;
|
841
|
+
}
|
842
|
+
|
843
|
+
Ext.apply(this, config);
|
844
|
+
|
845
|
+
this.paramNames = Ext.applyIf(this.paramNames || {}, this.defaultParamNames);
|
846
|
+
|
847
|
+
if(this.url && !this.proxy){
|
848
|
+
this.proxy = new Ext.data.HttpProxy({url: this.url});
|
849
|
+
}
|
850
|
+
// If Store is RESTful, so too is the DataProxy
|
851
|
+
if (this.restful === true && this.proxy) {
|
852
|
+
// When operating RESTfully, a unique transaction is generated for each record.
|
853
|
+
this.batch = false;
|
854
|
+
Ext.data.Api.restify(this.proxy);
|
855
|
+
}
|
856
|
+
|
857
|
+
if(this.reader){ // reader passed
|
858
|
+
if(!this.recordType){
|
859
|
+
this.recordType = this.reader.recordType;
|
860
|
+
}
|
861
|
+
if(this.reader.onMetaChange){
|
862
|
+
this.reader.onMetaChange = this.onMetaChange.createDelegate(this);
|
863
|
+
}
|
864
|
+
if (this.writer) { // writer passed
|
865
|
+
this.writer.meta = this.reader.meta;
|
866
|
+
this.pruneModifiedRecords = true;
|
867
|
+
}
|
868
|
+
}
|
869
|
+
|
870
|
+
/**
|
871
|
+
* The {@link Ext.data.Record Record} constructor as supplied to (or created by) the
|
872
|
+
* {@link Ext.data.DataReader Reader}. Read-only.
|
873
|
+
* <p>If the Reader was constructed by passing in an Array of {@link Ext.data.Field} definition objects,
|
874
|
+
* instead of a Record constructor, it will implicitly create a Record constructor from that Array (see
|
875
|
+
* {@link Ext.data.Record}.{@link Ext.data.Record#create create} for additional details).</p>
|
876
|
+
* <p>This property may be used to create new Records of the type held in this Store, for example:</p><pre><code>
|
877
|
+
// create the data store
|
878
|
+
var store = new Ext.data.ArrayStore({
|
879
|
+
autoDestroy: true,
|
880
|
+
fields: [
|
881
|
+
{name: 'company'},
|
882
|
+
{name: 'price', type: 'float'},
|
883
|
+
{name: 'change', type: 'float'},
|
884
|
+
{name: 'pctChange', type: 'float'},
|
885
|
+
{name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'}
|
886
|
+
]
|
887
|
+
});
|
888
|
+
store.loadData(myData);
|
889
|
+
|
890
|
+
// create the Grid
|
891
|
+
var grid = new Ext.grid.EditorGridPanel({
|
892
|
+
store: store,
|
893
|
+
colModel: new Ext.grid.ColumnModel({
|
894
|
+
columns: [
|
895
|
+
{id:'company', header: 'Company', width: 160, dataIndex: 'company'},
|
896
|
+
{header: 'Price', renderer: 'usMoney', dataIndex: 'price'},
|
897
|
+
{header: 'Change', renderer: change, dataIndex: 'change'},
|
898
|
+
{header: '% Change', renderer: pctChange, dataIndex: 'pctChange'},
|
899
|
+
{header: 'Last Updated', width: 85,
|
900
|
+
renderer: Ext.util.Format.dateRenderer('m/d/Y'),
|
901
|
+
dataIndex: 'lastChange'}
|
902
|
+
],
|
903
|
+
defaults: {
|
904
|
+
sortable: true,
|
905
|
+
width: 75
|
906
|
+
}
|
907
|
+
}),
|
908
|
+
autoExpandColumn: 'company', // match the id specified in the column model
|
909
|
+
height:350,
|
910
|
+
width:600,
|
911
|
+
title:'Array Grid',
|
912
|
+
tbar: [{
|
913
|
+
text: 'Add Record',
|
914
|
+
handler : function(){
|
915
|
+
var defaultData = {
|
916
|
+
change: 0,
|
917
|
+
company: 'New Company',
|
918
|
+
lastChange: (new Date()).clearTime(),
|
919
|
+
pctChange: 0,
|
920
|
+
price: 10
|
921
|
+
};
|
922
|
+
var recId = 3; // provide unique id
|
923
|
+
var p = new store.recordType(defaultData, recId); // create new record
|
924
|
+
grid.stopEditing();
|
925
|
+
store.{@link #insert}(0, p); // insert a new record into the store (also see {@link #add})
|
926
|
+
grid.startEditing(0, 0);
|
927
|
+
}
|
928
|
+
}]
|
929
|
+
});
|
930
|
+
* </code></pre>
|
931
|
+
* @property recordType
|
932
|
+
* @type Function
|
933
|
+
*/
|
934
|
+
|
935
|
+
if(this.recordType){
|
936
|
+
/**
|
937
|
+
* A {@link Ext.util.MixedCollection MixedCollection} containing the defined {@link Ext.data.Field Field}s
|
938
|
+
* for the {@link Ext.data.Record Records} stored in this Store. Read-only.
|
939
|
+
* @property fields
|
940
|
+
* @type Ext.util.MixedCollection
|
941
|
+
*/
|
942
|
+
this.fields = this.recordType.prototype.fields;
|
943
|
+
}
|
944
|
+
this.modified = [];
|
945
|
+
|
946
|
+
this.addEvents(
|
947
|
+
/**
|
948
|
+
* @event datachanged
|
949
|
+
* Fires when the data cache has changed in a bulk manner (e.g., it has been sorted, filtered, etc.) and a
|
950
|
+
* widget that is using this Store as a Record cache should refresh its view.
|
951
|
+
* @param {Store} this
|
952
|
+
*/
|
953
|
+
'datachanged',
|
954
|
+
/**
|
955
|
+
* @event metachange
|
956
|
+
* Fires when this store's reader provides new metadata (fields). This is currently only supported for JsonReaders.
|
957
|
+
* @param {Store} this
|
958
|
+
* @param {Object} meta The JSON metadata
|
959
|
+
*/
|
960
|
+
'metachange',
|
961
|
+
/**
|
962
|
+
* @event add
|
963
|
+
* Fires when Records have been {@link #add}ed to the Store
|
964
|
+
* @param {Store} this
|
965
|
+
* @param {Ext.data.Record[]} records The array of Records added
|
966
|
+
* @param {Number} index The index at which the record(s) were added
|
967
|
+
*/
|
968
|
+
'add',
|
969
|
+
/**
|
970
|
+
* @event remove
|
971
|
+
* Fires when a Record has been {@link #remove}d from the Store
|
972
|
+
* @param {Store} this
|
973
|
+
* @param {Ext.data.Record} record The Record that was removed
|
974
|
+
* @param {Number} index The index at which the record was removed
|
975
|
+
*/
|
976
|
+
'remove',
|
977
|
+
/**
|
978
|
+
* @event update
|
979
|
+
* Fires when a Record has been updated
|
980
|
+
* @param {Store} this
|
981
|
+
* @param {Ext.data.Record} record The Record that was updated
|
982
|
+
* @param {String} operation The update operation being performed. Value may be one of:
|
983
|
+
* <pre><code>
|
984
|
+
Ext.data.Record.EDIT
|
985
|
+
Ext.data.Record.REJECT
|
986
|
+
Ext.data.Record.COMMIT
|
987
|
+
* </code></pre>
|
988
|
+
*/
|
989
|
+
'update',
|
990
|
+
/**
|
991
|
+
* @event clear
|
992
|
+
* Fires when the data cache has been cleared.
|
993
|
+
* @param {Store} this
|
994
|
+
*/
|
995
|
+
'clear',
|
996
|
+
/**
|
997
|
+
* @event exception
|
998
|
+
* <p>Fires if an exception occurs in the Proxy during a remote request.
|
999
|
+
* This event is relayed through the corresponding {@link Ext.data.DataProxy}.
|
1000
|
+
* See {@link Ext.data.DataProxy}.{@link Ext.data.DataProxy#exception exception}
|
1001
|
+
* for additional details.
|
1002
|
+
* @param {misc} misc See {@link Ext.data.DataProxy}.{@link Ext.data.DataProxy#exception exception}
|
1003
|
+
* for description.
|
1004
|
+
*/
|
1005
|
+
'exception',
|
1006
|
+
/**
|
1007
|
+
* @event beforeload
|
1008
|
+
* Fires before a request is made for a new data object. If the beforeload handler returns
|
1009
|
+
* <tt>false</tt> the {@link #load} action will be canceled.
|
1010
|
+
* @param {Store} this
|
1011
|
+
* @param {Object} options The loading options that were specified (see {@link #load} for details)
|
1012
|
+
*/
|
1013
|
+
'beforeload',
|
1014
|
+
/**
|
1015
|
+
* @event load
|
1016
|
+
* Fires after a new set of Records has been loaded.
|
1017
|
+
* @param {Store} this
|
1018
|
+
* @param {Ext.data.Record[]} records The Records that were loaded
|
1019
|
+
* @param {Object} options The loading options that were specified (see {@link #load} for details)
|
1020
|
+
*/
|
1021
|
+
'load',
|
1022
|
+
/**
|
1023
|
+
* @event loadexception
|
1024
|
+
* <p>This event is <b>deprecated</b> in favor of the catch-all <b><code>{@link #exception}</code></b>
|
1025
|
+
* event instead.</p>
|
1026
|
+
* <p>This event is relayed through the corresponding {@link Ext.data.DataProxy}.
|
1027
|
+
* See {@link Ext.data.DataProxy}.{@link Ext.data.DataProxy#loadexception loadexception}
|
1028
|
+
* for additional details.
|
1029
|
+
* @param {misc} misc See {@link Ext.data.DataProxy}.{@link Ext.data.DataProxy#loadexception loadexception}
|
1030
|
+
* for description.
|
1031
|
+
*/
|
1032
|
+
'loadexception',
|
1033
|
+
/**
|
1034
|
+
* @event beforewrite
|
1035
|
+
* @param {DataProxy} this
|
1036
|
+
* @param {String} action [Ext.data.Api.actions.create|update|destroy]
|
1037
|
+
* @param {Record/Array[Record]} rs
|
1038
|
+
* @param {Object} options The loading options that were specified. Edit <code>options.params</code> to add Http parameters to the request. (see {@link #save} for details)
|
1039
|
+
* @param {Object} arg The callback's arg object passed to the {@link #request} function
|
1040
|
+
*/
|
1041
|
+
'beforewrite',
|
1042
|
+
/**
|
1043
|
+
* @event write
|
1044
|
+
* Fires if the server returns 200 after an Ext.data.Api.actions CRUD action.
|
1045
|
+
* Success or failure of the action is available in the <code>result['successProperty']</code> property.
|
1046
|
+
* The server-code might set the <code>successProperty</code> to <tt>false</tt> if a database validation
|
1047
|
+
* failed, for example.
|
1048
|
+
* @param {Ext.data.Store} store
|
1049
|
+
* @param {String} action [Ext.data.Api.actions.create|update|destroy]
|
1050
|
+
* @param {Object} result The 'data' picked-out out of the response for convenience.
|
1051
|
+
* @param {Ext.Direct.Transaction} res
|
1052
|
+
* @param {Record/Record[]} rs Store's records, the subject(s) of the write-action
|
1053
|
+
*/
|
1054
|
+
'write'
|
1055
|
+
);
|
1056
|
+
|
1057
|
+
if(this.proxy){
|
1058
|
+
this.relayEvents(this.proxy, ['loadexception', 'exception']);
|
1059
|
+
}
|
1060
|
+
// With a writer set for the Store, we want to listen to add/remove events to remotely create/destroy records.
|
1061
|
+
if (this.writer) {
|
1062
|
+
this.on({
|
1063
|
+
scope: this,
|
1064
|
+
add: this.createRecords,
|
1065
|
+
remove: this.destroyRecord,
|
1066
|
+
update: this.updateRecord
|
1067
|
+
});
|
1068
|
+
}
|
1069
|
+
|
1070
|
+
this.sortToggle = {};
|
1071
|
+
if(this.sortField){
|
1072
|
+
this.setDefaultSort(this.sortField, this.sortDir);
|
1073
|
+
}else if(this.sortInfo){
|
1074
|
+
this.setDefaultSort(this.sortInfo.field, this.sortInfo.direction);
|
1075
|
+
}
|
1076
|
+
|
1077
|
+
Ext.data.Store.superclass.constructor.call(this);
|
1078
|
+
|
1079
|
+
if(this.id){
|
1080
|
+
this.storeId = this.id;
|
1081
|
+
delete this.id;
|
1082
|
+
}
|
1083
|
+
if(this.storeId){
|
1084
|
+
Ext.StoreMgr.register(this);
|
1085
|
+
}
|
1086
|
+
if(this.inlineData){
|
1087
|
+
this.loadData(this.inlineData);
|
1088
|
+
delete this.inlineData;
|
1089
|
+
}else if(this.autoLoad){
|
1090
|
+
this.load.defer(10, this, [
|
1091
|
+
typeof this.autoLoad == 'object' ?
|
1092
|
+
this.autoLoad : undefined]);
|
1093
|
+
}
|
1094
|
+
};
|
1095
|
+
Ext.extend(Ext.data.Store, Ext.util.Observable, {
|
1096
|
+
/**
|
1097
|
+
* @cfg {String} storeId If passed, the id to use to register with the <b>{@link Ext.StoreMgr StoreMgr}</b>.
|
1098
|
+
* <p><b>Note</b>: if a (deprecated) <tt>{@link #id}</tt> is specified it will supersede the <tt>storeId</tt>
|
1099
|
+
* assignment.</p>
|
1100
|
+
*/
|
1101
|
+
/**
|
1102
|
+
* @cfg {String} url If a <tt>{@link #proxy}</tt> is not specified the <tt>url</tt> will be used to
|
1103
|
+
* implicitly configure a {@link Ext.data.HttpProxy HttpProxy} if an <tt>url</tt> is specified.
|
1104
|
+
* Typically this option, or the <code>{@link #data}</code> option will be specified.
|
1105
|
+
*/
|
1106
|
+
/**
|
1107
|
+
* @cfg {Boolean/Object} autoLoad If <tt>{@link #data}</tt> is not specified, and if <tt>autoLoad</tt>
|
1108
|
+
* is <tt>true</tt> or an <tt>Object</tt>, this store's {@link #load} method is automatically called
|
1109
|
+
* after creation. If the value of <tt>autoLoad</tt> is an <tt>Object</tt>, this <tt>Object</tt> will
|
1110
|
+
* be passed to the store's {@link #load} method.
|
1111
|
+
*/
|
1112
|
+
/**
|
1113
|
+
* @cfg {Ext.data.DataProxy} proxy The {@link Ext.data.DataProxy DataProxy} object which provides
|
1114
|
+
* access to a data object. See <code>{@link #url}</code>.
|
1115
|
+
*/
|
1116
|
+
/**
|
1117
|
+
* @cfg {Array} data An inline data object readable by the <code>{@link #reader}</code>.
|
1118
|
+
* Typically this option, or the <code>{@link #url}</code> option will be specified.
|
1119
|
+
*/
|
1120
|
+
/**
|
1121
|
+
* @cfg {Ext.data.DataReader} reader The {@link Ext.data.DataReader Reader} object which processes the
|
1122
|
+
* data object and returns an Array of {@link Ext.data.Record} objects which are cached keyed by their
|
1123
|
+
* <b><tt>{@link Ext.data.Record#id id}</tt></b> property.
|
1124
|
+
*/
|
1125
|
+
/**
|
1126
|
+
* @cfg {Ext.data.DataWriter} writer
|
1127
|
+
* <p>The {@link Ext.data.DataWriter Writer} object which processes a record object for being written
|
1128
|
+
* to the server-side database.</p>
|
1129
|
+
* <br><p>When a writer is installed into a Store the {@link #add}, {@link #remove}, and {@link #update}
|
1130
|
+
* events on the store are monitored in order to remotely {@link #createRecords create records},
|
1131
|
+
* {@link #destroyRecord destroy records}, or {@link #updateRecord update records}.</p>
|
1132
|
+
* <br><p>The proxy for this store will relay any {@link #writexception} events to this store.</p>
|
1133
|
+
* <br><p>Sample implementation:
|
1134
|
+
* <pre><code>
|
1135
|
+
var writer = new {@link Ext.data.JsonWriter}({
|
1136
|
+
encode: true,
|
1137
|
+
writeAllFields: true // write all fields, not just those that changed
|
1138
|
+
});
|
1139
|
+
|
1140
|
+
// Typical Store collecting the Proxy, Reader and Writer together.
|
1141
|
+
var store = new Ext.data.Store({
|
1142
|
+
storeId: 'user',
|
1143
|
+
root: 'records',
|
1144
|
+
proxy: proxy,
|
1145
|
+
reader: reader,
|
1146
|
+
writer: writer, // <-- plug a DataWriter into the store just as you would a Reader
|
1147
|
+
paramsAsHash: true,
|
1148
|
+
autoSave: false // <-- false to delay executing create, update, destroy requests
|
1149
|
+
// until specifically told to do so.
|
1150
|
+
});
|
1151
|
+
* </code></pre></p>
|
1152
|
+
*/
|
1153
|
+
writer : undefined,
|
1154
|
+
/**
|
1155
|
+
* @cfg {Object} baseParams
|
1156
|
+
* <p>An object containing properties which are to be sent as parameters
|
1157
|
+
* for <i>every</i> HTTP request.</p>
|
1158
|
+
* <p>Parameters are encoded as standard HTTP parameters using {@link Ext#urlEncode}.</p>
|
1159
|
+
* <p><b>Note</b>: <code>baseParams</code> may be superseded by any <code>params</code>
|
1160
|
+
* specified in a <code>{@link #load}</code> request, see <code>{@link #load}</code>
|
1161
|
+
* for more details.</p>
|
1162
|
+
* This property may be modified after creation using the <code>{@link #setBaseParam}</code>
|
1163
|
+
* method.
|
1164
|
+
* @property
|
1165
|
+
*/
|
1166
|
+
/**
|
1167
|
+
* @cfg {Object} sortInfo A config object to specify the sort order in the request of a Store's
|
1168
|
+
* {@link #load} operation. Note that for local sorting, the <tt>direction</tt> property is
|
1169
|
+
* case-sensitive. See also {@link #remoteSort} and {@link #paramNames}.
|
1170
|
+
* For example:<pre><code>
|
1171
|
+
sortInfo: {
|
1172
|
+
field: 'fieldName',
|
1173
|
+
direction: 'ASC' // or 'DESC' (case sensitive for local sorting)
|
1174
|
+
}
|
1175
|
+
</code></pre>
|
1176
|
+
*/
|
1177
|
+
/**
|
1178
|
+
* @cfg {boolean} remoteSort <tt>true</tt> if sorting is to be handled by requesting the <tt>{@link #proxy Proxy}</tt>
|
1179
|
+
* to provide a refreshed version of the data object in sorted order, as opposed to sorting the Record cache
|
1180
|
+
* in place (defaults to <tt>false</tt>).
|
1181
|
+
* <p>If <tt>remoteSort</tt> is <tt>true</tt>, then clicking on a {@link Ext.grid.Column Grid Column}'s
|
1182
|
+
* {@link Ext.grid.Column#header header} causes the current page to be requested from the server appending
|
1183
|
+
* the following two parameters to the <b><tt>{@link #load params}</tt></b>:<div class="mdetail-params"><ul>
|
1184
|
+
* <li><b><tt>sort</tt></b> : String<p class="sub-desc">The <tt>name</tt> (as specified in the Record's
|
1185
|
+
* {@link Ext.data.Field Field definition}) of the field to sort on.</p></li>
|
1186
|
+
* <li><b><tt>dir</tt></b> : String<p class="sub-desc">The direction of the sort, 'ASC' or 'DESC' (case-sensitive).</p></li>
|
1187
|
+
* </ul></div></p>
|
1188
|
+
*/
|
1189
|
+
remoteSort : false,
|
1190
|
+
|
1191
|
+
/**
|
1192
|
+
* @cfg {Boolean} autoDestroy <tt>true</tt> to destroy the store when the component the store is bound
|
1193
|
+
* to is destroyed (defaults to <tt>false</tt>).
|
1194
|
+
* <p><b>Note</b>: this should be set to true when using stores that are bound to only 1 component.</p>
|
1195
|
+
*/
|
1196
|
+
autoDestroy : false,
|
1197
|
+
|
1198
|
+
/**
|
1199
|
+
* @cfg {Boolean} pruneModifiedRecords <tt>true</tt> to clear all modified record information each time
|
1200
|
+
* the store is loaded or when a record is removed (defaults to <tt>false</tt>). See {@link #getModifiedRecords}
|
1201
|
+
* for the accessor method to retrieve the modified records.
|
1202
|
+
*/
|
1203
|
+
pruneModifiedRecords : false,
|
1204
|
+
|
1205
|
+
/**
|
1206
|
+
* Contains the last options object used as the parameter to the {@link #load} method. See {@link #load}
|
1207
|
+
* for the details of what this may contain. This may be useful for accessing any params which were used
|
1208
|
+
* to load the current Record cache.
|
1209
|
+
* @property
|
1210
|
+
*/
|
1211
|
+
lastOptions : null,
|
1212
|
+
|
1213
|
+
/**
|
1214
|
+
* @cfg {Boolean} autoSave
|
1215
|
+
* <p>Defaults to <tt>true</tt> causing the store to automatically {@link #save} records to
|
1216
|
+
* the server when a record is modified (ie: becomes 'dirty'). Specify <tt>false</tt> to manually call {@link #save}
|
1217
|
+
* to send all modifiedRecords to the server.</p>
|
1218
|
+
* <br><p><b>Note</b>: each CRUD action will be sent as a separate request.</p>
|
1219
|
+
*/
|
1220
|
+
autoSave : true,
|
1221
|
+
|
1222
|
+
/**
|
1223
|
+
* @cfg {Boolean} batch
|
1224
|
+
* <p>Defaults to <tt>true</tt> (unless <code>{@link #restful}:true</code>). Multiple
|
1225
|
+
* requests for each CRUD action (CREATE, READ, UPDATE and DESTROY) will be combined
|
1226
|
+
* and sent as one transaction. Only applies when <code>{@link #autoSave}</code> is set
|
1227
|
+
* to <tt>false</tt>.</p>
|
1228
|
+
* <br><p>If Store is RESTful, the DataProxy is also RESTful, and a unique transaction is
|
1229
|
+
* generated for each record.</p>
|
1230
|
+
*/
|
1231
|
+
batch : true,
|
1232
|
+
|
1233
|
+
/**
|
1234
|
+
* @cfg {Boolean} restful
|
1235
|
+
* Defaults to <tt>false</tt>. Set to <tt>true</tt> to have the Store and the set
|
1236
|
+
* Proxy operate in a RESTful manner. The store will automatically generate GET, POST,
|
1237
|
+
* PUT and DELETE requests to the server. The HTTP method used for any given CRUD
|
1238
|
+
* action is described in {@link Ext.data.Api#restActions}. For additional information
|
1239
|
+
* see {@link Ext.data.DataProxy#restful}.
|
1240
|
+
* <p><b>Note</b>: if <code>{@link #restful}:true</code> <code>batch</code> will
|
1241
|
+
* internally be set to <tt>false</tt>.</p>
|
1242
|
+
*/
|
1243
|
+
restful: false,
|
1244
|
+
|
1245
|
+
/**
|
1246
|
+
* @cfg {Object} paramNames
|
1247
|
+
* <p>An object containing properties which specify the names of the paging and
|
1248
|
+
* sorting parameters passed to remote servers when loading blocks of data. By default, this
|
1249
|
+
* object takes the following form:</p><pre><code>
|
1250
|
+
{
|
1251
|
+
start : 'start', // The parameter name which specifies the start row
|
1252
|
+
limit : 'limit', // The parameter name which specifies number of rows to return
|
1253
|
+
sort : 'sort', // The parameter name which specifies the column to sort on
|
1254
|
+
dir : 'dir' // The parameter name which specifies the sort direction
|
1255
|
+
}
|
1256
|
+
</code></pre>
|
1257
|
+
* <p>The server must produce the requested data block upon receipt of these parameter names.
|
1258
|
+
* If different parameter names are required, this property can be overriden using a configuration
|
1259
|
+
* property.</p>
|
1260
|
+
* <p>A {@link Ext.PagingToolbar PagingToolbar} bound to this Store uses this property to determine
|
1261
|
+
* the parameter names to use in its {@link #load requests}.
|
1262
|
+
*/
|
1263
|
+
paramNames : undefined,
|
1264
|
+
|
1265
|
+
/**
|
1266
|
+
* @cfg {Object} defaultParamNames
|
1267
|
+
* Provides the default values for the {@link #paramNames} property. To globally modify the parameters
|
1268
|
+
* for all stores, this object should be changed on the store prototype.
|
1269
|
+
*/
|
1270
|
+
defaultParamNames : {
|
1271
|
+
start : 'start',
|
1272
|
+
limit : 'limit',
|
1273
|
+
sort : 'sort',
|
1274
|
+
dir : 'dir'
|
1275
|
+
},
|
1276
|
+
|
1277
|
+
/**
|
1278
|
+
* Destroys the store.
|
1279
|
+
*/
|
1280
|
+
destroy : function(){
|
1281
|
+
if(this.storeId){
|
1282
|
+
Ext.StoreMgr.unregister(this);
|
1283
|
+
}
|
1284
|
+
this.data = null;
|
1285
|
+
Ext.destroy(this.proxy);
|
1286
|
+
this.reader = this.writer = null;
|
1287
|
+
this.purgeListeners();
|
1288
|
+
},
|
1289
|
+
|
1290
|
+
/**
|
1291
|
+
* Add Records to the Store and fires the {@link #add} event. To add Records
|
1292
|
+
* to the store from a remote source use <code>{@link #load}({add:true})</code>.
|
1293
|
+
* See also <code>{@link #recordType}</code> and <code>{@link #insert}</code>.
|
1294
|
+
* @param {Ext.data.Record[]} records An Array of Ext.data.Record objects
|
1295
|
+
* to add to the cache. See {@link #recordType}.
|
1296
|
+
*/
|
1297
|
+
add : function(records){
|
1298
|
+
records = [].concat(records);
|
1299
|
+
if(records.length < 1){
|
1300
|
+
return;
|
1301
|
+
}
|
1302
|
+
for(var i = 0, len = records.length; i < len; i++){
|
1303
|
+
records[i].join(this);
|
1304
|
+
}
|
1305
|
+
var index = this.data.length;
|
1306
|
+
this.data.addAll(records);
|
1307
|
+
if(this.snapshot){
|
1308
|
+
this.snapshot.addAll(records);
|
1309
|
+
}
|
1310
|
+
this.fireEvent('add', this, records, index);
|
1311
|
+
},
|
1312
|
+
|
1313
|
+
/**
|
1314
|
+
* (Local sort only) Inserts the passed Record into the Store at the index where it
|
1315
|
+
* should go based on the current sort information.
|
1316
|
+
* @param {Ext.data.Record} record
|
1317
|
+
*/
|
1318
|
+
addSorted : function(record){
|
1319
|
+
var index = this.findInsertIndex(record);
|
1320
|
+
this.insert(index, record);
|
1321
|
+
},
|
1322
|
+
|
1323
|
+
/**
|
1324
|
+
* Remove a Record from the Store and fires the {@link #remove} event.
|
1325
|
+
* @param {Ext.data.Record} record The Ext.data.Record object to remove from the cache.
|
1326
|
+
*/
|
1327
|
+
remove : function(record){
|
1328
|
+
var index = this.data.indexOf(record);
|
1329
|
+
if(index > -1){
|
1330
|
+
this.data.removeAt(index);
|
1331
|
+
if(this.pruneModifiedRecords){
|
1332
|
+
this.modified.remove(record);
|
1333
|
+
}
|
1334
|
+
if(this.snapshot){
|
1335
|
+
this.snapshot.remove(record);
|
1336
|
+
}
|
1337
|
+
this.fireEvent('remove', this, record, index);
|
1338
|
+
}
|
1339
|
+
},
|
1340
|
+
|
1341
|
+
/**
|
1342
|
+
* Remove a Record from the Store at the specified index. Fires the {@link #remove} event.
|
1343
|
+
* @param {Number} index The index of the record to remove.
|
1344
|
+
*/
|
1345
|
+
removeAt : function(index){
|
1346
|
+
this.remove(this.getAt(index));
|
1347
|
+
},
|
1348
|
+
|
1349
|
+
/**
|
1350
|
+
* Remove all Records from the Store and fires the {@link #clear} event.
|
1351
|
+
*/
|
1352
|
+
removeAll : function(){
|
1353
|
+
this.data.clear();
|
1354
|
+
if(this.snapshot){
|
1355
|
+
this.snapshot.clear();
|
1356
|
+
}
|
1357
|
+
if(this.pruneModifiedRecords){
|
1358
|
+
this.modified = [];
|
1359
|
+
}
|
1360
|
+
this.fireEvent('clear', this);
|
1361
|
+
},
|
1362
|
+
|
1363
|
+
/**
|
1364
|
+
* Inserts Records into the Store at the given index and fires the {@link #add} event.
|
1365
|
+
* See also <code>{@link #add}</code> and <code>{@link #addSorted}</code>.
|
1366
|
+
* @param {Number} index The start index at which to insert the passed Records.
|
1367
|
+
* @param {Ext.data.Record[]} records An Array of Ext.data.Record objects to add to the cache.
|
1368
|
+
*/
|
1369
|
+
insert : function(index, records){
|
1370
|
+
records = [].concat(records);
|
1371
|
+
for(var i = 0, len = records.length; i < len; i++){
|
1372
|
+
this.data.insert(index, records[i]);
|
1373
|
+
records[i].join(this);
|
1374
|
+
}
|
1375
|
+
this.fireEvent('add', this, records, index);
|
1376
|
+
},
|
1377
|
+
|
1378
|
+
/**
|
1379
|
+
* Get the index within the cache of the passed Record.
|
1380
|
+
* @param {Ext.data.Record} record The Ext.data.Record object to find.
|
1381
|
+
* @return {Number} The index of the passed Record. Returns -1 if not found.
|
1382
|
+
*/
|
1383
|
+
indexOf : function(record){
|
1384
|
+
return this.data.indexOf(record);
|
1385
|
+
},
|
1386
|
+
|
1387
|
+
/**
|
1388
|
+
* Get the index within the cache of the Record with the passed id.
|
1389
|
+
* @param {String} id The id of the Record to find.
|
1390
|
+
* @return {Number} The index of the Record. Returns -1 if not found.
|
1391
|
+
*/
|
1392
|
+
indexOfId : function(id){
|
1393
|
+
return this.data.indexOfKey(id);
|
1394
|
+
},
|
1395
|
+
|
1396
|
+
/**
|
1397
|
+
* Get the Record with the specified id.
|
1398
|
+
* @param {String} id The id of the Record to find.
|
1399
|
+
* @return {Ext.data.Record} The Record with the passed id. Returns undefined if not found.
|
1400
|
+
*/
|
1401
|
+
getById : function(id){
|
1402
|
+
return this.data.key(id);
|
1403
|
+
},
|
1404
|
+
|
1405
|
+
/**
|
1406
|
+
* Get the Record at the specified index.
|
1407
|
+
* @param {Number} index The index of the Record to find.
|
1408
|
+
* @return {Ext.data.Record} The Record at the passed index. Returns undefined if not found.
|
1409
|
+
*/
|
1410
|
+
getAt : function(index){
|
1411
|
+
return this.data.itemAt(index);
|
1412
|
+
},
|
1413
|
+
|
1414
|
+
/**
|
1415
|
+
* Returns a range of Records between specified indices.
|
1416
|
+
* @param {Number} startIndex (optional) The starting index (defaults to 0)
|
1417
|
+
* @param {Number} endIndex (optional) The ending index (defaults to the last Record in the Store)
|
1418
|
+
* @return {Ext.data.Record[]} An array of Records
|
1419
|
+
*/
|
1420
|
+
getRange : function(start, end){
|
1421
|
+
return this.data.getRange(start, end);
|
1422
|
+
},
|
1423
|
+
|
1424
|
+
// private
|
1425
|
+
storeOptions : function(o){
|
1426
|
+
o = Ext.apply({}, o);
|
1427
|
+
delete o.callback;
|
1428
|
+
delete o.scope;
|
1429
|
+
this.lastOptions = o;
|
1430
|
+
},
|
1431
|
+
|
1432
|
+
/**
|
1433
|
+
* <p>Loads the Record cache from the configured <tt>{@link #proxy}</tt> using the configured <tt>{@link #reader}</tt>.</p>
|
1434
|
+
* <br><p>Notes:</p><div class="mdetail-params"><ul>
|
1435
|
+
* <li><b><u>Important</u></b>: loading is asynchronous! This call will return before the new data has been
|
1436
|
+
* loaded. To perform any post-processing where information from the load call is required, specify
|
1437
|
+
* the <tt>callback</tt> function to be called, or use a {@link Ext.util.Observable#listeners a 'load' event handler}.</li>
|
1438
|
+
* <li>If using {@link Ext.PagingToolbar remote paging}, the first load call must specify the <tt>start</tt> and <tt>limit</tt>
|
1439
|
+
* properties in the <code>options.params</code> property to establish the initial position within the
|
1440
|
+
* dataset, and the number of Records to cache on each read from the Proxy.</li>
|
1441
|
+
* <li>If using {@link #remoteSort remote sorting}, the configured <code>{@link #sortInfo}</code>
|
1442
|
+
* will be automatically included with the posted parameters according to the specified
|
1443
|
+
* <code>{@link #paramNames}</code>.</li>
|
1444
|
+
* </ul></div>
|
1445
|
+
* @param {Object} options An object containing properties which control loading options:<ul>
|
1446
|
+
* <li><b><tt>params</tt></b> :Object<div class="sub-desc"><p>An object containing properties to pass as HTTP
|
1447
|
+
* parameters to a remote data source. <b>Note</b>: <code>params</code> will override any
|
1448
|
+
* <code>{@link #baseParams}</code> of the same name.</p>
|
1449
|
+
* <p>Parameters are encoded as standard HTTP parameters using {@link Ext#urlEncode}.</p></div></li>
|
1450
|
+
* <li><b><tt>callback</tt></b> : Function<div class="sub-desc"><p>A function to be called after the Records
|
1451
|
+
* have been loaded. The <tt>callback</tt> is called after the load event and is passed the following arguments:<ul>
|
1452
|
+
* <li><tt>r</tt> : Ext.data.Record[]</li>
|
1453
|
+
* <li><tt>options</tt>: Options object from the load call</li>
|
1454
|
+
* <li><tt>success</tt>: Boolean success indicator</li></ul></p></div></li>
|
1455
|
+
* <li><b><tt>scope</tt></b> : Object<div class="sub-desc"><p>Scope with which to call the callback (defaults
|
1456
|
+
* to the Store object)</p></div></li>
|
1457
|
+
* <li><b><tt>add</tt></b> : Boolean<div class="sub-desc"><p>Indicator to append loaded records rather than
|
1458
|
+
* replace the current cache. <b>Note</b>: see note for <tt>{@link #loadData}</tt></p></div></li>
|
1459
|
+
* </ul>
|
1460
|
+
* @return {Boolean} If the <i>developer</i> provided <tt>{@link #beforeload}</tt> event handler returns
|
1461
|
+
* <tt>false</tt>, the load call will abort and will return <tt>false</tt>; otherwise will return <tt>true</tt>.
|
1462
|
+
*/
|
1463
|
+
load : function(options) {
|
1464
|
+
options = options || {};
|
1465
|
+
this.storeOptions(options);
|
1466
|
+
if(this.sortInfo && this.remoteSort){
|
1467
|
+
var pn = this.paramNames;
|
1468
|
+
options.params = options.params || {};
|
1469
|
+
options.params[pn.sort] = this.sortInfo.field;
|
1470
|
+
options.params[pn.dir] = this.sortInfo.direction;
|
1471
|
+
}
|
1472
|
+
try {
|
1473
|
+
return this.execute('read', null, options); // <-- null represents rs. No rs for load actions.
|
1474
|
+
} catch(e) {
|
1475
|
+
this.handleException(e);
|
1476
|
+
return false;
|
1477
|
+
}
|
1478
|
+
},
|
1479
|
+
|
1480
|
+
/**
|
1481
|
+
* updateRecord Should not be used directly. This method will be called automatically if a Writer is set.
|
1482
|
+
* Listens to 'update' event.
|
1483
|
+
* @param {Object} store
|
1484
|
+
* @param {Object} record
|
1485
|
+
* @param {Object} action
|
1486
|
+
* @private
|
1487
|
+
*/
|
1488
|
+
updateRecord : function(store, record, action) {
|
1489
|
+
if (action == Ext.data.Record.EDIT && this.autoSave === true && (!record.phantom || (record.phantom && record.isValid))) {
|
1490
|
+
this.save();
|
1491
|
+
}
|
1492
|
+
},
|
1493
|
+
|
1494
|
+
/**
|
1495
|
+
* Should not be used directly. Store#add will call this automatically if a Writer is set
|
1496
|
+
* @param {Object} store
|
1497
|
+
* @param {Object} rs
|
1498
|
+
* @param {Object} index
|
1499
|
+
* @private
|
1500
|
+
*/
|
1501
|
+
createRecords : function(store, rs, index) {
|
1502
|
+
for (var i = 0, len = rs.length; i < len; i++) {
|
1503
|
+
if (rs[i].phantom && rs[i].isValid()) {
|
1504
|
+
rs[i].markDirty(); // <-- Mark new records dirty
|
1505
|
+
this.modified.push(rs[i]); // <-- add to modified
|
1506
|
+
}
|
1507
|
+
}
|
1508
|
+
if (this.autoSave === true) {
|
1509
|
+
this.save();
|
1510
|
+
}
|
1511
|
+
},
|
1512
|
+
|
1513
|
+
/**
|
1514
|
+
* Destroys a record or records. Should not be used directly. It's called by Store#remove if a Writer is set.
|
1515
|
+
* @param {Store} this
|
1516
|
+
* @param {Ext.data.Record/Ext.data.Record[]}
|
1517
|
+
* @param {Number} index
|
1518
|
+
* @private
|
1519
|
+
*/
|
1520
|
+
destroyRecord : function(store, record, index) {
|
1521
|
+
if (this.modified.indexOf(record) != -1) { // <-- handled already if @cfg pruneModifiedRecords == true
|
1522
|
+
this.modified.remove(record);
|
1523
|
+
}
|
1524
|
+
if (!record.phantom) {
|
1525
|
+
this.removed.push(record);
|
1526
|
+
|
1527
|
+
// since the record has already been removed from the store but the server request has not yet been executed,
|
1528
|
+
// must keep track of the last known index this record existed. If a server error occurs, the record can be
|
1529
|
+
// put back into the store. @see Store#createCallback where the record is returned when response status === false
|
1530
|
+
record.lastIndex = index;
|
1531
|
+
|
1532
|
+
if (this.autoSave === true) {
|
1533
|
+
this.save();
|
1534
|
+
}
|
1535
|
+
}
|
1536
|
+
},
|
1537
|
+
|
1538
|
+
/**
|
1539
|
+
* This method should generally not be used directly. This method is called internally
|
1540
|
+
* by {@link #load}, or if a Writer is set will be called automatically when {@link #add},
|
1541
|
+
* {@link #remove}, or {@link #update} events fire.
|
1542
|
+
* @param {String} action Action name ('read', 'create', 'update', or 'destroy')
|
1543
|
+
* @param {Record/Record[]} rs
|
1544
|
+
* @param {Object} options
|
1545
|
+
* @throws Error
|
1546
|
+
* @private
|
1547
|
+
*/
|
1548
|
+
execute : function(action, rs, options) {
|
1549
|
+
// blow up if action not Ext.data.CREATE, READ, UPDATE, DESTROY
|
1550
|
+
if (!Ext.data.Api.isAction(action)) {
|
1551
|
+
throw new Ext.data.Api.Error('execute', action);
|
1552
|
+
}
|
1553
|
+
// make sure options has a params key
|
1554
|
+
options = Ext.applyIf(options||{}, {
|
1555
|
+
params: {}
|
1556
|
+
});
|
1557
|
+
|
1558
|
+
// have to separate before-events since load has a different signature than create,destroy and save events since load does not
|
1559
|
+
// include the rs (record resultset) parameter. Capture return values from the beforeaction into doRequest flag.
|
1560
|
+
var doRequest = true;
|
1561
|
+
|
1562
|
+
if (action === 'read') {
|
1563
|
+
doRequest = this.fireEvent('beforeload', this, options);
|
1564
|
+
}
|
1565
|
+
else {
|
1566
|
+
// if Writer is configured as listful, force single-recoord rs to be [{}} instead of {}
|
1567
|
+
if (this.writer.listful === true && this.restful !== true) {
|
1568
|
+
rs = (Ext.isArray(rs)) ? rs : [rs];
|
1569
|
+
}
|
1570
|
+
// if rs has just a single record, shift it off so that Writer writes data as '{}' rather than '[{}]'
|
1571
|
+
else if (Ext.isArray(rs) && rs.length == 1) {
|
1572
|
+
rs = rs.shift();
|
1573
|
+
}
|
1574
|
+
// Write the action to options.params
|
1575
|
+
if ((doRequest = this.fireEvent('beforewrite', this, action, rs, options)) !== false) {
|
1576
|
+
this.writer.write(action, options.params, rs);
|
1577
|
+
}
|
1578
|
+
}
|
1579
|
+
if (doRequest !== false) {
|
1580
|
+
// Send request to proxy.
|
1581
|
+
var params = Ext.apply({}, options.params, this.baseParams);
|
1582
|
+
if (this.writer && this.proxy.url && !this.proxy.restful && !Ext.data.Api.hasUniqueUrl(this.proxy, action)) {
|
1583
|
+
params.xaction = action;
|
1584
|
+
}
|
1585
|
+
// Note: Up until this point we've been dealing with 'action' as a key from Ext.data.Api.actions. We'll flip it now
|
1586
|
+
// and send the value into DataProxy#request, since it's the value which maps to the DataProxy#api
|
1587
|
+
this.proxy.request(Ext.data.Api.actions[action], rs, params, this.reader, this.createCallback(action, rs), this, options);
|
1588
|
+
}
|
1589
|
+
return doRequest;
|
1590
|
+
},
|
1591
|
+
|
1592
|
+
/**
|
1593
|
+
* Saves all pending changes to the store. If the commensurate Ext.data.Api.actions action is not configured, then
|
1594
|
+
* the configured <code>{@link #url}</code> will be used.
|
1595
|
+
* <pre>
|
1596
|
+
* change url
|
1597
|
+
* --------------- --------------------
|
1598
|
+
* removed records Ext.data.Api.actions.destroy
|
1599
|
+
* phantom records Ext.data.Api.actions.create
|
1600
|
+
* {@link #getModifiedRecords modified records} Ext.data.Api.actions.update
|
1601
|
+
* </pre>
|
1602
|
+
* @TODO: Create extensions of Error class and send associated Record with thrown exceptions.
|
1603
|
+
* e.g.: Ext.data.DataReader.Error or Ext.data.Error or Ext.data.DataProxy.Error, etc.
|
1604
|
+
*/
|
1605
|
+
save : function() {
|
1606
|
+
if (!this.writer) {
|
1607
|
+
throw new Ext.data.Store.Error('writer-undefined');
|
1608
|
+
}
|
1609
|
+
|
1610
|
+
// DESTROY: First check for removed records. Records in this.removed are guaranteed non-phantoms. @see Store#remove
|
1611
|
+
if (this.removed.length) {
|
1612
|
+
this.doTransaction('destroy', this.removed);
|
1613
|
+
}
|
1614
|
+
|
1615
|
+
// Check for modified records. Use a copy so Store#rejectChanges will work if server returns error.
|
1616
|
+
var rs = [].concat(this.getModifiedRecords());
|
1617
|
+
if (!rs.length) { // Bail-out if empty...
|
1618
|
+
return true;
|
1619
|
+
}
|
1620
|
+
|
1621
|
+
// CREATE: Next check for phantoms within rs. splice-off and execute create.
|
1622
|
+
var phantoms = [];
|
1623
|
+
for (var i = rs.length-1; i >= 0; i--) {
|
1624
|
+
if (rs[i].phantom === true) {
|
1625
|
+
var rec = rs.splice(i, 1).shift();
|
1626
|
+
if (rec.isValid()) {
|
1627
|
+
phantoms.push(rec);
|
1628
|
+
}
|
1629
|
+
} else if (!rs[i].isValid()) { // <-- while we're here, splice-off any !isValid real records
|
1630
|
+
rs.splice(i,1);
|
1631
|
+
}
|
1632
|
+
}
|
1633
|
+
// If we have valid phantoms, create them...
|
1634
|
+
if (phantoms.length) {
|
1635
|
+
this.doTransaction('create', phantoms);
|
1636
|
+
}
|
1637
|
+
|
1638
|
+
// UPDATE: And finally, if we're still here after splicing-off phantoms and !isValid real records, update the rest...
|
1639
|
+
if (rs.length) {
|
1640
|
+
this.doTransaction('update', rs);
|
1641
|
+
}
|
1642
|
+
return true;
|
1643
|
+
},
|
1644
|
+
|
1645
|
+
// private. Simply wraps call to Store#execute in try/catch. Defers to Store#handleException on error. Loops if batch: false
|
1646
|
+
doTransaction : function(action, rs) {
|
1647
|
+
function transaction(records) {
|
1648
|
+
try {
|
1649
|
+
this.execute(action, records);
|
1650
|
+
} catch (e) {
|
1651
|
+
this.handleException(e);
|
1652
|
+
}
|
1653
|
+
}
|
1654
|
+
if (this.batch === false) {
|
1655
|
+
for (var i = 0, len = rs.length; i < len; i++) {
|
1656
|
+
transaction.call(this, rs[i]);
|
1657
|
+
}
|
1658
|
+
} else {
|
1659
|
+
transaction.call(this, rs);
|
1660
|
+
}
|
1661
|
+
},
|
1662
|
+
|
1663
|
+
// @private callback-handler for remote CRUD actions
|
1664
|
+
// Do not override -- override loadRecords, onCreateRecords, onDestroyRecords and onUpdateRecords instead.
|
1665
|
+
createCallback : function(action, rs) {
|
1666
|
+
var actions = Ext.data.Api.actions;
|
1667
|
+
return (action == 'read') ? this.loadRecords : function(data, response, success) {
|
1668
|
+
// calls: onCreateRecords | onUpdateRecords | onDestroyRecords
|
1669
|
+
this['on' + Ext.util.Format.capitalize(action) + 'Records'](success, rs, data);
|
1670
|
+
// If success === false here, exception will have been called in DataProxy
|
1671
|
+
if (success === true) {
|
1672
|
+
this.fireEvent('write', this, action, data, response, rs);
|
1673
|
+
}
|
1674
|
+
};
|
1675
|
+
},
|
1676
|
+
|
1677
|
+
// Clears records from modified array after an exception event.
|
1678
|
+
// NOTE: records are left marked dirty. Do we want to commit them even though they were not updated/realized?
|
1679
|
+
clearModified : function(rs) {
|
1680
|
+
if (Ext.isArray(rs)) {
|
1681
|
+
for (var n=rs.length-1;n>=0;n--) {
|
1682
|
+
this.modified.splice(this.modified.indexOf(rs[n]), 1);
|
1683
|
+
}
|
1684
|
+
} else {
|
1685
|
+
this.modified.splice(this.modified.indexOf(rs), 1);
|
1686
|
+
}
|
1687
|
+
},
|
1688
|
+
|
1689
|
+
// remap record ids in MixedCollection after records have been realized. @see Store#onCreateRecords, @see DataReader#realize
|
1690
|
+
reMap : function(record) {
|
1691
|
+
if (Ext.isArray(record)) {
|
1692
|
+
for (var i = 0, len = record.length; i < len; i++) {
|
1693
|
+
this.reMap(record[i]);
|
1694
|
+
}
|
1695
|
+
} else {
|
1696
|
+
delete this.data.map[record._phid];
|
1697
|
+
this.data.map[record.id] = record;
|
1698
|
+
var index = this.data.keys.indexOf(record._phid);
|
1699
|
+
this.data.keys.splice(index, 1, record.id);
|
1700
|
+
delete record._phid;
|
1701
|
+
}
|
1702
|
+
},
|
1703
|
+
|
1704
|
+
// @protected onCreateRecord proxy callback for create action
|
1705
|
+
onCreateRecords : function(success, rs, data) {
|
1706
|
+
if (success === true) {
|
1707
|
+
try {
|
1708
|
+
this.reader.realize(rs, data);
|
1709
|
+
this.reMap(rs);
|
1710
|
+
}
|
1711
|
+
catch (e) {
|
1712
|
+
this.handleException(e);
|
1713
|
+
if (Ext.isArray(rs)) {
|
1714
|
+
// Recurse to run back into the try {}. DataReader#realize splices-off the rs until empty.
|
1715
|
+
this.onCreateRecords(success, rs, data);
|
1716
|
+
}
|
1717
|
+
}
|
1718
|
+
}
|
1719
|
+
},
|
1720
|
+
|
1721
|
+
// @protected, onUpdateRecords proxy callback for update action
|
1722
|
+
onUpdateRecords : function(success, rs, data) {
|
1723
|
+
if (success === true) {
|
1724
|
+
try {
|
1725
|
+
this.reader.update(rs, data);
|
1726
|
+
} catch (e) {
|
1727
|
+
this.handleException(e);
|
1728
|
+
if (Ext.isArray(rs)) {
|
1729
|
+
// Recurse to run back into the try {}. DataReader#update splices-off the rs until empty.
|
1730
|
+
this.onUpdateRecords(success, rs, data);
|
1731
|
+
}
|
1732
|
+
}
|
1733
|
+
}
|
1734
|
+
},
|
1735
|
+
|
1736
|
+
// @protected onDestroyRecords proxy callback for destroy action
|
1737
|
+
onDestroyRecords : function(success, rs, data) {
|
1738
|
+
// splice each rec out of this.removed
|
1739
|
+
rs = (rs instanceof Ext.data.Record) ? [rs] : rs;
|
1740
|
+
for (var i=0,len=rs.length;i<len;i++) {
|
1741
|
+
this.removed.splice(this.removed.indexOf(rs[i]), 1);
|
1742
|
+
}
|
1743
|
+
if (success === false) {
|
1744
|
+
// put records back into store if remote destroy fails.
|
1745
|
+
// @TODO: Might want to let developer decide.
|
1746
|
+
for (i=rs.length-1;i>=0;i--) {
|
1747
|
+
this.insert(rs[i].lastIndex, rs[i]); // <-- lastIndex set in Store#destroyRecord
|
1748
|
+
}
|
1749
|
+
}
|
1750
|
+
},
|
1751
|
+
|
1752
|
+
// protected handleException. Possibly temporary until Ext framework has an exception-handler.
|
1753
|
+
handleException : function(e) {
|
1754
|
+
// @see core/Error.js
|
1755
|
+
Ext.handleError(e);
|
1756
|
+
},
|
1757
|
+
|
1758
|
+
/**
|
1759
|
+
* <p>Reloads the Record cache from the configured Proxy using the configured {@link Ext.data.Reader Reader} and
|
1760
|
+
* the options from the last load operation performed.</p>
|
1761
|
+
* <p><b>Note</b>: see the Important note in {@link #load}.</p>
|
1762
|
+
* @param {Object} options (optional) An <tt>Object</tt> containing {@link #load loading options} which may
|
1763
|
+
* override the options used in the last {@link #load} operation. See {@link #load} for details (defaults to
|
1764
|
+
* <tt>null</tt>, in which case the {@link #lastOptions} are used).
|
1765
|
+
*/
|
1766
|
+
reload : function(options){
|
1767
|
+
this.load(Ext.applyIf(options||{}, this.lastOptions));
|
1768
|
+
},
|
1769
|
+
|
1770
|
+
// private
|
1771
|
+
// Called as a callback by the Reader during a load operation.
|
1772
|
+
loadRecords : function(o, options, success){
|
1773
|
+
if(!o || success === false){
|
1774
|
+
if(success !== false){
|
1775
|
+
this.fireEvent('load', this, [], options);
|
1776
|
+
}
|
1777
|
+
if(options.callback){
|
1778
|
+
options.callback.call(options.scope || this, [], options, false, o);
|
1779
|
+
}
|
1780
|
+
return;
|
1781
|
+
}
|
1782
|
+
var r = o.records, t = o.totalRecords || r.length;
|
1783
|
+
if(!options || options.add !== true){
|
1784
|
+
if(this.pruneModifiedRecords){
|
1785
|
+
this.modified = [];
|
1786
|
+
}
|
1787
|
+
for(var i = 0, len = r.length; i < len; i++){
|
1788
|
+
r[i].join(this);
|
1789
|
+
}
|
1790
|
+
if(this.snapshot){
|
1791
|
+
this.data = this.snapshot;
|
1792
|
+
delete this.snapshot;
|
1793
|
+
}
|
1794
|
+
this.data.clear();
|
1795
|
+
this.data.addAll(r);
|
1796
|
+
this.totalLength = t;
|
1797
|
+
this.applySort();
|
1798
|
+
this.fireEvent('datachanged', this);
|
1799
|
+
}else{
|
1800
|
+
this.totalLength = Math.max(t, this.data.length+r.length);
|
1801
|
+
this.add(r);
|
1802
|
+
}
|
1803
|
+
this.fireEvent('load', this, r, options);
|
1804
|
+
if(options.callback){
|
1805
|
+
options.callback.call(options.scope || this, r, options, true);
|
1806
|
+
}
|
1807
|
+
},
|
1808
|
+
|
1809
|
+
/**
|
1810
|
+
* Loads data from a passed data block and fires the {@link #load} event. A {@link Ext.data.Reader Reader}
|
1811
|
+
* which understands the format of the data must have been configured in the constructor.
|
1812
|
+
* @param {Object} data The data block from which to read the Records. The format of the data expected
|
1813
|
+
* is dependent on the type of {@link Ext.data.Reader Reader} that is configured and should correspond to
|
1814
|
+
* that {@link Ext.data.Reader Reader}'s <tt>{@link Ext.data.Reader#readRecords}</tt> parameter.
|
1815
|
+
* @param {Boolean} append (Optional) <tt>true</tt> to append the new Records rather the default to replace
|
1816
|
+
* the existing cache.
|
1817
|
+
* <b>Note</b>: that Records in a Store are keyed by their {@link Ext.data.Record#id id}, so added Records
|
1818
|
+
* with ids which are already present in the Store will <i>replace</i> existing Records. Only Records with
|
1819
|
+
* new, unique ids will be added.
|
1820
|
+
*/
|
1821
|
+
loadData : function(o, append){
|
1822
|
+
var r = this.reader.readRecords(o);
|
1823
|
+
this.loadRecords(r, {add: append}, true);
|
1824
|
+
},
|
1825
|
+
|
1826
|
+
/**
|
1827
|
+
* Gets the number of cached records.
|
1828
|
+
* <p>If using paging, this may not be the total size of the dataset. If the data object
|
1829
|
+
* used by the Reader contains the dataset size, then the {@link #getTotalCount} function returns
|
1830
|
+
* the dataset size. <b>Note</b>: see the Important note in {@link #load}.</p>
|
1831
|
+
* @return {Number} The number of Records in the Store's cache.
|
1832
|
+
*/
|
1833
|
+
getCount : function(){
|
1834
|
+
return this.data.length || 0;
|
1835
|
+
},
|
1836
|
+
|
1837
|
+
/**
|
1838
|
+
* Gets the total number of records in the dataset as returned by the server.
|
1839
|
+
* <p>If using paging, for this to be accurate, the data object used by the {@link #reader Reader}
|
1840
|
+
* must contain the dataset size. For remote data sources, the value for this property
|
1841
|
+
* (<tt>totalProperty</tt> for {@link Ext.data.JsonReader JsonReader},
|
1842
|
+
* <tt>totalRecords</tt> for {@link Ext.data.XmlReader XmlReader}) shall be returned by a query on the server.
|
1843
|
+
* <b>Note</b>: see the Important note in {@link #load}.</p>
|
1844
|
+
* @return {Number} The number of Records as specified in the data object passed to the Reader
|
1845
|
+
* by the Proxy.
|
1846
|
+
* <p><b>Note</b>: this value is not updated when changing the contents of the Store locally.</p>
|
1847
|
+
*/
|
1848
|
+
getTotalCount : function(){
|
1849
|
+
return this.totalLength || 0;
|
1850
|
+
},
|
1851
|
+
|
1852
|
+
/**
|
1853
|
+
* Returns an object describing the current sort state of this Store.
|
1854
|
+
* @return {Object} The sort state of the Store. An object with two properties:<ul>
|
1855
|
+
* <li><b>field : String<p class="sub-desc">The name of the field by which the Records are sorted.</p></li>
|
1856
|
+
* <li><b>direction : String<p class="sub-desc">The sort order, 'ASC' or 'DESC' (case-sensitive).</p></li>
|
1857
|
+
* </ul>
|
1858
|
+
* See <tt>{@link #sortInfo}</tt> for additional details.
|
1859
|
+
*/
|
1860
|
+
getSortState : function(){
|
1861
|
+
return this.sortInfo;
|
1862
|
+
},
|
1863
|
+
|
1864
|
+
// private
|
1865
|
+
applySort : function(){
|
1866
|
+
if(this.sortInfo && !this.remoteSort){
|
1867
|
+
var s = this.sortInfo, f = s.field;
|
1868
|
+
this.sortData(f, s.direction);
|
1869
|
+
}
|
1870
|
+
},
|
1871
|
+
|
1872
|
+
// private
|
1873
|
+
sortData : function(f, direction){
|
1874
|
+
direction = direction || 'ASC';
|
1875
|
+
var st = this.fields.get(f).sortType;
|
1876
|
+
var fn = function(r1, r2){
|
1877
|
+
var v1 = st(r1.data[f]), v2 = st(r2.data[f]);
|
1878
|
+
return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
|
1879
|
+
};
|
1880
|
+
this.data.sort(direction, fn);
|
1881
|
+
if(this.snapshot && this.snapshot != this.data){
|
1882
|
+
this.snapshot.sort(direction, fn);
|
1883
|
+
}
|
1884
|
+
},
|
1885
|
+
|
1886
|
+
/**
|
1887
|
+
* Sets the default sort column and order to be used by the next {@link #load} operation.
|
1888
|
+
* @param {String} fieldName The name of the field to sort by.
|
1889
|
+
* @param {String} dir (optional) The sort order, 'ASC' or 'DESC' (case-sensitive, defaults to <tt>'ASC'</tt>)
|
1890
|
+
*/
|
1891
|
+
setDefaultSort : function(field, dir){
|
1892
|
+
dir = dir ? dir.toUpperCase() : 'ASC';
|
1893
|
+
this.sortInfo = {field: field, direction: dir};
|
1894
|
+
this.sortToggle[field] = dir;
|
1895
|
+
},
|
1896
|
+
|
1897
|
+
/**
|
1898
|
+
* Sort the Records.
|
1899
|
+
* If remote sorting is used, the sort is performed on the server, and the cache is reloaded. If local
|
1900
|
+
* sorting is used, the cache is sorted internally. See also {@link #remoteSort} and {@link #paramNames}.
|
1901
|
+
* @param {String} fieldName The name of the field to sort by.
|
1902
|
+
* @param {String} dir (optional) The sort order, 'ASC' or 'DESC' (case-sensitive, defaults to <tt>'ASC'</tt>)
|
1903
|
+
*/
|
1904
|
+
sort : function(fieldName, dir){
|
1905
|
+
var f = this.fields.get(fieldName);
|
1906
|
+
if(!f){
|
1907
|
+
return false;
|
1908
|
+
}
|
1909
|
+
if(!dir){
|
1910
|
+
if(this.sortInfo && this.sortInfo.field == f.name){ // toggle sort dir
|
1911
|
+
dir = (this.sortToggle[f.name] || 'ASC').toggle('ASC', 'DESC');
|
1912
|
+
}else{
|
1913
|
+
dir = f.sortDir;
|
1914
|
+
}
|
1915
|
+
}
|
1916
|
+
var st = (this.sortToggle) ? this.sortToggle[f.name] : null;
|
1917
|
+
var si = (this.sortInfo) ? this.sortInfo : null;
|
1918
|
+
|
1919
|
+
this.sortToggle[f.name] = dir;
|
1920
|
+
this.sortInfo = {field: f.name, direction: dir};
|
1921
|
+
if(!this.remoteSort){
|
1922
|
+
this.applySort();
|
1923
|
+
this.fireEvent('datachanged', this);
|
1924
|
+
}else{
|
1925
|
+
if (!this.load(this.lastOptions)) {
|
1926
|
+
if (st) {
|
1927
|
+
this.sortToggle[f.name] = st;
|
1928
|
+
}
|
1929
|
+
if (si) {
|
1930
|
+
this.sortInfo = si;
|
1931
|
+
}
|
1932
|
+
}
|
1933
|
+
}
|
1934
|
+
},
|
1935
|
+
|
1936
|
+
/**
|
1937
|
+
* Calls the specified function for each of the {@link Ext.data.Record Records} in the cache.
|
1938
|
+
* @param {Function} fn The function to call. The {@link Ext.data.Record Record} is passed as the first parameter.
|
1939
|
+
* Returning <tt>false</tt> aborts and exits the iteration.
|
1940
|
+
* @param {Object} scope (optional) The scope in which to call the function (defaults to the {@link Ext.data.Record Record}).
|
1941
|
+
*/
|
1942
|
+
each : function(fn, scope){
|
1943
|
+
this.data.each(fn, scope);
|
1944
|
+
},
|
1945
|
+
|
1946
|
+
/**
|
1947
|
+
* Gets all {@link Ext.data.Record records} modified since the last commit. Modified records are
|
1948
|
+
* persisted across load operations (e.g., during paging). <b>Note</b>: deleted records are not
|
1949
|
+
* included. See also <tt>{@link #pruneModifiedRecords}</tt> and
|
1950
|
+
* {@link Ext.data.Record}<tt>{@link Ext.data.Record#markDirty markDirty}.</tt>.
|
1951
|
+
* @return {Ext.data.Record[]} An array of {@link Ext.data.Record Records} containing outstanding
|
1952
|
+
* modifications. To obtain modified fields within a modified record see
|
1953
|
+
*{@link Ext.data.Record}<tt>{@link Ext.data.Record#modified modified}.</tt>.
|
1954
|
+
*/
|
1955
|
+
getModifiedRecords : function(){
|
1956
|
+
return this.modified;
|
1957
|
+
},
|
1958
|
+
|
1959
|
+
// private
|
1960
|
+
createFilterFn : function(property, value, anyMatch, caseSensitive){
|
1961
|
+
if(Ext.isEmpty(value, false)){
|
1962
|
+
return false;
|
1963
|
+
}
|
1964
|
+
value = this.data.createValueMatcher(value, anyMatch, caseSensitive);
|
1965
|
+
return function(r){
|
1966
|
+
return value.test(r.data[property]);
|
1967
|
+
};
|
1968
|
+
},
|
1969
|
+
|
1970
|
+
/**
|
1971
|
+
* Sums the value of <tt>property</tt> for each {@link Ext.data.Record record} between <tt>start</tt>
|
1972
|
+
* and <tt>end</tt> and returns the result.
|
1973
|
+
* @param {String} property A field in each record
|
1974
|
+
* @param {Number} start (optional) The record index to start at (defaults to <tt>0</tt>)
|
1975
|
+
* @param {Number} end (optional) The last record index to include (defaults to length - 1)
|
1976
|
+
* @return {Number} The sum
|
1977
|
+
*/
|
1978
|
+
sum : function(property, start, end){
|
1979
|
+
var rs = this.data.items, v = 0;
|
1980
|
+
start = start || 0;
|
1981
|
+
end = (end || end === 0) ? end : rs.length-1;
|
1982
|
+
|
1983
|
+
for(var i = start; i <= end; i++){
|
1984
|
+
v += (rs[i].data[property] || 0);
|
1985
|
+
}
|
1986
|
+
return v;
|
1987
|
+
},
|
1988
|
+
|
1989
|
+
/**
|
1990
|
+
* Filter the {@link Ext.data.Record records} by a specified property.
|
1991
|
+
* @param {String} field A field on your records
|
1992
|
+
* @param {String/RegExp} value Either a string that the field should begin with, or a RegExp to test
|
1993
|
+
* against the field.
|
1994
|
+
* @param {Boolean} anyMatch (optional) <tt>true</tt> to match any part not just the beginning
|
1995
|
+
* @param {Boolean} caseSensitive (optional) <tt>true</tt> for case sensitive comparison
|
1996
|
+
*/
|
1997
|
+
filter : function(property, value, anyMatch, caseSensitive){
|
1998
|
+
var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
|
1999
|
+
return fn ? this.filterBy(fn) : this.clearFilter();
|
2000
|
+
},
|
2001
|
+
|
2002
|
+
/**
|
2003
|
+
* Filter by a function. The specified function will be called for each
|
2004
|
+
* Record in this Store. If the function returns <tt>true</tt> the Record is included,
|
2005
|
+
* otherwise it is filtered out.
|
2006
|
+
* @param {Function} fn The function to be called. It will be passed the following parameters:<ul>
|
2007
|
+
* <li><b>record</b> : Ext.data.Record<p class="sub-desc">The {@link Ext.data.Record record}
|
2008
|
+
* to test for filtering. Access field values using {@link Ext.data.Record#get}.</p></li>
|
2009
|
+
* <li><b>id</b> : Object<p class="sub-desc">The ID of the Record passed.</p></li>
|
2010
|
+
* </ul>
|
2011
|
+
* @param {Object} scope (optional) The scope of the function (defaults to this)
|
2012
|
+
*/
|
2013
|
+
filterBy : function(fn, scope){
|
2014
|
+
this.snapshot = this.snapshot || this.data;
|
2015
|
+
this.data = this.queryBy(fn, scope||this);
|
2016
|
+
this.fireEvent('datachanged', this);
|
2017
|
+
},
|
2018
|
+
|
2019
|
+
/**
|
2020
|
+
* Query the records by a specified property.
|
2021
|
+
* @param {String} field A field on your records
|
2022
|
+
* @param {String/RegExp} value Either a string that the field
|
2023
|
+
* should begin with, or a RegExp to test against the field.
|
2024
|
+
* @param {Boolean} anyMatch (optional) True to match any part not just the beginning
|
2025
|
+
* @param {Boolean} caseSensitive (optional) True for case sensitive comparison
|
2026
|
+
* @return {MixedCollection} Returns an Ext.util.MixedCollection of the matched records
|
2027
|
+
*/
|
2028
|
+
query : function(property, value, anyMatch, caseSensitive){
|
2029
|
+
var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
|
2030
|
+
return fn ? this.queryBy(fn) : this.data.clone();
|
2031
|
+
},
|
2032
|
+
|
2033
|
+
/**
|
2034
|
+
* Query the cached records in this Store using a filtering function. The specified function
|
2035
|
+
* will be called with each record in this Store. If the function returns <tt>true</tt> the record is
|
2036
|
+
* included in the results.
|
2037
|
+
* @param {Function} fn The function to be called. It will be passed the following parameters:<ul>
|
2038
|
+
* <li><b>record</b> : Ext.data.Record<p class="sub-desc">The {@link Ext.data.Record record}
|
2039
|
+
* to test for filtering. Access field values using {@link Ext.data.Record#get}.</p></li>
|
2040
|
+
* <li><b>id</b> : Object<p class="sub-desc">The ID of the Record passed.</p></li>
|
2041
|
+
* </ul>
|
2042
|
+
* @param {Object} scope (optional) The scope of the function (defaults to this)
|
2043
|
+
* @return {MixedCollection} Returns an Ext.util.MixedCollection of the matched records
|
2044
|
+
**/
|
2045
|
+
queryBy : function(fn, scope){
|
2046
|
+
var data = this.snapshot || this.data;
|
2047
|
+
return data.filterBy(fn, scope||this);
|
2048
|
+
},
|
2049
|
+
|
2050
|
+
/**
|
2051
|
+
* Finds the index of the first matching record in this store by a specific property/value.
|
2052
|
+
* @param {String} property A property on your objects
|
2053
|
+
* @param {String/RegExp} value Either a string that the property value
|
2054
|
+
* should begin with, or a RegExp to test against the property.
|
2055
|
+
* @param {Number} startIndex (optional) The index to start searching at
|
2056
|
+
* @param {Boolean} anyMatch (optional) True to match any part of the string, not just the beginning
|
2057
|
+
* @param {Boolean} caseSensitive (optional) True for case sensitive comparison
|
2058
|
+
* @return {Number} The matched index or -1
|
2059
|
+
*/
|
2060
|
+
find : function(property, value, start, anyMatch, caseSensitive){
|
2061
|
+
var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
|
2062
|
+
return fn ? this.data.findIndexBy(fn, null, start) : -1;
|
2063
|
+
},
|
2064
|
+
|
2065
|
+
/**
|
2066
|
+
* Finds the index of the first matching record in this store by a specific property/value.
|
2067
|
+
* @param {String} property A property on your objects
|
2068
|
+
* @param {String/RegExp} value The value to match against
|
2069
|
+
* @param {Number} startIndex (optional) The index to start searching at
|
2070
|
+
* @return {Number} The matched index or -1
|
2071
|
+
*/
|
2072
|
+
findExact: function(property, value, start){
|
2073
|
+
return this.data.findIndexBy(function(rec){
|
2074
|
+
return rec.get(property) === value;
|
2075
|
+
}, this, start);
|
2076
|
+
},
|
2077
|
+
|
2078
|
+
/**
|
2079
|
+
* Find the index of the first matching Record in this Store by a function.
|
2080
|
+
* If the function returns <tt>true</tt> it is considered a match.
|
2081
|
+
* @param {Function} fn The function to be called. It will be passed the following parameters:<ul>
|
2082
|
+
* <li><b>record</b> : Ext.data.Record<p class="sub-desc">The {@link Ext.data.Record record}
|
2083
|
+
* to test for filtering. Access field values using {@link Ext.data.Record#get}.</p></li>
|
2084
|
+
* <li><b>id</b> : Object<p class="sub-desc">The ID of the Record passed.</p></li>
|
2085
|
+
* </ul>
|
2086
|
+
* @param {Object} scope (optional) The scope of the function (defaults to this)
|
2087
|
+
* @param {Number} startIndex (optional) The index to start searching at
|
2088
|
+
* @return {Number} The matched index or -1
|
2089
|
+
*/
|
2090
|
+
findBy : function(fn, scope, start){
|
2091
|
+
return this.data.findIndexBy(fn, scope, start);
|
2092
|
+
},
|
2093
|
+
|
2094
|
+
/**
|
2095
|
+
* Collects unique values for a particular dataIndex from this store.
|
2096
|
+
* @param {String} dataIndex The property to collect
|
2097
|
+
* @param {Boolean} allowNull (optional) Pass true to allow null, undefined or empty string values
|
2098
|
+
* @param {Boolean} bypassFilter (optional) Pass true to collect from all records, even ones which are filtered
|
2099
|
+
* @return {Array} An array of the unique values
|
2100
|
+
**/
|
2101
|
+
collect : function(dataIndex, allowNull, bypassFilter){
|
2102
|
+
var d = (bypassFilter === true && this.snapshot) ?
|
2103
|
+
this.snapshot.items : this.data.items;
|
2104
|
+
var v, sv, r = [], l = {};
|
2105
|
+
for(var i = 0, len = d.length; i < len; i++){
|
2106
|
+
v = d[i].data[dataIndex];
|
2107
|
+
sv = String(v);
|
2108
|
+
if((allowNull || !Ext.isEmpty(v)) && !l[sv]){
|
2109
|
+
l[sv] = true;
|
2110
|
+
r[r.length] = v;
|
2111
|
+
}
|
2112
|
+
}
|
2113
|
+
return r;
|
2114
|
+
},
|
2115
|
+
|
2116
|
+
/**
|
2117
|
+
* Revert to a view of the Record cache with no filtering applied.
|
2118
|
+
* @param {Boolean} suppressEvent If <tt>true</tt> the filter is cleared silently without firing the
|
2119
|
+
* {@link #datachanged} event.
|
2120
|
+
*/
|
2121
|
+
clearFilter : function(suppressEvent){
|
2122
|
+
if(this.isFiltered()){
|
2123
|
+
this.data = this.snapshot;
|
2124
|
+
delete this.snapshot;
|
2125
|
+
if(suppressEvent !== true){
|
2126
|
+
this.fireEvent('datachanged', this);
|
2127
|
+
}
|
2128
|
+
}
|
2129
|
+
},
|
2130
|
+
|
2131
|
+
/**
|
2132
|
+
* Returns true if this store is currently filtered
|
2133
|
+
* @return {Boolean}
|
2134
|
+
*/
|
2135
|
+
isFiltered : function(){
|
2136
|
+
return this.snapshot && this.snapshot != this.data;
|
2137
|
+
},
|
2138
|
+
|
2139
|
+
// private
|
2140
|
+
afterEdit : function(record){
|
2141
|
+
if(this.modified.indexOf(record) == -1){
|
2142
|
+
this.modified.push(record);
|
2143
|
+
}
|
2144
|
+
this.fireEvent('update', this, record, Ext.data.Record.EDIT);
|
2145
|
+
},
|
2146
|
+
|
2147
|
+
// private
|
2148
|
+
afterReject : function(record){
|
2149
|
+
this.modified.remove(record);
|
2150
|
+
this.fireEvent('update', this, record, Ext.data.Record.REJECT);
|
2151
|
+
},
|
2152
|
+
|
2153
|
+
// private
|
2154
|
+
afterCommit : function(record){
|
2155
|
+
this.modified.remove(record);
|
2156
|
+
this.fireEvent('update', this, record, Ext.data.Record.COMMIT);
|
2157
|
+
},
|
2158
|
+
|
2159
|
+
/**
|
2160
|
+
* Commit all Records with {@link #getModifiedRecords outstanding changes}. To handle updates for changes,
|
2161
|
+
* subscribe to the Store's {@link #update update event}, and perform updating when the third parameter is
|
2162
|
+
* Ext.data.Record.COMMIT.
|
2163
|
+
*/
|
2164
|
+
commitChanges : function(){
|
2165
|
+
var m = this.modified.slice(0);
|
2166
|
+
this.modified = [];
|
2167
|
+
for(var i = 0, len = m.length; i < len; i++){
|
2168
|
+
m[i].commit();
|
2169
|
+
}
|
2170
|
+
},
|
2171
|
+
|
2172
|
+
/**
|
2173
|
+
* {@link Ext.data.Record#reject Reject} outstanding changes on all {@link #getModifiedRecords modified records}.
|
2174
|
+
*/
|
2175
|
+
rejectChanges : function(){
|
2176
|
+
var m = this.modified.slice(0);
|
2177
|
+
this.modified = [];
|
2178
|
+
for(var i = 0, len = m.length; i < len; i++){
|
2179
|
+
m[i].reject();
|
2180
|
+
}
|
2181
|
+
},
|
2182
|
+
|
2183
|
+
// private
|
2184
|
+
onMetaChange : function(meta, rtype, o){
|
2185
|
+
this.recordType = rtype;
|
2186
|
+
this.fields = rtype.prototype.fields;
|
2187
|
+
delete this.snapshot;
|
2188
|
+
if(meta.sortInfo){
|
2189
|
+
this.sortInfo = meta.sortInfo;
|
2190
|
+
}else if(this.sortInfo && !this.fields.get(this.sortInfo.field)){
|
2191
|
+
delete this.sortInfo;
|
2192
|
+
}
|
2193
|
+
this.modified = [];
|
2194
|
+
this.fireEvent('metachange', this, this.reader.meta);
|
2195
|
+
},
|
2196
|
+
|
2197
|
+
// private
|
2198
|
+
findInsertIndex : function(record){
|
2199
|
+
this.suspendEvents();
|
2200
|
+
var data = this.data.clone();
|
2201
|
+
this.data.add(record);
|
2202
|
+
this.applySort();
|
2203
|
+
var index = this.data.indexOf(record);
|
2204
|
+
this.data = data;
|
2205
|
+
this.resumeEvents();
|
2206
|
+
return index;
|
2207
|
+
},
|
2208
|
+
|
2209
|
+
/**
|
2210
|
+
* Set the value for a property name in this store's {@link #baseParams}. Usage:</p><pre><code>
|
2211
|
+
myStore.setBaseParam('foo', {bar:3});
|
2212
|
+
</code></pre>
|
2213
|
+
* @param {String} name Name of the property to assign
|
2214
|
+
* @param {Mixed} value Value to assign the <tt>name</tt>d property
|
2215
|
+
**/
|
2216
|
+
setBaseParam : function (name, value){
|
2217
|
+
this.baseParams = this.baseParams || {};
|
2218
|
+
this.baseParams[name] = value;
|
2219
|
+
}
|
2220
|
+
});
|
2221
|
+
|
2222
|
+
Ext.reg('store', Ext.data.Store);
|
2223
|
+
|
2224
|
+
/**
|
2225
|
+
* @class Ext.data.Store.Error
|
2226
|
+
* @extends Ext.Error
|
2227
|
+
* Store Error extension.
|
2228
|
+
* @param {String} name
|
2229
|
+
*/
|
2230
|
+
Ext.data.Store.Error = Ext.extend(Ext.Error, {
|
2231
|
+
name: 'Ext.data.Store'
|
2232
|
+
});
|
2233
|
+
Ext.apply(Ext.data.Store.Error.prototype, {
|
2234
|
+
lang: {
|
2235
|
+
'writer-undefined' : 'Attempted to execute a write-action without a DataWriter installed.'
|
2236
|
+
}
|
2237
|
+
});
|
2238
|
+
|
2239
|
+
/**
|
2240
|
+
* @class Ext.data.Field
|
2241
|
+
* <p>This class encapsulates the field definition information specified in the field definition objects
|
2242
|
+
* passed to {@link Ext.data.Record#create}.</p>
|
2243
|
+
* <p>Developers do not need to instantiate this class. Instances are created by {@link Ext.data.Record.create}
|
2244
|
+
* and cached in the {@link Ext.data.Record#fields fields} property of the created Record constructor's <b>prototype.</b></p>
|
2245
|
+
*/
|
2246
|
+
Ext.data.Field = function(config){
|
2247
|
+
if(typeof config == "string"){
|
2248
|
+
config = {name: config};
|
2249
|
+
}
|
2250
|
+
Ext.apply(this, config);
|
2251
|
+
|
2252
|
+
if(!this.type){
|
2253
|
+
this.type = "auto";
|
2254
|
+
}
|
2255
|
+
|
2256
|
+
var st = Ext.data.SortTypes;
|
2257
|
+
// named sortTypes are supported, here we look them up
|
2258
|
+
if(typeof this.sortType == "string"){
|
2259
|
+
this.sortType = st[this.sortType];
|
2260
|
+
}
|
2261
|
+
|
2262
|
+
// set default sortType for strings and dates
|
2263
|
+
if(!this.sortType){
|
2264
|
+
switch(this.type){
|
2265
|
+
case "string":
|
2266
|
+
this.sortType = st.asUCString;
|
2267
|
+
break;
|
2268
|
+
case "date":
|
2269
|
+
this.sortType = st.asDate;
|
2270
|
+
break;
|
2271
|
+
default:
|
2272
|
+
this.sortType = st.none;
|
2273
|
+
}
|
2274
|
+
}
|
2275
|
+
|
2276
|
+
// define once
|
2277
|
+
var stripRe = /[\$,%]/g;
|
2278
|
+
|
2279
|
+
// prebuilt conversion function for this field, instead of
|
2280
|
+
// switching every time we're reading a value
|
2281
|
+
if(!this.convert){
|
2282
|
+
var cv, dateFormat = this.dateFormat;
|
2283
|
+
switch(this.type){
|
2284
|
+
case "":
|
2285
|
+
case "auto":
|
2286
|
+
case undefined:
|
2287
|
+
cv = function(v){ return v; };
|
2288
|
+
break;
|
2289
|
+
case "string":
|
2290
|
+
cv = function(v){ return (v === undefined || v === null) ? '' : String(v); };
|
2291
|
+
break;
|
2292
|
+
case "int":
|
2293
|
+
cv = function(v){
|
2294
|
+
return v !== undefined && v !== null && v !== '' ?
|
2295
|
+
parseInt(String(v).replace(stripRe, ""), 10) : '';
|
2296
|
+
};
|
2297
|
+
break;
|
2298
|
+
case "float":
|
2299
|
+
cv = function(v){
|
2300
|
+
return v !== undefined && v !== null && v !== '' ?
|
2301
|
+
parseFloat(String(v).replace(stripRe, ""), 10) : '';
|
2302
|
+
};
|
2303
|
+
break;
|
2304
|
+
case "bool":
|
2305
|
+
case "boolean":
|
2306
|
+
cv = function(v){ return v === true || v === "true" || v == 1; };
|
2307
|
+
break;
|
2308
|
+
case "date":
|
2309
|
+
cv = function(v){
|
2310
|
+
if(!v){
|
2311
|
+
return '';
|
2312
|
+
}
|
2313
|
+
if(Ext.isDate(v)){
|
2314
|
+
return v;
|
2315
|
+
}
|
2316
|
+
if(dateFormat){
|
2317
|
+
if(dateFormat == "timestamp"){
|
2318
|
+
return new Date(v*1000);
|
2319
|
+
}
|
2320
|
+
if(dateFormat == "time"){
|
2321
|
+
return new Date(parseInt(v, 10));
|
2322
|
+
}
|
2323
|
+
return Date.parseDate(v, dateFormat);
|
2324
|
+
}
|
2325
|
+
var parsed = Date.parse(v);
|
2326
|
+
return parsed ? new Date(parsed) : null;
|
2327
|
+
};
|
2328
|
+
break;
|
2329
|
+
|
2330
|
+
}
|
2331
|
+
this.convert = cv;
|
2332
|
+
}
|
2333
|
+
};
|
2334
|
+
|
2335
|
+
Ext.data.Field.prototype = {
|
2336
|
+
/**
|
2337
|
+
* @cfg {String} name
|
2338
|
+
* The name by which the field is referenced within the Record. This is referenced by, for example,
|
2339
|
+
* the <tt>dataIndex</tt> property in column definition objects passed to {@link Ext.grid.ColumnModel}.
|
2340
|
+
* <p>Note: In the simplest case, if no properties other than <tt>name</tt> are required, a field
|
2341
|
+
* definition may consist of just a String for the field name.</p>
|
2342
|
+
*/
|
2343
|
+
/**
|
2344
|
+
* @cfg {String} type
|
2345
|
+
* (Optional) The data type for conversion to displayable value if <tt>{@link Ext.data.Field#convert convert}</tt>
|
2346
|
+
* has not been specified. Possible values are
|
2347
|
+
* <div class="mdetail-params"><ul>
|
2348
|
+
* <li>auto (Default, implies no conversion)</li>
|
2349
|
+
* <li>string</li>
|
2350
|
+
* <li>int</li>
|
2351
|
+
* <li>float</li>
|
2352
|
+
* <li>boolean</li>
|
2353
|
+
* <li>date</li></ul></div>
|
2354
|
+
*/
|
2355
|
+
/**
|
2356
|
+
* @cfg {Function} convert
|
2357
|
+
* (Optional) A function which converts the value provided by the Reader into an object that will be stored
|
2358
|
+
* in the Record. It is passed the following parameters:<div class="mdetail-params"><ul>
|
2359
|
+
* <li><b>v</b> : Mixed<div class="sub-desc">The data value as read by the Reader, if undefined will use
|
2360
|
+
* the configured <tt>{@link Ext.data.Field#defaultValue defaultValue}</tt>.</div></li>
|
2361
|
+
* <li><b>rec</b> : Mixed<div class="sub-desc">The data object containing the row as read by the Reader.
|
2362
|
+
* Depending on the Reader type, this could be an Array ({@link Ext.data.ArrayReader ArrayReader}), an object
|
2363
|
+
* ({@link Ext.data.JsonReader JsonReader}), or an XML element ({@link Ext.data.XMLReader XMLReader}).</div></li>
|
2364
|
+
* </ul></div>
|
2365
|
+
* <pre><code>
|
2366
|
+
// example of convert function
|
2367
|
+
function fullName(v, record){
|
2368
|
+
return record.name.last + ', ' + record.name.first;
|
2369
|
+
}
|
2370
|
+
|
2371
|
+
function location(v, record){
|
2372
|
+
return !record.city ? '' : (record.city + ', ' + record.state);
|
2373
|
+
}
|
2374
|
+
|
2375
|
+
var Dude = Ext.data.Record.create([
|
2376
|
+
{name: 'fullname', convert: fullName},
|
2377
|
+
{name: 'firstname', mapping: 'name.first'},
|
2378
|
+
{name: 'lastname', mapping: 'name.last'},
|
2379
|
+
{name: 'city', defaultValue: 'homeless'},
|
2380
|
+
'state',
|
2381
|
+
{name: 'location', convert: location}
|
2382
|
+
]);
|
2383
|
+
|
2384
|
+
// create the data store
|
2385
|
+
var store = new Ext.data.Store({
|
2386
|
+
reader: new Ext.data.JsonReader(
|
2387
|
+
{
|
2388
|
+
idProperty: 'key',
|
2389
|
+
root: 'daRoot',
|
2390
|
+
totalProperty: 'total'
|
2391
|
+
},
|
2392
|
+
Dude // recordType
|
2393
|
+
)
|
2394
|
+
});
|
2395
|
+
|
2396
|
+
var myData = [
|
2397
|
+
{ key: 1,
|
2398
|
+
name: { first: 'Fat', last: 'Albert' }
|
2399
|
+
// notice no city, state provided in data object
|
2400
|
+
},
|
2401
|
+
{ key: 2,
|
2402
|
+
name: { first: 'Barney', last: 'Rubble' },
|
2403
|
+
city: 'Bedrock', state: 'Stoneridge'
|
2404
|
+
},
|
2405
|
+
{ key: 3,
|
2406
|
+
name: { first: 'Cliff', last: 'Claven' },
|
2407
|
+
city: 'Boston', state: 'MA'
|
2408
|
+
}
|
2409
|
+
];
|
2410
|
+
* </code></pre>
|
2411
|
+
*/
|
2412
|
+
/**
|
2413
|
+
* @cfg {String} dateFormat
|
2414
|
+
* (Optional) A format string for the {@link Date#parseDate Date.parseDate} function, or "timestamp" if the
|
2415
|
+
* value provided by the Reader is a UNIX timestamp, or "time" if the value provided by the Reader is a
|
2416
|
+
* javascript millisecond timestamp.
|
2417
|
+
*/
|
2418
|
+
dateFormat: null,
|
2419
|
+
/**
|
2420
|
+
* @cfg {Mixed} defaultValue
|
2421
|
+
* (Optional) The default value used <b>when a Record is being created by a {@link Ext.data.Reader Reader}</b>
|
2422
|
+
* when the item referenced by the <tt>{@link Ext.data.Field#mapping mapping}</tt> does not exist in the data
|
2423
|
+
* object (i.e. undefined). (defaults to "")
|
2424
|
+
*/
|
2425
|
+
defaultValue: "",
|
2426
|
+
/**
|
2427
|
+
* @cfg {String/Number} mapping
|
2428
|
+
* <p>(Optional) A path expression for use by the {@link Ext.data.DataReader} implementation
|
2429
|
+
* that is creating the {@link Ext.data.Record Record} to extract the Field value from the data object.
|
2430
|
+
* If the path expression is the same as the field name, the mapping may be omitted.</p>
|
2431
|
+
* <p>The form of the mapping expression depends on the Reader being used.</p>
|
2432
|
+
* <div class="mdetail-params"><ul>
|
2433
|
+
* <li>{@link Ext.data.JsonReader}<div class="sub-desc">The mapping is a string containing the javascript
|
2434
|
+
* expression to reference the data from an element of the data item's {@link Ext.data.JsonReader#root root} Array. Defaults to the field name.</div></li>
|
2435
|
+
* <li>{@link Ext.data.XmlReader}<div class="sub-desc">The mapping is an {@link Ext.DomQuery} path to the data
|
2436
|
+
* item relative to the DOM element that represents the {@link Ext.data.XmlReader#record record}. Defaults to the field name.</div></li>
|
2437
|
+
* <li>{@link Ext.data.ArrayReader}<div class="sub-desc">The mapping is a number indicating the Array index
|
2438
|
+
* of the field's value. Defaults to the field specification's Array position.</div></li>
|
2439
|
+
* </ul></div>
|
2440
|
+
* <p>If a more complex value extraction strategy is required, then configure the Field with a {@link #convert}
|
2441
|
+
* function. This is passed the whole row object, and may interrogate it in whatever way is necessary in order to
|
2442
|
+
* return the desired data.</p>
|
2443
|
+
*/
|
2444
|
+
mapping: null,
|
2445
|
+
/**
|
2446
|
+
* @cfg {Function} sortType
|
2447
|
+
* (Optional) A function which converts a Field's value to a comparable value in order to ensure
|
2448
|
+
* correct sort ordering. Predefined functions are provided in {@link Ext.data.SortTypes}. A custom
|
2449
|
+
* sort example:<pre><code>
|
2450
|
+
// current sort after sort we want
|
2451
|
+
// +-+------+ +-+------+
|
2452
|
+
// |1|First | |1|First |
|
2453
|
+
// |2|Last | |3|Second|
|
2454
|
+
// |3|Second| |2|Last |
|
2455
|
+
// +-+------+ +-+------+
|
2456
|
+
|
2457
|
+
sortType: function(value) {
|
2458
|
+
switch (value.toLowerCase()) // native toLowerCase():
|
2459
|
+
{
|
2460
|
+
case 'first': return 1;
|
2461
|
+
case 'second': return 2;
|
2462
|
+
default: return 3;
|
2463
|
+
}
|
2464
|
+
}
|
2465
|
+
* </code></pre>
|
2466
|
+
*/
|
2467
|
+
sortType : null,
|
2468
|
+
/**
|
2469
|
+
* @cfg {String} sortDir
|
2470
|
+
* (Optional) Initial direction to sort (<tt>"ASC"</tt> or <tt>"DESC"</tt>). Defaults to
|
2471
|
+
* <tt>"ASC"</tt>.
|
2472
|
+
*/
|
2473
|
+
sortDir : "ASC",
|
2474
|
+
/**
|
2475
|
+
* @cfg {Boolean} allowBlank
|
2476
|
+
* (Optional) Used for validating a {@link Ext.data.Record record}, defaults to <tt>true</tt>.
|
2477
|
+
* An empty value here will cause {@link Ext.data.Record}.{@link Ext.data.Record#isValid isValid}
|
2478
|
+
* to evaluate to <tt>false</tt>.
|
2479
|
+
*/
|
2480
|
+
allowBlank : true
|
2481
|
+
};/**
|
2482
|
+
* @class Ext.data.DataReader
|
2483
|
+
* Abstract base class for reading structured data from a data source and converting
|
2484
|
+
* it into an object containing {@link Ext.data.Record} objects and metadata for use
|
2485
|
+
* by an {@link Ext.data.Store}. This class is intended to be extended and should not
|
2486
|
+
* be created directly. For existing implementations, see {@link Ext.data.ArrayReader},
|
2487
|
+
* {@link Ext.data.JsonReader} and {@link Ext.data.XmlReader}.
|
2488
|
+
* @constructor Create a new DataReader
|
2489
|
+
* @param {Object} meta Metadata configuration options (implementation-specific).
|
2490
|
+
* @param {Array/Object} recordType
|
2491
|
+
* <p>Either an Array of {@link Ext.data.Field Field} definition objects (which
|
2492
|
+
* will be passed to {@link Ext.data.Record#create}, or a {@link Ext.data.Record Record}
|
2493
|
+
* constructor created using {@link Ext.data.Record#create}.</p>
|
2494
|
+
*/
|
2495
|
+
Ext.data.DataReader = function(meta, recordType){
|
2496
|
+
/**
|
2497
|
+
* This DataReader's configured metadata as passed to the constructor.
|
2498
|
+
* @type Mixed
|
2499
|
+
* @property meta
|
2500
|
+
*/
|
2501
|
+
this.meta = meta;
|
2502
|
+
/**
|
2503
|
+
* @cfg {Array/Object} fields
|
2504
|
+
* <p>Either an Array of {@link Ext.data.Field Field} definition objects (which
|
2505
|
+
* will be passed to {@link Ext.data.Record#create}, or a {@link Ext.data.Record Record}
|
2506
|
+
* constructor created from {@link Ext.data.Record#create}.</p>
|
2507
|
+
*/
|
2508
|
+
this.recordType = Ext.isArray(recordType) ?
|
2509
|
+
Ext.data.Record.create(recordType) : recordType;
|
2510
|
+
};
|
2511
|
+
|
2512
|
+
Ext.data.DataReader.prototype = {
|
2513
|
+
|
2514
|
+
/**
|
2515
|
+
* Abstract method, overridden in {@link Ext.data.JsonReader}
|
2516
|
+
*/
|
2517
|
+
buildExtractors : Ext.emptyFn,
|
2518
|
+
|
2519
|
+
/**
|
2520
|
+
* Used for un-phantoming a record after a successful database insert. Sets the records pk along with new data from server.
|
2521
|
+
* You <b>must</b> return at least the database pk using the idProperty defined in your DataReader configuration. The incoming
|
2522
|
+
* data from server will be merged with the data in the local record.
|
2523
|
+
* In addition, you <b>must</b> return record-data from the server in the same order received.
|
2524
|
+
* Will perform a commit as well, un-marking dirty-fields. Store's "update" event will be suppressed.
|
2525
|
+
* @param {Record/Record[]} record The phantom record to be realized.
|
2526
|
+
* @param {Object/Object[]} data The new record data to apply. Must include the primary-key from database defined in idProperty field.
|
2527
|
+
*/
|
2528
|
+
realize: function(rs, data){
|
2529
|
+
if (Ext.isArray(rs)) {
|
2530
|
+
for (var i = rs.length - 1; i >= 0; i--) {
|
2531
|
+
// recurse
|
2532
|
+
if (Ext.isArray(data)) {
|
2533
|
+
this.realize(rs.splice(i,1).shift(), data.splice(i,1).shift());
|
2534
|
+
}
|
2535
|
+
else {
|
2536
|
+
// weird...rs is an array but data isn't?? recurse but just send in the whole invalid data object.
|
2537
|
+
// the else clause below will detect !this.isData and throw exception.
|
2538
|
+
this.realize(rs.splice(i,1).shift(), data);
|
2539
|
+
}
|
2540
|
+
}
|
2541
|
+
}
|
2542
|
+
else {
|
2543
|
+
// If rs is NOT an array but data IS, see if data contains just 1 record. If so extract it and carry on.
|
2544
|
+
if (Ext.isArray(data) && data.length == 1) {
|
2545
|
+
data = data.shift();
|
2546
|
+
}
|
2547
|
+
if (!this.isData(data)) {
|
2548
|
+
// TODO: Let exception-handler choose to commit or not rather than blindly rs.commit() here.
|
2549
|
+
//rs.commit();
|
2550
|
+
throw new Ext.data.DataReader.Error('realize', rs);
|
2551
|
+
}
|
2552
|
+
this.buildExtractors();
|
2553
|
+
var values = this.extractValues(data, rs.fields.items, rs.fields.items.length);
|
2554
|
+
rs.phantom = false; // <-- That's what it's all about
|
2555
|
+
rs._phid = rs.id; // <-- copy phantom-id -> _phid, so we can remap in Store#onCreateRecords
|
2556
|
+
rs.id = data[this.meta.idProperty];
|
2557
|
+
rs.data = values;
|
2558
|
+
rs.commit();
|
2559
|
+
}
|
2560
|
+
},
|
2561
|
+
|
2562
|
+
/**
|
2563
|
+
* Used for updating a non-phantom or "real" record's data with fresh data from server after remote-save.
|
2564
|
+
* You <b>must</b> return a complete new record from the server. If you don't, your local record's missing fields
|
2565
|
+
* will be populated with the default values specified in your Ext.data.Record.create specification. Without a defaultValue,
|
2566
|
+
* local fields will be populated with empty string "". So return your entire record's data after both remote create and update.
|
2567
|
+
* In addition, you <b>must</b> return record-data from the server in the same order received.
|
2568
|
+
* Will perform a commit as well, un-marking dirty-fields. Store's "update" event will be suppressed as the record receives
|
2569
|
+
* a fresh new data-hash.
|
2570
|
+
* @param {Record/Record[]} rs
|
2571
|
+
* @param {Object/Object[]} data
|
2572
|
+
*/
|
2573
|
+
update : function(rs, data) {
|
2574
|
+
if (Ext.isArray(rs)) {
|
2575
|
+
for (var i=rs.length-1; i >= 0; i--) {
|
2576
|
+
if (Ext.isArray(data)) {
|
2577
|
+
this.update(rs.splice(i,1).shift(), data.splice(i,1).shift());
|
2578
|
+
}
|
2579
|
+
else {
|
2580
|
+
// weird...rs is an array but data isn't?? recurse but just send in the whole data object.
|
2581
|
+
// the else clause below will detect !this.isData and throw exception.
|
2582
|
+
this.update(rs.splice(i,1).shift(), data);
|
2583
|
+
}
|
2584
|
+
}
|
2585
|
+
}
|
2586
|
+
else {
|
2587
|
+
// If rs is NOT an array but data IS, see if data contains just 1 record. If so extract it and carry on.
|
2588
|
+
if (Ext.isArray(data) && data.length == 1) {
|
2589
|
+
data = data.shift();
|
2590
|
+
}
|
2591
|
+
if (!this.isData(data)) {
|
2592
|
+
// TODO: create custom Exception class to return record in thrown exception. Allow exception-handler the choice
|
2593
|
+
// to commit or not rather than blindly rs.commit() here.
|
2594
|
+
rs.commit();
|
2595
|
+
throw new Ext.data.DataReader.Error('update', rs);
|
2596
|
+
}
|
2597
|
+
this.buildExtractors();
|
2598
|
+
rs.data = this.extractValues(Ext.apply(rs.data, data), rs.fields.items, rs.fields.items.length);
|
2599
|
+
rs.commit();
|
2600
|
+
}
|
2601
|
+
},
|
2602
|
+
|
2603
|
+
/**
|
2604
|
+
* Returns true if the supplied data-hash <b>looks</b> and quacks like data. Checks to see if it has a key
|
2605
|
+
* corresponding to idProperty defined in your DataReader config containing non-empty pk.
|
2606
|
+
* @param {Object} data
|
2607
|
+
* @return {Boolean}
|
2608
|
+
*/
|
2609
|
+
isData : function(data) {
|
2610
|
+
return (data && Ext.isObject(data) && !Ext.isEmpty(data[this.meta.idProperty])) ? true : false;
|
2611
|
+
}
|
2612
|
+
};
|
2613
|
+
|
2614
|
+
/**
|
2615
|
+
* @class Ext.data.DataReader.Error
|
2616
|
+
* @extends Ext.Error
|
2617
|
+
* General error class for Ext.data.DataReader
|
2618
|
+
*/
|
2619
|
+
Ext.data.DataReader.Error = Ext.extend(Ext.Error, {
|
2620
|
+
constructor : function(message, arg) {
|
2621
|
+
this.arg = arg;
|
2622
|
+
Ext.Error.call(this, message);
|
2623
|
+
},
|
2624
|
+
name: 'Ext.data.DataReader'
|
2625
|
+
});
|
2626
|
+
Ext.apply(Ext.data.DataReader.Error.prototype, {
|
2627
|
+
lang : {
|
2628
|
+
'update': "#update received invalid data from server. Please see docs for DataReader#update and review your DataReader configuration.",
|
2629
|
+
'realize': "#realize was called with invalid remote-data. Please see the docs for DataReader#realize and review your DataReader configuration.",
|
2630
|
+
'invalid-response': "#readResponse received an invalid response from the server."
|
2631
|
+
}
|
2632
|
+
});
|
2633
|
+
|
2634
|
+
|
2635
|
+
/**
|
2636
|
+
* @class Ext.data.DataWriter
|
2637
|
+
* <p>Ext.data.DataWriter facilitates create, update, and destroy actions between
|
2638
|
+
* an Ext.data.Store and a server-side framework. A Writer enabled Store will
|
2639
|
+
* automatically manage the Ajax requests to perform CRUD actions on a Store.</p>
|
2640
|
+
* <p>Ext.data.DataWriter is an abstract base class which is intended to be extended
|
2641
|
+
* and should not be created directly. For existing implementations, see
|
2642
|
+
* {@link Ext.data.JsonWriter}.</p>
|
2643
|
+
* <p>Creating a writer is simple:</p>
|
2644
|
+
* <pre><code>
|
2645
|
+
var writer = new Ext.data.JsonWriter();
|
2646
|
+
* </code></pre>
|
2647
|
+
* <p>The proxy for a writer enabled store can be configured with a simple <code>url</code>:</p>
|
2648
|
+
* <pre><code>
|
2649
|
+
// Create a standard HttpProxy instance.
|
2650
|
+
var proxy = new Ext.data.HttpProxy({
|
2651
|
+
url: 'app.php/users'
|
2652
|
+
});
|
2653
|
+
* </code></pre>
|
2654
|
+
* <p>For finer grained control, the proxy may also be configured with an <code>api</code>:</p>
|
2655
|
+
* <pre><code>
|
2656
|
+
// Use the api specification
|
2657
|
+
var proxy = new Ext.data.HttpProxy({
|
2658
|
+
api: {
|
2659
|
+
read : 'app.php/users/read',
|
2660
|
+
create : 'app.php/users/create',
|
2661
|
+
update : 'app.php/users/update',
|
2662
|
+
destroy : 'app.php/users/destroy'
|
2663
|
+
}
|
2664
|
+
});
|
2665
|
+
* </code></pre>
|
2666
|
+
* <p>Creating a Writer enabled store:</p>
|
2667
|
+
* <pre><code>
|
2668
|
+
var store = new Ext.data.Store({
|
2669
|
+
proxy: proxy,
|
2670
|
+
reader: reader,
|
2671
|
+
writer: writer
|
2672
|
+
});
|
2673
|
+
* </code></pre>
|
2674
|
+
* @constructor Create a new DataWriter
|
2675
|
+
* @param {Object} meta Metadata configuration options (implementation-specific)
|
2676
|
+
* @param {Object} recordType Either an Array of field definition objects as specified
|
2677
|
+
* in {@link Ext.data.Record#create}, or an {@link Ext.data.Record} object created
|
2678
|
+
* using {@link Ext.data.Record#create}.
|
2679
|
+
*/
|
2680
|
+
Ext.data.DataWriter = function(config){
|
2681
|
+
/**
|
2682
|
+
* This DataWriter's configured metadata as passed to the constructor.
|
2683
|
+
* @type Mixed
|
2684
|
+
* @property meta
|
2685
|
+
*/
|
2686
|
+
Ext.apply(this, config);
|
2687
|
+
};
|
2688
|
+
|
2689
|
+
Ext.data.DataWriter.prototype = {
|
2690
|
+
|
2691
|
+
/**
|
2692
|
+
* @cfg {Boolean} writeAllFields
|
2693
|
+
* <tt>false</tt> by default. Set <tt>true</tt> to have DataWriter return ALL fields of a modified
|
2694
|
+
* record -- not just those that changed.
|
2695
|
+
* <tt>false</tt> to have DataWriter only request modified fields from a record.
|
2696
|
+
*/
|
2697
|
+
writeAllFields : false,
|
2698
|
+
/**
|
2699
|
+
* @cfg {Boolean} listful
|
2700
|
+
* <tt>false</tt> by default. Set <tt>true</tt> to have the DataWriter <b>always</b> write HTTP params as a list,
|
2701
|
+
* even when acting upon a single record.
|
2702
|
+
*/
|
2703
|
+
listful : false, // <-- listful is actually not used internally here in DataWriter. @see Ext.data.Store#execute.
|
2704
|
+
|
2705
|
+
/**
|
2706
|
+
* Writes data in preparation for server-write action. Simply proxies to DataWriter#update, DataWriter#create
|
2707
|
+
* DataWriter#destroy.
|
2708
|
+
* @param {String} action [CREATE|UPDATE|DESTROY]
|
2709
|
+
* @param {Object} params The params-hash to write-to
|
2710
|
+
* @param {Record/Record[]} rs The recordset write.
|
2711
|
+
*/
|
2712
|
+
write : function(action, params, rs) {
|
2713
|
+
this.render(action, rs, params, this[action](rs));
|
2714
|
+
},
|
2715
|
+
|
2716
|
+
/**
|
2717
|
+
* abstract method meant to be overridden by all DataWriter extensions. It's the extension's job to apply the "data" to the "params".
|
2718
|
+
* The data-object provided to render is populated with data according to the meta-info defined in the user's DataReader config,
|
2719
|
+
* @param {String} action [Ext.data.Api.actions.create|read|update|destroy]
|
2720
|
+
* @param {Record[]} rs Store recordset
|
2721
|
+
* @param {Object} params Http params to be sent to server.
|
2722
|
+
* @param {Object} data object populated according to DataReader meta-data.
|
2723
|
+
*/
|
2724
|
+
render : Ext.emptyFn,
|
2725
|
+
|
2726
|
+
/**
|
2727
|
+
* update
|
2728
|
+
* @param {Object} p Params-hash to apply result to.
|
2729
|
+
* @param {Record/Record[]} rs Record(s) to write
|
2730
|
+
* @private
|
2731
|
+
*/
|
2732
|
+
update : function(rs) {
|
2733
|
+
var params = {};
|
2734
|
+
if (Ext.isArray(rs)) {
|
2735
|
+
var data = [],
|
2736
|
+
ids = [];
|
2737
|
+
Ext.each(rs, function(val){
|
2738
|
+
ids.push(val.id);
|
2739
|
+
data.push(this.updateRecord(val));
|
2740
|
+
}, this);
|
2741
|
+
params[this.meta.idProperty] = ids;
|
2742
|
+
params[this.meta.root] = data;
|
2743
|
+
}
|
2744
|
+
else if (rs instanceof Ext.data.Record) {
|
2745
|
+
params[this.meta.idProperty] = rs.id;
|
2746
|
+
params[this.meta.root] = this.updateRecord(rs);
|
2747
|
+
}
|
2748
|
+
return params;
|
2749
|
+
},
|
2750
|
+
|
2751
|
+
/**
|
2752
|
+
* @cfg {Function} saveRecord Abstract method that should be implemented in all subclasses
|
2753
|
+
* (e.g.: {@link Ext.data.JsonWriter#saveRecord JsonWriter.saveRecord}
|
2754
|
+
*/
|
2755
|
+
updateRecord : Ext.emptyFn,
|
2756
|
+
|
2757
|
+
/**
|
2758
|
+
* create
|
2759
|
+
* @param {Object} p Params-hash to apply result to.
|
2760
|
+
* @param {Record/Record[]} rs Record(s) to write
|
2761
|
+
* @private
|
2762
|
+
*/
|
2763
|
+
create : function(rs) {
|
2764
|
+
var params = {};
|
2765
|
+
if (Ext.isArray(rs)) {
|
2766
|
+
var data = [];
|
2767
|
+
Ext.each(rs, function(val){
|
2768
|
+
data.push(this.createRecord(val));
|
2769
|
+
}, this);
|
2770
|
+
params[this.meta.root] = data;
|
2771
|
+
}
|
2772
|
+
else if (rs instanceof Ext.data.Record) {
|
2773
|
+
params[this.meta.root] = this.createRecord(rs);
|
2774
|
+
}
|
2775
|
+
return params;
|
2776
|
+
},
|
2777
|
+
|
2778
|
+
/**
|
2779
|
+
* @cfg {Function} createRecord Abstract method that should be implemented in all subclasses
|
2780
|
+
* (e.g.: {@link Ext.data.JsonWriter#createRecord JsonWriter.createRecord})
|
2781
|
+
*/
|
2782
|
+
createRecord : Ext.emptyFn,
|
2783
|
+
|
2784
|
+
/**
|
2785
|
+
* destroy
|
2786
|
+
* @param {Object} p Params-hash to apply result to.
|
2787
|
+
* @param {Record/Record[]} rs Record(s) to write
|
2788
|
+
* @private
|
2789
|
+
*/
|
2790
|
+
destroy : function(rs) {
|
2791
|
+
var params = {};
|
2792
|
+
if (Ext.isArray(rs)) {
|
2793
|
+
var data = [],
|
2794
|
+
ids = [];
|
2795
|
+
Ext.each(rs, function(val){
|
2796
|
+
data.push(this.destroyRecord(val));
|
2797
|
+
}, this);
|
2798
|
+
params[this.meta.root] = data;
|
2799
|
+
} else if (rs instanceof Ext.data.Record) {
|
2800
|
+
params[this.meta.root] = this.destroyRecord(rs);
|
2801
|
+
}
|
2802
|
+
return params;
|
2803
|
+
},
|
2804
|
+
|
2805
|
+
/**
|
2806
|
+
* @cfg {Function} destroyRecord Abstract method that should be implemented in all subclasses
|
2807
|
+
* (e.g.: {@link Ext.data.JsonWriter#destroyRecord JsonWriter.destroyRecord})
|
2808
|
+
*/
|
2809
|
+
destroyRecord : Ext.emptyFn,
|
2810
|
+
|
2811
|
+
/**
|
2812
|
+
* Converts a Record to a hash
|
2813
|
+
* @param {Record}
|
2814
|
+
* @private
|
2815
|
+
*/
|
2816
|
+
toHash : function(rec) {
|
2817
|
+
var map = rec.fields.map,
|
2818
|
+
data = {},
|
2819
|
+
raw = (this.writeAllFields === false && rec.phantom === false) ? rec.getChanges() : rec.data,
|
2820
|
+
m;
|
2821
|
+
Ext.iterate(raw, function(prop, value){
|
2822
|
+
if((m = map[prop])){
|
2823
|
+
data[m.mapping ? m.mapping : m.name] = value;
|
2824
|
+
}
|
2825
|
+
});
|
2826
|
+
data[this.meta.idProperty] = rec.id;
|
2827
|
+
return data;
|
2828
|
+
}
|
2829
|
+
};/**
|
2830
|
+
* @class Ext.data.DataProxy
|
2831
|
+
* @extends Ext.util.Observable
|
2832
|
+
* <p>Abstract base class for implementations which provide retrieval of unformatted data objects.
|
2833
|
+
* This class is intended to be extended and should not be created directly. For existing implementations,
|
2834
|
+
* see {@link Ext.data.DirectProxy}, {@link Ext.data.HttpProxy}, {@link Ext.data.ScriptTagProxy} and
|
2835
|
+
* {@link Ext.data.MemoryProxy}.</p>
|
2836
|
+
* <p>DataProxy implementations are usually used in conjunction with an implementation of {@link Ext.data.DataReader}
|
2837
|
+
* (of the appropriate type which knows how to parse the data object) to provide a block of
|
2838
|
+
* {@link Ext.data.Records} to an {@link Ext.data.Store}.</p>
|
2839
|
+
* <p>The parameter to a DataProxy constructor may be an {@link Ext.data.Connection} or can also be the
|
2840
|
+
* config object to an {@link Ext.data.Connection}.</p>
|
2841
|
+
* <p>Custom implementations must implement either the <code><b>doRequest</b></code> method (preferred) or the
|
2842
|
+
* <code>load</code> method (deprecated). See
|
2843
|
+
* {@link Ext.data.HttpProxy}.{@link Ext.data.HttpProxy#doRequest doRequest} or
|
2844
|
+
* {@link Ext.data.HttpProxy}.{@link Ext.data.HttpProxy#load load} for additional details.</p>
|
2845
|
+
* <p><b><u>Example 1</u></b></p>
|
2846
|
+
* <pre><code>
|
2847
|
+
proxy: new Ext.data.ScriptTagProxy({
|
2848
|
+
{@link Ext.data.Connection#url url}: 'http://extjs.com/forum/topics-remote.php'
|
2849
|
+
}),
|
2850
|
+
* </code></pre>
|
2851
|
+
* <p><b><u>Example 2</u></b></p>
|
2852
|
+
* <pre><code>
|
2853
|
+
proxy : new Ext.data.HttpProxy({
|
2854
|
+
{@link Ext.data.Connection#method method}: 'GET',
|
2855
|
+
{@link Ext.data.HttpProxy#prettyUrls prettyUrls}: false,
|
2856
|
+
{@link Ext.data.Connection#url url}: 'local/default.php', // see options parameter for {@link Ext.Ajax#request}
|
2857
|
+
{@link #api}: {
|
2858
|
+
// all actions except the following will use above url
|
2859
|
+
create : 'local/new.php',
|
2860
|
+
update : 'local/update.php'
|
2861
|
+
}
|
2862
|
+
}),
|
2863
|
+
* </code></pre>
|
2864
|
+
*/
|
2865
|
+
Ext.data.DataProxy = function(conn){
|
2866
|
+
// make sure we have a config object here to support ux proxies.
|
2867
|
+
// All proxies should now send config into superclass constructor.
|
2868
|
+
conn = conn || {};
|
2869
|
+
|
2870
|
+
// This line caused a bug when people use custom Connection object having its own request method.
|
2871
|
+
// http://extjs.com/forum/showthread.php?t=67194. Have to set DataProxy config
|
2872
|
+
//Ext.applyIf(this, conn);
|
2873
|
+
|
2874
|
+
this.api = conn.api;
|
2875
|
+
this.url = conn.url;
|
2876
|
+
this.restful = conn.restful;
|
2877
|
+
this.listeners = conn.listeners;
|
2878
|
+
|
2879
|
+
// deprecated
|
2880
|
+
this.prettyUrls = conn.prettyUrls;
|
2881
|
+
|
2882
|
+
/**
|
2883
|
+
* @cfg {Object} api
|
2884
|
+
* Specific urls to call on CRUD action methods "read", "create", "update" and "destroy".
|
2885
|
+
* Defaults to:<pre><code>
|
2886
|
+
api: {
|
2887
|
+
read : undefined,
|
2888
|
+
create : undefined,
|
2889
|
+
update : undefined,
|
2890
|
+
destroy : undefined
|
2891
|
+
}
|
2892
|
+
</code></pre>
|
2893
|
+
* <p>If the specific URL for a given CRUD action is undefined, the CRUD action request
|
2894
|
+
* will be directed to the configured <tt>{@link Ext.data.Connection#url url}</tt>.</p>
|
2895
|
+
* <br><p><b>Note</b>: To modify the URL for an action dynamically the appropriate API
|
2896
|
+
* property should be modified before the action is requested using the corresponding before
|
2897
|
+
* action event. For example to modify the URL associated with the load action:
|
2898
|
+
* <pre><code>
|
2899
|
+
// modify the url for the action
|
2900
|
+
myStore.on({
|
2901
|
+
beforeload: {
|
2902
|
+
fn: function (store, options) {
|
2903
|
+
// use <tt>{@link Ext.data.HttpProxy#setUrl setUrl}</tt> to change the URL for *just* this request.
|
2904
|
+
store.proxy.setUrl('changed1.php');
|
2905
|
+
|
2906
|
+
// set optional second parameter to true to make this URL change
|
2907
|
+
// permanent, applying this URL for all subsequent requests.
|
2908
|
+
store.proxy.setUrl('changed1.php', true);
|
2909
|
+
|
2910
|
+
// manually set the <b>private</b> connection URL.
|
2911
|
+
// <b>Warning:</b> Accessing the private URL property should be avoided.
|
2912
|
+
// Use the public method <tt>{@link Ext.data.HttpProxy#setUrl setUrl}</tt> instead, shown above.
|
2913
|
+
// It should be noted that changing the URL like this will affect
|
2914
|
+
// the URL for just this request. Subsequent requests will use the
|
2915
|
+
// API or URL defined in your initial proxy configuration.
|
2916
|
+
store.proxy.conn.url = 'changed1.php';
|
2917
|
+
|
2918
|
+
// proxy URL will be superseded by API (only if proxy created to use ajax):
|
2919
|
+
// It should be noted that proxy API changes are permanent and will
|
2920
|
+
// be used for all subsequent requests.
|
2921
|
+
store.proxy.api.load = 'changed2.php';
|
2922
|
+
|
2923
|
+
// However, altering the proxy API should be done using the public
|
2924
|
+
// method <tt>{@link Ext.data.DataProxy#setApi setApi}</tt> instead.
|
2925
|
+
store.proxy.setApi('load', 'changed2.php');
|
2926
|
+
|
2927
|
+
// Or set the entire API with a config-object.
|
2928
|
+
// When using the config-object option, you must redefine the <b>entire</b>
|
2929
|
+
// API -- not just a specific action of it.
|
2930
|
+
store.proxy.setApi({
|
2931
|
+
read : 'changed_read.php',
|
2932
|
+
create : 'changed_create.php',
|
2933
|
+
update : 'changed_update.php',
|
2934
|
+
destroy : 'changed_destroy.php'
|
2935
|
+
});
|
2936
|
+
}
|
2937
|
+
}
|
2938
|
+
});
|
2939
|
+
* </code></pre>
|
2940
|
+
* </p>
|
2941
|
+
*/
|
2942
|
+
// Prepare the proxy api. Ensures all API-actions are defined with the Object-form.
|
2943
|
+
try {
|
2944
|
+
Ext.data.Api.prepare(this);
|
2945
|
+
} catch (e) {
|
2946
|
+
if (e instanceof Ext.data.Api.Error) {
|
2947
|
+
e.toConsole();
|
2948
|
+
}
|
2949
|
+
}
|
2950
|
+
|
2951
|
+
this.addEvents(
|
2952
|
+
/**
|
2953
|
+
* @event exception
|
2954
|
+
* <p>Fires if an exception occurs in the Proxy during a remote request.
|
2955
|
+
* This event is relayed through a corresponding
|
2956
|
+
* {@link Ext.data.Store}.{@link Ext.data.Store#exception exception},
|
2957
|
+
* so any Store instance may observe this event.
|
2958
|
+
* This event can be fired for one of two reasons:</p>
|
2959
|
+
* <div class="mdetail-params"><ul>
|
2960
|
+
* <li>remote-request <b>failed</b> : <div class="sub-desc">
|
2961
|
+
* The server did not return status === 200.
|
2962
|
+
* </div></li>
|
2963
|
+
* <li>remote-request <b>succeeded</b> : <div class="sub-desc">
|
2964
|
+
* The remote-request succeeded but the reader could not read the response.
|
2965
|
+
* This means the server returned data, but the configured Reader threw an
|
2966
|
+
* error while reading the response. In this case, this event will be
|
2967
|
+
* raised and the caught error will be passed along into this event.
|
2968
|
+
* </div></li>
|
2969
|
+
* </ul></div>
|
2970
|
+
* <br><p>This event fires with two different contexts based upon the 2nd
|
2971
|
+
* parameter <tt>type [remote|response]</tt>. The first four parameters
|
2972
|
+
* are identical between the two contexts -- only the final two parameters
|
2973
|
+
* differ.</p>
|
2974
|
+
* @param {DataProxy} this The proxy that sent the request
|
2975
|
+
* @param {String} type
|
2976
|
+
* <p>The value of this parameter will be either <tt>'response'</tt> or <tt>'remote'</tt>.</p>
|
2977
|
+
* <div class="mdetail-params"><ul>
|
2978
|
+
* <li><b><tt>'response'</tt></b> : <div class="sub-desc">
|
2979
|
+
* <p>An <b>invalid</b> response from the server was returned: either 404,
|
2980
|
+
* 500 or the response meta-data does not match that defined in the DataReader
|
2981
|
+
* (e.g.: root, idProperty, successProperty).</p>
|
2982
|
+
* </div></li>
|
2983
|
+
* <li><b><tt>'remote'</tt></b> : <div class="sub-desc">
|
2984
|
+
* <p>A <b>valid</b> response was returned from the server having
|
2985
|
+
* successProperty === false. This response might contain an error-message
|
2986
|
+
* sent from the server. For example, the user may have failed
|
2987
|
+
* authentication/authorization or a database validation error occurred.</p>
|
2988
|
+
* </div></li>
|
2989
|
+
* </ul></div>
|
2990
|
+
* @param {String} action Name of the action (see {@link Ext.data.Api#actions}.
|
2991
|
+
* @param {Object} options The options for the action that were specified in the {@link #request}.
|
2992
|
+
* @param {Object} response
|
2993
|
+
* <p>The value of this parameter depends on the value of the <code>type</code> parameter:</p>
|
2994
|
+
* <div class="mdetail-params"><ul>
|
2995
|
+
* <li><b><tt>'response'</tt></b> : <div class="sub-desc">
|
2996
|
+
* <p>The raw browser response object (e.g.: XMLHttpRequest)</p>
|
2997
|
+
* </div></li>
|
2998
|
+
* <li><b><tt>'remote'</tt></b> : <div class="sub-desc">
|
2999
|
+
* <p>The decoded response object sent from the server.</p>
|
3000
|
+
* </div></li>
|
3001
|
+
* </ul></div>
|
3002
|
+
* @param {Mixed} arg
|
3003
|
+
* <p>The type and value of this parameter depends on the value of the <code>type</code> parameter:</p>
|
3004
|
+
* <div class="mdetail-params"><ul>
|
3005
|
+
* <li><b><tt>'response'</tt></b> : Error<div class="sub-desc">
|
3006
|
+
* <p>The JavaScript Error object caught if the configured Reader could not read the data.
|
3007
|
+
* If the remote request returns success===false, this parameter will be null.</p>
|
3008
|
+
* </div></li>
|
3009
|
+
* <li><b><tt>'remote'</tt></b> : Record/Record[]<div class="sub-desc">
|
3010
|
+
* <p>This parameter will only exist if the <tt>action</tt> was a <b>write</b> action
|
3011
|
+
* (Ext.data.Api.actions.create|update|destroy).</p>
|
3012
|
+
* </div></li>
|
3013
|
+
* </ul></div>
|
3014
|
+
*/
|
3015
|
+
'exception',
|
3016
|
+
/**
|
3017
|
+
* @event beforeload
|
3018
|
+
* Fires before a request to retrieve a data object.
|
3019
|
+
* @param {DataProxy} this The proxy for the request
|
3020
|
+
* @param {Object} params The params object passed to the {@link #request} function
|
3021
|
+
*/
|
3022
|
+
'beforeload',
|
3023
|
+
/**
|
3024
|
+
* @event load
|
3025
|
+
* Fires before the load method's callback is called.
|
3026
|
+
* @param {DataProxy} this The proxy for the request
|
3027
|
+
* @param {Object} o The request transaction object
|
3028
|
+
* @param {Object} options The callback's <tt>options</tt> property as passed to the {@link #request} function
|
3029
|
+
*/
|
3030
|
+
'load',
|
3031
|
+
/**
|
3032
|
+
* @event loadexception
|
3033
|
+
* <p>This event is <b>deprecated</b>. The signature of the loadexception event
|
3034
|
+
* varies depending on the proxy, use the catch-all {@link #exception} event instead.
|
3035
|
+
* This event will fire in addition to the {@link #exception} event.</p>
|
3036
|
+
* @param {misc} misc See {@link #exception}.
|
3037
|
+
* @deprecated
|
3038
|
+
*/
|
3039
|
+
'loadexception',
|
3040
|
+
/**
|
3041
|
+
* @event beforewrite
|
3042
|
+
* Fires before a request is generated for one of the actions Ext.data.Api.actions.create|update|destroy
|
3043
|
+
* @param {DataProxy} this The proxy for the request
|
3044
|
+
* @param {String} action [Ext.data.Api.actions.create|update|destroy]
|
3045
|
+
* @param {Record/Array[Record]} rs The Record(s) to create|update|destroy.
|
3046
|
+
* @param {Object} params The request <code>params</code> object. Edit <code>params</code> to add parameters to the request.
|
3047
|
+
*/
|
3048
|
+
'beforewrite',
|
3049
|
+
/**
|
3050
|
+
* @event write
|
3051
|
+
* Fires before the request-callback is called
|
3052
|
+
* @param {DataProxy} this The proxy that sent the request
|
3053
|
+
* @param {String} action [Ext.data.Api.actions.create|upate|destroy]
|
3054
|
+
* @param {Object} data The data object extracted from the server-response
|
3055
|
+
* @param {Object} response The decoded response from server
|
3056
|
+
* @param {Record/Record{}} rs The records from Store
|
3057
|
+
* @param {Object} options The callback's <tt>options</tt> property as passed to the {@link #request} function
|
3058
|
+
*/
|
3059
|
+
'write'
|
3060
|
+
);
|
3061
|
+
Ext.data.DataProxy.superclass.constructor.call(this);
|
3062
|
+
};
|
3063
|
+
|
3064
|
+
Ext.extend(Ext.data.DataProxy, Ext.util.Observable, {
|
3065
|
+
/**
|
3066
|
+
* @cfg {Boolean} restful
|
3067
|
+
* <p>Defaults to <tt>false</tt>. Set to <tt>true</tt> to operate in a RESTful manner.</p>
|
3068
|
+
* <br><p> Note: this parameter will automatically be set to <tt>true</tt> if the
|
3069
|
+
* {@link Ext.data.Store} it is plugged into is set to <code>restful: true</code>. If the
|
3070
|
+
* Store is RESTful, there is no need to set this option on the proxy.</p>
|
3071
|
+
* <br><p>RESTful implementations enable the serverside framework to automatically route
|
3072
|
+
* actions sent to one url based upon the HTTP method, for example:
|
3073
|
+
* <pre><code>
|
3074
|
+
store: new Ext.data.Store({
|
3075
|
+
restful: true,
|
3076
|
+
proxy: new Ext.data.HttpProxy({url:'/users'}); // all requests sent to /users
|
3077
|
+
...
|
3078
|
+
)}
|
3079
|
+
* </code></pre>
|
3080
|
+
* There is no <code>{@link #api}</code> specified in the configuration of the proxy,
|
3081
|
+
* all requests will be marshalled to a single RESTful url (/users) so the serverside
|
3082
|
+
* framework can inspect the HTTP Method and act accordingly:
|
3083
|
+
* <pre>
|
3084
|
+
<u>Method</u> <u>url</u> <u>action</u>
|
3085
|
+
POST /users create
|
3086
|
+
GET /users read
|
3087
|
+
PUT /users/23 update
|
3088
|
+
DESTROY /users/23 delete
|
3089
|
+
* </pre></p>
|
3090
|
+
*/
|
3091
|
+
restful: false,
|
3092
|
+
|
3093
|
+
/**
|
3094
|
+
* <p>Redefines the Proxy's API or a single action of an API. Can be called with two method signatures.</p>
|
3095
|
+
* <p>If called with an object as the only parameter, the object should redefine the <b>entire</b> API, e.g.:</p><pre><code>
|
3096
|
+
proxy.setApi({
|
3097
|
+
read : '/users/read',
|
3098
|
+
create : '/users/create',
|
3099
|
+
update : '/users/update',
|
3100
|
+
destroy : '/users/destroy'
|
3101
|
+
});
|
3102
|
+
</code></pre>
|
3103
|
+
* <p>If called with two parameters, the first parameter should be a string specifying the API action to
|
3104
|
+
* redefine and the second parameter should be the URL (or function if using DirectProxy) to call for that action, e.g.:</p><pre><code>
|
3105
|
+
proxy.setApi(Ext.data.Api.actions.read, '/users/new_load_url');
|
3106
|
+
</code></pre>
|
3107
|
+
* @param {String/Object} api An API specification object, or the name of an action.
|
3108
|
+
* @param {String/Function} url The URL (or function if using DirectProxy) to call for the action.
|
3109
|
+
*/
|
3110
|
+
setApi : function() {
|
3111
|
+
if (arguments.length == 1) {
|
3112
|
+
var valid = Ext.data.Api.isValid(arguments[0]);
|
3113
|
+
if (valid === true) {
|
3114
|
+
this.api = arguments[0];
|
3115
|
+
}
|
3116
|
+
else {
|
3117
|
+
throw new Ext.data.Api.Error('invalid', valid);
|
3118
|
+
}
|
3119
|
+
}
|
3120
|
+
else if (arguments.length == 2) {
|
3121
|
+
if (!Ext.data.Api.isAction(arguments[0])) {
|
3122
|
+
throw new Ext.data.Api.Error('invalid', arguments[0]);
|
3123
|
+
}
|
3124
|
+
this.api[arguments[0]] = arguments[1];
|
3125
|
+
}
|
3126
|
+
Ext.data.Api.prepare(this);
|
3127
|
+
},
|
3128
|
+
|
3129
|
+
/**
|
3130
|
+
* Returns true if the specified action is defined as a unique action in the api-config.
|
3131
|
+
* request. If all API-actions are routed to unique urls, the xaction parameter is unecessary. However, if no api is defined
|
3132
|
+
* and all Proxy actions are routed to DataProxy#url, the server-side will require the xaction parameter to perform a switch to
|
3133
|
+
* the corresponding code for CRUD action.
|
3134
|
+
* @param {String [Ext.data.Api.CREATE|READ|UPDATE|DESTROY]} action
|
3135
|
+
* @return {Boolean}
|
3136
|
+
*/
|
3137
|
+
isApiAction : function(action) {
|
3138
|
+
return (this.api[action]) ? true : false;
|
3139
|
+
},
|
3140
|
+
|
3141
|
+
/**
|
3142
|
+
* All proxy actions are executed through this method. Automatically fires the "before" + action event
|
3143
|
+
* @param {String} action Name of the action
|
3144
|
+
* @param {Ext.data.Record/Ext.data.Record[]/null} rs Will be null when action is 'load'
|
3145
|
+
* @param {Object} params
|
3146
|
+
* @param {Ext.data.DataReader} reader
|
3147
|
+
* @param {Function} callback
|
3148
|
+
* @param {Object} scope Scope with which to call the callback (defaults to the Proxy object)
|
3149
|
+
* @param {Object} options Any options specified for the action (e.g. see {@link Ext.data.Store#load}.
|
3150
|
+
*/
|
3151
|
+
request : function(action, rs, params, reader, callback, scope, options) {
|
3152
|
+
if (!this.api[action] && !this.load) {
|
3153
|
+
throw new Ext.data.DataProxy.Error('action-undefined', action);
|
3154
|
+
}
|
3155
|
+
params = params || {};
|
3156
|
+
if ((action === Ext.data.Api.actions.read) ? this.fireEvent("beforeload", this, params) : this.fireEvent("beforewrite", this, action, rs, params) !== false) {
|
3157
|
+
this.doRequest.apply(this, arguments);
|
3158
|
+
}
|
3159
|
+
else {
|
3160
|
+
callback.call(scope || this, null, options, false);
|
3161
|
+
}
|
3162
|
+
},
|
3163
|
+
|
3164
|
+
|
3165
|
+
/**
|
3166
|
+
* <b>Deprecated</b> load method using old method signature. See {@doRequest} for preferred method.
|
3167
|
+
* @deprecated
|
3168
|
+
* @param {Object} params
|
3169
|
+
* @param {Object} reader
|
3170
|
+
* @param {Object} callback
|
3171
|
+
* @param {Object} scope
|
3172
|
+
* @param {Object} arg
|
3173
|
+
*/
|
3174
|
+
load : null,
|
3175
|
+
|
3176
|
+
/**
|
3177
|
+
* @cfg {Function} doRequest Abstract method that should be implemented in all subclasses
|
3178
|
+
* (e.g.: {@link Ext.data.HttpProxy#doRequest HttpProxy.doRequest},
|
3179
|
+
* {@link Ext.data.DirectProxy#doRequest DirectProxy.doRequest}).
|
3180
|
+
*/
|
3181
|
+
doRequest : function(action, rs, params, reader, callback, scope, options) {
|
3182
|
+
// default implementation of doRequest for backwards compatibility with 2.0 proxies.
|
3183
|
+
// If we're executing here, the action is probably "load".
|
3184
|
+
// Call with the pre-3.0 method signature.
|
3185
|
+
this.load(params, reader, callback, scope, options);
|
3186
|
+
},
|
3187
|
+
|
3188
|
+
/**
|
3189
|
+
* buildUrl
|
3190
|
+
* Sets the appropriate url based upon the action being executed. If restful is true, and only a single record is being acted upon,
|
3191
|
+
* url will be built Rails-style, as in "/controller/action/32". restful will aply iff the supplied record is an
|
3192
|
+
* instance of Ext.data.Record rather than an Array of them.
|
3193
|
+
* @param {String} action The api action being executed [read|create|update|destroy]
|
3194
|
+
* @param {Ext.data.Record/Array[Ext.data.Record]} The record or Array of Records being acted upon.
|
3195
|
+
* @return {String} url
|
3196
|
+
* @private
|
3197
|
+
*/
|
3198
|
+
buildUrl : function(action, record) {
|
3199
|
+
record = record || null;
|
3200
|
+
var url = (this.api[action]) ? this.api[action].url : this.url;
|
3201
|
+
if (!url) {
|
3202
|
+
throw new Ext.data.Api.Error('invalid-url', action);
|
3203
|
+
}
|
3204
|
+
|
3205
|
+
var format = null;
|
3206
|
+
var m = url.match(/(.*)(\.\w+)$/); // <-- look for urls with "provides" suffix, e.g.: /users.json, /users.xml, etc
|
3207
|
+
if (m) {
|
3208
|
+
format = m[2];
|
3209
|
+
url = m[1];
|
3210
|
+
}
|
3211
|
+
// prettyUrls is deprectated in favor of restful-config
|
3212
|
+
if ((this.prettyUrls === true || this.restful === true) && record instanceof Ext.data.Record && !record.phantom) {
|
3213
|
+
url += '/' + record.id;
|
3214
|
+
}
|
3215
|
+
if (format) { // <-- append the request format if exists (ie: /users/update/69[.json])
|
3216
|
+
url += format;
|
3217
|
+
}
|
3218
|
+
return url;
|
3219
|
+
},
|
3220
|
+
|
3221
|
+
/**
|
3222
|
+
* Destroys the proxy by purging any event listeners and cancelling any active requests.
|
3223
|
+
*/
|
3224
|
+
destroy: function(){
|
3225
|
+
this.purgeListeners();
|
3226
|
+
}
|
3227
|
+
});
|
3228
|
+
|
3229
|
+
/**
|
3230
|
+
* @class Ext.data.DataProxy.Error
|
3231
|
+
* @extends Ext.Error
|
3232
|
+
* DataProxy Error extension.
|
3233
|
+
* constructor
|
3234
|
+
* @param {String} name
|
3235
|
+
* @param {Record/Array[Record]/Array}
|
3236
|
+
*/
|
3237
|
+
Ext.data.DataProxy.Error = Ext.extend(Ext.Error, {
|
3238
|
+
constructor : function(message, arg) {
|
3239
|
+
this.arg = arg;
|
3240
|
+
Ext.Error.call(this, message);
|
3241
|
+
},
|
3242
|
+
name: 'Ext.data.DataProxy'
|
3243
|
+
});
|
3244
|
+
Ext.apply(Ext.data.DataProxy.Error.prototype, {
|
3245
|
+
lang: {
|
3246
|
+
'action-undefined': "DataProxy attempted to execute an API-action but found an undefined url / function. Please review your Proxy url/api-configuration.",
|
3247
|
+
'api-invalid': 'Recieved an invalid API-configuration. Please ensure your proxy API-configuration contains only the actions from Ext.data.Api.actions.'
|
3248
|
+
}
|
3249
|
+
});
|
3250
|
+
/**
|
3251
|
+
* @class Ext.data.ScriptTagProxy
|
3252
|
+
* @extends Ext.data.DataProxy
|
3253
|
+
* An implementation of Ext.data.DataProxy that reads a data object from a URL which may be in a domain
|
3254
|
+
* other than the originating domain of the running page.<br>
|
3255
|
+
* <p>
|
3256
|
+
* <b>Note that if you are retrieving data from a page that is in a domain that is NOT the same as the originating domain
|
3257
|
+
* of the running page, you must use this class, rather than HttpProxy.</b><br>
|
3258
|
+
* <p>
|
3259
|
+
* The content passed back from a server resource requested by a ScriptTagProxy <b>must</b> be executable JavaScript
|
3260
|
+
* source code because it is used as the source inside a <script> tag.<br>
|
3261
|
+
* <p>
|
3262
|
+
* In order for the browser to process the returned data, the server must wrap the data object
|
3263
|
+
* with a call to a callback function, the name of which is passed as a parameter by the ScriptTagProxy.
|
3264
|
+
* Below is a Java example for a servlet which returns data for either a ScriptTagProxy, or an HttpProxy
|
3265
|
+
* depending on whether the callback name was passed:
|
3266
|
+
* <p>
|
3267
|
+
* <pre><code>
|
3268
|
+
boolean scriptTag = false;
|
3269
|
+
String cb = request.getParameter("callback");
|
3270
|
+
if (cb != null) {
|
3271
|
+
scriptTag = true;
|
3272
|
+
response.setContentType("text/javascript");
|
3273
|
+
} else {
|
3274
|
+
response.setContentType("application/x-json");
|
3275
|
+
}
|
3276
|
+
Writer out = response.getWriter();
|
3277
|
+
if (scriptTag) {
|
3278
|
+
out.write(cb + "(");
|
3279
|
+
}
|
3280
|
+
out.print(dataBlock.toJsonString());
|
3281
|
+
if (scriptTag) {
|
3282
|
+
out.write(");");
|
3283
|
+
}
|
3284
|
+
</code></pre>
|
3285
|
+
*
|
3286
|
+
* @constructor
|
3287
|
+
* @param {Object} config A configuration object.
|
3288
|
+
*/
|
3289
|
+
Ext.data.ScriptTagProxy = function(config){
|
3290
|
+
Ext.apply(this, config);
|
3291
|
+
|
3292
|
+
Ext.data.ScriptTagProxy.superclass.constructor.call(this, config);
|
3293
|
+
|
3294
|
+
this.head = document.getElementsByTagName("head")[0];
|
3295
|
+
|
3296
|
+
/**
|
3297
|
+
* @event loadexception
|
3298
|
+
* <b>Deprecated</b> in favor of 'exception' event.
|
3299
|
+
* Fires if an exception occurs in the Proxy during data loading. This event can be fired for one of two reasons:
|
3300
|
+
* <ul><li><b>The load call timed out.</b> This means the load callback did not execute within the time limit
|
3301
|
+
* specified by {@link #timeout}. In this case, this event will be raised and the
|
3302
|
+
* fourth parameter (read error) will be null.</li>
|
3303
|
+
* <li><b>The load succeeded but the reader could not read the response.</b> This means the server returned
|
3304
|
+
* data, but the configured Reader threw an error while reading the data. In this case, this event will be
|
3305
|
+
* raised and the caught error will be passed along as the fourth parameter of this event.</li></ul>
|
3306
|
+
* Note that this event is also relayed through {@link Ext.data.Store}, so you can listen for it directly
|
3307
|
+
* on any Store instance.
|
3308
|
+
* @param {Object} this
|
3309
|
+
* @param {Object} options The loading options that were specified (see {@link #load} for details). If the load
|
3310
|
+
* call timed out, this parameter will be null.
|
3311
|
+
* @param {Object} arg The callback's arg object passed to the {@link #load} function
|
3312
|
+
* @param {Error} e The JavaScript Error object caught if the configured Reader could not read the data.
|
3313
|
+
* If the remote request returns success: false, this parameter will be null.
|
3314
|
+
*/
|
3315
|
+
};
|
3316
|
+
|
3317
|
+
Ext.data.ScriptTagProxy.TRANS_ID = 1000;
|
3318
|
+
|
3319
|
+
Ext.extend(Ext.data.ScriptTagProxy, Ext.data.DataProxy, {
|
3320
|
+
/**
|
3321
|
+
* @cfg {String} url The URL from which to request the data object.
|
3322
|
+
*/
|
3323
|
+
/**
|
3324
|
+
* @cfg {Number} timeout (optional) The number of milliseconds to wait for a response. Defaults to 30 seconds.
|
3325
|
+
*/
|
3326
|
+
timeout : 30000,
|
3327
|
+
/**
|
3328
|
+
* @cfg {String} callbackParam (Optional) The name of the parameter to pass to the server which tells
|
3329
|
+
* the server the name of the callback function set up by the load call to process the returned data object.
|
3330
|
+
* Defaults to "callback".<p>The server-side processing must read this parameter value, and generate
|
3331
|
+
* javascript output which calls this named function passing the data object as its only parameter.
|
3332
|
+
*/
|
3333
|
+
callbackParam : "callback",
|
3334
|
+
/**
|
3335
|
+
* @cfg {Boolean} nocache (optional) Defaults to true. Disable caching by adding a unique parameter
|
3336
|
+
* name to the request.
|
3337
|
+
*/
|
3338
|
+
nocache : true,
|
3339
|
+
|
3340
|
+
/**
|
3341
|
+
* HttpProxy implementation of DataProxy#doRequest
|
3342
|
+
* @param {String} action
|
3343
|
+
* @param {Ext.data.Record/Ext.data.Record[]} rs If action is <tt>read</tt>, rs will be null
|
3344
|
+
* @param {Object} params An object containing properties which are to be used as HTTP parameters
|
3345
|
+
* for the request to the remote server.
|
3346
|
+
* @param {Ext.data.DataReader} reader The Reader object which converts the data
|
3347
|
+
* object into a block of Ext.data.Records.
|
3348
|
+
* @param {Function} callback The function into which to pass the block of Ext.data.Records.
|
3349
|
+
* The function must be passed <ul>
|
3350
|
+
* <li>The Record block object</li>
|
3351
|
+
* <li>The "arg" argument from the load function</li>
|
3352
|
+
* <li>A boolean success indicator</li>
|
3353
|
+
* </ul>
|
3354
|
+
* @param {Object} scope The scope in which to call the callback
|
3355
|
+
* @param {Object} arg An optional argument which is passed to the callback as its second parameter.
|
3356
|
+
*/
|
3357
|
+
doRequest : function(action, rs, params, reader, callback, scope, arg) {
|
3358
|
+
var p = Ext.urlEncode(Ext.apply(params, this.extraParams));
|
3359
|
+
|
3360
|
+
var url = this.buildUrl(action, rs);
|
3361
|
+
if (!url) {
|
3362
|
+
throw new Ext.data.Api.Error('invalid-url', url);
|
3363
|
+
}
|
3364
|
+
url = Ext.urlAppend(url, p);
|
3365
|
+
|
3366
|
+
if(this.nocache){
|
3367
|
+
url = Ext.urlAppend(url, '_dc=' + (new Date().getTime()));
|
3368
|
+
}
|
3369
|
+
var transId = ++Ext.data.ScriptTagProxy.TRANS_ID;
|
3370
|
+
var trans = {
|
3371
|
+
id : transId,
|
3372
|
+
action: action,
|
3373
|
+
cb : "stcCallback"+transId,
|
3374
|
+
scriptId : "stcScript"+transId,
|
3375
|
+
params : params,
|
3376
|
+
arg : arg,
|
3377
|
+
url : url,
|
3378
|
+
callback : callback,
|
3379
|
+
scope : scope,
|
3380
|
+
reader : reader
|
3381
|
+
};
|
3382
|
+
window[trans.cb] = this.createCallback(action, rs, trans);
|
3383
|
+
url += String.format("&{0}={1}", this.callbackParam, trans.cb);
|
3384
|
+
if(this.autoAbort !== false){
|
3385
|
+
this.abort();
|
3386
|
+
}
|
3387
|
+
|
3388
|
+
trans.timeoutId = this.handleFailure.defer(this.timeout, this, [trans]);
|
3389
|
+
|
3390
|
+
var script = document.createElement("script");
|
3391
|
+
script.setAttribute("src", url);
|
3392
|
+
script.setAttribute("type", "text/javascript");
|
3393
|
+
script.setAttribute("id", trans.scriptId);
|
3394
|
+
this.head.appendChild(script);
|
3395
|
+
|
3396
|
+
this.trans = trans;
|
3397
|
+
},
|
3398
|
+
|
3399
|
+
// @private createCallback
|
3400
|
+
createCallback : function(action, rs, trans) {
|
3401
|
+
var self = this;
|
3402
|
+
return function(res) {
|
3403
|
+
self.trans = false;
|
3404
|
+
self.destroyTrans(trans, true);
|
3405
|
+
if (action === Ext.data.Api.actions.read) {
|
3406
|
+
self.onRead.call(self, action, trans, res);
|
3407
|
+
} else {
|
3408
|
+
self.onWrite.call(self, action, trans, res, rs);
|
3409
|
+
}
|
3410
|
+
};
|
3411
|
+
},
|
3412
|
+
/**
|
3413
|
+
* Callback for read actions
|
3414
|
+
* @param {String} action [Ext.data.Api.actions.create|read|update|destroy]
|
3415
|
+
* @param {Object} trans The request transaction object
|
3416
|
+
* @param {Object} res The server response
|
3417
|
+
* @private
|
3418
|
+
*/
|
3419
|
+
onRead : function(action, trans, res) {
|
3420
|
+
var result;
|
3421
|
+
try {
|
3422
|
+
result = trans.reader.readRecords(res);
|
3423
|
+
}catch(e){
|
3424
|
+
// @deprecated: fire loadexception
|
3425
|
+
this.fireEvent("loadexception", this, trans, res, e);
|
3426
|
+
|
3427
|
+
this.fireEvent('exception', this, 'response', action, trans, res, e);
|
3428
|
+
trans.callback.call(trans.scope||window, null, trans.arg, false);
|
3429
|
+
return;
|
3430
|
+
}
|
3431
|
+
if (result.success === false) {
|
3432
|
+
// @deprecated: fire old loadexception for backwards-compat.
|
3433
|
+
this.fireEvent('loadexception', this, trans, res);
|
3434
|
+
|
3435
|
+
this.fireEvent('exception', this, 'remote', action, trans, res, null);
|
3436
|
+
} else {
|
3437
|
+
this.fireEvent("load", this, res, trans.arg);
|
3438
|
+
}
|
3439
|
+
trans.callback.call(trans.scope||window, result, trans.arg, result.success);
|
3440
|
+
},
|
3441
|
+
/**
|
3442
|
+
* Callback for write actions
|
3443
|
+
* @param {String} action [Ext.data.Api.actions.create|read|update|destroy]
|
3444
|
+
* @param {Object} trans The request transaction object
|
3445
|
+
* @param {Object} res The server response
|
3446
|
+
* @private
|
3447
|
+
*/
|
3448
|
+
onWrite : function(action, trans, res, rs) {
|
3449
|
+
var reader = trans.reader;
|
3450
|
+
try {
|
3451
|
+
// though we already have a response object here in STP, run through readResponse to catch any meta-data exceptions.
|
3452
|
+
reader.readResponse(action, res);
|
3453
|
+
} catch (e) {
|
3454
|
+
this.fireEvent('exception', this, 'response', action, trans, res, e);
|
3455
|
+
trans.callback.call(trans.scope||window, null, res, false);
|
3456
|
+
return;
|
3457
|
+
}
|
3458
|
+
if(!res[reader.meta.successProperty] === true){
|
3459
|
+
this.fireEvent('exception', this, 'remote', action, trans, res, rs);
|
3460
|
+
trans.callback.call(trans.scope||window, null, res, false);
|
3461
|
+
return;
|
3462
|
+
}
|
3463
|
+
this.fireEvent("write", this, action, res[reader.meta.root], res, rs, trans.arg );
|
3464
|
+
trans.callback.call(trans.scope||window, res[reader.meta.root], res, true);
|
3465
|
+
},
|
3466
|
+
|
3467
|
+
// private
|
3468
|
+
isLoading : function(){
|
3469
|
+
return this.trans ? true : false;
|
3470
|
+
},
|
3471
|
+
|
3472
|
+
/**
|
3473
|
+
* Abort the current server request.
|
3474
|
+
*/
|
3475
|
+
abort : function(){
|
3476
|
+
if(this.isLoading()){
|
3477
|
+
this.destroyTrans(this.trans);
|
3478
|
+
}
|
3479
|
+
},
|
3480
|
+
|
3481
|
+
// private
|
3482
|
+
destroyTrans : function(trans, isLoaded){
|
3483
|
+
this.head.removeChild(document.getElementById(trans.scriptId));
|
3484
|
+
clearTimeout(trans.timeoutId);
|
3485
|
+
if(isLoaded){
|
3486
|
+
window[trans.cb] = undefined;
|
3487
|
+
try{
|
3488
|
+
delete window[trans.cb];
|
3489
|
+
}catch(e){}
|
3490
|
+
}else{
|
3491
|
+
// if hasn't been loaded, wait for load to remove it to prevent script error
|
3492
|
+
window[trans.cb] = function(){
|
3493
|
+
window[trans.cb] = undefined;
|
3494
|
+
try{
|
3495
|
+
delete window[trans.cb];
|
3496
|
+
}catch(e){}
|
3497
|
+
};
|
3498
|
+
}
|
3499
|
+
},
|
3500
|
+
|
3501
|
+
// private
|
3502
|
+
handleFailure : function(trans){
|
3503
|
+
this.trans = false;
|
3504
|
+
this.destroyTrans(trans, false);
|
3505
|
+
if (trans.action === Ext.data.Api.actions.read) {
|
3506
|
+
// @deprecated firing loadexception
|
3507
|
+
this.fireEvent("loadexception", this, null, trans.arg);
|
3508
|
+
}
|
3509
|
+
|
3510
|
+
this.fireEvent('exception', this, 'response', trans.action, {
|
3511
|
+
response: null,
|
3512
|
+
options: trans.arg
|
3513
|
+
});
|
3514
|
+
trans.callback.call(trans.scope||window, null, trans.arg, false);
|
3515
|
+
},
|
3516
|
+
|
3517
|
+
// inherit docs
|
3518
|
+
destroy: function(){
|
3519
|
+
this.abort();
|
3520
|
+
Ext.data.ScriptTagProxy.superclass.destroy.call(this);
|
3521
|
+
}
|
3522
|
+
});/**
|
3523
|
+
* @class Ext.data.HttpProxy
|
3524
|
+
* @extends Ext.data.DataProxy
|
3525
|
+
* <p>An implementation of {@link Ext.data.DataProxy} that processes data requests within the same
|
3526
|
+
* domain of the originating page.</p>
|
3527
|
+
* <p><b>Note</b>: this class cannot be used to retrieve data from a domain other
|
3528
|
+
* than the domain from which the running page was served. For cross-domain requests, use a
|
3529
|
+
* {@link Ext.data.ScriptTagProxy ScriptTagProxy}.</p>
|
3530
|
+
* <p>Be aware that to enable the browser to parse an XML document, the server must set
|
3531
|
+
* the Content-Type header in the HTTP response to "<tt>text/xml</tt>".</p>
|
3532
|
+
* @constructor
|
3533
|
+
* @param {Object} conn
|
3534
|
+
* An {@link Ext.data.Connection} object, or options parameter to {@link Ext.Ajax#request}.
|
3535
|
+
* <p>Note that if this HttpProxy is being used by a (@link Ext.data.Store Store}, then the
|
3536
|
+
* Store's call to {@link #load} will override any specified <tt>callback</tt> and <tt>params</tt>
|
3537
|
+
* options. In this case, use the Store's {@link Ext.data.Store#events events} to modify parameters,
|
3538
|
+
* or react to loading events. The Store's {@link Ext.data.Store#baseParams baseParams} may also be
|
3539
|
+
* used to pass parameters known at instantiation time.</p>
|
3540
|
+
* <p>If an options parameter is passed, the singleton {@link Ext.Ajax} object will be used to make
|
3541
|
+
* the request.</p>
|
3542
|
+
*/
|
3543
|
+
Ext.data.HttpProxy = function(conn){
|
3544
|
+
Ext.data.HttpProxy.superclass.constructor.call(this, conn);
|
3545
|
+
|
3546
|
+
/**
|
3547
|
+
* The Connection object (Or options parameter to {@link Ext.Ajax#request}) which this HttpProxy
|
3548
|
+
* uses to make requests to the server. Properties of this object may be changed dynamically to
|
3549
|
+
* change the way data is requested.
|
3550
|
+
* @property
|
3551
|
+
*/
|
3552
|
+
this.conn = conn;
|
3553
|
+
|
3554
|
+
// nullify the connection url. The url param has been copied to 'this' above. The connection
|
3555
|
+
// url will be set during each execution of doRequest when buildUrl is called. This makes it easier for users to override the
|
3556
|
+
// connection url during beforeaction events (ie: beforeload, beforesave, etc). The connection url will be nullified
|
3557
|
+
// after each request as well. Url is always re-defined during doRequest.
|
3558
|
+
this.conn.url = null;
|
3559
|
+
|
3560
|
+
this.useAjax = !conn || !conn.events;
|
3561
|
+
|
3562
|
+
//private. A hash containing active requests, keyed on action [Ext.data.Api.actions.create|read|update|destroy]
|
3563
|
+
var actions = Ext.data.Api.actions;
|
3564
|
+
this.activeRequest = {};
|
3565
|
+
for (var verb in actions) {
|
3566
|
+
this.activeRequest[actions[verb]] = undefined;
|
3567
|
+
}
|
3568
|
+
};
|
3569
|
+
|
3570
|
+
Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {
|
3571
|
+
/**
|
3572
|
+
* @cfg {Boolean} restful
|
3573
|
+
* <p>If set to <tt>true</tt>, a {@link Ext.data.Record#phantom non-phantom} record's
|
3574
|
+
* {@link Ext.data.Record#id id} will be appended to the url (defaults to <tt>false</tt>).</p><br>
|
3575
|
+
* <p>The url is built based upon the action being executed <tt>[load|create|save|destroy]</tt>
|
3576
|
+
* using the commensurate <tt>{@link #api}</tt> property, or if undefined default to the
|
3577
|
+
* configured {@link Ext.data.Store}.{@link Ext.data.Store#url url}.</p><br>
|
3578
|
+
* <p>Some MVC (e.g., Ruby on Rails, Merb and Django) support this style of segment based urls
|
3579
|
+
* where the segments in the URL follow the Model-View-Controller approach.</p><pre><code>
|
3580
|
+
* someSite.com/controller/action/id
|
3581
|
+
* </code></pre>
|
3582
|
+
* Where the segments in the url are typically:<div class="mdetail-params"><ul>
|
3583
|
+
* <li>The first segment : represents the controller class that should be invoked.</li>
|
3584
|
+
* <li>The second segment : represents the class function, or method, that should be called.</li>
|
3585
|
+
* <li>The third segment : represents the ID (a variable typically passed to the method).</li>
|
3586
|
+
* </ul></div></p>
|
3587
|
+
* <p>For example:</p>
|
3588
|
+
* <pre><code>
|
3589
|
+
api: {
|
3590
|
+
load : '/controller/load',
|
3591
|
+
create : '/controller/new', // Server MUST return idProperty of new record
|
3592
|
+
save : '/controller/update',
|
3593
|
+
destroy : '/controller/destroy_action'
|
3594
|
+
}
|
3595
|
+
|
3596
|
+
// Alternatively, one can use the object-form to specify each API-action
|
3597
|
+
api: {
|
3598
|
+
load: {url: 'read.php', method: 'GET'},
|
3599
|
+
create: 'create.php',
|
3600
|
+
destroy: 'destroy.php',
|
3601
|
+
save: 'update.php'
|
3602
|
+
}
|
3603
|
+
*/
|
3604
|
+
|
3605
|
+
/**
|
3606
|
+
* Return the {@link Ext.data.Connection} object being used by this Proxy.
|
3607
|
+
* @return {Connection} The Connection object. This object may be used to subscribe to events on
|
3608
|
+
* a finer-grained basis than the DataProxy events.
|
3609
|
+
*/
|
3610
|
+
getConnection : function() {
|
3611
|
+
return this.useAjax ? Ext.Ajax : this.conn;
|
3612
|
+
},
|
3613
|
+
|
3614
|
+
/**
|
3615
|
+
* Used for overriding the url used for a single request. Designed to be called during a beforeaction event. Calling setUrl
|
3616
|
+
* will override any urls set via the api configuration parameter. Set the optional parameter makePermanent to set the url for
|
3617
|
+
* all subsequent requests. If not set to makePermanent, the next request will use the same url or api configuration defined
|
3618
|
+
* in the initial proxy configuration.
|
3619
|
+
* @param {String} url
|
3620
|
+
* @param {Boolean} makePermanent (Optional) [false]
|
3621
|
+
*
|
3622
|
+
* (e.g.: beforeload, beforesave, etc).
|
3623
|
+
*/
|
3624
|
+
setUrl : function(url, makePermanent) {
|
3625
|
+
this.conn.url = url;
|
3626
|
+
if (makePermanent === true) {
|
3627
|
+
this.url = url;
|
3628
|
+
Ext.data.Api.prepare(this);
|
3629
|
+
}
|
3630
|
+
},
|
3631
|
+
|
3632
|
+
/**
|
3633
|
+
* HttpProxy implementation of DataProxy#doRequest
|
3634
|
+
* @param {String} action The crud action type (create, read, update, destroy)
|
3635
|
+
* @param {Ext.data.Record/Ext.data.Record[]} rs If action is load, rs will be null
|
3636
|
+
* @param {Object} params An object containing properties which are to be used as HTTP parameters
|
3637
|
+
* for the request to the remote server.
|
3638
|
+
* @param {Ext.data.DataReader} reader The Reader object which converts the data
|
3639
|
+
* object into a block of Ext.data.Records.
|
3640
|
+
* @param {Function} callback
|
3641
|
+
* <div class="sub-desc"><p>A function to be called after the request.
|
3642
|
+
* The <tt>callback</tt> is passed the following arguments:<ul>
|
3643
|
+
* <li><tt>r</tt> : Ext.data.Record[] The block of Ext.data.Records.</li>
|
3644
|
+
* <li><tt>options</tt>: Options object from the action request</li>
|
3645
|
+
* <li><tt>success</tt>: Boolean success indicator</li></ul></p></div>
|
3646
|
+
* @param {Object} scope The scope in which to call the callback
|
3647
|
+
* @param {Object} arg An optional argument which is passed to the callback as its second parameter.
|
3648
|
+
*/
|
3649
|
+
doRequest : function(action, rs, params, reader, cb, scope, arg) {
|
3650
|
+
var o = {
|
3651
|
+
method: (this.api[action]) ? this.api[action]['method'] : undefined,
|
3652
|
+
request: {
|
3653
|
+
callback : cb,
|
3654
|
+
scope : scope,
|
3655
|
+
arg : arg
|
3656
|
+
},
|
3657
|
+
reader: reader,
|
3658
|
+
callback : this.createCallback(action, rs),
|
3659
|
+
scope: this
|
3660
|
+
};
|
3661
|
+
// Sample the request data: If it's an object, then it hasn't been json-encoded yet.
|
3662
|
+
// Transmit data using jsonData config of Ext.Ajax.request
|
3663
|
+
if (typeof(params[reader.meta.root]) === 'object') {
|
3664
|
+
o.jsonData = params;
|
3665
|
+
} else {
|
3666
|
+
o.params = params || {};
|
3667
|
+
}
|
3668
|
+
// Set the connection url. If this.conn.url is not null here,
|
3669
|
+
// the user may have overridden the url during a beforeaction event-handler.
|
3670
|
+
// this.conn.url is nullified after each request.
|
3671
|
+
if (this.conn.url === null) {
|
3672
|
+
this.conn.url = this.buildUrl(action, rs);
|
3673
|
+
}
|
3674
|
+
else if (this.restful === true && rs instanceof Ext.data.Record && !rs.phantom) {
|
3675
|
+
this.conn.url += '/' + rs.id;
|
3676
|
+
}
|
3677
|
+
if(this.useAjax){
|
3678
|
+
|
3679
|
+
Ext.applyIf(o, this.conn);
|
3680
|
+
|
3681
|
+
// If a currently running request is found for this action, abort it.
|
3682
|
+
if (this.activeRequest[action]) {
|
3683
|
+
// Disabled aborting activeRequest while implementing REST. activeRequest[action] will have to become an array
|
3684
|
+
//Ext.Ajax.abort(this.activeRequest[action]);
|
3685
|
+
}
|
3686
|
+
this.activeRequest[action] = Ext.Ajax.request(o);
|
3687
|
+
}else{
|
3688
|
+
this.conn.request(o);
|
3689
|
+
}
|
3690
|
+
// request is sent, nullify the connection url in preparation for the next request
|
3691
|
+
this.conn.url = null;
|
3692
|
+
},
|
3693
|
+
|
3694
|
+
/**
|
3695
|
+
* Returns a callback function for a request. Note a special case is made for the
|
3696
|
+
* read action vs all the others.
|
3697
|
+
* @param {String} action [create|update|delete|load]
|
3698
|
+
* @param {Ext.data.Record[]} rs The Store-recordset being acted upon
|
3699
|
+
* @private
|
3700
|
+
*/
|
3701
|
+
createCallback : function(action, rs) {
|
3702
|
+
return function(o, success, response) {
|
3703
|
+
this.activeRequest[action] = undefined;
|
3704
|
+
if (!success) {
|
3705
|
+
if (action === Ext.data.Api.actions.read) {
|
3706
|
+
// @deprecated: fire loadexception for backwards compat.
|
3707
|
+
this.fireEvent('loadexception', this, o, response);
|
3708
|
+
}
|
3709
|
+
this.fireEvent('exception', this, 'response', action, o, response);
|
3710
|
+
o.request.callback.call(o.request.scope, null, o.request.arg, false);
|
3711
|
+
return;
|
3712
|
+
}
|
3713
|
+
if (action === Ext.data.Api.actions.read) {
|
3714
|
+
this.onRead(action, o, response);
|
3715
|
+
} else {
|
3716
|
+
this.onWrite(action, o, response, rs);
|
3717
|
+
}
|
3718
|
+
}
|
3719
|
+
},
|
3720
|
+
|
3721
|
+
/**
|
3722
|
+
* Callback for read action
|
3723
|
+
* @param {String} action Action name as per {@link Ext.data.Api.actions#read}.
|
3724
|
+
* @param {Object} o The request transaction object
|
3725
|
+
* @param {Object} res The server response
|
3726
|
+
* @private
|
3727
|
+
*/
|
3728
|
+
onRead : function(action, o, response) {
|
3729
|
+
var result;
|
3730
|
+
try {
|
3731
|
+
result = o.reader.read(response);
|
3732
|
+
}catch(e){
|
3733
|
+
// @deprecated: fire old loadexception for backwards-compat.
|
3734
|
+
this.fireEvent('loadexception', this, o, response, e);
|
3735
|
+
this.fireEvent('exception', this, 'response', action, o, response, e);
|
3736
|
+
o.request.callback.call(o.request.scope, null, o.request.arg, false);
|
3737
|
+
return;
|
3738
|
+
}
|
3739
|
+
if (result.success === false) {
|
3740
|
+
// @deprecated: fire old loadexception for backwards-compat.
|
3741
|
+
this.fireEvent('loadexception', this, o, response);
|
3742
|
+
|
3743
|
+
// Get DataReader read-back a response-object to pass along to exception event
|
3744
|
+
var res = o.reader.readResponse(action, response);
|
3745
|
+
this.fireEvent('exception', this, 'remote', action, o, res, null);
|
3746
|
+
}
|
3747
|
+
else {
|
3748
|
+
this.fireEvent('load', this, o, o.request.arg);
|
3749
|
+
}
|
3750
|
+
o.request.callback.call(o.request.scope, result, o.request.arg, result.success);
|
3751
|
+
},
|
3752
|
+
/**
|
3753
|
+
* Callback for write actions
|
3754
|
+
* @param {String} action [Ext.data.Api.actions.create|read|update|destroy]
|
3755
|
+
* @param {Object} trans The request transaction object
|
3756
|
+
* @param {Object} res The server response
|
3757
|
+
* @private
|
3758
|
+
*/
|
3759
|
+
onWrite : function(action, o, response, rs) {
|
3760
|
+
var reader = o.reader;
|
3761
|
+
var res;
|
3762
|
+
try {
|
3763
|
+
res = reader.readResponse(action, response);
|
3764
|
+
} catch (e) {
|
3765
|
+
this.fireEvent('exception', this, 'response', action, o, response, e);
|
3766
|
+
o.request.callback.call(o.request.scope, null, o.request.arg, false);
|
3767
|
+
return;
|
3768
|
+
}
|
3769
|
+
if (res[reader.meta.successProperty] === false) {
|
3770
|
+
this.fireEvent('exception', this, 'remote', action, o, res, rs);
|
3771
|
+
} else {
|
3772
|
+
this.fireEvent('write', this, action, res[reader.meta.root], res, rs, o.request.arg);
|
3773
|
+
}
|
3774
|
+
o.request.callback.call(o.request.scope, res[reader.meta.root], res, res[reader.meta.successProperty]);
|
3775
|
+
},
|
3776
|
+
|
3777
|
+
// inherit docs
|
3778
|
+
destroy: function(){
|
3779
|
+
if(!this.useAjax){
|
3780
|
+
this.conn.abort();
|
3781
|
+
}else if(this.activeRequest){
|
3782
|
+
var actions = Ext.data.Api.actions;
|
3783
|
+
for (var verb in actions) {
|
3784
|
+
if(this.activeRequest[actions[verb]]){
|
3785
|
+
Ext.Ajax.abort(this.activeRequest[actions[verb]]);
|
3786
|
+
}
|
3787
|
+
}
|
3788
|
+
}
|
3789
|
+
Ext.data.HttpProxy.superclass.destroy.call(this);
|
3790
|
+
}
|
3791
|
+
});/**
|
3792
|
+
* @class Ext.data.MemoryProxy
|
3793
|
+
* @extends Ext.data.DataProxy
|
3794
|
+
* An implementation of Ext.data.DataProxy that simply passes the data specified in its constructor
|
3795
|
+
* to the Reader when its load method is called.
|
3796
|
+
* @constructor
|
3797
|
+
* @param {Object} data The data object which the Reader uses to construct a block of Ext.data.Records.
|
3798
|
+
*/
|
3799
|
+
Ext.data.MemoryProxy = function(data){
|
3800
|
+
// Must define a dummy api with "read" action to satisfy DataProxy#doRequest and Ext.data.Api#prepare *before* calling super
|
3801
|
+
var api = {};
|
3802
|
+
api[Ext.data.Api.actions.read] = true;
|
3803
|
+
Ext.data.MemoryProxy.superclass.constructor.call(this, {
|
3804
|
+
api: api
|
3805
|
+
});
|
3806
|
+
this.data = data;
|
3807
|
+
};
|
3808
|
+
|
3809
|
+
Ext.extend(Ext.data.MemoryProxy, Ext.data.DataProxy, {
|
3810
|
+
/**
|
3811
|
+
* @event loadexception
|
3812
|
+
* Fires if an exception occurs in the Proxy during data loading. Note that this event is also relayed
|
3813
|
+
* through {@link Ext.data.Store}, so you can listen for it directly on any Store instance.
|
3814
|
+
* @param {Object} this
|
3815
|
+
* @param {Object} arg The callback's arg object passed to the {@link #load} function
|
3816
|
+
* @param {Object} null This parameter does not apply and will always be null for MemoryProxy
|
3817
|
+
* @param {Error} e The JavaScript Error object caught if the configured Reader could not read the data
|
3818
|
+
*/
|
3819
|
+
|
3820
|
+
/**
|
3821
|
+
* MemoryProxy implementation of DataProxy#doRequest
|
3822
|
+
* @param {String} action
|
3823
|
+
* @param {Ext.data.Record/Ext.data.Record[]} rs If action is load, rs will be null
|
3824
|
+
* @param {Object} params An object containing properties which are to be used as HTTP parameters
|
3825
|
+
* for the request to the remote server.
|
3826
|
+
* @param {Ext.data.DataReader} reader The Reader object which converts the data
|
3827
|
+
* object into a block of Ext.data.Records.
|
3828
|
+
* @param {Function} callback The function into which to pass the block of Ext.data.Records.
|
3829
|
+
* The function must be passed <ul>
|
3830
|
+
* <li>The Record block object</li>
|
3831
|
+
* <li>The "arg" argument from the load function</li>
|
3832
|
+
* <li>A boolean success indicator</li>
|
3833
|
+
* </ul>
|
3834
|
+
* @param {Object} scope The scope in which to call the callback
|
3835
|
+
* @param {Object} arg An optional argument which is passed to the callback as its second parameter.
|
3836
|
+
*/
|
3837
|
+
doRequest : function(action, rs, params, reader, callback, scope, arg) {
|
3838
|
+
// No implementation for CRUD in MemoryProxy. Assumes all actions are 'load'
|
3839
|
+
params = params || {};
|
3840
|
+
var result;
|
3841
|
+
try {
|
3842
|
+
result = reader.readRecords(this.data);
|
3843
|
+
}catch(e){
|
3844
|
+
// @deprecated loadexception
|
3845
|
+
this.fireEvent("loadexception", this, null, arg, e);
|
3846
|
+
|
3847
|
+
this.fireEvent('exception', this, 'response', action, arg, null, e);
|
3848
|
+
callback.call(scope, null, arg, false);
|
3849
|
+
return;
|
3850
|
+
}
|
3851
|
+
callback.call(scope, result, arg, true);
|
3852
|
+
}
|
3853
|
+
});
|