<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>public/viewers/extjs/ext/source/core/Error.js</filename>
    </added>
    <added>
      <filename>public/viewers/extjs/ext/source/data/XmlWriter.js</filename>
    </added>
    <added>
      <filename>public/viewers/extjs/javascripts/data/ActionWriter.js</filename>
    </added>
    <added>
      <filename>public/viewers/extjs/javascripts/widgets/InfoBars/EditingInfoBar.js</filename>
    </added>
    <added>
      <filename>public/viewers/extjs/javascripts/widgets/InstanceEditor.js</filename>
    </added>
    <added>
      <filename>public/viewers/extjs/javascripts/widgets/fieldlets/LinkFieldlet.js</filename>
    </added>
    <added>
      <filename>public/viewers/extjs/javascripts/widgets/fieldlets/StringFieldlet.js</filename>
    </added>
    <added>
      <filename>public/viewers/extjs/javascripts/widgets/layouts/FormLayout.js</filename>
    </added>
    <added>
      <filename>public/viewers/extjs/javascripts/widgets/layouts/InstanceEditorLayout.js</filename>
    </added>
    <added>
      <filename>public/viewers/extjs/stylesheets/fields.css</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -35,7 +35,7 @@
                     &lt;preferences&gt;
                         &lt;pref key=&quot;type&quot;&gt;multi&lt;/pref&gt;
                         &lt;pref key=&quot;duplication&quot;&gt;
-                            &lt;pref key=&quot;target_classes&quot;&gt;
+                            &lt;pref key=&quot;targetClasses&quot;&gt;
                                 &lt;pref key=&quot;1d03ca03e76d140e&quot;&gt;1d5a79532c8ff7f7&lt;/pref&gt;
                             &lt;/pref&gt;
                         &lt;/pref&gt;
@@ -80,7 +80,7 @@
                     &lt;preferences&gt;
                         &lt;pref key=&quot;type&quot;&gt;multi&lt;/pref&gt;
                         &lt;pref key=&quot;duplication&quot;&gt;
-                            &lt;pref key=&quot;target_classes&quot;&gt;
+                            &lt;pref key=&quot;targetClasses&quot;&gt;
                                 &lt;pref key=&quot;1d03ca03e76d140e&quot;&gt;f8d9a751b11f32f5&lt;/pref&gt;
                             &lt;/pref&gt;
                         &lt;/pref&gt;
@@ -140,7 +140,7 @@
                     &lt;preferences&gt;
                         &lt;pref key=&quot;type&quot;&gt;multi&lt;/pref&gt;
                         &lt;pref key=&quot;duplication&quot;&gt;
-                            &lt;pref key=&quot;target_classes&quot;&gt;
+                            &lt;pref key=&quot;targetClasses&quot;&gt;
                                 &lt;pref key=&quot;fdae913172896bce&quot;&gt;bd3ca4b17e13bf0b&lt;/pref&gt;
                             &lt;/pref&gt;
                         &lt;/pref&gt;
@@ -163,7 +163,7 @@
                     &lt;preferences&gt;
                         &lt;pref key=&quot;type&quot;&gt;multi&lt;/pref&gt;
                         &lt;pref key=&quot;duplication&quot;&gt;
-                            &lt;pref key=&quot;target_classes&quot;&gt;
+                            &lt;pref key=&quot;targetClasses&quot;&gt;
                                 &lt;pref key=&quot;71aa43efd0fdd671&quot;&gt;24864cb27445ef74&lt;/pref&gt;
                             &lt;/pref&gt;
                         &lt;/pref&gt;
@@ -262,7 +262,7 @@
                     &lt;preferences&gt;
                         &lt;pref key=&quot;type&quot;&gt;multi&lt;/pref&gt;
                         &lt;pref key=&quot;duplication&quot;&gt;
-                            &lt;pref key=&quot;target_classes&quot;&gt;
+                            &lt;pref key=&quot;targetClasses&quot;&gt;
                                 &lt;pref key=&quot;1d03ca03e76d140e&quot;&gt;8ba8ae0d944a1187&lt;/pref&gt;
                             &lt;/pref&gt;
                         &lt;/pref&gt;
@@ -297,6 +297,7 @@
                             &lt;preferences&gt;
                                 &lt;pref key=&quot;for&quot;&gt;main&lt;/pref&gt;
                                 &lt;pref key=&quot;xtype&quot;&gt;Nifty.EntityPane&lt;/pref&gt;
+                                &lt;pref key=&quot;labelAlign&quot;&gt;top&lt;/pref&gt;
                             &lt;/preferences&gt;
                             &lt;items&gt;
                                 &lt;item using=&quot;uid-26c24af2e134d3f9&quot;&gt;
@@ -304,7 +305,7 @@
                                         &lt;pref key=&quot;xtype&quot;&gt;Nifty.SingleField&lt;/pref&gt;
                                         &lt;pref key=&quot;field&quot;&gt;26c24af2e134d3f9&lt;/pref&gt;
                                         &lt;pref key=&quot;tooltip&quot;&gt;The name of this Company&lt;/pref&gt;
-                                        &lt;pref key=&quot;viewTemplate&quot;&gt;&lt;![CDATA[Molsh: &lt;strong&gt;{String:0f843ee1c18d74a0}&lt;/strong&gt;, Syga: {Weird:0f843ee1c18d74a0}]]&gt;&lt;/pref&gt;
+                                        &lt;pref key=&quot;viewTemplate&quot;&gt;&lt;![CDATA[{String:0f843ee1c18d74a0}]]&gt;&lt;/pref&gt;
                                     &lt;/preferences&gt;
                                 &lt;/item&gt;
                                 &lt;item using=&quot;uid-24864cb27445ef74&quot;&gt;
@@ -312,7 +313,128 @@
                                         &lt;pref key=&quot;xtype&quot;&gt;Nifty.MultiField&lt;/pref&gt;
                                         &lt;pref key=&quot;field&quot;&gt;24864cb27445ef74&lt;/pref&gt;
                                         &lt;pref key=&quot;tooltip&quot;&gt;The name of this Company&lt;/pref&gt;
-                                        &lt;pref key=&quot;viewTemplate&quot;&gt;&lt;![CDATA[{Link:344715e69dfefe30}]]&gt;&lt;/pref&gt;
+                                        &lt;pref key=&quot;viewTemplate&quot;&gt;&lt;![CDATA[&lt;small&gt;{#}&lt;/small&gt; {Link:344715e69dfefe30}]]&gt;&lt;/pref&gt;
+                                    &lt;/preferences&gt;
+                                &lt;/item&gt;
+                            &lt;/items&gt;
+                        &lt;/item&gt;
+                    &lt;/items&gt;
+                &lt;/layout&gt;
+                &lt;layout id=&quot;uid-1599e67e872cdfb1&quot; name=&quot;Product&quot;&gt;
+                    &lt;preferences&gt;
+                        &lt;pref key=&quot;type&quot; &gt;Entity&lt;/pref&gt;
+                        &lt;pref key=&quot;for&quot;&gt;1d03ca03e76d140e&lt;/pref&gt;
+                    &lt;/preferences&gt;
+                    &lt;items&gt;
+                        &lt;item&gt;
+                            &lt;preferences&gt;
+                                &lt;pref key=&quot;for&quot;&gt;main&lt;/pref&gt;
+                                &lt;pref key=&quot;xtype&quot;&gt;Nifty.EntityPane&lt;/pref&gt;
+                                &lt;pref key=&quot;labelAlign&quot;&gt;top&lt;/pref&gt;
+                            &lt;/preferences&gt;
+                            &lt;items&gt;
+                                &lt;item using=&quot;uid-d7ab61ad24519b82&quot;&gt;
+                                    &lt;preferences&gt;
+                                        &lt;pref key=&quot;xtype&quot;&gt;Nifty.SingleField&lt;/pref&gt;
+                                        &lt;pref key=&quot;field&quot;&gt;d7ab61ad24519b82&lt;/pref&gt;
+                                        &lt;pref key=&quot;tooltip&quot;&gt;Product Name&lt;/pref&gt;
+                                        &lt;pref key=&quot;viewTemplate&quot;&gt;&lt;![CDATA[{String:4dde5fffb2ca29af}]]&gt;&lt;/pref&gt;
+                                    &lt;/preferences&gt;
+                                &lt;/item&gt;
+                                &lt;item using=&quot;uid-c3eaca4f1ad150d9&quot;&gt;
+                                    &lt;preferences&gt;
+                                        &lt;pref key=&quot;xtype&quot;&gt;Nifty.SingleField&lt;/pref&gt;
+                                        &lt;pref key=&quot;field&quot;&gt;c3eaca4f1ad150d9&lt;/pref&gt;
+                                        &lt;pref key=&quot;tooltip&quot;&gt;List Price&lt;/pref&gt;
+                                        &lt;pref key=&quot;viewTemplate&quot;&gt;&lt;![CDATA[{String:9ec6e056b8bf203a}]]&gt;&lt;/pref&gt;
+                                    &lt;/preferences&gt;
+                                &lt;/item&gt;
+                                &lt;item using=&quot;uid-2a1f35b7547e73a7&quot;&gt;
+                                    &lt;preferences&gt;
+                                        &lt;pref key=&quot;xtype&quot;&gt;Nifty.SingleField&lt;/pref&gt;
+                                        &lt;pref key=&quot;field&quot;&gt;2a1f35b7547e73a7&lt;/pref&gt;
+                                        &lt;pref key=&quot;tooltip&quot;&gt;Type&lt;/pref&gt;
+                                        &lt;pref key=&quot;viewTemplate&quot;&gt;&lt;![CDATA[{String:4589dcc19104b5ad}]]&gt;&lt;/pref&gt;
+                                    &lt;/preferences&gt;
+                                &lt;/item&gt;
+                                &lt;item using=&quot;uid-1d5a79532c8ff7f7&quot;&gt;
+                                      &lt;preferences&gt;
+                                        &lt;pref key=&quot;xtype&quot;&gt;Nifty.MultiField&lt;/pref&gt;
+                                        &lt;pref key=&quot;field&quot;&gt;1d5a79532c8ff7f7&lt;/pref&gt;
+                                        &lt;pref key=&quot;tooltip&quot;&gt;Contributors&lt;/pref&gt;
+                                        &lt;pref key=&quot;viewTemplate&quot;&gt;&lt;![CDATA[{Link:1d97f15ccd526b90} &lt;small&gt;({String:228c9c108a81686b})&lt;/small&gt;]]&gt;&lt;/pref&gt;
+                                    &lt;/preferences&gt;
+                                &lt;/item&gt;
+
+                                &lt;item using=&quot;uid-f8d9a751b11f32f5&quot;&gt;
+                                      &lt;preferences&gt;
+                                        &lt;pref key=&quot;xtype&quot;&gt;Nifty.MultiField&lt;/pref&gt;
+                                        &lt;pref key=&quot;field&quot;&gt;f8d9a751b11f32f5&lt;/pref&gt;
+                                        &lt;pref key=&quot;tooltip&quot;&gt;Publisher&lt;/pref&gt;
+                                        &lt;pref key=&quot;viewTemplate&quot;&gt;&lt;![CDATA[{Link:3d346ea5d84496bc}]]&gt;&lt;/pref&gt;
+                                    &lt;/preferences&gt;
+                                &lt;/item&gt;
+
+                                &lt;item using=&quot;uid-de614cd2b830d038&quot;&gt;
+                                    &lt;preferences&gt;
+                                        &lt;pref key=&quot;xtype&quot;&gt;Nifty.SingleField&lt;/pref&gt;
+                                        &lt;pref key=&quot;field&quot;&gt;de614cd2b830d038&lt;/pref&gt;
+                                        &lt;pref key=&quot;tooltip&quot;&gt;Publication Date&lt;/pref&gt;
+                                        &lt;pref key=&quot;viewTemplate&quot;&gt;&lt;![CDATA[{String:4ec5d0e8ae9ffe9e}]]&gt;&lt;/pref&gt;
+                                    &lt;/preferences&gt;
+                                &lt;/item&gt;
+
+                                &lt;item using=&quot;uid-565f4687e3a91c9c&quot;&gt;
+                                    &lt;preferences&gt;
+                                        &lt;pref key=&quot;xtype&quot;&gt;Nifty.SingleField&lt;/pref&gt;
+                                        &lt;pref key=&quot;field&quot;&gt;565f4687e3a91c9c&lt;/pref&gt;
+                                        &lt;pref key=&quot;tooltip&quot;&gt;Sales Rank&lt;/pref&gt;
+                                        &lt;pref key=&quot;viewTemplate&quot;&gt;&lt;![CDATA[{String:7d25a2d2d51debd2}]]&gt;&lt;/pref&gt;
+                                    &lt;/preferences&gt;
+                                &lt;/item&gt;
+
+                                &lt;item using=&quot;uid-6396d04d06f6d6aa&quot;&gt;
+                                    &lt;preferences&gt;
+                                        &lt;pref key=&quot;xtype&quot;&gt;Nifty.SingleField&lt;/pref&gt;
+                                        &lt;pref key=&quot;field&quot;&gt;6396d04d06f6d6aa&lt;/pref&gt;
+                                        &lt;pref key=&quot;tooltip&quot;&gt;ASIN&lt;/pref&gt;
+                                        &lt;pref key=&quot;viewTemplate&quot;&gt;&lt;![CDATA[{String:58911e1905ce1f41}]]&gt;&lt;/pref&gt;
+                                    &lt;/preferences&gt;
+                                &lt;/item&gt;
+
+                                &lt;item using=&quot;uid-5bbe3d13c443372c&quot;&gt;
+                                      &lt;preferences&gt;
+                                        &lt;pref key=&quot;xtype&quot;&gt;Nifty.MultiField&lt;/pref&gt;
+                                        &lt;pref key=&quot;field&quot;&gt;5bbe3d13c443372c&lt;/pref&gt;
+                                        &lt;pref key=&quot;tooltip&quot;&gt;Attributes&lt;/pref&gt;
+                                        &lt;pref key=&quot;viewTemplate&quot;&gt;&lt;![CDATA[&lt;strong&gt;{String:2aab167708c27f7b}:&lt;/strong&gt; {String:2209ceaece034343}]]&gt;&lt;/pref&gt;
+                                    &lt;/preferences&gt;
+                                &lt;/item&gt;
+
+                                &lt;item using=&quot;uid-6e436fc498ede989&quot;&gt;
+                                      &lt;preferences&gt;
+                                        &lt;pref key=&quot;xtype&quot;&gt;Nifty.MultiField&lt;/pref&gt;
+                                        &lt;pref key=&quot;field&quot;&gt;6e436fc498ede989&lt;/pref&gt;
+                                        &lt;pref key=&quot;tooltip&quot;&gt;Subjects&lt;/pref&gt;
+                                        &lt;pref key=&quot;viewTemplate&quot;&gt;&lt;![CDATA[{String:521df08f37ce47a2}]]&gt;&lt;/pref&gt;
+                                    &lt;/preferences&gt;
+                                &lt;/item&gt;
+
+                                &lt;item using=&quot;uid-5f9c00833dad6aae&quot;&gt;
+                                      &lt;preferences&gt;
+                                        &lt;pref key=&quot;xtype&quot;&gt;Nifty.MultiField&lt;/pref&gt;
+                                        &lt;pref key=&quot;field&quot;&gt;5f9c00833dad6aae&lt;/pref&gt;
+                                        &lt;pref key=&quot;tooltip&quot;&gt;Reviews&lt;/pref&gt;
+                                        &lt;pref key=&quot;viewTemplate&quot;&gt;&lt;![CDATA[&lt;small&gt;{String:20ea1f8c74ed3125}&lt;/small&gt;: &lt;br/&gt; {String:fd0816ebcab622ca}]]&gt;&lt;/pref&gt;
+                                    &lt;/preferences&gt;
+                                &lt;/item&gt;
+
+                                 &lt;item using=&quot;uid-8ba8ae0d944a1187&quot;&gt;
+                                      &lt;preferences&gt;
+                                        &lt;pref key=&quot;xtype&quot;&gt;Nifty.MultiField&lt;/pref&gt;
+                                        &lt;pref key=&quot;field&quot;&gt;8ba8ae0d944a1187&lt;/pref&gt;
+                                        &lt;pref key=&quot;tooltip&quot;&gt;Related Products&lt;/pref&gt;
+                                        &lt;pref key=&quot;viewTemplate&quot;&gt;&lt;![CDATA[{Link:fa7d917d1f2be9bb}]]&gt;&lt;/pref&gt;
                                     &lt;/preferences&gt;
                                 &lt;/item&gt;
                             &lt;/items&gt;</diff>
      <filename>Samples/Amazonifty/schema.xml</filename>
    </modified>
    <modified>
      <diff>@@ -20,7 +20,14 @@ module App
     def inspect
       &quot;&lt;DataContainer (#{@instances.keys.size} instances)&gt;&quot;
     end
-  
+
+    def entity=(entity)
+      @entity = entity
+
+      # set the classes hash
+      @field_class = entity.class::FIELDS
+    end
+
     private
   
     def setup_storage
@@ -34,7 +41,7 @@ module App
       @field_class = {}
 
       # FieldID =&gt; list of Instance IDs
-      @fields = Hash.new {|hash, key| hash[key] = Set.new}
+      @fields = Hash.new {|hash, key| hash[key] = SortedSet.new}
 
       # EntityID =&gt; Entity instance
       # Used to store extra entities and their data for later
@@ -58,7 +65,6 @@ module App
 
         # 2. Get the field class and set it as the instance's class
         field_class = @instance_class[instance_id] ||= kind[:field_class]
-        @field_class[field_class::IDENTIFIER] = field_class
 
         # 3. Set the instance as an instance of its field (reverse of 2)
         @fields[field_class::IDENTIFIER] &lt;&lt; instance_id</diff>
      <filename>app/models/app/data_container.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,21 +1,21 @@
 module VM
   module Builders
-   class FieldBuilder &lt; AbstractBuilder
-     register_for :field
-     set_options  :model_class_name =&gt; 'Field',
-                  :extras =&gt; [
-                    :set_fieldlets,
-                    :set_duplication,
-                    :set_type,
-                    :cache_schema
-                  ]
-
-     ALLOWED_TYPES = [:single, :multi]
-
-     ##
-     # Setup the fieldlets constants
-     #
-     def set_fieldlets
+    class FieldBuilder &lt; AbstractBuilder
+      register_for :field
+      set_options  :model_class_name =&gt; 'Field',
+        :extras =&gt; [
+        :set_fieldlets,
+        :set_duplication,
+        :set_type,
+        :cache_schema
+      ]
+
+      ALLOWED_TYPES = [:single, :multi]
+
+      ##
+      # Setup the fieldlets constants
+      #
+      def set_fieldlets
         # We save two consts for every derived field class:
         # 1. FIELDLETS - A hash FieldletID(hex)=&gt;FieldletInfo (like in the namespace)
         # 2. FIELDLET_IDS - An ordered list of fieldlet ids. This is needed for
@@ -34,72 +34,72 @@ module VM
 
         # Set the consts
         self.set_consts!({'FIELDLET_IDS' =&gt; @fieldlet_ids,
-                          'FIELDLETS' =&gt; fieldlet_hash})
-     end
-
-     ##
-     # Setup field duplication
-     #
-     def set_duplication
-       duplication = @prefs['duplication']
-       if !duplication
-        self.set_consts!({'DUPLICATION' =&gt; nil})
-        return
-       end
-
-
-       duplication_hash = {}
-       duplication['target_classes'].each do |entity_kind,field_kind|
-						duplication_hash[@schema.get(entity_kind).generated] = @schema.get(field_kind).generated
-			 end
-
-
-       self.set_consts!({
-           'DUPLICATION' =&gt; duplication_hash
-         })
-
-     end
-
-     ##
-     # Setup field type to be single or multi, for use later
-     #
-     def set_type
-       field_type = @prefs['type']
-       return Merb.logger.error(&quot;Must enter a field type for field #{@element.generated::IDENTIFIER}&quot;) if !field_type
-
-       field_type = field_type.to_sym
-       if ALLOWED_TYPES.include?(field_type)
-         self.set_consts!({'TYPE' =&gt; field_type})
-       else
-         # TODO Make this a pretty exception and not a lame str
-         Merb.logger.error(&quot;Invalid field type for field&quot;)
-       end
-     end
-
-     # Save the Field's schema in output format
-     # Called by Entity#schema_hash
-     def cache_schema
-       res = {:name =&gt; @element[:name],
-              :prefs =&gt; @prefs,
-              :type =&gt; @prefs[&quot;type&quot;]
-       }
-
-       # Prepare fieldlet schema
-       flets = {}
+            'FIELDLETS' =&gt; fieldlet_hash})
+      end
+
+      ##
+      # Setup field duplication
+      #
+      def set_duplication
+        duplication = @prefs['duplication']
+        if !duplication
+          self.set_consts!({'DUPLICATION' =&gt; nil})
+          return
+        end
+
+
+        duplication_hash = {}
+        duplication['targetClasses'].each do |entity_kind,field_kind|
+          duplication_hash[@schema.get(entity_kind).generated] = @schema.get(field_kind).generated
+        end
+
+
+        self.set_consts!({
+            'DUPLICATION' =&gt; duplication_hash
+          })
+
+      end
+
+      ##
+      # Setup field type to be single or multi, for use later
+      #
+      def set_type
+        field_type = @prefs['type']
+        return Merb.logger.error(&quot;Must enter a field type for field #{@element.generated::IDENTIFIER}&quot;) if !field_type
+
+        field_type = field_type.to_sym
+        if ALLOWED_TYPES.include?(field_type)
+          self.set_consts!({'TYPE' =&gt; field_type})
+        else
+          # TODO Make this a pretty exception and not a lame str
+          Merb.logger.error(&quot;Invalid field type for field&quot;)
+        end
+      end
+
+      # Save the Field's schema in output format
+      # Called by Entity#schema_hash
+      def cache_schema
+        res = {:name =&gt; @element[:name],
+          :prefs =&gt; @prefs,
+          :type =&gt; @prefs[&quot;type&quot;]
+        }
+
+        # Prepare fieldlet schema
+        flets = {}
        
-       @fieldlet_ids.each do |fid|
-         flet_schema = @ns::FIELDLETS[fid]
-         flets[&quot;%016x&quot; % fid] = {
-                       :name =&gt; flet_schema[:name],
-                       :type =&gt; flet_schema[:prefs][&quot;type&quot;],
-                       :prefs =&gt; flet_schema[:prefs]
-                      }
-       end
-       res[:fieldlets] = flets
-
-       self.set_consts!({'SCHEMA_CACHE' =&gt; res})
-     end
-
-   end
+        @fieldlet_ids.each do |fid|
+          flet_schema = @ns::FIELDLETS[fid]
+          flets[&quot;%016x&quot; % fid] = {
+            :name =&gt; flet_schema[:name],
+            :type =&gt; flet_schema[:prefs][&quot;type&quot;],
+            :prefs =&gt; flet_schema[:prefs]
+          }
+        end
+        res[:fieldlets] = flets
+
+        self.set_consts!({'SCHEMA_CACHE' =&gt; res})
+      end
+
+    end
   end
 end
\ No newline at end of file</diff>
      <filename>app/models/vm/builders/field_builder.rb</filename>
    </modified>
    <modified>
      <diff>@@ -8,7 +8,8 @@
     &lt;%=
     stylesheets_include('../ext/resources/css/ext-all.css',
       'nifty-base.css',
-      'nifty-pane.css')
+      'nifty-pane.css',
+      'fields.css')
   %&gt;
   &lt;/head&gt;
   &lt;body&gt;
@@ -38,7 +39,9 @@
       'data/AbstractInstanceStore',
       'data/MultiInstanceStore',
       'data/SingleInstanceStore',
+      'data/ActionWriter',
       'Router',
+      'widgets/InfoBars/EditingInfoBar',
       'widgets/MainPane',
       'widgets/Page',
       'widgets/EntityPane',
@@ -46,7 +49,10 @@
       'widgets/fields/SingleField',
       'widgets/fields/MultiField',
       'widgets/fieldlets/StringFieldlet',
-      'widgets/fieldlets/LinkFieldlet'
+      'widgets/fieldlets/LinkFieldlet',
+      'widgets/layouts/InstanceEditorLayout',
+      'widgets/layouts/FormLayout',
+      'widgets/InstanceEditor'
     )%&gt;
   &lt;/body&gt;
 &lt;/html&gt;</diff>
      <filename>app/views/viewers/extjs.html.erb</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,6 @@
 # dependencies are generated using a strict version, don't forget to edit the dependency versions when upgrading.
 merb_gems_version = &quot;1.0.11&quot;
-sequel_gem_version = &quot;3.0.0&quot;
+sequel_gem_version = &quot;3.1.0&quot;
 
 # For more information about each component, please read http://wiki.merbivore.com/faqs/merb_components
 #dependency &quot;merb-action-args&quot;, merb_gems_version</diff>
      <filename>config/dependencies.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,211 +1,211 @@
 /*
- * Ext JS Library 3.0 RC 1.1
+ * Ext JS Library 3.0 RC2
  * Copyright(c) 2006-2009, Ext JS, LLC.
  * licensing@extjs.com
  * 
  * http://extjs.com/license
  */
 
-
-Ext.DomHelper = function(){
-    var tempTableEl = null,
-    	emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i,
-    	tableRe = /^table|tbody|tr|td$/i,
-    	pub,
-    	// kill repeat to save bytes
-    	afterbegin = &quot;afterbegin&quot;,
-    	afterend = &quot;afterend&quot;,
-    	beforebegin = &quot;beforebegin&quot;,
-    	beforeend = &quot;beforeend&quot;,
-    	ts = '&lt;table&gt;',
-        te = '&lt;/table&gt;',
-        tbs = ts+'&lt;tbody&gt;',
-        tbe = '&lt;/tbody&gt;'+te,
-        trs = tbs + '&lt;tr&gt;',
-        tre = '&lt;/tr&gt;'+tbe;
-        
-    // private
-    function doInsert(el, o, returnElement, pos, sibling, append){        
-        var newNode = pub.insertHtml(pos, Ext.getDom(el), createHtml(o));        
-        return returnElement ? Ext.get(newNode, true) : newNode;
-    }
-
-    // build as innerHTML where available
-    function createHtml(o){
-	    var b = &quot;&quot;,
-	    	attr,
-	    	val,
-	    	key,
-	    	keyVal,
-	    	cn;
-	    	
-        if(typeof o == 'string'){
-            b = o;
-        } else if (Ext.isArray(o)) {            
-	        Ext.each(o, function(v) {    
-                b += createHtml(v);
-            });            
-        } else {
-	        b += &quot;&lt;&quot; + (o.tag = o.tag || &quot;div&quot;);
-	        for(attr in o){		        
-		        val = o[attr];		        	
-		        if (!/tag|children|cn|html$/i.test(attr) &amp;&amp; !Ext.isFunction(val)) {		            			        
-		            if (Ext.isObject(val)) {	
-		            	b += &quot; &quot; + attr + &quot;='&quot;;
-	                    for (key in val) {
-		                    keyVal = val[key];
-		                    b += !Ext.isFunction(keyVal) ? key + &quot;:&quot; + keyVal + &quot;;&quot; : &quot;&quot;;	                        
-	                    }
-	                    b += &quot;'&quot;;			          
-	                } else {		                
-		             	b += &quot; &quot; + ({cls : &quot;class&quot;, htmlFor : &quot;for&quot;}[attr] || attr) + &quot;='&quot; + val + &quot;'&quot;;   
-	                }
-	            }
-	        }
-	        // Now either just close the tag or try to add children and close the tag.
-	        if (emptyTags.test(o.tag)) {
-	            b += &quot;/&gt;&quot;;
-	        } else {
-	            b += &quot;&gt;&quot;;
-	            if (cn = o.children || o.cn) {
-	                b += createHtml(cn);
-	            } else if(o.html){
-	                b += o.html;
-	            }
-	            b += &quot;&lt;/&quot; + o.tag + &quot;&gt;&quot;;
-        	}	        
-        }        
-        return b;
-    };    
-
-    function ieTable(depth, s, h, e){
-        tempTableEl.innerHTML = [s, h, e].join('');
-        var i = -1, 
-        	el = tempTableEl;
-        while(++i &lt; depth){
-            el = el.firstChild;
-        }
-        return el;
-    };
-
-    
-    function insertIntoTable(tag, where, el, html) {        
-	    var node,
-        	before;
-        	
-        tempTableEl = tempTableEl || document.createElement('div');        
-        		
-  	    if(tag == 'td' &amp;&amp; (where == afterbegin || where == beforeend) ||
-  	       !/td|tr|tbody/i.test(tag) &amp;&amp; (where == beforebegin || where == afterend)) { 
-            return;
-        }
-        before = where == beforebegin ? el :
-		 		 where == afterend ? el.nextSibling :
-				 where == afterbegin ? el.firstChild : null;
-				    
-        if (where == beforebegin || where == afterend) {	        
-        	el = el.parentNode;
-    	}
-        
-        if (tag == 'td' || (tag == &quot;tr&quot; &amp;&amp; (where == beforeend || where == afterbegin))) {
-	        node = ieTable(4, trs, html, tre);
-        } else if ((tag == &quot;tbody&quot; &amp;&amp; (where == beforeend || where == afterbegin)) || 
-        		   (tag == &quot;tr&quot; &amp;&amp; (where == beforebegin || where == afterend))) {
-	        node = ieTable(3, tbs, html, tbe);
-        } else {
-	     	node = ieTable(2, ts, html, te);   
-        }  
-        el.insertBefore(node, before);
-        return node;
-    };
-
-
-    pub = {
-	    
-	    markup : function(o){
-	        return createHtml(o);
-	    },	    
-	
-	    
-	    insertHtml : function(where, el, html){
-	        var hash = {},
-	        	hashVal,
- 	        	setStart,
-	        	range,
-	        	frag,
-	        	rangeEl,
-	        	rs;
-	        
-	        where = where.toLowerCase();	
-	        // add these here because they are used in both branches of the condition.	
-	        hash[beforebegin] = ['BeforeBegin', 'previousSibling'];	 
-	        hash[afterend] = ['AfterEnd', 'nextSibling'];	            
-	           
-	        if (el.insertAdjacentHTML) {
-	            if(tableRe.test(el.tagName) &amp;&amp; (rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html))){
-	            	return rs;	                
-	            }
-	            // add these two to the hash.
-	            hash[afterbegin] = ['AfterBegin', 'firstChild'];
-	            hash[beforeend] = ['BeforeEnd', 'lastChild'];	            
-	            if (hashVal = hash[where]) {
-		        	el.insertAdjacentHTML(hashVal[0], html);
-	            	return el[hashVal[1]];           	
-	            }	            
-	        } else {
-		        range = el.ownerDocument.createRange();	        		        
-		        setStart = &quot;setStart&quot; + (/end/i.test(where) ? &quot;After&quot; : &quot;Before&quot;);
-		        if (hash[where]) {
-			     	range[setStart](el);
-			     	frag = range.createContextualFragment(html);
-			     	el.parentNode.insertBefore(frag, where == beforebegin ? el : el.nextSibling);   
-			     	return el[(where == beforebegin ? &quot;previous&quot; : &quot;next&quot;) + &quot;Sibling&quot;];
-		        } else {			        
-			        rangeEl = (where == afterbegin ? &quot;first&quot; : &quot;last&quot;) + &quot;Child&quot;;
-			        if (el.firstChild) {
-				        range[setStart](el[rangeEl]);
-				        frag = range.createContextualFragment(html);
-				        where == afterbegin ? el.insertBefore(frag, el.firstChild) : el.appendChild(frag);			       	
-			        } else {
-		 	            el.innerHTML = html;	    	        
-	 	            }
-	 	            return el[rangeEl];
-		        }
-	        }
-	        throw 'Illegal insertion point -&gt; &quot;' + where + '&quot;';
-	    },
-	
-	    
-	    insertBefore : function(el, o, returnElement){
-	        return doInsert(el, o, returnElement, beforebegin);
-	    },
-	
-	    
-	    insertAfter : function(el, o, returnElement){
-	        return doInsert(el, o, returnElement, afterend, &quot;nextSibling&quot;);
-	    },
-	
-	    
-	    insertFirst : function(el, o, returnElement){
-	        return doInsert(el, o, returnElement, afterbegin, &quot;firstChild&quot;);
-	    },	    
-	
-	    
-	    append : function(el, o, returnElement){
-		    return doInsert(el, o, returnElement, beforeend, &quot;&quot;, true);
-	    },
-	
-	    
-	    overwrite : function(el, o, returnElement){
-	        el = Ext.getDom(el);
-	        el.innerHTML = createHtml(o);
-	        return returnElement ? Ext.get(el.firstChild) : el.firstChild;
-	    },
-	    
-	    createHtml : createHtml
-    };    
-    return pub;
-}();
+
+Ext.DomHelper = function(){
+    var tempTableEl = null,
+    	emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i,
+    	tableRe = /^table|tbody|tr|td$/i,
+    	pub,
+    	// kill repeat to save bytes
+    	afterbegin = &quot;afterbegin&quot;,
+    	afterend = &quot;afterend&quot;,
+    	beforebegin = &quot;beforebegin&quot;,
+    	beforeend = &quot;beforeend&quot;,
+    	ts = '&lt;table&gt;',
+        te = '&lt;/table&gt;',
+        tbs = ts+'&lt;tbody&gt;',
+        tbe = '&lt;/tbody&gt;'+te,
+        trs = tbs + '&lt;tr&gt;',
+        tre = '&lt;/tr&gt;'+tbe;
+        
+    // private
+    function doInsert(el, o, returnElement, pos, sibling, append){        
+        var newNode = pub.insertHtml(pos, Ext.getDom(el), createHtml(o));        
+        return returnElement ? Ext.get(newNode, true) : newNode;
+    }
+
+    // build as innerHTML where available
+    function createHtml(o){
+	    var b = &quot;&quot;,
+	    	attr,
+	    	val,
+	    	key,
+	    	keyVal,
+	    	cn;
+	    	
+        if(typeof o == 'string'){
+            b = o;
+        } else if (Ext.isArray(o)) {            
+	        Ext.each(o, function(v) {    
+                b += createHtml(v);
+            });            
+        } else {
+	        b += &quot;&lt;&quot; + (o.tag = o.tag || &quot;div&quot;);
+	        for(attr in o){		        
+		        val = o[attr];		        	
+		        if (!/tag|children|cn|html$/i.test(attr) &amp;&amp; !Ext.isFunction(val)) {		            			        
+		            if (Ext.isObject(val)) {	
+		            	b += &quot; &quot; + attr + &quot;='&quot;;
+	                    for (key in val) {
+		                    keyVal = val[key];
+		                    b += !Ext.isFunction(keyVal) ? key + &quot;:&quot; + keyVal + &quot;;&quot; : &quot;&quot;;	                        
+	                    }
+	                    b += &quot;'&quot;;			          
+	                } else {		                
+		             	b += &quot; &quot; + ({cls : &quot;class&quot;, htmlFor : &quot;for&quot;}[attr] || attr) + &quot;='&quot; + val + &quot;'&quot;;   
+	                }
+	            }
+	        }
+	        // Now either just close the tag or try to add children and close the tag.
+	        if (emptyTags.test(o.tag)) {
+	            b += &quot;/&gt;&quot;;
+	        } else {
+	            b += &quot;&gt;&quot;;
+	            if (cn = o.children || o.cn) {
+	                b += createHtml(cn);
+	            } else if(o.html){
+	                b += o.html;
+	            }
+	            b += &quot;&lt;/&quot; + o.tag + &quot;&gt;&quot;;
+        	}	        
+        }        
+        return b;
+    };    
+
+    function ieTable(depth, s, h, e){
+        tempTableEl.innerHTML = [s, h, e].join('');
+        var i = -1, 
+        	el = tempTableEl;
+        while(++i &lt; depth){
+            el = el.firstChild;
+        }
+        return el;
+    };
+
+    
+    function insertIntoTable(tag, where, el, html) {        
+	    var node,
+        	before;
+        	
+        tempTableEl = tempTableEl || document.createElement('div');        
+        		
+  	    if(tag == 'td' &amp;&amp; (where == afterbegin || where == beforeend) ||
+  	       !/td|tr|tbody/i.test(tag) &amp;&amp; (where == beforebegin || where == afterend)) { 
+            return;
+        }
+        before = where == beforebegin ? el :
+		 		 where == afterend ? el.nextSibling :
+				 where == afterbegin ? el.firstChild : null;
+				    
+        if (where == beforebegin || where == afterend) {	        
+        	el = el.parentNode;
+    	}
+        
+        if (tag == 'td' || (tag == &quot;tr&quot; &amp;&amp; (where == beforeend || where == afterbegin))) {
+	        node = ieTable(4, trs, html, tre);
+        } else if ((tag == &quot;tbody&quot; &amp;&amp; (where == beforeend || where == afterbegin)) || 
+        		   (tag == &quot;tr&quot; &amp;&amp; (where == beforebegin || where == afterend))) {
+	        node = ieTable(3, tbs, html, tbe);
+        } else {
+	     	node = ieTable(2, ts, html, te);   
+        }  
+        el.insertBefore(node, before);
+        return node;
+    };
+
+
+    pub = {
+	    
+	    markup : function(o){
+	        return createHtml(o);
+	    },	    
+	
+	    
+	    insertHtml : function(where, el, html){
+	        var hash = {},
+	        	hashVal,
+ 	        	setStart,
+	        	range,
+	        	frag,
+	        	rangeEl,
+	        	rs;
+	        
+	        where = where.toLowerCase();	
+	        // add these here because they are used in both branches of the condition.	
+	        hash[beforebegin] = ['BeforeBegin', 'previousSibling'];	 
+	        hash[afterend] = ['AfterEnd', 'nextSibling'];	            
+	           
+	        if (el.insertAdjacentHTML) {
+	            if(tableRe.test(el.tagName) &amp;&amp; (rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html))){
+	            	return rs;	                
+	            }
+	            // add these two to the hash.
+	            hash[afterbegin] = ['AfterBegin', 'firstChild'];
+	            hash[beforeend] = ['BeforeEnd', 'lastChild'];	            
+	            if (hashVal = hash[where]) {
+		        	el.insertAdjacentHTML(hashVal[0], html);
+	            	return el[hashVal[1]];           	
+	            }	            
+	        } else {
+		        range = el.ownerDocument.createRange();	        		        
+		        setStart = &quot;setStart&quot; + (/end/i.test(where) ? &quot;After&quot; : &quot;Before&quot;);
+		        if (hash[where]) {
+			     	range[setStart](el);
+			     	frag = range.createContextualFragment(html);
+			     	el.parentNode.insertBefore(frag, where == beforebegin ? el : el.nextSibling);   
+			     	return el[(where == beforebegin ? &quot;previous&quot; : &quot;next&quot;) + &quot;Sibling&quot;];
+		        } else {			        
+			        rangeEl = (where == afterbegin ? &quot;first&quot; : &quot;last&quot;) + &quot;Child&quot;;
+			        if (el.firstChild) {
+				        range[setStart](el[rangeEl]);
+				        frag = range.createContextualFragment(html);
+				        where == afterbegin ? el.insertBefore(frag, el.firstChild) : el.appendChild(frag);			       	
+			        } else {
+		 	            el.innerHTML = html;	    	        
+	 	            }
+	 	            return el[rangeEl];
+		        }
+	        }
+	        throw 'Illegal insertion point -&gt; &quot;' + where + '&quot;';
+	    },
+	
+	    
+	    insertBefore : function(el, o, returnElement){
+	        return doInsert(el, o, returnElement, beforebegin);
+	    },
+	
+	    
+	    insertAfter : function(el, o, returnElement){
+	        return doInsert(el, o, returnElement, afterend, &quot;nextSibling&quot;);
+	    },
+	
+	    
+	    insertFirst : function(el, o, returnElement){
+	        return doInsert(el, o, returnElement, afterbegin, &quot;firstChild&quot;);
+	    },	    
+	
+	    
+	    append : function(el, o, returnElement){
+		    return doInsert(el, o, returnElement, beforeend, &quot;&quot;, true);
+	    },
+	
+	    
+	    overwrite : function(el, o, returnElement){
+	        el = Ext.getDom(el);
+	        el.innerHTML = createHtml(o);
+	        return returnElement ? Ext.get(el.firstChild) : el.firstChild;
+	    },
+	    
+	    createHtml : createHtml
+    };    
+    return pub;
+}();
 
 Ext.apply(Ext.DomHelper, 
 function(){
@@ -294,15 +294,15 @@ function(){
 	    			style; 
 	    			
 	    		el = Ext.fly(el);	    			
-				if(Ext.isFunction(styles)) {
+				if(Ext.isFunction(styles)){
    					styles = styles.call();
 				}
-				if (typeof styles == &quot;string&quot;) {
-					styles = styles.split(/:|;/g);
-					for (len = styles.length; i &lt; len;) {
+				if(typeof styles == &quot;string&quot;){
+					styles = styles.trim().split(/\s*(?::|;)\s*/);
+					for(len = styles.length; i &lt; len;){
 						el.setStyle(styles[i++], styles[i++]);	
 					}
-				} else if (Ext.isObject(styles)) {
+				}else if (Ext.isObject(styles)){
 					el.setStyle(styles);
 				}			
 			}	
@@ -332,112 +332,112 @@ function(){
         createDom: createDom
 	}
 	return pub;	
-}());
-
-Ext.Template = function(html){
-    var me = this,
-    	a = arguments,
-    	buf = [];
-
-    if (Ext.isArray(html)) {
-        html = html.join(&quot;&quot;);
-    } else if (a.length &gt; 1) {
-	    Ext.each(a, function(v) {
-            if (Ext.isObject(v)) {
-                Ext.apply(me, v);
-            } else {
-                buf.push(v);
-            }
-        });
-        html = buf.join('');
-    }
-
-    
-    me.html = html;
-    if (me.compiled) {
-        me.compile();
-    }
-};
-Ext.Template.prototype = {
-    
-    applyTemplate : function(values){
-		var me = this;
-
-        return me.compiled ?
-        		me.compiled(values) :
-				me.html.replace(me.re, function(m, name){
-		        	return values[name] !== undefined ? values[name] : &quot;&quot;;
-		        });
-	},
-
-    
-    set : function(html, compile){
-	    var me = this;
-        me.html = html;
-        me.compiled = null;
-        return compile ? me.compile() : me;
-    },
-
-    
-    re : /\{([\w-]+)\}/g,
-
-    
-    compile : function(){
-        var me = this,
-        	sep = Ext.isGecko ? &quot;+&quot; : &quot;,&quot;;
-
-        function fn(m, name){                        
-	        name = &quot;values['&quot; + name + &quot;']&quot;;
-	        return &quot;'&quot;+ sep + '(' + name + &quot; == undefined ? '' : &quot; + name + ')' + sep + &quot;'&quot;;
-        }
-                
-        eval(&quot;this.compiled = function(values){ return &quot; + (Ext.isGecko ? &quot;'&quot; : &quot;['&quot;) +
-             me.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, &quot;\\'&quot;).replace(this.re, fn) +
-             (Ext.isGecko ?  &quot;';};&quot; : &quot;'].join('');};&quot;));
-        return me;
-    },
-
-    
-    insertFirst: function(el, values, returnElement){
-        return this.doInsert('afterBegin', el, values, returnElement);
-    },
-
-    
-    insertBefore: function(el, values, returnElement){
-        return this.doInsert('beforeBegin', el, values, returnElement);
-    },
-
-    
-    insertAfter : function(el, values, returnElement){
-        return this.doInsert('afterEnd', el, values, returnElement);
-    },
-
-    
-    append : function(el, values, returnElement){
-        return this.doInsert('beforeEnd', el, values, returnElement);
-    },
-
-    doInsert : function(where, el, values, returnEl){
-        el = Ext.getDom(el);
-        var newNode = Ext.DomHelper.insertHtml(where, el, this.applyTemplate(values));
-        return returnEl ? Ext.get(newNode, true) : newNode;
-    },
-
-    
-    overwrite : function(el, values, returnElement){
-        el = Ext.getDom(el);
-        el.innerHTML = this.applyTemplate(values);
-        return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
-    }
-};
-
-Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate;
-
-
-Ext.Template.from = function(el, config){
-    el = Ext.getDom(el);
-    return new Ext.Template(el.value || el.innerHTML, config || '');
-};
+}());
+
+Ext.Template = function(html){
+    var me = this,
+    	a = arguments,
+    	buf = [];
+
+    if (Ext.isArray(html)) {
+        html = html.join(&quot;&quot;);
+    } else if (a.length &gt; 1) {
+	    Ext.each(a, function(v) {
+            if (Ext.isObject(v)) {
+                Ext.apply(me, v);
+            } else {
+                buf.push(v);
+            }
+        });
+        html = buf.join('');
+    }
+
+    
+    me.html = html;
+    if (me.compiled) {
+        me.compile();
+    }
+};
+Ext.Template.prototype = {
+    
+    applyTemplate : function(values){
+		var me = this;
+
+        return me.compiled ?
+        		me.compiled(values) :
+				me.html.replace(me.re, function(m, name){
+		        	return values[name] !== undefined ? values[name] : &quot;&quot;;
+		        });
+	},
+
+    
+    set : function(html, compile){
+	    var me = this;
+        me.html = html;
+        me.compiled = null;
+        return compile ? me.compile() : me;
+    },
+
+    
+    re : /\{([\w-]+)\}/g,
+
+    
+    compile : function(){
+        var me = this,
+        	sep = Ext.isGecko ? &quot;+&quot; : &quot;,&quot;;
+
+        function fn(m, name){                        
+	        name = &quot;values['&quot; + name + &quot;']&quot;;
+	        return &quot;'&quot;+ sep + '(' + name + &quot; == undefined ? '' : &quot; + name + ')' + sep + &quot;'&quot;;
+        }
+                
+        eval(&quot;this.compiled = function(values){ return &quot; + (Ext.isGecko ? &quot;'&quot; : &quot;['&quot;) +
+             me.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, &quot;\\'&quot;).replace(this.re, fn) +
+             (Ext.isGecko ?  &quot;';};&quot; : &quot;'].join('');};&quot;));
+        return me;
+    },
+
+    
+    insertFirst: function(el, values, returnElement){
+        return this.doInsert('afterBegin', el, values, returnElement);
+    },
+
+    
+    insertBefore: function(el, values, returnElement){
+        return this.doInsert('beforeBegin', el, values, returnElement);
+    },
+
+    
+    insertAfter : function(el, values, returnElement){
+        return this.doInsert('afterEnd', el, values, returnElement);
+    },
+
+    
+    append : function(el, values, returnElement){
+        return this.doInsert('beforeEnd', el, values, returnElement);
+    },
+
+    doInsert : function(where, el, values, returnEl){
+        el = Ext.getDom(el);
+        var newNode = Ext.DomHelper.insertHtml(where, el, this.applyTemplate(values));
+        return returnEl ? Ext.get(newNode, true) : newNode;
+    },
+
+    
+    overwrite : function(el, values, returnElement){
+        el = Ext.getDom(el);
+        el.innerHTML = this.applyTemplate(values);
+        return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
+    }
+};
+
+Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate;
+
+
+Ext.Template.from = function(el, config){
+    el = Ext.getDom(el);
+    return new Ext.Template(el.value || el.innerHTML, config || '');
+};
 
 Ext.apply(Ext.Template.prototype, {
     
@@ -526,7 +526,7 @@ Ext.apply(Ext.Template.prototype, {
         return this[fnName](value, allValues);
     }
 });
-Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate; 
+Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate; 
 
 
 Ext.DomQuery = function(){
@@ -544,6 +544,7 @@ Ext.DomQuery = function(){
 	    // IE runs the same speed using setAttribute, however FF slows way down
 	    // and Safari completely fails so they need to continue to use expandos.
 	    isIE = window.ActiveXObject ? true : false,
+        isOpera = Ext.isOpera,
 	    key = 30803;
 	    
     // this eval is stop the compressor from
@@ -638,7 +639,7 @@ Ext.DomQuery = function(){
         }else if(mode == &quot;/&quot; || mode == &quot;&gt;&quot;){
             var utag = tagName.toUpperCase();
             for(var i = 0, ni, cn; ni = ns[i]; i++){
-                cn = ni.children || ni.childNodes;
+                cn = isOpera ? ni.childNodes : (ni.children || ni.childNodes);
                 for(var j = 0, cj; cj = cn[j]; j++){
                     if(cj.nodeName == utag || cj.nodeName == tagName  || tagName == '*'){
                         result[++ri] = cj;
@@ -654,10 +655,12 @@ Ext.DomQuery = function(){
                 }
             }
         }else if(mode == &quot;~&quot;){
+            var utag = tagName.toUpperCase();
             for(var i = 0, n; n = ns[i]; i++){
-                while((n = n.nextSibling) &amp;&amp; (n.nodeType != 1 || (tagName == '*' || n.tagName.toLowerCase()!=tagName)));
-                if(n){
-                    result[++ri] = n;
+                while((n = n.nextSibling)){
+                    if (n.nodeName == utag || n.nodeName == tagName || tagName == '*'){
+                        result[++ri] = n;
+                    }
                 }
             }
         }
@@ -1224,286 +1227,286 @@ Ext.DomQuery = function(){
 
 
 Ext.query = Ext.DomQuery.select;
-
-(function(){
-
-var EXTUTIL = Ext.util, 
-    TOARRAY = Ext.toArray, 
-    EACH = Ext.each, 
-    ISOBJECT = Ext.isObject,
-    TRUE = true,
-    FALSE = false;
-
-EXTUTIL.Observable = function(){
-    
-    var me = this, e = me.events;
-    if(me.listeners){
-        me.on(me.listeners);
-        delete me.listeners;
-    }
-    me.events = e || {};
-};
-
-EXTUTIL.Observable.prototype = function(){
-    var filterOptRe = /^(?:scope|delay|buffer|single)$/, toLower = function(s){
-        return s.toLowerCase();    
-    };
-        
-    return {
-        
-    
-        fireEvent : function(){
-            var a = TOARRAY(arguments),
-                ename = toLower(a[0]),
-                me = this,
-                ret = TRUE,
-                ce = me.events[ename],
-                q,
-                c;
-            if (me.eventsSuspended === TRUE) {
-                if (q = me.suspendedEventsQueue) {
-                    q.push(a);
-                }
-            }
-            else if(ISOBJECT(ce) &amp;&amp; ce.bubble){
-                if(ce.fire.apply(ce, a.slice(1)) === FALSE) {
-                    return FALSE;
-                }
-                c = me.getBubbleTarget &amp;&amp; me.getBubbleTarget();
-                if(c &amp;&amp; c.enableBubble) {
-                    c.enableBubble(ename);
-                    return c.fireEvent.apply(c, a);
-                }
-            }
-            else {            
-                if (ISOBJECT(ce)) {
-                    a.shift();
-                    ret = ce.fire.apply(ce, a);
-                }
-            }
-            return ret;
-        },
-
-        
-        addListener : function(eventName, fn, scope, o){
-            var me = this,
-                e,
-                oe,
-                isF,
-            ce;
-            if (ISOBJECT(eventName)) {
-                o = eventName;
-                for (e in o){
-                    oe = o[e];
-                    if (!filterOptRe.test(e)) {
-                        me.addListener(e, oe.fn || oe, oe.scope || o.scope, oe.fn ? oe : o);
-                    }
-                }
-            } else {
-                eventName = toLower(eventName);
-                ce = me.events[eventName] || TRUE;
-                if (typeof ce == &quot;boolean&quot;) {
-                    me.events[eventName] = ce = new EXTUTIL.Event(me, eventName);
-                }
-                ce.addListener(fn, scope, ISOBJECT(o) ? o : {});
-            }
-        },
-
-        
-        removeListener : function(eventName, fn, scope){
-            var ce = this.events[toLower(eventName)];
-            if (ISOBJECT(ce)) {
-                ce.removeListener(fn, scope);
-            }
-        },
-
-        
-        purgeListeners : function(){
-            var events = this.events,
-                evt,
-                key;
-            for(key in events){
-                evt = events[key];
-                if(ISOBJECT(evt)){
-                    evt.clearListeners();
-                }
-            }
-        },
-
-        
-        addEvents : function(o){
-            var me = this;
-            me.events = me.events || {};
-            if (typeof o == 'string') {
-                EACH(arguments, function(a) {
-                    me.events[a] = me.events[a] || TRUE;
-                });
-            } else {
-                Ext.applyIf(me.events, o);
-            }
-        },
-
-        
-        hasListener : function(eventName){
-            var e = this.events[eventName];
-            return ISOBJECT(e) &amp;&amp; e.listeners.length &gt; 0;
-        },
-
-        
-        suspendEvents : function(queueSuspended){
-            this.eventsSuspended = TRUE;
-            if (queueSuspended){
-                this.suspendedEventsQueue = [];
-            }
-        },
-
-        
-        resumeEvents : function(){
-            var me = this;
-            me.eventsSuspended = !delete me.suspendedEventQueue;
-            EACH(me.suspendedEventsQueue, function(e) {
-                me.fireEvent.apply(me, e);
-            });
-        }
-    }
-}();
-
-var OBSERVABLE = EXTUTIL.Observable.prototype;
-
-OBSERVABLE.on = OBSERVABLE.addListener;
-
-OBSERVABLE.un = OBSERVABLE.removeListener;
-
-
-EXTUTIL.Observable.releaseCapture = function(o){
-    o.fireEvent = OBSERVABLE.fireEvent;
-};
-
-function createTargeted(h, o, scope){
-    return function(){
-        if(o.target == arguments[0]){
-            h.apply(scope, TOARRAY(arguments));
-        }
-    };
-};
-
-function createBuffered(h, o, scope){
-    var task = new EXTUTIL.DelayedTask();
-    return function(){
-        task.delay(o.buffer, h, scope, TOARRAY(arguments));
-    };
-}
-    
-function createSingle(h, e, fn, scope){
-    return function(){
-        e.removeListener(fn, scope);
-        return h.apply(scope, arguments);
-    };
-}
-    
-function createDelayed(h, o, scope){
-    return function(){
-        var args = TOARRAY(arguments);
-        (function(){
-            h.apply(scope, args);
-        }).defer(o.delay || 10);
-    };
-};
-
-EXTUTIL.Event = function(obj, name){
-    this.name = name;
-    this.obj = obj;
-    this.listeners = [];
-};
-
-EXTUTIL.Event.prototype = {
-    addListener : function(fn, scope, options){
-        var me = this,
-            l;
-        scope = scope || me.obj;
-        if(!me.isListening(fn, scope)){
-            l = me.createListener(fn, scope, options);
-            if(me.firing){ // if we are currently firing this event, don't disturb the listener loop                                    
-                me.listeners = me.listeners.slice(0);                
-            }
-            me.listeners.push(l);
-        }
-    },
-
-    createListener: function(fn, scope, o){
-        o = o || {}, scope = scope || this.obj;
-        var l = {
-            fn: fn,
-            scope: scope,
-            options: o
-        }, h = fn;
-        if(o.target){
-            h = createTargeted(h, o, scope);
-        }
-        if(o.delay){
-            h = createDelayed(h, o, scope);
-        }
-        if(o.single){
-            h = createSingle(h, this, fn, scope);
-        }
-        if(o.buffer){
-            h = createBuffered(h, o, scope);
-        }
-        l.fireFn = h;
-        return l;
-    },
-
-    findListener : function(fn, scope){ 
-        var s, ret = -1;
-        EACH(this.listeners, function(l, i) {
-            s = l.scope;
-            if(l.fn == fn &amp;&amp; (s == scope || s == this.obj)){
-                ret = i;
-                return FALSE;
-            }
-        },
-        this);
-        return ret;
-    },
-
-    isListening : function(fn, scope){
-        return this.findListener(fn, scope) != -1;
-    },
-
-    removeListener : function(fn, scope){
-        var index,
-            me = this,
-            ret = FALSE;
-        if((index = me.findListener(fn, scope)) != -1){
-            if (me.firing) {
-                me.listeners = me.listeners.slice(0);
-            }
-            me.listeners.splice(index, 1);
-            ret = TRUE;
-        }
-        return ret;
-    },
-
-    clearListeners : function(){
-        this.listeners = [];
-    },
-
-    fire : function(){
-        var me = this,
-            args = TOARRAY(arguments),
-            ret = TRUE;
-
-        EACH(me.listeners, function(l) {
-            me.firing = TRUE;
-            if (l.fireFn.apply(l.scope || me.obj || window, args) === FALSE) {
-                return ret = me.firing = FALSE;
-            }
-        });
-        me.firing = FALSE;
-        return ret;
-    }
-};
-})();
+
+(function(){
+
+var EXTUTIL = Ext.util, 
+    TOARRAY = Ext.toArray, 
+    EACH = Ext.each, 
+    ISOBJECT = Ext.isObject,
+    TRUE = true,
+    FALSE = false;
+
+EXTUTIL.Observable = function(){
+    
+    var me = this, e = me.events;
+    if(me.listeners){
+        me.on(me.listeners);
+        delete me.listeners;
+    }
+    me.events = e || {};
+};
+
+EXTUTIL.Observable.prototype = function(){
+    var filterOptRe = /^(?:scope|delay|buffer|single)$/, toLower = function(s){
+        return s.toLowerCase();    
+    };
+        
+    return {
+        
+    
+        fireEvent : function(){
+            var a = TOARRAY(arguments),
+                ename = toLower(a[0]),
+                me = this,
+                ret = TRUE,
+                ce = me.events[ename],
+                q,
+                c;
+            if (me.eventsSuspended === TRUE) {
+                if (q = me.suspendedEventsQueue) {
+                    q.push(a);
+                }
+            }
+            else if(ISOBJECT(ce) &amp;&amp; ce.bubble){
+                if(ce.fire.apply(ce, a.slice(1)) === FALSE) {
+                    return FALSE;
+                }
+                c = me.getBubbleTarget &amp;&amp; me.getBubbleTarget();
+                if(c &amp;&amp; c.enableBubble) {
+                    c.enableBubble(ename);
+                    return c.fireEvent.apply(c, a);
+                }
+            }
+            else {            
+                if (ISOBJECT(ce)) {
+                    a.shift();
+                    ret = ce.fire.apply(ce, a);
+                }
+            }
+            return ret;
+        },
+
+        
+        addListener : function(eventName, fn, scope, o){
+            var me = this,
+                e,
+                oe,
+                isF,
+            ce;
+            if (ISOBJECT(eventName)) {
+                o = eventName;
+                for (e in o){
+                    oe = o[e];
+                    if (!filterOptRe.test(e)) {
+                        me.addListener(e, oe.fn || oe, oe.scope || o.scope, oe.fn ? oe : o);
+                    }
+                }
+            } else {
+                eventName = toLower(eventName);
+                ce = me.events[eventName] || TRUE;
+                if (typeof ce == &quot;boolean&quot;) {
+                    me.events[eventName] = ce = new EXTUTIL.Event(me, eventName);
+                }
+                ce.addListener(fn, scope, ISOBJECT(o) ? o : {});
+            }
+        },
+
+        
+        removeListener : function(eventName, fn, scope){
+            var ce = this.events[toLower(eventName)];
+            if (ISOBJECT(ce)) {
+                ce.removeListener(fn, scope);
+            }
+        },
+
+        
+        purgeListeners : function(){
+            var events = this.events,
+                evt,
+                key;
+            for(key in events){
+                evt = events[key];
+                if(ISOBJECT(evt)){
+                    evt.clearListeners();
+                }
+            }
+        },
+
+        
+        addEvents : function(o){
+            var me = this;
+            me.events = me.events || {};
+            if (typeof o == 'string') {
+                EACH(arguments, function(a) {
+                    me.events[a] = me.events[a] || TRUE;
+                });
+            } else {
+                Ext.applyIf(me.events, o);
+            }
+        },
+
+        
+        hasListener : function(eventName){
+            var e = this.events[eventName];
+            return ISOBJECT(e) &amp;&amp; e.listeners.length &gt; 0;
+        },
+
+        
+        suspendEvents : function(queueSuspended){
+            this.eventsSuspended = TRUE;
+            if (queueSuspended){
+                this.suspendedEventsQueue = [];
+            }
+        },
+
+        
+        resumeEvents : function(){
+            var me = this;
+            me.eventsSuspended = !delete me.suspendedEventQueue;
+            EACH(me.suspendedEventsQueue, function(e) {
+                me.fireEvent.apply(me, e);
+            });
+        }
+    }
+}();
+
+var OBSERVABLE = EXTUTIL.Observable.prototype;
+
+OBSERVABLE.on = OBSERVABLE.addListener;
+
+OBSERVABLE.un = OBSERVABLE.removeListener;
+
+
+EXTUTIL.Observable.releaseCapture = function(o){
+    o.fireEvent = OBSERVABLE.fireEvent;
+};
+
+function createTargeted(h, o, scope){
+    return function(){
+        if(o.target == arguments[0]){
+            h.apply(scope, TOARRAY(arguments));
+        }
+    };
+};
+
+function createBuffered(h, o, scope){
+    var task = new EXTUTIL.DelayedTask();
+    return function(){
+        task.delay(o.buffer, h, scope, TOARRAY(arguments));
+    };
+}
+    
+function createSingle(h, e, fn, scope){
+    return function(){
+        e.removeListener(fn, scope);
+        return h.apply(scope, arguments);
+    };
+}
+    
+function createDelayed(h, o, scope){
+    return function(){
+        var args = TOARRAY(arguments);
+        (function(){
+            h.apply(scope, args);
+        }).defer(o.delay || 10);
+    };
+};
+
+EXTUTIL.Event = function(obj, name){
+    this.name = name;
+    this.obj = obj;
+    this.listeners = [];
+};
+
+EXTUTIL.Event.prototype = {
+    addListener : function(fn, scope, options){
+        var me = this,
+            l;
+        scope = scope || me.obj;
+        if(!me.isListening(fn, scope)){
+            l = me.createListener(fn, scope, options);
+            if(me.firing){ // if we are currently firing this event, don't disturb the listener loop                                    
+                me.listeners = me.listeners.slice(0);                
+            }
+            me.listeners.push(l);
+        }
+    },
+
+    createListener: function(fn, scope, o){
+        o = o || {}, scope = scope || this.obj;
+        var l = {
+            fn: fn,
+            scope: scope,
+            options: o
+        }, h = fn;
+        if(o.target){
+            h = createTargeted(h, o, scope);
+        }
+        if(o.delay){
+            h = createDelayed(h, o, scope);
+        }
+        if(o.single){
+            h = createSingle(h, this, fn, scope);
+        }
+        if(o.buffer){
+            h = createBuffered(h, o, scope);
+        }
+        l.fireFn = h;
+        return l;
+    },
+
+    findListener : function(fn, scope){ 
+        var s, ret = -1;
+        EACH(this.listeners, function(l, i) {
+            s = l.scope;
+            if(l.fn == fn &amp;&amp; (s == scope || s == this.obj)){
+                ret = i;
+                return FALSE;
+            }
+        },
+        this);
+        return ret;
+    },
+
+    isListening : function(fn, scope){
+        return this.findListener(fn, scope) != -1;
+    },
+
+    removeListener : function(fn, scope){
+        var index,
+            me = this,
+            ret = FALSE;
+        if((index = me.findListener(fn, scope)) != -1){
+            if (me.firing) {
+                me.listeners = me.listeners.slice(0);
+            }
+            me.listeners.splice(index, 1);
+            ret = TRUE;
+        }
+        return ret;
+    },
+
+    clearListeners : function(){
+        this.listeners = [];
+    },
+
+    fire : function(){
+        var me = this,
+            args = TOARRAY(arguments),
+            ret = TRUE;
+
+        EACH(me.listeners, function(l) {
+            me.firing = TRUE;
+            if (l.fireFn.apply(l.scope || me.obj || window, args) === FALSE) {
+                return ret = me.firing = FALSE;
+            }
+        });
+        me.firing = FALSE;
+        return ret;
+    }
+};
+})();
 
 Ext.apply(Ext.util.Observable.prototype, function(){    
     // this is considered experimental (along with beforeMethod, afterMethod, removeMethodListener?)
@@ -1646,473 +1649,480 @@ Ext.util.Observable.observeClass = function(c){
         return (c.fireEvent.apply(c, arguments) !== false) &amp;&amp;
         (Ext.util.Observable.prototype.fireEvent.apply(this, arguments) !== false);
     };
-};
-
-Ext.EventManager = function(){
-    var docReadyEvent, 
-    	docReadyProcId, 
-    	docReadyState = false,    	
-    	E = Ext.lib.Event,
-    	D = Ext.lib.Dom,
-    	DOC = document,
-    	WINDOW = window,
-    	IEDEFERED = &quot;ie-deferred-loader&quot;,
-    	DOMCONTENTLOADED = &quot;DOMContentLoaded&quot;,
-    	elHash = {},
-    	propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
-
-    /// There is some jquery work around stuff here that isn't needed in Ext Core.
-    function addListener(el, ename, fn, wrap, scope){	    
-        var id = Ext.id(el),
-        	es = elHash[id] = elHash[id] || {};     	
-       
-        (es[ename] = es[ename] || []).push([fn, wrap, scope]);
-        E.on(el, ename, wrap);
-
-        // this is a workaround for jQuery and should somehow be removed from Ext Core in the future
-        // without breaking ExtJS.
-        if(ename == &quot;mousewheel&quot; &amp;&amp; el.addEventListener){ // workaround for jQuery
-        	var args = [&quot;DOMMouseScroll&quot;, wrap, false];
-        	el.addEventListener.apply(el, args);
-            E.on(window, 'unload', function(){
-	            el.removeEventListener.apply(el, args);                
-            });
-        }
-        if(ename == &quot;mousedown&quot; &amp;&amp; el == document){ // fix stopped mousedowns on the document
-            Ext.EventManager.stoppedMouseDownEvent.addListener(wrap);
-        }
-    };
-    
-    function fireDocReady(){
-        if(!docReadyState){            
-            Ext.isReady = docReadyState = true;
-            if(docReadyProcId){
-                clearInterval(docReadyProcId);
-            }
-            if(Ext.isGecko || Ext.isOpera) {
-                DOC.removeEventListener(DOMCONTENTLOADED, fireDocReady, false);
-            }
-            if(Ext.isIE){
-                var defer = DOC.getElementById(IEDEFERED);
-                if(defer){
-                    defer.onreadystatechange = null;
-                    defer.parentNode.removeChild(defer);
-                }
-            }
-            if(docReadyEvent){
-                docReadyEvent.fire();
-                docReadyEvent.clearListeners();
-            }
-        }
-    };
-
-    function initDocReady(){
-	    var COMPLETE = &quot;complete&quot;;
-	    	
-        docReadyEvent = new Ext.util.Event();
-        if (Ext.isGecko || Ext.isOpera) {
-            DOC.addEventListener(DOMCONTENTLOADED, fireDocReady, false);
-        } else if (Ext.isIE){
-            DOC.write(&quot;&lt;s&quot;+'cript id=' + IEDEFERED + ' defer=&quot;defer&quot; src=&quot;/'+'/:&quot;&gt;&lt;/s'+&quot;cript&gt;&quot;);            
-            DOC.getElementById(IEDEFERED).onreadystatechange = function(){
-                if(this.readyState == COMPLETE){
-                    fireDocReady();
-                }
-            };
-        } else if (Ext.isWebKit){
-            docReadyProcId = setInterval(function(){                
-                if(DOC.readyState == COMPLETE) {
-                    fireDocReady();
-                 }
-            }, 10);
-        }
-        // no matter what, make sure it fires on load
-        E.on(WINDOW, &quot;load&quot;, fireDocReady);
-    };
-
-    function createTargeted(h, o){
-        return function(){
-	        var args = Ext.toArray(arguments);
-            if(o.target == Ext.EventObject.setEvent(args[0]).target){
-                h.apply(this, args);
-            }
-        };
-    };    
-    
-    function createBuffered(h, o){
-        var task = new Ext.util.DelayedTask(h);
-        return function(e){
-            // create new event object impl so new events don't wipe out properties            
-            task.delay(o.buffer, h, null, [new Ext.EventObjectImpl(e)]);
-        };
-    };
-
-    function createSingle(h, el, ename, fn, scope){
-        return function(e){
-            Ext.EventManager.removeListener(el, ename, fn, scope);
-            h(e);
-        };
-    };
-
-    function createDelayed(h, o){
-        return function(e){
-            // create new event object impl so new events don't wipe out properties   
-            e = new Ext.EventObjectImpl(e);
-            setTimeout(function(){
-                h(e);
-            }, o.delay || 10);
-        };
-    };
-
-    function listen(element, ename, opt, fn, scope){
-        var o = !Ext.isObject(opt) ? {} : opt,
-        	el = Ext.getDom(element);
-        	
-        fn = fn || o.fn; 
-        scope = scope || o.scope;
-        
-        if(!el){
-            throw &quot;Error listening for \&quot;&quot; + ename + '\&quot;. Element &quot;' + element + '&quot; doesn\'t exist.';
-        }
-        function h(e){
-            // prevent errors while unload occurring
-            if(!Ext){// !window[xname]){  ==&gt; can't we do this? 
-                return;
-            }
-            e = Ext.EventObject.setEvent(e);
-            var t;
-            if (o.delegate) {
-                if(!(t = e.getTarget(o.delegate, el))){
-                    return;
-                }
-            } else {
-                t = e.target;
-            }            
-            if (o.stopEvent) {
-                e.stopEvent();
-            }
-            if (o.preventDefault) {
-               e.preventDefault();
-            }
-            if (o.stopPropagation) {
-                e.stopPropagation();
-            }
-            if (o.normalized) {
-                e = e.browserEvent;
-            }
-            
-            fn.call(scope || el, e, t, o);
-        };
-        if(o.target){
-            h = createTargeted(h, o);
-        }
-        if(o.delay){
-            h = createDelayed(h, o);
-        }
-        if(o.single){
-            h = createSingle(h, el, ename, fn, scope);
-        }
-        if(o.buffer){
-            h = createBuffered(h, o);
-        }
-
-        addListener(el, ename, fn, h, scope);
-        return h;
-    };
-
-    var pub = {
-	    
-		addListener : function(element, eventName, fn, scope, options){		     		     		     
-            if(Ext.isObject(eventName)){                
-	            var o = eventName, e, val;
-                for(e in o){
-	                val = o[e];
-                    if(!propRe.test(e)){                            		         
-	                    if(Ext.isFunction(val)){
-	                        // shared options
-	                        listen(element, e, o, val, o.scope);
-	                    }else{
-	                        // individual options
-	                        listen(element, e, val);
-	                    }
-                    }
-                }
-            } else {
-            	listen(element, eventName, options, fn, scope);
-        	}
-        },
-        
-        
-        removeListener : function(element, eventName, fn, scope){            
-            var el = Ext.getDom(element),
-                id = Ext.id(el),
-        	    wrap;      
-	        
-	        Ext.each((elHash[id] || {})[eventName], function (v,i,a) {
-			    if (Ext.isArray(v) &amp;&amp; v[0] == fn &amp;&amp; (!scope || v[2] == scope)) {		        			        
-			        E.un(el, eventName, wrap = v[1]);
-			        a.splice(i,1);
-			        return false;			        
-		        }
-	        });	
-
-            // jQuery workaround that should be removed from Ext Core
-	        if(eventName == &quot;mousewheel&quot; &amp;&amp; el.addEventListener &amp;&amp; wrap){
-	            el.removeEventListener(&quot;DOMMouseScroll&quot;, wrap, false);
-	        }
-            	        
-	        if(eventName == &quot;mousedown&quot; &amp;&amp; el == DOC &amp;&amp; wrap){ // fix stopped mousedowns on the document
-	            Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);
-	        }
-        },
-        
-        
-        removeAll : function(el){
-	        var id = Ext.id(el = Ext.getDom(el)), 
-				es = elHash[id], 				
-				ename;
-	       
-	        for(ename in es){
-	            if(es.hasOwnProperty(ename)){	                    
-	                Ext.each(es[ename], function(v) {
-	                    E.un(el, ename, v.wrap);                    
-	                });
-	            }            
-	        }
-	        elHash[id] = null;       
-        },
-
-        
-        onDocumentReady : function(fn, scope, options){
-            if(docReadyState){ // if it already fired
-                docReadyEvent.addListener(fn, scope, options);
-                docReadyEvent.fire();
-                docReadyEvent.clearListeners();               
-            } else {
-                if(!docReadyEvent) initDocReady();
-                options = options || {};
-	            options.delay = options.delay || 1;	            
-	            docReadyEvent.addListener(fn, scope, options);
-            }
-        },
-        
-        elHash : elHash   
-    };
-     
-    pub.on = pub.addListener;
-    
-    pub.un = pub.removeListener;
-
-    pub.stoppedMouseDownEvent = new Ext.util.Event();
-    return pub;
-}();
-
-Ext.onReady = Ext.EventManager.onDocumentReady;
-
-
-//Initialize doc classes
-(function(){
-    
-    var initExtCss = function(){
-        // find the body element
-        var bd = document.body || document.getElementsByTagName('body')[0];
-        if(!bd){ return false; }
-        var cls = [' ',
-                Ext.isIE ? &quot;ext-ie &quot; + (Ext.isIE6 ? 'ext-ie6' : (Ext.isIE7 ? 'ext-ie7' : 'ext-ie8'))
-                : Ext.isGecko ? &quot;ext-gecko &quot; + (Ext.isGecko2 ? 'ext-gecko2' : 'ext-gecko3')
-                : Ext.isOpera ? &quot;ext-opera&quot;
-                : Ext.isWebKit ? &quot;ext-webkit&quot;
-                : Ext.isSafari ? &quot;ext-safari&quot;
-                : Ext.isChrome ? &quot;ext-chrome&quot; : &quot;&quot;];
-
-        if(Ext.isMac){
-            cls.push(&quot;ext-mac&quot;);
-        }
-        if(Ext.isLinux){
-            cls.push(&quot;ext-linux&quot;);
-        }
-        if(Ext.isBorderBox){
-            cls.push('ext-border-box');
-        }
-        if(Ext.isStrict){ // add to the parent to allow for selectors like &quot;.ext-strict .ext-ie&quot;
-            var p = bd.parentNode;
-            if(p){
-                p.className += ' ext-strict';
-            }
-        }
-        bd.className += cls.join(' ');
-        return true;
-    }
-
-    if(!initExtCss()){
-        Ext.onReady(initExtCss);
-    }
-})();
-
-
-
-Ext.EventObject = function(){
-    var E = Ext.lib.Event,
-    	// safari keypress events for special keys return bad keycodes
-    	safariKeys = {
-	        3 : 13, // enter
-	        63234 : 37, // left
-	        63235 : 39, // right
-	        63232 : 38, // up
-	        63233 : 40, // down
-	        63276 : 33, // page up
-	        63277 : 34, // page down
-	        63272 : 46, // delete
-	        63273 : 36, // home
-	        63275 : 35  // end
-    	},
-    	// normalize button clicks
-    	btnMap = Ext.isIE ? {1:0,4:1,2:2} :
-                (Ext.isWebKit ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
-
-    Ext.EventObjectImpl = function(e){
-        if(e){
-            this.setEvent(e.browserEvent || e);
-        }
-    };
-
-    Ext.EventObjectImpl.prototype = {
-           
-        setEvent : function(e){
-	        var me = this;
-            if(e == me || (e &amp;&amp; e.browserEvent)){ // already wrapped
-                return e;
-            }
-            me.browserEvent = e;
-            if(e){
-                // normalize buttons
-                me.button = e.button ? btnMap[e.button] : (e.which ? e.which - 1 : -1);
-                if(e.type == 'click' &amp;&amp; me.button == -1){
-                    me.button = 0;
-                }
-                me.type = e.type;
-                me.shiftKey = e.shiftKey;
-                // mac metaKey behaves like ctrlKey
-                me.ctrlKey = e.ctrlKey || e.metaKey;
-                me.altKey = e.altKey;
-                // in getKey these will be normalized for the mac
-                me.keyCode = e.keyCode;
-                me.charCode = e.charCode;
-                // cache the target for the delayed and or buffered events
-                me.target = E.getTarget(e);
-                // same for XY
-                me.xy = E.getXY(e);
-            }else{
-                me.button = -1;
-                me.shiftKey = false;
-                me.ctrlKey = false;
-                me.altKey = false;
-                me.keyCode = 0;
-                me.charCode = 0;
-                me.target = null;
-                me.xy = [0, 0];
-            }
-            return me;
-        },
-
-        
-        stopEvent : function(){
-	        var me = this;
-            if(me.browserEvent){
-                if(me.browserEvent.type == 'mousedown'){
-                    Ext.EventManager.stoppedMouseDownEvent.fire(me);
-                }
-                E.stopEvent(me.browserEvent);
-            }
-        },
-
-        
-        preventDefault : function(){
-            if(this.browserEvent){
-                E.preventDefault(this.browserEvent);
-            }
-        },        
-
-        
-        stopPropagation : function(){
-	        var me = this;
-            if(me.browserEvent){
-                if(me.browserEvent.type == 'mousedown'){
-                    Ext.EventManager.stoppedMouseDownEvent.fire(me);
-                }
-                E.stopPropagation(me.browserEvent);
-            }
-        },
-
-        
-        getCharCode : function(){
-            return this.charCode || this.keyCode;
-        },
-
-        
-        getKey : function(){
-            return this.normalizeKey(this.keyCode || this.charCode)
-        },
-		
-		// private
-		normalizeKey: function(k){
-			return Ext.isSafari ? (safariKeys[k] || k) : k; 
-		},
-
-        
-        getPageX : function(){
-            return this.xy[0];
-        },
-
-        
-        getPageY : function(){
-            return this.xy[1];
-        },
-
-//         
-//         getTime : function(){
-//             if(this.browserEvent){
-//                 return E.getTime(this.browserEvent);
-//             }
-//             return null;
-//         },
-
-        
-        getXY : function(){
-            return this.xy;
-        },
-
-        
-        getTarget : function(selector, maxDepth, returnEl){
-            return selector ? Ext.fly(this.target).findParent(selector, maxDepth, returnEl) : (returnEl ? Ext.get(this.target) : this.target);
-        },
-
-        
-        getRelatedTarget : function(){
-            return this.browserEvent ? E.getRelatedTarget(this.browserEvent) : null;
-        },
-
-        
-        getWheelDelta : function(){
-            var e = this.browserEvent;
-            var delta = 0;
-            if(e.wheelDelta){ 
-                delta = e.wheelDelta/120;
-            }else if(e.detail){ 
-                delta = -e.detail/3;
-            }
-            return delta;
-        },
-		
-		
-		within : function(el, related, allowEl){
-			var t = this[related ? &quot;getRelatedTarget&quot; : &quot;getTarget&quot;]();
-			return t &amp;&amp; ((allowEl ? (t == Ext.getDom(el)) : false) || Ext.fly(el).contains(t));
-		}
-	 };
-
-    return new Ext.EventObjectImpl();
-}();
+};
+
+Ext.EventManager = function(){
+    var docReadyEvent, 
+    	docReadyProcId, 
+    	docReadyState = false,    	
+    	E = Ext.lib.Event,
+    	D = Ext.lib.Dom,
+    	DOC = document,
+    	WINDOW = window,
+    	IEDEFERED = &quot;ie-deferred-loader&quot;,
+    	DOMCONTENTLOADED = &quot;DOMContentLoaded&quot;,
+    	elHash = {},
+    	propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
+
+    /// There is some jquery work around stuff here that isn't needed in Ext Core.
+    function addListener(el, ename, fn, wrap, scope){	    
+        var id = Ext.id(el),
+        	es = elHash[id] = elHash[id] || {};     	
+       
+        (es[ename] = es[ename] || []).push([fn, wrap, scope]);
+        E.on(el, ename, wrap);
+
+        // this is a workaround for jQuery and should somehow be removed from Ext Core in the future
+        // without breaking ExtJS.
+        if(ename == &quot;mousewheel&quot; &amp;&amp; el.addEventListener){ // workaround for jQuery
+        	var args = [&quot;DOMMouseScroll&quot;, wrap, false];
+        	el.addEventListener.apply(el, args);
+            E.on(window, 'unload', function(){
+	            el.removeEventListener.apply(el, args);                
+            });
+        }
+        if(ename == &quot;mousedown&quot; &amp;&amp; el == document){ // fix stopped mousedowns on the document
+            Ext.EventManager.stoppedMouseDownEvent.addListener(wrap);
+        }
+    };
+    
+    function fireDocReady(){
+        if(!docReadyState){            
+            Ext.isReady = docReadyState = true;
+            if(docReadyProcId){
+                clearInterval(docReadyProcId);
+            }
+            if(Ext.isGecko || Ext.isOpera) {
+                DOC.removeEventListener(DOMCONTENTLOADED, fireDocReady, false);
+            }
+            if(Ext.isIE){
+                var defer = DOC.getElementById(IEDEFERED);
+                if(defer){
+                    defer.onreadystatechange = null;
+                    defer.parentNode.removeChild(defer);
+                }
+            }
+            if(docReadyEvent){
+                docReadyEvent.fire();
+                docReadyEvent.clearListeners();
+            }
+        }
+    };
+
+    function initDocReady(){
+	    var COMPLETE = &quot;complete&quot;;
+	    	
+        docReadyEvent = new Ext.util.Event();
+        if (Ext.isGecko || Ext.isOpera) {
+            DOC.addEventListener(DOMCONTENTLOADED, fireDocReady, false);
+        } else if (Ext.isIE){
+            DOC.write(&quot;&lt;s&quot;+'cript id=' + IEDEFERED + ' defer=&quot;defer&quot; src=&quot;/'+'/:&quot;&gt;&lt;/s'+&quot;cript&gt;&quot;);            
+            DOC.getElementById(IEDEFERED).onreadystatechange = function(){
+                if(this.readyState == COMPLETE){
+                    fireDocReady();
+                }
+            };
+        } else if (Ext.isWebKit){
+            docReadyProcId = setInterval(function(){                
+                if(DOC.readyState == COMPLETE) {
+                    fireDocReady();
+                 }
+            }, 10);
+        }
+        // no matter what, make sure it fires on load
+        E.on(WINDOW, &quot;load&quot;, fireDocReady);
+    };
+
+    function createTargeted(h, o){
+        return function(){
+	        var args = Ext.toArray(arguments);
+            if(o.target == Ext.EventObject.setEvent(args[0]).target){
+                h.apply(this, args);
+            }
+        };
+    };    
+    
+    function createBuffered(h, o){
+        var task = new Ext.util.DelayedTask(h);
+        return function(e){
+            // create new event object impl so new events don't wipe out properties            
+            task.delay(o.buffer, h, null, [new Ext.EventObjectImpl(e)]);
+        };
+    };
+
+    function createSingle(h, el, ename, fn, scope){
+        return function(e){
+            Ext.EventManager.removeListener(el, ename, fn, scope);
+            h(e);
+        };
+    };
+
+    function createDelayed(h, o){
+        return function(e){
+            // create new event object impl so new events don't wipe out properties   
+            e = new Ext.EventObjectImpl(e);
+            setTimeout(function(){
+                h(e);
+            }, o.delay || 10);
+        };
+    };
+
+    function listen(element, ename, opt, fn, scope){
+        var o = !Ext.isObject(opt) ? {} : opt,
+        	el = Ext.getDom(element);
+        	
+        fn = fn || o.fn; 
+        scope = scope || o.scope;
+        
+        if(!el){
+            throw &quot;Error listening for \&quot;&quot; + ename + '\&quot;. Element &quot;' + element + '&quot; doesn\'t exist.';
+        }
+        function h(e){
+            // prevent errors while unload occurring
+            if(!Ext){// !window[xname]){  ==&gt; can't we do this? 
+                return;
+            }
+            e = Ext.EventObject.setEvent(e);
+            var t;
+            if (o.delegate) {
+                if(!(t = e.getTarget(o.delegate, el))){
+                    return;
+                }
+            } else {
+                t = e.target;
+            }            
+            if (o.stopEvent) {
+                e.stopEvent();
+            }
+            if (o.preventDefault) {
+               e.preventDefault();
+            }
+            if (o.stopPropagation) {
+                e.stopPropagation();
+            }
+            if (o.normalized) {
+                e = e.browserEvent;
+            }
+            
+            fn.call(scope || el, e, t, o);
+        };
+        if(o.target){
+            h = createTargeted(h, o);
+        }
+        if(o.delay){
+            h = createDelayed(h, o);
+        }
+        if(o.single){
+            h = createSingle(h, el, ename, fn, scope);
+        }
+        if(o.buffer){
+            h = createBuffered(h, o);
+        }
+
+        addListener(el, ename, fn, h, scope);
+        return h;
+    };
+
+    var pub = {
+	    
+		addListener : function(element, eventName, fn, scope, options){		     		     		     
+            if(Ext.isObject(eventName)){                
+	            var o = eventName, e, val;
+                for(e in o){
+	                val = o[e];
+                    if(!propRe.test(e)){                            		         
+	                    if(Ext.isFunction(val)){
+	                        // shared options
+	                        listen(element, e, o, val, o.scope);
+	                    }else{
+	                        // individual options
+	                        listen(element, e, val);
+	                    }
+                    }
+                }
+            } else {
+            	listen(element, eventName, options, fn, scope);
+        	}
+        },
+        
+        
+        removeListener : function(element, eventName, fn, scope){            
+            var el = Ext.getDom(element),
+                id = Ext.id(el),
+        	    wrap;      
+	        
+	        Ext.each((elHash[id] || {})[eventName], function (v,i,a) {
+			    if (Ext.isArray(v) &amp;&amp; v[0] == fn &amp;&amp; (!scope || v[2] == scope)) {		        			        
+			        E.un(el, eventName, wrap = v[1]);
+			        a.splice(i,1);
+			        return false;			        
+		        }
+	        });	
+
+            // jQuery workaround that should be removed from Ext Core
+	        if(eventName == &quot;mousewheel&quot; &amp;&amp; el.addEventListener &amp;&amp; wrap){
+	            el.removeEventListener(&quot;DOMMouseScroll&quot;, wrap, false);
+	        }
+            	        
+	        if(eventName == &quot;mousedown&quot; &amp;&amp; el == DOC &amp;&amp; wrap){ // fix stopped mousedowns on the document
+	            Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);
+	        }
+        },
+        
+        
+        removeAll : function(el){
+	        var id = Ext.id(el = Ext.getDom(el)), 
+				es = elHash[id], 				
+				ename;
+	       
+	        for(ename in es){
+	            if(es.hasOwnProperty(ename)){	                    
+	                Ext.each(es[ename], function(v) {
+	                    E.un(el, ename, v.wrap);                    
+	                });
+	            }            
+	        }
+	        elHash[id] = null;       
+        },
+
+        
+        onDocumentReady : function(fn, scope, options){
+            if(docReadyState){ // if it already fired
+                docReadyEvent.addListener(fn, scope, options);
+                docReadyEvent.fire();
+                docReadyEvent.clearListeners();               
+            } else {
+                if(!docReadyEvent) initDocReady();
+                options = options || {};
+	            options.delay = options.delay || 1;	            
+	            docReadyEvent.addListener(fn, scope, options);
+            }
+        },
+        
+        elHash : elHash   
+    };
+     
+    pub.on = pub.addListener;
+    
+    pub.un = pub.removeListener;
+
+    pub.stoppedMouseDownEvent = new Ext.util.Event();
+    return pub;
+}();
+
+Ext.onReady = Ext.EventManager.onDocumentReady;
+
+
+//Initialize doc classes
+(function(){
+    
+    var initExtCss = function(){
+        // find the body element
+        var bd = document.body || document.getElementsByTagName('body')[0];
+        if(!bd){ return false; }
+        var cls = [' ',
+                Ext.isIE ? &quot;ext-ie &quot; + (Ext.isIE6 ? 'ext-ie6' : (Ext.isIE7 ? 'ext-ie7' : 'ext-ie8'))
+                : Ext.isGecko ? &quot;ext-gecko &quot; + (Ext.isGecko2 ? 'ext-gecko2' : 'ext-gecko3')
+                : Ext.isOpera ? &quot;ext-opera&quot;
+                : Ext.isWebKit ? &quot;ext-webkit&quot; : &quot;&quot;];
+
+        if(Ext.isSafari){
+            cls.push(&quot;ext-safari &quot; + (Ext.isSafari2 ? 'ext-safari2' : (Ext.isSafari3 ? 'ext-safari3' : 'ext-safari4')));
+        }else if(Ext.isChrome){
+            cls.push(&quot;ext-chrome&quot;);
+        }
+
+        if(Ext.isMac){
+            cls.push(&quot;ext-mac&quot;);
+        }
+        if(Ext.isLinux){
+            cls.push(&quot;ext-linux&quot;);
+        }
+        if(Ext.isBorderBox){
+            cls.push('ext-border-box');
+        }
+        if(Ext.isStrict){ // add to the parent to allow for selectors like &quot;.ext-strict .ext-ie&quot;
+            var p = bd.parentNode;
+            if(p){
+                p.className += ' ext-strict';
+            }
+        }
+        bd.className += cls.join(' ');
+        return true;
+    }
+
+    if(!initExtCss()){
+        Ext.onReady(initExtCss);
+    }
+})();
+
+
+
+Ext.EventObject = function(){
+    var E = Ext.lib.Event,
+    	// safari keypress events for special keys return bad keycodes
+    	safariKeys = {
+	        3 : 13, // enter
+	        63234 : 37, // left
+	        63235 : 39, // right
+	        63232 : 38, // up
+	        63233 : 40, // down
+	        63276 : 33, // page up
+	        63277 : 34, // page down
+	        63272 : 46, // delete
+	        63273 : 36, // home
+	        63275 : 35  // end
+    	},
+    	// normalize button clicks
+    	btnMap = Ext.isIE ? {1:0,4:1,2:2} :
+                (Ext.isWebKit ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
+
+    Ext.EventObjectImpl = function(e){
+        if(e){
+            this.setEvent(e.browserEvent || e);
+        }
+    };
+
+    Ext.EventObjectImpl.prototype = {
+           
+        setEvent : function(e){
+	        var me = this;
+            if(e == me || (e &amp;&amp; e.browserEvent)){ // already wrapped
+                return e;
+            }
+            me.browserEvent = e;
+            if(e){
+                // normalize buttons
+                me.button = e.button ? btnMap[e.button] : (e.which ? e.which - 1 : -1);
+                if(e.type == 'click' &amp;&amp; me.button == -1){
+                    me.button = 0;
+                }
+                me.type = e.type;
+                me.shiftKey = e.shiftKey;
+                // mac metaKey behaves like ctrlKey
+                me.ctrlKey = e.ctrlKey || e.metaKey;
+                me.altKey = e.altKey;
+                // in getKey these will be normalized for the mac
+                me.keyCode = e.keyCode;
+                me.charCode = e.charCode;
+                // cache the target for the delayed and or buffered events
+                me.target = E.getTarget(e);
+                // same for XY
+                me.xy = E.getXY(e);
+            }else{
+                me.button = -1;
+                me.shiftKey = false;
+                me.ctrlKey = false;
+                me.altKey = false;
+                me.keyCode = 0;
+                me.charCode = 0;
+                me.target = null;
+                me.xy = [0, 0];
+            }
+            return me;
+        },
+
+        
+        stopEvent : function(){
+	        var me = this;
+            if(me.browserEvent){
+                if(me.browserEvent.type == 'mousedown'){
+                    Ext.EventManager.stoppedMouseDownEvent.fire(me);
+                }
+                E.stopEvent(me.browserEvent);
+            }
+        },
+
+        
+        preventDefault : function(){
+            if(this.browserEvent){
+                E.preventDefault(this.browserEvent);
+            }
+        },        
+
+        
+        stopPropagation : function(){
+	        var me = this;
+            if(me.browserEvent){
+                if(me.browserEvent.type == 'mousedown'){
+                    Ext.EventManager.stoppedMouseDownEvent.fire(me);
+                }
+                E.stopPropagation(me.browserEvent);
+            }
+        },
+
+        
+        getCharCode : function(){
+            return this.charCode || this.keyCode;
+        },
+
+        
+        getKey : function(){
+            return this.normalizeKey(this.keyCode || this.charCode)
+        },
+		
+		// private
+		normalizeKey: function(k){
+			return Ext.isSafari ? (safariKeys[k] || k) : k; 
+		},
+
+        
+        getPageX : function(){
+            return this.xy[0];
+        },
+
+        
+        getPageY : function(){
+            return this.xy[1];
+        },
+
+//         
+//         getTime : function(){
+//             if(this.browserEvent){
+//                 return E.getTime(this.browserEvent);
+//             }
+//             return null;
+//         },
+
+        
+        getXY : function(){
+            return this.xy;
+        },
+
+        
+        getTarget : function(selector, maxDepth, returnEl){
+            return selector ? Ext.fly(this.target).findParent(selector, maxDepth, returnEl) : (returnEl ? Ext.get(this.target) : this.target);
+        },
+
+        
+        getRelatedTarget : function(){
+            return this.browserEvent ? E.getRelatedTarget(this.browserEvent) : null;
+        },
+
+        
+        getWheelDelta : function(){
+            var e = this.browserEvent;
+            var delta = 0;
+            if(e.wheelDelta){ 
+                delta = e.wheelDelta/120;
+            }else if(e.detail){ 
+                delta = -e.detail/3;
+            }
+            return delta;
+        },
+		
+		
+		within : function(el, related, allowEl){
+            if(el){
+			    var t = this[related ? &quot;getRelatedTarget&quot; : &quot;getTarget&quot;]();
+			    return t &amp;&amp; ((allowEl ? (t == Ext.getDom(el)) : false) || Ext.fly(el).contains(t));
+            }
+            return false;
+		}
+	 };
+
+    return new Ext.EventObjectImpl();
+}();
 
 Ext.apply(Ext.EventManager, function(){
 	var resizeEvent, 
@@ -2375,24 +2385,20 @@ Ext.apply(Ext.EventObjectImpl.prototype, {
     
     isNavKeyPress : function(){
         var me = this,
-        	k = this.normalizeKey(me.keyCode);
-        return (k &gt;= 33 &amp;&amp; k &lt;= 40) || k == me.RETURN || k == me.TAB || k == me.ESC;
+        	k = this.normalizeKey(me.keyCode);		
+        return (k &gt;= 33 &amp;&amp; k &lt;= 40) ||  // Page Up/Down, End, Home, Left, Up, Right, Down
+		k == me.RETURN ||
+		k == me.TAB ||
+		k == me.ESC;
     },
 
     isSpecialKey : function(){
-        var k = this.keyCode;
-        return (this.type == 'keypress' &amp;&amp; 
-        		this.ctrlKey) ||
-        		k == 9 || 
-        		k == 13  || 
-        		k == 40 || 
-        		k == 27 ||
-	            (k == 16) || 
-	            (k == 17) ||
-	            (k &gt;= 18 &amp;&amp; k &lt;= 20) ||
-	            (k &gt;= 33 &amp;&amp; k &lt;= 35) ||
-	            (k &gt;= 36 &amp;&amp; k &lt;= 39) ||
-	            (k &gt;= 44 &amp;&amp; k &lt;= 45);
+        var k = this.normalizeKey(this.keyCode);
+        return (this.type == 'keypress' &amp;&amp; this.ctrlKey) ||
+		this.isNavKeyPress() ||
+        (k == this.BACKSPACE) || // Backspace
+		(k &gt;= 16 &amp;&amp; k &lt;= 20) || // Shift, Ctrl, Alt, Pause, Caps Lock
+		(k &gt;= 44 &amp;&amp; k &lt;= 45);   // Print Screen, Insert
     },
 	
 	getPoint : function(){
@@ -2403,387 +2409,396 @@ Ext.apply(Ext.EventObjectImpl.prototype, {
     hasModifier : function(){
         return ((this.ctrlKey || this.altKey) || this.shiftKey);
     }
-});
-
-(function(){
-var DOC = document;
-
-Ext.Element = function(element, forceNew){
-    var dom = typeof element == &quot;string&quot; ?
-              DOC.getElementById(element) : element,
-    	id;
-
-    if(!dom) return null;
-
-    id = dom.id;
-
-    if(!forceNew &amp;&amp; id &amp;&amp; Ext.Element.cache[id]){ // element object already exists
-        return Ext.Element.cache[id];
-    }
-
-    
-    this.dom = dom;
-
-    
-    this.id = id || Ext.id(dom);
-};
-
-var	D = Ext.lib.Dom,
-	DH = Ext.DomHelper,
-	E = Ext.lib.Event,
-	A = Ext.lib.Anim,
-	El = Ext.Element;
-
-El.prototype = {
-	
-    set : function(o, useSet){
-        var el = this.dom,
-        	attr,
-        	val;       	
-       
-        for(attr in o){
-	        val = o[attr];
-            if (attr != &quot;style&quot; &amp;&amp; !Ext.isFunction(val)) {
-	            if (attr == &quot;cls&quot; ) {
-	                el.className = val;
-	            } else if (o.hasOwnProperty(attr)) {
-	                if (useSet || !!el.setAttribute) el.setAttribute(attr, val);
-	                else el[attr] = val;
-	            }
-            }
-        }
-        if(o.style){
-            Ext.DomHelper.applyStyles(el, o.style);
-        }
-        return this;
-    },
-	
-//  Mouse events
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-//  Keyboard events
-    
-    
-    
-
-
-//  HTML frame/object events
-    
-    
-    
-    
-    
-    
-
-//  Form events
-    
-    
-    
-    
-    
-    
-
-//  User Interface events
-    
-    
-    
-
-//  DOM Mutation events
-    
-    
-    
-    
-    
-    
-    
-
-    
-    defaultUnit : &quot;px&quot;,
-
-    
-    is : function(simpleSelector){
-        return Ext.DomQuery.is(this.dom, simpleSelector);
-    },
-
-    
-    focus : function(defer) {
-	    var me = this;
-        try{
-            if(!isNaN(defer)){
-                me.focus.defer(defer, me);
-            }else{
-                me.dom.focus();
-            }
-        }catch(e){}
-        return me;
-    },
-
-    
-    blur : function() {
-        try{
-            this.dom.blur();
-        }catch(e){}
-        return this;
-    },
-
-    
-    getValue : function(asNumber){
-	    var val = this.dom.value;
-        return asNumber ? parseInt(val, 10) : val;
-    },
-
-    
-    addListener : function(eventName, fn, scope, options){
-        Ext.EventManager.on(this.dom,  eventName, fn, scope || this, options);
-        return this;
-    },
-
-    
-    removeListener : function(eventName, fn, scope){
-        Ext.EventManager.removeListener(this.dom,  eventName, fn, scope || this);
-        return this;
-    },
-
-    
-    removeAllListeners : function(){
-        Ext.EventManager.removeAll(this.dom);
-        return this;
-    },
-
-    
-    addUnits : function(size){
-        if(size === &quot;&quot; || size == &quot;auto&quot; || size === undefined){
-	        size = size || '';
-	    } else if(!isNaN(size) || !unitPattern.test(size)){
-	        size = size + (this.defaultUnit || 'px');
-	    }
-	    return size;
-    },
-
-    
-    load : function(url, params, cb){
-        Ext.Ajax.request(Ext.apply({
-            params: params,
-            url: url.url || url,
-            callback: cb,
-            el: this,
-            indicatorText: url.indicatorText || ''
-        }, Ext.isObject(url) ? url : {}));
-        return this;
-    },
-
-    
-    isBorderBox : function(){
-        return noBoxAdjust[(this.dom.tagName || &quot;&quot;).toLowerCase()] || Ext.isBorderBox;
-    },
-
-    
-    remove : function(){
-        Ext.removeNode(this.dom);
-        delete El.cache[this.dom.id];
-    },
-
-    
-    hover : function(overFn, outFn, scope, options){
-        var me = this;
-        me.on('mouseenter', overFn, scope || me.dom, options);
-        me.on('mouseleave', outFn, scope || me.dom, options);
-        return me;
-    },
-
-	
-    contains : function(el){
-        return !el ? false : Ext.lib.Dom.isAncestor(this.dom, el.dom ? el.dom : el);
-    },
-
-    
-    getAttributeNS : Ext.isIE ? function(ns, name){
-        var d = this.dom,
-        	type = typeof d[ns + &quot;:&quot; + name];
-
-        if(!Ext.isEmpty(type) &amp;&amp; type != 'unknown'){
-            return d[ns + &quot;:&quot; + name];
-        }
-        return d[name];
-    } : function(ns, name){
-        var d = this.dom;
-        return d.getAttributeNS(ns, name) || d.getAttribute(ns + &quot;:&quot; + name) || d.getAttribute(name) || d[name];
-    },
-    
-    update : function(html) {
-	    this.dom.innerHTML = html;
-    }
-};
-
-var ep = El.prototype;
-
-El.addMethods = function(o){
-   Ext.apply(ep, o);
-};
-
-
-ep.on = ep.addListener;
-
-
-ep.un = ep.removeListener;
-
-
-ep.autoBoxAdjust = true;
-
-// private
-var unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i,
-	docEl;
-
-
-El.cache = {};
-
-
-El.get = function(el){
-    var ex,
-     	elm,
-     	id;
-    if(!el){ return null; }
-    if (typeof el == &quot;string&quot;) { // element id
-        if (!(elm = DOC.getElementById(el))) {
-            return null;
-        }
-        if (ex = El.cache[el]) {
-            ex.dom = elm;
-        } else {
-            ex = El.cache[el] = new El(elm);
-        }
-        return ex;
-    } else if (el.tagName) { // dom element
-        if(!(id = el.id)){
-            id = Ext.id(el);
-        }
-        if(ex = El.cache[id]){
-            ex.dom = el;
-        }else{
-            ex = El.cache[id] = new El(el);
-        }
-        return ex;
-    } else if (el instanceof El) {
-        if(el != docEl){
-            el.dom = DOC.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
-                                                          // catch case where it hasn't been appended
-            El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
-        }
-        return el;
-    } else if(el.isComposite) {
-        return el;
-    } else if(Ext.isArray(el)) {
-        return El.select(el);
-    } else if(el == DOC) {
-        // create a bogus element object representing the document object
-        if(!docEl){
-            var f = function(){};
-            f.prototype = El.prototype;
-            docEl = new f();
-            docEl.dom = DOC;
-        }
-        return docEl;
-    }
-    return null;
-};
-
-// private
-// Garbage collection - uncache elements/purge listeners on orphaned elements
-// so we don't hold a reference and cause the browser to retain them
-function garbageCollect(){
-    if(!Ext.enableGarbageCollector){
-        clearInterval(El.collectorThread);
-    } else {
-	    var eid,
-	    	el,
-	    	d;
-
-	    for(eid in El.cache){
-	        el = El.cache[eid];
-	        d = el.dom;
-	        // -------------------------------------------------------
-	        // Determining what is garbage:
-	        // -------------------------------------------------------
-	        // !d
-	        // dom node is null, definitely garbage
-	        // -------------------------------------------------------
-	        // !d.parentNode
-	        // no parentNode == direct orphan, definitely garbage
-	        // -------------------------------------------------------
-	        // !d.offsetParent &amp;&amp; !document.getElementById(eid)
-	        // display none elements have no offsetParent so we will
-	        // also try to look it up by it's id. However, check
-	        // offsetParent first so we don't do unneeded lookups.
-	        // This enables collection of elements that are not orphans
-	        // directly, but somewhere up the line they have an orphan
-	        // parent.
-	        // -------------------------------------------------------
-	        if(!d || !d.parentNode || (!d.offsetParent &amp;&amp; !DOC.getElementById(eid))){
-	            delete El.cache[eid];
-	            if(d &amp;&amp; Ext.enableListenerCollection){
-	                Ext.EventManager.removeAll(d);
-	            }
-	        }
-	    }
-    }
-}
-El.collectorThreadId = setInterval(garbageCollect, 30000);
-
-var flyFn = function(){};
-flyFn.prototype = El.prototype;
-
-// dom is optional
-El.Flyweight = function(dom){
-    this.dom = dom;
-};
-
-El.Flyweight.prototype = new flyFn();
-El.Flyweight.prototype.isFlyweight = true;
-El._flyweights = {};
-
-
-El.fly = function(el, named){
-    var ret = null;
-	named = named || '_global';
-
-    if (el = Ext.getDom(el)) {
-    	(El._flyweights[named] = El._flyweights[named] || new El.Flyweight()).dom = el;
-    	ret = El._flyweights[named];
-	}
-	return ret;
-};
-
-
-Ext.get = El.get;
-
-
-Ext.fly = El.fly;
-
-// speedy lookup for elements never to box adjust
-var noBoxAdjust = Ext.isStrict ? {
-    select:1
-} : {
-    input:1, select:1, textarea:1
-};
-if(Ext.isIE || Ext.isGecko){
-    noBoxAdjust['button'] = 1;
-}
-
-
-Ext.EventManager.on(window, 'unload', function(){
-    delete El.cache;
-    delete El._flyweights;
-});
-})();
-
+});
+
+(function(){
+var DOC = document;
+
+Ext.Element = function(element, forceNew){
+    var dom = typeof element == &quot;string&quot; ?
+              DOC.getElementById(element) : element,
+    	id;
+
+    if(!dom) return null;
+
+    id = dom.id;
+
+    if(!forceNew &amp;&amp; id &amp;&amp; Ext.Element.cache[id]){ // element object already exists
+        return Ext.Element.cache[id];
+    }
+
+    
+    this.dom = dom;
+
+    
+    this.id = id || Ext.id(dom);
+};
+
+var	D = Ext.lib.Dom,
+	DH = Ext.DomHelper,
+	E = Ext.lib.Event,
+	A = Ext.lib.Anim,
+	El = Ext.Element;
+
+El.prototype = {
+	
+    set : function(o, useSet){
+        var el = this.dom,
+        	attr,
+        	val;       	
+       
+        for(attr in o){
+	        val = o[attr];
+            if (attr != &quot;style&quot; &amp;&amp; !Ext.isFunction(val)) {
+	            if (attr == &quot;cls&quot; ) {
+	                el.className = val;
+	            } else if (o.hasOwnProperty(attr)) {
+	                if (useSet || !!el.setAttribute) el.setAttribute(attr, val);
+	                else el[attr] = val;
+	            }
+            }
+        }
+        if(o.style){
+            Ext.DomHelper.applyStyles(el, o.style);
+        }
+        return this;
+    },
+	
+//  Mouse events
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+//  Keyboard events
+    
+    
+    
+
+
+//  HTML frame/object events
+    
+    
+    
+    
+    
+    
+
+//  Form events
+    
+    
+    
+    
+    
+    
+
+//  User Interface events
+    
+    
+    
+
+//  DOM Mutation events
+    
+    
+    
+    
+    
+    
+    
+
+    
+    defaultUnit : &quot;px&quot;,
+
+    
+    is : function(simpleSelector){
+        return Ext.DomQuery.is(this.dom, simpleSelector);
+    },
+
+    
+    focus : function(defer,  dom) {
+        var me = this,
+            dom = dom || me.dom;
+        try{
+            if(Number(defer)){
+                me.focus.defer(defer, null, [null, dom]);
+            }else{
+                dom.focus();
+            }
+        }catch(e){}
+        return me;
+    },
+
+    
+    blur : function() {
+        try{
+            this.dom.blur();
+        }catch(e){}
+        return this;
+    },
+
+    
+    getValue : function(asNumber){
+	    var val = this.dom.value;
+        return asNumber ? parseInt(val, 10) : val;
+    },
+
+    
+    addListener : function(eventName, fn, scope, options){
+        Ext.EventManager.on(this.dom,  eventName, fn, scope || this, options);
+        return this;
+    },
+
+    
+    removeListener : function(eventName, fn, scope){
+        Ext.EventManager.removeListener(this.dom,  eventName, fn, scope || this);
+        return this;
+    },
+
+    
+    removeAllListeners : function(){
+        Ext.EventManager.removeAll(this.dom);
+        return this;
+    },
+
+    
+    addUnits : function(size){
+        if(size === &quot;&quot; || size == &quot;auto&quot; || size === undefined){
+	        size = size || '';
+	    } else if(!isNaN(size) || !unitPattern.test(size)){
+	        size = size + (this.defaultUnit || 'px');
+	    }
+	    return size;
+    },
+
+    
+    load : function(url, params, cb){
+        Ext.Ajax.request(Ext.apply({
+            params: params,
+            url: url.url || url,
+            callback: cb,
+            el: this.dom,
+            indicatorText: url.indicatorText || ''
+        }, Ext.isObject(url) ? url : {}));
+        return this;
+    },
+
+    
+    isBorderBox : function(){
+        return noBoxAdjust[(this.dom.tagName || &quot;&quot;).toLowerCase()] || Ext.isBorderBox;
+    },
+
+    
+    remove : function(){
+        var me = this;
+        
+        me.removeAllListeners();
+        delete El.cache[me.dom.id];
+        Ext.removeNode(me.dom);
+    },
+
+    
+    hover : function(overFn, outFn, scope, options){
+        var me = this;
+        me.on('mouseenter', overFn, scope || me.dom, options);
+        me.on('mouseleave', outFn, scope || me.dom, options);
+        return me;
+    },
+
+	
+    contains : function(el){
+        return !el ? false : Ext.lib.Dom.isAncestor(this.dom, el.dom ? el.dom : el);
+    },
+
+    
+    getAttributeNS : function(ns, name){
+        return this.getAttribute(name, ns); 
+    },
+    
+    
+    getAttribute : Ext.isIE ? function(name, ns){
+        var d = this.dom,
+            type = typeof d[ns + &quot;:&quot; + name];
+
+        if(!Ext.isEmpty(type) &amp;&amp; type != 'unknown'){
+            return d[ns + &quot;:&quot; + name];
+        }
+        return d[name];
+    } : function(name, ns){
+        var d = this.dom;
+        return d.getAttributeNS(ns, name) || d.getAttribute(ns + &quot;:&quot; + name) || d.getAttribute(name) || d[name];
+    },
+    
+    update : function(html) {
+	    this.dom.innerHTML = html;
+    }
+};
+
+var ep = El.prototype;
+
+El.addMethods = function(o){
+   Ext.apply(ep, o);
+};
+
+
+ep.on = ep.addListener;
+
+
+ep.un = ep.removeListener;
+
+
+ep.autoBoxAdjust = true;
+
+// private
+var unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i,
+	docEl;
+
+
+El.cache = {};
+
+
+El.get = function(el){
+    var ex,
+     	elm,
+     	id;
+    if(!el){ return null; }
+    if (typeof el == &quot;string&quot;) { // element id
+        if (!(elm = DOC.getElementById(el))) {
+            return null;
+        }
+        if (ex = El.cache[el]) {
+            ex.dom = elm;
+        } else {
+            ex = El.cache[el] = new El(elm);
+        }
+        return ex;
+    } else if (el.tagName) { // dom element
+        if(!(id = el.id)){
+            id = Ext.id(el);
+        }
+        if(ex = El.cache[id]){
+            ex.dom = el;
+        }else{
+            ex = El.cache[id] = new El(el);
+        }
+        return ex;
+    } else if (el instanceof El) {
+        if(el != docEl){
+            el.dom = DOC.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
+                                                          // catch case where it hasn't been appended
+            El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
+        }
+        return el;
+    } else if(el.isComposite) {
+        return el;
+    } else if(Ext.isArray(el)) {
+        return El.select(el);
+    } else if(el == DOC) {
+        // create a bogus element object representing the document object
+        if(!docEl){
+            var f = function(){};
+            f.prototype = El.prototype;
+            docEl = new f();
+            docEl.dom = DOC;
+        }
+        return docEl;
+    }
+    return null;
+};
+
+// private
+// Garbage collection - uncache elements/purge listeners on orphaned elements
+// so we don't hold a reference and cause the browser to retain them
+function garbageCollect(){
+    if(!Ext.enableGarbageCollector){
+        clearInterval(El.collectorThread);
+    } else {
+	    var eid,
+	    	el,
+	    	d;
+
+	    for(eid in El.cache){
+	        el = El.cache[eid];
+	        d = el.dom;
+	        // -------------------------------------------------------
+	        // Determining what is garbage:
+	        // -------------------------------------------------------
+	        // !d
+	        // dom node is null, definitely garbage
+	        // -------------------------------------------------------
+	        // !d.parentNode
+	        // no parentNode == direct orphan, definitely garbage
+	        // -------------------------------------------------------
+	        // !d.offsetParent &amp;&amp; !document.getElementById(eid)
+	        // display none elements have no offsetParent so we will
+	        // also try to look it up by it's id. However, check
+	        // offsetParent first so we don't do unneeded lookups.
+	        // This enables collection of elements that are not orphans
+	        // directly, but somewhere up the line they have an orphan
+	        // parent.
+	        // -------------------------------------------------------
+	        if(!d || !d.parentNode || (!d.offsetParent &amp;&amp; !DOC.getElementById(eid))){
+	            delete El.cache[eid];
+	            if(d &amp;&amp; Ext.enableListenerCollection){
+	                Ext.EventManager.removeAll(d);
+	            }
+	        }
+	    }
+    }
+}
+El.collectorThreadId = setInterval(garbageCollect, 30000);
+
+var flyFn = function(){};
+flyFn.prototype = El.prototype;
+
+// dom is optional
+El.Flyweight = function(dom){
+    this.dom = dom;
+};
+
+El.Flyweight.prototype = new flyFn();
+El.Flyweight.prototype.isFlyweight = true;
+El._flyweights = {};
+
+
+El.fly = function(el, named){
+    var ret = null;
+	named = named || '_global';
+
+    if (el = Ext.getDom(el)) {
+    	(El._flyweights[named] = El._flyweights[named] || new El.Flyweight()).dom = el;
+    	ret = El._flyweights[named];
+	}
+	return ret;
+};
+
+
+Ext.get = El.get;
+
+
+Ext.fly = El.fly;
+
+// speedy lookup for elements never to box adjust
+var noBoxAdjust = Ext.isStrict ? {
+    select:1
+} : {
+    input:1, select:1, textarea:1
+};
+if(Ext.isIE || Ext.isGecko){
+    noBoxAdjust['button'] = 1;
+}
+
+
+Ext.EventManager.on(window, 'unload', function(){
+    delete El.cache;
+    delete El._flyweights;
+});
+})();
+
 
 Ext.Element.addMethods({    
     
@@ -2926,7 +2941,7 @@ Ext.Element.uncache = function(el){
             delete Ext.Element.cache[a[i].id || a[i]];
         }
     }
-};
+};
 
 Ext.Element.addMethods({
     
@@ -3206,7 +3221,7 @@ Ext.Element.addMethods({
         return this.alignTo(centerIn || document, 'c-c');        
     }    
 });
-
+
 
 Ext.Element.addMethods(function(){
 	var PARENTNODE = 'parentNode',
@@ -3221,8 +3236,10 @@ Ext.Element.addMethods(function(){
 	        var p = this.dom,
 	        	b = document.body, 
 	        	depth = 0, 	        	
-	        	stopEl;
-	        	
+	        	stopEl;	        
+            if(Ext.isGecko &amp;&amp; Object.prototype.toString.call(p) == '[object XULElement]') {
+                return null;
+            }
 	        maxDepth = maxDepth || 50;
 	        if (isNaN(maxDepth)) {
 	            stopEl = Ext.getDom(maxDepth);
@@ -3308,13 +3325,16 @@ Ext.Element.addMethods(function(){
 	        return null;
 	    }	
     }
-}());
+}());
 
 Ext.Element.addMethods(
 function() {
 	var GETDOM = Ext.getDom,
 		GET = Ext.get,
-		DH = Ext.DomHelper;
+		DH = Ext.DomHelper,
+        isEl = function(el){
+            return  (el.nodeType || el.dom || typeof el == 'string');  
+        };
 	
 	return {
 	    
@@ -3336,14 +3356,14 @@ function() {
 	
 	    
 	    insertAfter: function(el){
-	        GETDOM(el).parentNode.insertBefore(this.dom, el.nextSibling);
+	        (el = GETDOM(el)).parentNode.insertBefore(this.dom, el.nextSibling);
 	        return this;
 	    },
 	
 	    
 	    insertFirst: function(el, returnDom){
             el = el || {};
-            if(el.nodeType || el.dom){ // element
+            if(isEl(el)){ // element
                 el = GETDOM(el);
                 this.dom.insertBefore(el, this.dom.firstChild);
                 return !returnDom ? GET(el) : el;
@@ -3364,7 +3384,7 @@ function() {
 	    replaceWith: function(el){
 		    var me = this,
 		    	Element = Ext.Element;
-            if(el.nodeType || el.dom){
+            if(isEl(el)){
                 el = GETDOM(el);
                 me.dom.parentNode.insertBefore(el, me.dom);
             }else{
@@ -3398,7 +3418,7 @@ function() {
 		    return returnEl ? Ext.get(el) : el;
 		}
 	}
-}());
+}());
 
 Ext.apply(Ext.Element.prototype, function() {
 	var GETDOM = Ext.getDom,
@@ -3436,7 +3456,7 @@ Ext.apply(Ext.Element.prototype, function() {
 	        return rt;
 	    }
     }
-}());
+}());
 
 Ext.Element.addMethods(function(){  
     // local style camelizing for speed
@@ -3444,6 +3464,8 @@ Ext.Element.addMethods(function(){
         camelRe = /(-[a-z])/gi,
         classReCache = {},
         view = document.defaultView,
+        propFloat = Ext.isIE ? 'styleFloat' : 'cssFloat',
+        opacityRe = /alpha\(opacity=(.*)\)/i,
         EL = Ext.Element,   
         PADDING = &quot;padding&quot;,
         MARGIN = &quot;margin&quot;,
@@ -3478,10 +3500,9 @@ Ext.Element.addMethods(function(){
     }
 
     function chkCache(prop) {
-        return propCache[prop] || (propCache[prop] = prop.replace(camelRe, camelFn))
+        return propCache[prop] || (propCache[prop] = prop == 'float' ? propFloat : prop.replace(camelRe, camelFn));
+
     }
-        
-            
             
     return {    
         // private  ==&gt; used by Fx  
@@ -3518,7 +3539,7 @@ Ext.Element.addMethods(function(){
         radioClass : function(className){
             Ext.each(this.dom.parentNode.childNodes, function(v) {
                 if(v.nodeType == 1) {
-                    Ext.get(v).removeClass(className);          
+                    Ext.fly(v).removeClass(className);          
                 }
             });
             return this.addClass(className);
@@ -3553,12 +3574,6 @@ Ext.Element.addMethods(function(){
         },
         
         isStyle : function(style, val) {
-//          var ret = false;
-//          style = this.getStyle(style);
-//          Ext.each(Ext.toArray(arguments,1),function(s){
-//              if(style == s) return false; // stop iterating.
-//          });
-//          return ret;
             return this.getStyle(style) == val;  
         },
     
@@ -3570,9 +3585,9 @@ Ext.Element.addMethods(function(){
                         v,                  
                         cs;
                     if(el == document) return null;
-                    prop = prop == 'float' ? 'cssFloat' : prop;
+                    prop = chkCache(prop);
                     return (v = el.style[prop]) ? v : 
-                           (cs = view.getComputedStyle(el, &quot;&quot;)) ? cs[chkCache(prop)] : null;
+                           (cs = view.getComputedStyle(el, &quot;&quot;)) ? cs[prop] : null;
                 } :
                 function(prop){      
                     var el = this.dom, 
@@ -3582,7 +3597,7 @@ Ext.Element.addMethods(function(){
                     if(el == document) return null;      
                     if (prop == 'opacity') {
                         if (el.style.filter.match) {                       
-                            if(m = el.style.filter.match(/alpha\(opacity=(.*)\)/i)){
+                            if(m = el.style.filter.match(opacityRe)){
                                 var fv = parseFloat(m[1]);
                                 if(!isNaN(fv)){
                                     return fv ? fv / 100 : 0;
@@ -3591,8 +3606,8 @@ Ext.Element.addMethods(function(){
                         }
                         return 1;
                     }
-                    prop = prop == 'float' ? 'styleFloat' : prop;   
-                    return el.style[prop] || ((cs = el.currentStyle) ? cs[chkCache(prop)] : null);
+                    prop = chkCache(prop);  
+                    return el.style[prop] || ((cs = el.currentStyle) ? cs[prop] : null);
                 };
         }(),
         
@@ -3628,10 +3643,9 @@ Ext.Element.addMethods(function(){
             }
             for (style in prop) {
                 value = prop[style];            
-                camel = chkCache(style);
-                camel == 'opacity' ? 
+                style == 'opacity' ? 
                     this.setOpacity(value) : 
-                    this.dom.style[camel] = value;
+                    this.dom.style[chkCache(style)] = value;
             }
             return this;
         },
@@ -3747,7 +3761,7 @@ Ext.Element.addMethods(function(){
         margins : margins
     }
 }()         
-);
+);
 
 
 // special markup used throughout Ext when box wrapping elements
@@ -3861,29 +3875,27 @@ Ext.Element.addMethods(function(){
 	    },
 	    
 	    
-	    addClassOnOver : function(className){
-		    var me = this;	    	
-	        me.hover(
+	    addClassOnOver : function(className){	    	
+	        this.hover(
 	            function(){
-	                Ext.fly(me, INTERNAL).addClass(className);
+	                Ext.fly(this, INTERNAL).addClass(className);
 	            },
 	            function(){
-	                Ext.fly(me, INTERNAL).removeClass(className);
+	                Ext.fly(this, INTERNAL).removeClass(className);
 	            }			   
 	        );
-	        return me;
+	        return this;
 	    },
 	
 	    
 	    addClassOnFocus : function(className){
-		    var me = this;
-	        me.on(&quot;focus&quot;, function(){
-	            Ext.fly(me, INTERNAL).addClass(className);
-	        }, me.dom);
-	        me.on(&quot;blur&quot;, function(){
-	            Ext.fly(me, INTERNAL).removeClass(className);
-	        }, me.dom);
-	        return me;
+		this.on(&quot;focus&quot;, function(){
+		    Ext.fly(this, INTERNAL).addClass(className);
+		}, this.dom);
+		this.on(&quot;blur&quot;, function(){
+		    Ext.fly(this, INTERNAL).removeClass(className);
+		}, this.dom);
+		return this;
 	    },
 	    
 	    
@@ -3950,10 +3962,19 @@ Ext.Element.addMethods(function(){
 	        }
 	    }	
     }
-}());
+}());
 
 (function(){
-var D = Ext.lib.Dom;
+var D = Ext.lib.Dom,
+        LEFT = &quot;left&quot;,
+        RIGHT = &quot;right&quot;,
+        TOP = &quot;top&quot;,
+        BOTTOM = &quot;bottom&quot;,
+        POSITION = &quot;position&quot;,
+        STATIC = &quot;static&quot;,
+        RELATIVE = &quot;relative&quot;,
+        AUTO = &quot;auto&quot;,
+        ZINDEX = &quot;z-index&quot;;
 
 function animTest(args, animate, i) {
 	return this.preanim &amp;&amp; !!animate ? this.preanim(args, i) : false	
@@ -3994,25 +4015,25 @@ Ext.Element.addMethods({
 
     
     setLeft : function(left){
-        this.setStyle(&quot;left&quot;, this.addUnits(left));
+        this.setStyle(LEFT, this.addUnits(left));
         return this;
     },
 
     
     setTop : function(top){
-        this.setStyle(&quot;top&quot;, this.addUnits(top));
+        this.setStyle(TOP, this.addUnits(top));
         return this;
     },
 
     
     setRight : function(right){
-        this.setStyle(&quot;right&quot;, this.addUnits(right));
+        this.setStyle(RIGHT, this.addUnits(right));
         return this;
     },
 
     
     setBottom : function(bottom){
-        this.setStyle(&quot;bottom&quot;, this.addUnits(bottom));
+        this.setStyle(BOTTOM, this.addUnits(bottom));
         return this;
     },
 
@@ -4039,7 +4060,7 @@ Ext.Element.addMethods({
     
     
     getLeft : function(local){
-	    return !local ? this.getX() : parseInt(this.getStyle(&quot;left&quot;), 10) || 0;
+	    return !local ? this.getX() : parseInt(this.getStyle(LEFT), 10) || 0;
     },
 
     
@@ -4050,7 +4071,7 @@ Ext.Element.addMethods({
 
     
     getTop : function(local) {
-	    return !local ? this.getY() : parseInt(this.getStyle(&quot;top&quot;), 10) || 0;
+	    return !local ? this.getY() : parseInt(this.getStyle(TOP), 10) || 0;
     },
 
     
@@ -4063,13 +4084,13 @@ Ext.Element.addMethods({
     position : function(pos, zIndex, x, y){
 	    var me = this;
 	    
-        if(!pos &amp;&amp; me.isStyle('position', 'static')){           
-            me.setStyle('position', 'relative');           
+        if(!pos &amp;&amp; me.isStyle(POSITION, STATIC)){           
+            me.setStyle(POSITION, RELATIVE);           
         } else if(pos) {
-            me.setStyle(&quot;position&quot;, pos);
+            me.setStyle(POSITION, pos);
         }
         if(zIndex){
-            me.setStyle(&quot;z-index&quot;, zIndex);
+            me.setStyle(ZINDEX, zIndex);
         }
         if(x || y) me.setXY([x || false, y || false]);
     },
@@ -4083,28 +4104,22 @@ Ext.Element.addMethods({
             top : value,
             bottom : value,
             &quot;z-index&quot; : &quot;&quot;,
-            position : &quot;static&quot;
+            position : STATIC
         });
         return this;
     },
 
     
     getPositioning : function(){
-	    var me = this;
-        function gs(pos) {
-	    	return me.getStyle(pos);    
-        }
-        
-        var l = gs(&quot;left&quot;),
-        	t = gs(&quot;top&quot;);
-
+        var l = this.getStyle(LEFT);
+        var t = this.getStyle(TOP);
         return {
-            position : gs(&quot;position&quot;),
-            left : l,
-            right : l ? &quot;&quot; : gs(&quot;right&quot;),
-            top : t,
-            bottom : t ? &quot;&quot; : gs(&quot;bottom&quot;),
-            &quot;z-index&quot; : gs(&quot;z-index&quot;)
+            &quot;position&quot; : this.getStyle(POSITION),
+            &quot;left&quot; : l,
+            &quot;right&quot; : l ? &quot;&quot; : this.getStyle(RIGHT),
+            &quot;top&quot; : t,
+            &quot;bottom&quot; : t ? &quot;&quot; : this.getStyle(BOTTOM),
+            &quot;z-index&quot; : this.getStyle(ZINDEX)
         };
     },
     
@@ -4115,10 +4130,10 @@ Ext.Element.addMethods({
 	    	
         me.setStyle(pc);
         
-        if(pc.right == &quot;auto&quot;){
+        if(pc.right == AUTO){
             style.right = &quot;&quot;;
         }
-        if(pc.bottom == &quot;auto&quot;){
+        if(pc.bottom == AUTO){
             style.bottom = &quot;&quot;;
         }
         
@@ -4130,10 +4145,10 @@ Ext.Element.addMethods({
 	    y = isNaN(x[1]) ? y : x[1];
         x = isNaN(x[0]) ? x : x[0];
         var me = this,
-        	relative = me.isStyle('position', &quot;relative&quot;),
+        	relative = me.isStyle(POSITION, RELATIVE),
         	o = me.getXY(),
-        	l = parseInt(me.getStyle('left'), 10),
-        	t = parseInt(me.getStyle('top'), 10);
+        	l = parseInt(me.getStyle(LEFT), 10),
+        	t = parseInt(me.getStyle(TOP), 10);
         
         l = !isNaN(l) ? l : (relative ? 0 : me.dom.offsetLeft);
         t = !isNaN(t) ? t : (relative ? 0 : me.dom.offsetTop);        
@@ -4143,7 +4158,7 @@ Ext.Element.addMethods({
     
     animTest : animTest
 });
-})();
+})();
 
 Ext.Element.addMethods({
     
@@ -4217,7 +4232,7 @@ Ext.Element.addMethods({
 	        };
         
  	    direction = direction.toLowerCase();    
- 	    me.moveTo(hash[direction][0], hash[direction][1], me.animTest.call(me, arguments, animate, 1));
+ 	    me.moveTo(hash[direction][0], hash[direction][1], me.animTest.call(me, arguments, animate, 2));
     },
     
     
@@ -4254,7 +4269,7 @@ Ext.Element.addMethods({
     setRegion : function(region, animate) {
         return this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.animTest.call(this, arguments, animate, 1));
     }
-});
+});
 
 Ext.Element.addMethods({
     
@@ -4265,35 +4280,35 @@ Ext.Element.addMethods({
 
     
     scrollTo : function(side, value){
-        this.dom[&quot;scroll&quot; + (/top/i.test(side) ? &quot;Top&quot; : &quot;Left&quot;)] = value;        
+        this.dom[&quot;scroll&quot; + (/top/i.test(side) ? &quot;Top&quot; : &quot;Left&quot;)] = value;
         return this;
     },
-    
+
     
     getScroll : function(){
         var d = this.dom, 
-        	doc = document,
-        	body = doc.body,
-        	docElement = doc.documentElement,
-        	l,
-        	t,
-        	ret;
-        	
-        if(d == doc || d == body){            
+            doc = document,
+            body = doc.body,
+            docElement = doc.documentElement,
+            l,
+            t,
+            ret;
+
+        if(d == doc || d == body){
             if(Ext.isIE &amp;&amp; Ext.isStrict){
                 l = docElement.scrollLeft; 
                 t = docElement.scrollTop;
             }else{
                 l = window.pageXOffset;
                 t = window.pageYOffset;
-            }            
+            }
             ret = {left: l || (body ? body.scrollLeft : 0), top: t || (body ? body.scrollTop : 0)};
         }else{
             ret = {left: d.scrollLeft, top: d.scrollTop};
         }
         return ret;
     }
-});
+});
 
 Ext.Element.addMethods({
     
@@ -4351,39 +4366,31 @@ Ext.Element.addMethods({
     
     
      scroll : function(direction, distance, animate){
-         if(this.isScrollable()){
-	         var el = this.dom,
-	         	l = el.scrollLeft, t = el.scrollTop,
-	         	w = el.scrollWidth, h = el.scrollHeight,
-	         	cw = el.clientWidth, ch = el.clientHeight,
-	         	scrolled = false,	         		         	
-	         	l = Math.min(l + distance, w-cw),
-	         	r = Math.max(l - distance, 0),
-	         	t = Math.max(t - distance, 0),
-	         	b = Math.min(t + distance, h-ch),
-	         	hash = {
-		        	l : l,
-		        	left : l,
-		        	r : r,
-		        	right : r,
-		        	t : t,
-		        	top : t,
-		        	up : t,
-		        	b : b, 
-		        	bottom : b,
-		        	down : b 		
-	         	};
-	         	
-	         direction = direction.toLowerCase();
-	         
-	         if (v = hash[direction]) {
-			     this.scrollTo(&quot;left&quot;, v, this.preanim(arguments, 2));
-		         scrolled = true;
-         	 }
-	         return scrolled;
+         if(!this.isScrollable()){
+             return;
+         }
+         var el = this.dom,
+            l = el.scrollLeft, t = el.scrollTop,
+            w = el.scrollWidth, h = el.scrollHeight,
+            cw = el.clientWidth, ch = el.clientHeight,
+            scrolled = false, v,
+            hash = {
+                l: Math.min(l + distance, w-cw),
+                r: v = Math.max(l - distance, 0),
+                t: Math.max(t - distance, 0),
+                b: Math.min(t + distance, h-ch)
+            };
+            hash.d = hash.b
+            hash.u = hash.t;
+            
+         direction = direction.substr(0, 1);
+         if((v = hash[direction]) &gt; -1){
+            scrolled = true;
+            this.scrollTo(direction == 'l' || direction == 'r' ? 'left' : 'top', v, this.preanim(arguments, 2));
          }
+         return scrolled;
     }
-});
+});
 
 
 Ext.Element.VISIBILITY = 1;
@@ -4447,34 +4454,35 @@ Ext.Element.addMethods(function(){
 	    
 	     setVisible : function(visible, animate){
 		    var me = this,
-	            visMode = me.visibilityMode;
-	            
-	        if (!animate || !me.anim) {
-	            if (me.visibilityMode == ELDISPLAY) {
-	                me.setDisplayed(visible);
-	            } else {
-	                me.fixDisplay();
-	                me.dom.style.visibility = visible ? &quot;visible&quot; : HIDDEN;
-	            }
-	        } else {
-	            // closure for composites            
-	            if(visible){
-	                me.setOpacity(.01);
-	                me.setVisible(true);
-	            }
-	            me.anim({opacity: { to: (visible?1:0) }},
-	                    me.preanim(arguments, 1),
-	                    null,
-	                    .35,
-	                    'easeIn',
-	                    function(){
-		                     if(!visible){
-                                 me.dom.style.display = (visMode == ELDISPLAY) ? NONE : HIDDEN;                     
-		                         Ext.get(me.dom).setOpacity(1);
-		                     }
-	                 	});
-	        }
-	        return me;
+                dom = me.dom,
+                isDisplay = (me.visibilityMode == ELDISPLAY);
+                
+            if (!animate || !me.anim) {
+                if(isDisplay){
+                    me.setDisplayed(visible);
+                }else{
+                    me.fixDisplay();
+                    dom.style.visibility = visible ? &quot;visible&quot; : HIDDEN;
+                }
+            }else{
+                // closure for composites            
+                if(visible){
+                    me.setOpacity(.01);
+                    me.setVisible(true);
+                }
+                me.anim({opacity: { to: (visible?1:0) }},
+                        me.preanim(arguments, 1),
+                        null,
+                        .35,
+                        'easeIn',
+                        function(){
+                             if(!visible){
+                                 dom.style[isDisplay ? DISPLAY : VISIBILITY] = (isDisplay) ? NONE : HIDDEN;                     
+                                 Ext.fly(dom).setOpacity(1);
+                             }
+                        });
+            }
+            return me;
 	    },
 	
 	    
@@ -4517,7 +4525,7 @@ Ext.Element.addMethods(function(){
 	        return this;
 	    }
 	}
-}());
+}());
 
 Ext.Element.addMethods(
 function(){
@@ -4587,7 +4595,7 @@ function(){
 	            mm.center(me);
 	        }
 	        if(Ext.isIE &amp;&amp; !(Ext.isIE7 &amp;&amp; Ext.isStrict) &amp;&amp; me.getStyle('height') == 'auto'){ // ie will not expand full height automatically
-	            me._mask.setSize(dom.clientWidth, me.getHeight());
+	            me._mask.setSize(undefined, me.getHeight());
 	        }
 	        return me._mask;
 	    },
@@ -4627,7 +4635,7 @@ function(){
 	        return shim;
 	    }
     }
-}());
+}());
 
 Ext.Element.addMethods({
     
@@ -4647,7 +4655,7 @@ Ext.Element.addMethods({
         var dd = new Ext.dd.DDTarget(Ext.id(this.dom), group, config);
         return Ext.apply(dd, overrides);
     }
-});
+});
 
 Ext.Element.addMethods({
     
@@ -4673,7 +4681,7 @@ Ext.Element.addMethods({
         }.createDelegate(this), 0);
         return this;
     }
-});
+});
 
 Ext.Element.addMethods({
     
@@ -4702,714 +4710,746 @@ Ext.Element.addMethods({
     addKeyMap : function(config){
         return new Ext.KeyMap(this, config);
     }
-});
-(function(){
-	// contants
-	var NULL = null,
-		UNDEFINED = undefined,
-		TRUE = true,
-		FALSE = false,
-    	SETX = &quot;setX&quot;,
-    	SETY = &quot;setY&quot;,
-    	SETXY = &quot;setXY&quot;,
-    	LEFT = &quot;left&quot;,
-    	BOTTOM = &quot;bottom&quot;,
-    	TOP = &quot;top&quot;,
-    	RIGHT = &quot;right&quot;,
-    	HEIGHT = &quot;height&quot;,
-    	WIDTH = &quot;width&quot;,
-    	POINTS = &quot;points&quot;,
-    	HIDDEN = &quot;hidden&quot;,
-    	ABSOLUTE = &quot;absolute&quot;,
-    	VISIBLE = &quot;visible&quot;,
-    	MOTION = &quot;motion&quot;,
-    	POSITION = &quot;position&quot;,
-    	EASEOUT = &quot;easeOut&quot;;
-    	
-//Notifies Element that fx methods are available
-Ext.enableFx = TRUE;
-
-
-Ext.Fx = {
-	
-	// private - calls the function taking arguments from the argHash based on the key.  Returns the return value of the function.
-	// 			 this is useful for replacing switch statements (for example).
-	switchStatements : function(key, fn, argHash){
-		return fn.apply(this, argHash[key]);
-	},
-	
-	
-    slideIn : function(anchor, o){        
-	    var me = this,
-        	el = me.getFxEl(),
-        	r,
-			b,				
-			wrap,				
-			after,
-			st,
-        	args, 
-        	pt,
-        	bw,
-        	bh,
-        	xy = me.getXY(),
-            dom = me.dom;
-        	
-        o = o || {};
-		anchor = anchor || &quot;t&quot;;
-
-        el.queueFx(o, function(){			
-			st = me.dom.style;				
-            	
-            // fix display to visibility
-            me.fixDisplay();            
-            
-            // restore values after effect
-			r = me.getFxRestore();		
-            b = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: dom.offsetWidth, height: dom.offsetHeight};
-            b.right = b.x + b.width;
-            b.bottom = b.y + b.height;
-            
-            // fixed size for slide
-            me.setWidth(b.width).setHeight(b.height);            
-            
-            // wrap if needed
-            wrap = me.fxWrap(r.pos, o, HIDDEN);
-            
-            st.visibility = VISIBLE;
-            st.position = ABSOLUTE;
-            
-        	// clear out temp styles after slide and unwrap
-        	function after(){
-                 el.fxUnwrap(wrap, r.pos, o);
-                 st.width = r.width;
-                 st.height = r.height;
-                 el.afterFx(o);
-            }
-            
-            // time to calculate the positions        
-        	pt = {to: [b.x, b.y]}; 
-        	bw = {to: b.width};
-        	bh = {to: b.height};
-            	
-			function argCalc(wrap, style, ww, wh, sXY, sXYval, s1, s2, w, h, p){	            	
-				var ret = {};
-            	wrap.setWidth(ww).setHeight(wh);
-            	if( wrap[sXY] )	wrap[sXY](sXYval);            		
-            	style[s1] = style[s2] = &quot;0&quot;;	            	
-            	if(w) ret.width = w;
-            	if(h) ret.height = h;
-            	if(p) ret.points = p;
-            	return ret;
-        	};
-
-            args = me.switchStatements(anchor.toLowerCase(), argCalc, {
-		            t  : [wrap, st, b.width, 0, NULL, NULL, LEFT, BOTTOM, NULL, bh, NULL],
-		            l  : [wrap, st, 0, b.height, NULL, NULL, RIGHT, TOP, bw, NULL, NULL],
-		            r  : [wrap, st, 0, b.height, SETX, b.right, LEFT, TOP, bw, NULL, pt],
-		            b  : [wrap, st, b.width, 0, SETY, b.bottom, LEFT, TOP, NULL, bh, pt],
-		            tl : [wrap, st, 0, 0, NULL, NULL, RIGHT, BOTTOM, bw, NULL, pt],
-		            bl : [wrap, st, 0, 0, SETY, b.y + b.height, RIGHT, TOP, bw, bh, pt],
-		            br : [wrap, st, 0, 0, SETXY, [b.right, b.bottom], LEFT, TOP, bw, bh, pt],
-		            tr : [0, 0, SETX, b.x + b.width, LEFT, BOTTOM, bw, bh, pt]
-            	});
-            
-            st.visibility = VISIBLE;
-            wrap.show();
-
-            arguments.callee.anim = wrap.fxanim(args,
-                o,
-                MOTION,
-                .5,
-                EASEOUT, 
-                after);
-        });
-        return me;
-    },
-    
-	
-    slideOut : function(anchor, o){
-	    var me = this,
-	    	el = me.getFxEl(),
-	    	xy = me.getXY(),
-            dom = me.dom,
-	    	wrap,
-	    	st,
-	    	r,
-	    	b,
-	    	a,
-	    	zero = {to: 0}; 
-	    		    
-        o = o || {};
-        anchor = anchor || &quot;t&quot;;
-
-        el.queueFx(o, function(){
-	        // restore values after effect
-            r = me.getFxRestore(); 
-            b = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: dom.offsetWidth, height: dom.offsetHeight};
-            b.right = b.x + b.width;
-            b.bottom = b.y + b.height;
-            	
-            // fixed size for slide            
-            me.setWidth(b.width).setHeight(b.height);
-
-            // wrap if needed
-            wrap = me.fxWrap(r.pos, o, VISIBLE);
-           	st = me.dom.style;
-           		
-            st.visibility = VISIBLE;
-            st.position = ABSOLUTE;
-            wrap.setWidth(b.width).setHeight(b.height);            
-
-            function after(){
-	            o.useDisplay ? el.setDisplayed(FALSE) : el.hide();                
-                el.fxUnwrap(wrap, r.pos, o);
-                st.width = r.width;
-                st.height = r.height;
-                el.afterFx(o);
-            }            
-            
-            function argCalc(style, s1, s2, p1, v1, p2, v2, p3, v3){	            	
-	            var ret = {};
-	            
-            	style[s1] = style[s2] = &quot;0&quot;;
-            	ret[p1] = v1;            	
-            	if(p2) ret[p2] = v2;            	
-            	if(p3) ret[p3] = v3;
-            	
-            	return ret;
-       		};
-       		
-       		a = me.switchStatements(anchor.toLowerCase(), argCalc, {
-	            t  : [st, LEFT, BOTTOM, HEIGHT, zero],
-	            l  : [st, RIGHT, TOP, WIDTH, zero],
-	            r  : [st, LEFT, TOP, WIDTH, zero, POINTS, {to : [b.right, b.y]}],
-	            b  : [st, LEFT, TOP, HEIGHT, zero, POINTS, {to : [b.x, b.bottom]}],
-	            tl : [st, RIGHT, BOTTOM, WIDTH, zero, HEIGHT, zero],
-	            bl : [st, RIGHT, TOP, WIDTH, zero, HEIGHT, zero, POINTS, {to : [b.X, b.bottom]}],
-	            br : [st, LEFT, TOP, WIDTH, zero, HEIGHT, zero, POINTS, {to : [b.x + b.width, b.bottom]}],
-	            tr : [st, LEFT, BOTTOM, WIDTH, zero, HEIGHT, zero, POINTS, {to : [b.right, b.y]}]
-            });
-            
-            arguments.callee.anim = wrap.fxanim(a,
-                o,
-                MOTION,
-                .5,
-                EASEOUT, 
-                after);
-        });
-        return me;
-    },
-
-	
-    puff : function(o){
-	    o = o || {};
-	    
-        var me = this,
-        	el = me.getFxEl(),
-        	r, 
-        	st = me.dom.style,
-        	width = me.getWidth(),
-        	height = me.getHeight();        	        
-
-        el.queueFx(o, function(){	        
-            me.clearOpacity();
-            me.show();
-
-            // restore values after effect
-            r = me.getFxRestore();        	       	 
-        	
-            function after(){
-            	o.useDisplay ? el.setDisplayed(FALSE) : el.hide();	                
-                el.clearOpacity();	
-                el.setPositioning(r.pos);
-                st.width = r.width;
-                st.height = r.height;
-                st.fontSize = '';
-                el.afterFx(o);
-            }	
-
-            arguments.callee.anim = me.fxanim({
-                    width : {to : me.adjustWidth(width * 2)},
-                    height : {to : me.adjustHeight(height * 2)},
-                    points : {by : [-width * .5, -height * .5]},
-                    opacity : {to : 0},
-                    fontSize: {to : 200, unit: &quot;%&quot;}
-                },
-                o,
-                MOTION,
-                .5,
-                EASEOUT,
-                 after);
-        });
-        return me;
-    },
-
-	
-    switchOff : function(o){
-	    o = o || {};
-	    
-        var me = this,
-        	el = me.getFxEl();        
-
-        el.queueFx(o, function(){
-	        me.clearOpacity();
-            me.clip();
-
-            // restore values after effect
-            var r = me.getFxRestore(),
-            	st = me.dom.style,
-            	after = function(){
-	                o.useDisplay ? el.setDisplayed(FALSE) : el.hide();	
-	                el.clearOpacity();
-	                el.setPositioning(r.pos);
-	                st.width = r.width;
-	                st.height = r.height;	
-	                el.afterFx(o);
-	            };
-
-            me.fxanim({opacity : {to : 0.3}}, 
-            	NULL, 
-            	NULL, 
-            	.1, 
-            	NULL, 
-            	function(){	            		            
-	                me.clearOpacity();
-		                (function(){			                
-		                    me.fxanim({
-		                        height : {to : 1},
-		                        points : {by : [0, me.getHeight() * .5]}
-		                    }, 
-		                    o, 
-		                    MOTION, 
-		                    0.3, 
-		                    'easeIn', 
-		                    after);
-		                }).defer(100);
-	            });
-        });
-        return me;
-    },
-
-    	
-    highlight : function(color, o){
-	    o = o || {};
-	    
-        var me = this,
-        	el = me.getFxEl(),
-        	attr = o.attr || &quot;backgroundColor&quot;,
-        	a = {};
-
-        el.queueFx(o, function(){
-            me.clearOpacity();
-            me.show();
-
-            function after(){
-                el.dom.style[attr] = me.dom.style[attr];
-                el.afterFx(o);
-            }            
-            	
-            a[attr] = {from: color || &quot;ffff9c&quot;, to: o.endColor || me.getColor(attr) || &quot;ffffff&quot;};
-            arguments.callee.anim = me.fxanim(a,
-                o,
-                'color',
-                1,
-                'easeIn', 
-                after);
-        });
-        return me;
-    },
-
-   
-    frame : function(color, count, o){
-        var me = this,
-        	el = me.getFxEl();
-        	
-        o = o || {};
-
-        el.queueFx(o, function(){
-            color = color || &quot;#C3DAF9&quot;
-            if(color.length == 6){
-                color = &quot;#&quot; + color;
-            }            
-            count = count || 1;
-            me.show();
-
-            var xy = me.getXY(),
-            	dom = me.dom,
-            	b = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: dom.offsetWidth, height: dom.offsetHeight};
-            
-            
-            
-        	function animFn(){
-                var proxy = Ext.get(document.body || document.documentElement).createChild({
-                     style:{
-                        visbility: HIDDEN,
-                        position : ABSOLUTE,
-                        &quot;z-index&quot;: 35000, // yee haw
-                        border : &quot;0px solid &quot; + color
-                     }
-            	}),
-            	scale = Ext.isBorderBox ? 2 : 1;
-                proxy.animate({
-                    top : {from : b.y, to : b.y - 20},
-                    left : {from : b.x, to : b.x - 20},
-                    borderWidth : {from : 0, to : 10},
-                    opacity : {from : 1, to : 0},
-                    height : {from : b.height, to : b.height + 20 * scale},
-                    width : {from : b.width, to : b.width + 20 * scale}
-                }, 
-                o.duration || 1, 
-                function() {
-                	proxy.remove();
-                	--count &gt; 0 ? animFn() : el.afterFx(o);
-            	});
-        	};
-            animFn.call(me);
-        });
-        return me;
-    },
-
-   
-    pause : function(seconds){
-        var el = this.getFxEl();
-
-        el.queueFx({}, function(){
-            setTimeout(function(){
-                el.afterFx({});
-            }, seconds * 1000);
-        });
-        return this;
-    },
-
-   
-    fadeIn : function(o){
-        var me = this,
-        	el = me.getFxEl();        
-        o = o || {};
-        
-        el.queueFx(o, function(){	        
-            me.setOpacity(0);
-            me.fixDisplay();
-            me.dom.style.visibility = VISIBLE;
-            var to = o.endOpacity || 1;
-            arguments.callee.anim = me.fxanim({opacity:{to:to}},
-                o, NULL, .5, EASEOUT, function(){
-                if(to == 1){
-                    this.clearOpacity();
-                }
-                el.afterFx(o);
-            });
-        });
-        return me;
-    },
-
-   
-    fadeOut : function(o){
-	    o = o || {};
-	    
-        var me = this,
-        	style = me.dom.style,
-        	el = me.getFxEl(),
-        	to = o.endOpacity || 0;        	
-        
-        el.queueFx(o, function(){                       
-            arguments.callee.anim = me.fxanim({ 
-	            opacity : {to : to}},
-                o, 
-                NULL, 
-                .5, 
-                EASEOUT, 
-                function(){
-	                if(to == 0){
-		               me.visibilityMode == Ext.Element.DISPLAY || o.useDisplay ? 
-		                	style.display = &quot;none&quot; :
-		                	style.visibility = HIDDEN;
-		                	
-	                    me.clearOpacity();
-                	}
-                	el.afterFx(o);
-            });
-        });
-        return me;
-    },
-
-   
-    scale : function(w, h, o){
-	    var me = this;
-        me.shift(Ext.apply({}, o, {
-            width: w,
-            height: h
-        }));
-        return me;
-    },
-
-   
-    shift : function(o){
-	    var me = this;
-	    o = o || {};
-        
-	    var	el = me.getFxEl();       	
-        el.queueFx(o, function(){
-	        var a = {};	
-	        
-            for (var prop in o) {
-	            if (o[prop] != UNDEFINED) {		            			                    
-		            a[prop] = {to : o[prop]};	            	
-	            }
-            } 
-            
-         	a.width ? a.width.to = me.adjustWidth(o.width) : a;
-         	a.height ? a.height.to = me.adjustWidth(o.height) : a;   
-            
-            if (a.x || a.y || a.xy) {
-	            a.points = a.xy || 
-	            		   {to : [ a.x ? a.x.to : me.getX(),
-	            				   a.y ? a.y.to : me.getY()]};	            	
-            }
-
-            arguments.callee.anim = me.fxanim(a,
-                o, 
-                MOTION, 
-                .35, 
-                EASEOUT, 
-                function(){
-                	el.afterFx(o);
-            	});
-        });
-        return me;
-    },
-
-	
-    ghost : function(anchor, o){
-        var me = this,
-        	el = me.getFxEl();
-        	
-        o = o || {};
-        anchor = anchor || &quot;b&quot;;
-
-        el.queueFx(o, function(){
-            // restore values after effect
-            var r = me.getFxRestore(),
-            	w = me.getWidth(),
-                h = me.getHeight(),
-            	st = me.dom.style,
-            	after = function(){
-	                if(o.useDisplay){
-	                    el.setDisplayed(FALSE);
-	                }else{
-	                    el.hide();
-                	}
-                	
-	                el.clearOpacity();
-	                el.setPositioning(r.pos);
-	                st.width = r.width;
-	                st.width = r.width;
-	
-	                el.afterFx(o);
-	            },
-            	a = {opacity: {to: 0}, 
-            		 points: {}}, 
-            	pt = a.points;
-            	
-            	pt.by = me.switchStatements(anchor.toLowerCase(), function(v1,v2){ return [v1, v2];}, {
-	            	t  : [0, -h],
-	            	l  : [-w, 0],
-	            	r  : [w, 0],
-	            	b  : [0, h],
-	            	tl : [-w, -h],
-	            	bl : [-w, h],
-	            	br : [w, h],
-	            	tr : [w, -h]	
-            	});
-            	
-            arguments.callee.anim = me.fxanim(a,
-                o,
-                MOTION,
-                .5,
-                EASEOUT, after);
-        });
-        return me;
-    },
-
-	
-    syncFx : function(){
-	    var me = this;
-        me.fxDefaults = Ext.apply(me.fxDefaults || {}, {
-            block : FALSE,
-            concurrent : TRUE,
-            stopFx : FALSE
-        });
-        return me;
-    },
-
-	
-    sequenceFx : function(){
-	    var me = this;
-        me.fxDefaults = Ext.apply(me.fxDefaults || {}, {
-            block : FALSE,
-            concurrent : FALSE,
-            stopFx : FALSE
-        });
-        return me;
-    },
-
-	
-    nextFx : function(){	    
-        var ef = this.fxQueue[0];
-        if(ef){
-            ef.call(this);
-        }
-    },
-
-	
-    hasActiveFx : function(){	    
-        return this.fxQueue &amp;&amp; this.fxQueue[0];
-    },
-
-	
-    stopFx : function(finish){
-	    var me = this;
-        if(me.hasActiveFx()){
-            var cur = me.fxQueue[0];
-            if(cur &amp;&amp; cur.anim &amp;&amp; cur.anim.isAnimated){
-                me.fxQueue = [cur]; // clear out others
-                cur.anim.stop(finish !== undefined ? finish : true);
-            }
-        }
-        return me;
-    },
-
-	
-    beforeFx : function(o){
-        if(this.hasActiveFx() &amp;&amp; !o.concurrent){
-           if(o.stopFx){
-               this.stopFx();
-               return TRUE;
-           }
-           return FALSE;
-        }
-        return TRUE;
-    },
-
-	
-    hasFxBlock : function(){
-        var q = this.fxQueue;
-        return q &amp;&amp; q[0] &amp;&amp; q[0].block;
-    },
-
-	
-    queueFx : function(o, fn){
-	    var me = this;
-        if(!me.fxQueue){
-            me.fxQueue = [];
-        }
-        if(!me.hasFxBlock()){
-            Ext.applyIf(o, me.fxDefaults);
-            if(!o.concurrent){
-                var run = me.beforeFx(o);
-                fn.block = o.block;
-                me.fxQueue.push(fn);
-                if(run){
-                    me.nextFx();
-                }
-            }else{
-                fn.call(me);
-            }
-        }
-        return me;
-    },
-
-	
-    fxWrap : function(pos, o, vis){	
-        var me = this,
-        	wrap,
-        	wrapXY;
-        if(!o.wrap || !(wrap = Ext.get(o.wrap))){            
-            if(o.fixPosition){
-                wrapXY = me.getXY();
-            }
-            var div = document.createElement(&quot;div&quot;);
-            div.style.visibility = vis;
-            wrap = Ext.get(me.dom.parentNode.insertBefore(div, me.dom));
-            wrap.setPositioning(pos);
-            if(wrap.isStyle(POSITION, &quot;static&quot;)){
-                wrap.position(&quot;relative&quot;);
-            }
-            me.clearPositioning('auto');
-            wrap.clip();
-            wrap.dom.appendChild(me.dom);
-            if(wrapXY){
-                wrap.setXY(wrapXY);
-            }
-        }
-        return wrap;
-    },
-
-	
-    fxUnwrap : function(wrap, pos, o){	    
-	    var me = this;
-        me.clearPositioning();
-        me.setPositioning(pos);
-        if(!o.wrap){
-            wrap.dom.parentNode.insertBefore(me.dom, wrap.dom);
-            wrap.remove();
-        }
-    },
-
-	
-    getFxRestore : function(){
-        var	st = this.dom.style;
-        return {pos: this.getPositioning(), width: st.width, height : st.height};
-    },
-
-	
-    afterFx : function(o){
-	    var me = this;
-        if(o.afterStyle){
-	        me.setStyle(o.afterStyle);            
-        }
-        if(o.afterCls){
-            me.addClass(o.afterCls);
-        }
-        if(o.remove == TRUE){
-            me.remove();
-        }
-        if(o.callback) o.callback.call(o.scope, me);
-        if(!o.concurrent){
-            me.fxQueue.shift();
-            me.nextFx();
-        }
-    },
-
-	
-    getFxEl : function(){ // support for composite element fx
-        return Ext.get(this.dom);
-    },
-
-	
-    fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
-        animType = animType || 'run';
-        opt = opt || {};
-        var anim = Ext.lib.Anim[animType](
-	            this.dom, 
-	            args,
-	            (opt.duration || defaultDur) || .35,
-	            (opt.easing || defaultEase) || EASEOUT,
-	            cb,	           
-	            this
-	        );
-        opt.anim = anim;
-        return anim;
-    }
-};
-
-// backwards compat
-Ext.Fx.resize = Ext.Fx.scale;
-
-//When included, Ext.Fx is automatically applied to Element so that all basic
-//effects are available directly via the Element API
-Ext.Element.addMethods(Ext.Fx);
-})();
+});
+(function(){
+	// contants
+	var NULL = null,
+		UNDEFINED = undefined,
+		TRUE = true,
+		FALSE = false,
+    	SETX = &quot;setX&quot;,
+    	SETY = &quot;setY&quot;,
+    	SETXY = &quot;setXY&quot;,
+    	LEFT = &quot;left&quot;,
+    	BOTTOM = &quot;bottom&quot;,
+    	TOP = &quot;top&quot;,
+    	RIGHT = &quot;right&quot;,
+    	HEIGHT = &quot;height&quot;,
+    	WIDTH = &quot;width&quot;,
+    	POINTS = &quot;points&quot;,
+    	HIDDEN = &quot;hidden&quot;,
+    	ABSOLUTE = &quot;absolute&quot;,
+    	VISIBLE = &quot;visible&quot;,
+    	MOTION = &quot;motion&quot;,
+    	POSITION = &quot;position&quot;,
+    	EASEOUT = &quot;easeOut&quot;;
+    	
+//Notifies Element that fx methods are available
+Ext.enableFx = TRUE;
+
+
+Ext.Fx = {
+	
+	// private - calls the function taking arguments from the argHash based on the key.  Returns the return value of the function.
+	// 			 this is useful for replacing switch statements (for example).
+	switchStatements : function(key, fn, argHash){
+		return fn.apply(this, argHash[key]);
+	},
+	
+	
+    slideIn : function(anchor, o){        
+	    var me = this,
+        	el = me.getFxEl(),
+        	r,
+			b,				
+			wrap,				
+			after,
+			st,
+        	args, 
+        	pt,
+        	bw,
+        	bh,
+        	xy = me.getXY(),
+            dom = me.dom;
+        	
+        o = o || {};
+		anchor = anchor || &quot;t&quot;;
+
+        el.queueFx(o, function(){			
+			st = me.dom.style;				
+            	
+            // fix display to visibility
+            me.fixDisplay();            
+            
+            // restore values after effect
+			r = me.getFxRestore();		
+            b = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: dom.offsetWidth, height: dom.offsetHeight};
+            b.right = b.x + b.width;
+            b.bottom = b.y + b.height;
+            
+            // fixed size for slide
+            me.setWidth(b.width).setHeight(b.height);            
+            
+            // wrap if needed
+            wrap = me.fxWrap(r.pos, o, HIDDEN);
+            
+            st.visibility = VISIBLE;
+            st.position = ABSOLUTE;
+            
+        	// clear out temp styles after slide and unwrap
+        	function after(){
+                 el.fxUnwrap(wrap, r.pos, o);
+                 st.width = r.width;
+                 st.height = r.height;
+                 el.afterFx(o);
+            }
+            
+            // time to calculate the positions        
+        	pt = {to: [b.x, b.y]}; 
+        	bw = {to: b.width};
+        	bh = {to: b.height};
+            	
+			function argCalc(wrap, style, ww, wh, sXY, sXYval, s1, s2, w, h, p){	            	
+				var ret = {};
+            	wrap.setWidth(ww).setHeight(wh);
+            	if( wrap[sXY] )	wrap[sXY](sXYval);            		
+            	style[s1] = style[s2] = &quot;0&quot;;	            	
+            	if(w) ret.width = w;
+            	if(h) ret.height = h;
+            	if(p) ret.points = p;
+            	return ret;
+        	};
+
+            args = me.switchStatements(anchor.toLowerCase(), argCalc, {
+		            t  : [wrap, st, b.width, 0, NULL, NULL, LEFT, BOTTOM, NULL, bh, NULL],
+		            l  : [wrap, st, 0, b.height, NULL, NULL, RIGHT, TOP, bw, NULL, NULL],
+		            r  : [wrap, st, b.width, b.height, SETX, b.right, LEFT, TOP, NULL, NULL, pt],
+		            b  : [wrap, st, b.width, b.height, SETY, b.bottom, LEFT, TOP, NULL, bh, pt],
+		            tl : [wrap, st, 0, 0, NULL, NULL, RIGHT, BOTTOM, bw, bh, pt],
+		            bl : [wrap, st, 0, 0, SETY, b.y + b.height, RIGHT, TOP, bw, bh, pt],
+		            br : [wrap, st, 0, 0, SETXY, [b.right, b.bottom], LEFT, TOP, bw, bh, pt],
+		            tr : [wrap, st, 0, 0, SETX, b.x + b.width, LEFT, BOTTOM, bw, bh, pt]
+            	});
+            
+            st.visibility = VISIBLE;
+            wrap.show();
+
+            arguments.callee.anim = wrap.fxanim(args,
+                o,
+                MOTION,
+                .5,
+                EASEOUT, 
+                after);
+        });
+        return me;
+    },
+    
+	
+    slideOut : function(anchor, o){
+	    var me = this,
+	    	el = me.getFxEl(),
+	    	xy = me.getXY(),
+            dom = me.dom,
+	    	wrap,
+	    	st,
+	    	r,
+	    	b,
+	    	a,
+	    	zero = {to: 0}; 
+	    		    
+        o = o || {};
+        anchor = anchor || &quot;t&quot;;
+
+        el.queueFx(o, function(){
+	        // restore values after effect
+            r = me.getFxRestore(); 
+            b = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: dom.offsetWidth, height: dom.offsetHeight};
+            b.right = b.x + b.width;
+            b.bottom = b.y + b.height;
+            	
+            // fixed size for slide            
+            me.setWidth(b.width).setHeight(b.height);
+
+            // wrap if needed
+            wrap = me.fxWrap(r.pos, o, VISIBLE);
+           	st = me.dom.style;
+           		
+            st.visibility = VISIBLE;
+            st.position = ABSOLUTE;
+            wrap.setWidth(b.width).setHeight(b.height);            
+
+            function after(){
+	            o.useDisplay ? el.setDisplayed(FALSE) : el.hide();                
+                el.fxUnwrap(wrap, r.pos, o);
+                st.width = r.width;
+                st.height = r.height;
+                el.afterFx(o);
+            }            
+            
+            function argCalc(style, s1, s2, p1, v1, p2, v2, p3, v3){	            	
+	            var ret = {};
+	            
+            	style[s1] = style[s2] = &quot;0&quot;;
+            	ret[p1] = v1;            	
+            	if(p2) ret[p2] = v2;            	
+            	if(p3) ret[p3] = v3;
+            	
+            	return ret;
+       		};
+       		
+       		a = me.switchStatements(anchor.toLowerCase(), argCalc, {
+	            t  : [st, LEFT, BOTTOM, HEIGHT, zero],
+	            l  : [st, RIGHT, TOP, WIDTH, zero],
+	            r  : [st, LEFT, TOP, WIDTH, zero, POINTS, {to : [b.right, b.y]}],
+	            b  : [st, LEFT, TOP, HEIGHT, zero, POINTS, {to : [b.x, b.bottom]}],
+	            tl : [st, RIGHT, BOTTOM, WIDTH, zero, HEIGHT, zero],
+	            bl : [st, RIGHT, TOP, WIDTH, zero, HEIGHT, zero, POINTS, {to : [b.x, b.bottom]}],
+	            br : [st, LEFT, TOP, WIDTH, zero, HEIGHT, zero, POINTS, {to : [b.x + b.width, b.bottom]}],
+	            tr : [st, LEFT, BOTTOM, WIDTH, zero, HEIGHT, zero, POINTS, {to : [b.right, b.y]}]
+            });
+            
+            arguments.callee.anim = wrap.fxanim(a,
+                o,
+                MOTION,
+                .5,
+                EASEOUT, 
+                after);
+        });
+        return me;
+    },
+
+	
+    puff : function(o){
+	    o = o || {};
+	    
+        var me = this,
+        	el = me.getFxEl(),
+        	r, 
+        	st = me.dom.style,
+        	width = me.getWidth(),
+        	height = me.getHeight();        	        
+
+        el.queueFx(o, function(){	        
+            me.clearOpacity();
+            me.show();
+
+            // restore values after effect
+            r = me.getFxRestore();        	       	 
+        	
+            function after(){
+            	o.useDisplay ? el.setDisplayed(FALSE) : el.hide();	                
+                el.clearOpacity();	
+                el.setPositioning(r.pos);
+                st.width = r.width;
+                st.height = r.height;
+                st.fontSize = '';
+                el.afterFx(o);
+            }	
+
+            arguments.callee.anim = me.fxanim({
+                    width : {to : me.adjustWidth(width * 2)},
+                    height : {to : me.adjustHeight(height * 2)},
+                    points : {by : [-width * .5, -height * .5]},
+                    opacity : {to : 0},
+                    fontSize: {to : 200, unit: &quot;%&quot;}
+                },
+                o,
+                MOTION,
+                .5,
+                EASEOUT,
+                 after);
+        });
+        return me;
+    },
+
+	
+    switchOff : function(o){
+	    o = o || {};
+	    
+        var me = this,
+        	el = me.getFxEl();        
+
+        el.queueFx(o, function(){
+	        me.clearOpacity();
+            me.clip();
+
+            // restore values after effect
+            var r = me.getFxRestore(),
+            	st = me.dom.style,
+            	after = function(){
+	                o.useDisplay ? el.setDisplayed(FALSE) : el.hide();	
+	                el.clearOpacity();
+	                el.setPositioning(r.pos);
+	                st.width = r.width;
+	                st.height = r.height;	
+	                el.afterFx(o);
+	            };
+
+            me.fxanim({opacity : {to : 0.3}}, 
+            	NULL, 
+            	NULL, 
+            	.1, 
+            	NULL, 
+            	function(){	            		            
+	                me.clearOpacity();
+		                (function(){			                
+		                    me.fxanim({
+		                        height : {to : 1},
+		                        points : {by : [0, me.getHeight() * .5]}
+		                    }, 
+		                    o, 
+		                    MOTION, 
+		                    0.3, 
+		                    'easeIn', 
+		                    after);
+		                }).defer(100);
+	            });
+        });
+        return me;
+    },
+
+    	
+    highlight : function(color, o){
+	    o = o || {};
+	    
+        var me = this,
+        	el = me.getFxEl(),
+        	attr = o.attr || &quot;backgroundColor&quot;,
+        	a = {};
+
+        el.queueFx(o, function(){
+            me.clearOpacity();
+            me.show();
+
+            function after(){
+                el.dom.style[attr] = me.dom.style[attr];
+                el.afterFx(o);
+            }            
+            	
+            a[attr] = {from: color || &quot;ffff9c&quot;, to: o.endColor || me.getColor(attr) || &quot;ffffff&quot;};
+            arguments.callee.anim = me.fxanim(a,
+                o,
+                'color',
+                1,
+                'easeIn', 
+                after);
+        });
+        return me;
+    },
+
+   
+    frame : function(color, count, o){
+        var me = this,
+            el = me.getFxEl(),
+            proxy,
+            active;
+            
+        o = o || {};
+
+        el.queueFx(o, function(){
+            color = color || &quot;#C3DAF9&quot;
+            if(color.length == 6){
+                color = &quot;#&quot; + color;
+            }            
+            count = count || 1;
+            me.show();
+
+            var xy = me.getXY(),
+                dom = me.dom,
+                b = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: dom.offsetWidth, height: dom.offsetHeight},
+                proxy,
+                queue = function(){
+                    proxy = Ext.get(document.body || document.documentElement).createChild({
+                        style:{
+                            visbility: HIDDEN,
+                            position : ABSOLUTE,
+                            &quot;z-index&quot;: 35000, // yee haw
+                            border : &quot;0px solid &quot; + color
+                        }
+                    });
+                    return proxy.queueFx({}, animFn);
+                };
+            
+            
+            arguments.callee.anim = {
+                isAnimated: true,
+                stop: function() {
+                    count = 0;
+                    proxy.stopFx();
+                }
+            };
+            
+            function animFn(){
+                var scale = Ext.isBorderBox ? 2 : 1;
+                active = proxy.anim({
+                    top : {from : b.y, to : b.y - 20},
+                    left : {from : b.x, to : b.x - 20},
+                    borderWidth : {from : 0, to : 10},
+                    opacity : {from : 1, to : 0},
+                    height : {from : b.height, to : b.height + 20 * scale},
+                    width : {from : b.width, to : b.width + 20 * scale}
+                },{
+                    duration: o.duration || 1,
+                    callback: function() {
+                        proxy.remove();
+                        --count &gt; 0 ? queue() : el.afterFx(o);
+                    }
+                });
+                arguments.callee.anim = {
+                    isAnimated: true,
+                    stop: function(){
+                        active.stop();
+                    }
+                };
+            };
+            queue();
+        });
+        return me;
+    },
+
+   
+    pause : function(seconds){        
+        var el = this.getFxEl(),
+            t;
+
+        el.queueFx({}, function(){
+            t = setTimeout(function(){
+                el.afterFx({});
+            }, seconds * 1000);
+            arguments.callee.anim = {
+                isAnimated: true,
+                stop: function(){
+                    clearTimeout(t);
+                    el.afterFx({});
+                }
+            };
+        });
+        return this;
+    },
+
+   
+    fadeIn : function(o){
+        var me = this,
+        	el = me.getFxEl();        
+        o = o || {};
+        
+        el.queueFx(o, function(){	        
+            me.setOpacity(0);
+            me.fixDisplay();
+            me.dom.style.visibility = VISIBLE;
+            var to = o.endOpacity || 1;
+            arguments.callee.anim = me.fxanim({opacity:{to:to}},
+                o, NULL, .5, EASEOUT, function(){
+                if(to == 1){
+                    this.clearOpacity();
+                }
+                el.afterFx(o);
+            });
+        });
+        return me;
+    },
+
+   
+    fadeOut : function(o){
+	    o = o || {};
+	    
+        var me = this,
+        	style = me.dom.style,
+        	el = me.getFxEl(),
+        	to = o.endOpacity || 0;        	
+        
+        el.queueFx(o, function(){                       
+            arguments.callee.anim = me.fxanim({ 
+	            opacity : {to : to}},
+                o, 
+                NULL, 
+                .5, 
+                EASEOUT, 
+                function(){
+	                if(to == 0){
+		               me.visibilityMode == Ext.Element.DISPLAY || o.useDisplay ? 
+		                	style.display = &quot;none&quot; :
+		                	style.visibility = HIDDEN;
+		                	
+	                    me.clearOpacity();
+                	}
+                	el.afterFx(o);
+            });
+        });
+        return me;
+    },
+
+   
+    scale : function(w, h, o){
+	    var me = this;
+        me.shift(Ext.apply({}, o, {
+            width: w,
+            height: h
+        }));
+        return me;
+    },
+
+   
+    shift : function(o){
+	    var me = this;
+	    o = o || {};
+        
+	    var	el = me.getFxEl();       	
+        el.queueFx(o, function(){
+	        var a = {};	
+	        
+            for (var prop in o) {
+	            if (o[prop] != UNDEFINED) {		            			                    
+		            a[prop] = {to : o[prop]};	            	
+	            }
+            } 
+            
+         	a.width ? a.width.to = me.adjustWidth(o.width) : a;
+         	a.height ? a.height.to = me.adjustWidth(o.height) : a;   
+            
+            if (a.x || a.y || a.xy) {
+	            a.points = a.xy || 
+	            		   {to : [ a.x ? a.x.to : me.getX(),
+	            				   a.y ? a.y.to : me.getY()]};	            	
+            }
+
+            arguments.callee.anim = me.fxanim(a,
+                o, 
+                MOTION, 
+                .35, 
+                EASEOUT, 
+                function(){
+                	el.afterFx(o);
+            	});
+        });
+        return me;
+    },
+
+	
+    ghost : function(anchor, o){
+        var me = this,
+        	el = me.getFxEl();
+        	
+        o = o || {};
+        anchor = anchor || &quot;b&quot;;
+
+        el.queueFx(o, function(){
+            // restore values after effect
+            var r = me.getFxRestore(),
+            	w = me.getWidth(),
+                h = me.getHeight(),
+            	st = me.dom.style,
+            	after = function(){
+	                if(o.useDisplay){
+	                    el.setDisplayed(FALSE);
+	                }else{
+	                    el.hide();
+                	}
+                	
+	                el.clearOpacity();
+	                el.setPositioning(r.pos);
+	                st.width = r.width;
+	                st.width = r.width;
+	
+	                el.afterFx(o);
+	            },
+            	a = {opacity: {to: 0}, 
+            		 points: {}}, 
+            	pt = a.points;
+            	
+            	pt.by = me.switchStatements(anchor.toLowerCase(), function(v1,v2){ return [v1, v2];}, {
+	            	t  : [0, -h],
+	            	l  : [-w, 0],
+	            	r  : [w, 0],
+	            	b  : [0, h],
+	            	tl : [-w, -h],
+	            	bl : [-w, h],
+	            	br : [w, h],
+	            	tr : [w, -h]	
+            	});
+            	
+            arguments.callee.anim = me.fxanim(a,
+                o,
+                MOTION,
+                .5,
+                EASEOUT, after);
+        });
+        return me;
+    },
+
+	
+    syncFx : function(){
+	    var me = this;
+        me.fxDefaults = Ext.apply(me.fxDefaults || {}, {
+            block : FALSE,
+            concurrent : TRUE,
+            stopFx : FALSE
+        });
+        return me;
+    },
+
+	
+    sequenceFx : function(){
+	    var me = this;
+        me.fxDefaults = Ext.apply(me.fxDefaults || {}, {
+            block : FALSE,
+            concurrent : FALSE,
+            stopFx : FALSE
+        });
+        return me;
+    },
+
+	
+    nextFx : function(){	    
+        var ef = this.fxQueue[0];
+        if(ef){
+            ef.call(this);
+        }
+    },
+
+	
+    hasActiveFx : function(){	    
+        return this.fxQueue &amp;&amp; this.fxQueue[0];
+    },
+
+	
+    stopFx : function(finish){
+	    var me = this;
+        if(me.hasActiveFx()){
+            var cur = me.fxQueue[0];
+            if(cur &amp;&amp; cur.anim){
+                if(cur.anim.isAnimated){
+                    me.fxQueue = [cur]; // clear out others
+                    cur.anim.stop(finish !== undefined ? finish : TRUE);
+                }else{
+                    me.fxQueue = [];
+                }
+            }
+        }
+        return me;
+    },
+
+	
+    beforeFx : function(o){
+        if(this.hasActiveFx() &amp;&amp; !o.concurrent){
+           if(o.stopFx){
+               this.stopFx();
+               return TRUE;
+           }
+           return FALSE;
+        }
+        return TRUE;
+    },
+
+	
+    hasFxBlock : function(){
+        var q = this.fxQueue;
+        return q &amp;&amp; q[0] &amp;&amp; q[0].block;
+    },
+
+	
+    queueFx : function(o, fn){
+	    var me = this;
+        if(!me.fxQueue){
+            me.fxQueue = [];
+        }
+        if(!me.hasFxBlock()){
+            Ext.applyIf(o, me.fxDefaults);
+            if(!o.concurrent){
+                var run = me.beforeFx(o);
+                fn.block = o.block;
+                me.fxQueue.push(fn);
+                if(run){
+                    me.nextFx();
+                }
+            }else{
+                fn.call(me);
+            }
+        }
+        return me;
+    },
+
+	
+    fxWrap : function(pos, o, vis){	
+        var me = this,
+        	wrap,
+        	wrapXY;
+        if(!o.wrap || !(wrap = Ext.get(o.wrap))){            
+            if(o.fixPosition){
+                wrapXY = me.getXY();
+            }
+            var div = document.createElement(&quot;div&quot;);
+            div.style.visibility = vis;
+            wrap = Ext.get(me.dom.parentNode.insertBefore(div, me.dom));
+            wrap.setPositioning(pos);
+            if(wrap.isStyle(POSITION, &quot;static&quot;)){
+                wrap.position(&quot;relative&quot;);
+            }
+            me.clearPositioning('auto');
+            wrap.clip();
+            wrap.dom.appendChild(me.dom);
+            if(wrapXY){
+                wrap.setXY(wrapXY);
+            }
+        }
+        return wrap;
+    },
+
+	
+    fxUnwrap : function(wrap, pos, o){	    
+	    var me = this;
+        me.clearPositioning();
+        me.setPositioning(pos);
+        if(!o.wrap){
+            wrap.dom.parentNode.insertBefore(me.dom, wrap.dom);
+            wrap.remove();
+        }
+    },
+
+	
+    getFxRestore : function(){
+        var	st = this.dom.style;
+        return {pos: this.getPositioning(), width: st.width, height : st.height};
+    },
+
+	
+    afterFx : function(o){
+	    var me = this;
+        if(o.afterStyle){
+	        me.setStyle(o.afterStyle);            
+        }
+        if(o.afterCls){
+            me.addClass(o.afterCls);
+        }
+        if(o.remove == TRUE){
+            me.remove();
+        }
+        if(o.callback) o.callback.call(o.scope, me);
+        if(!o.concurrent){
+            me.fxQueue.shift();
+            me.nextFx();
+        }
+    },
+
+	
+    getFxEl : function(){ // support for composite element fx
+        return Ext.get(this.dom);
+    },
+
+	
+    fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
+        animType = animType || 'run';
+        opt = opt || {};
+        var anim = Ext.lib.Anim[animType](
+	            this.dom, 
+	            args,
+	            (opt.duration || defaultDur) || .35,
+	            (opt.easing || defaultEase) || EASEOUT,
+	            cb,	           
+	            this
+	        );
+        opt.anim = anim;
+        return anim;
+    }
+};
+
+// backwards compat
+Ext.Fx.resize = Ext.Fx.scale;
+
+//When included, Ext.Fx is automatically applied to Element so that all basic
+//effects are available directly via the Element API
+Ext.Element.addMethods(Ext.Fx);
+})();
 
 Ext.CompositeElementLite = function(els, root){
     this.elements = [];
@@ -5536,7 +5576,7 @@ Ext.Element.select = function(selector, unique, root){
     return new Ext.CompositeElementLite(els);
 };
 
-Ext.select = Ext.Element.select;
+Ext.select = Ext.Element.select;
 
 Ext.apply(Ext.CompositeElementLite.prototype, {	
 	addElements : function(els, root){
@@ -5583,8 +5623,8 @@ Ext.apply(Ext.CompositeElementLite.prototype, {
         });
         this.fill(els);
         return this;
-    },
-    
+    },
+    
     
     removeElement : function(keys, removeDom){
         var me = this,
@@ -5599,8 +5639,8 @@ Ext.apply(Ext.CompositeElementLite.prototype, {
 	    });
         return this;
     }    
-});
-
+});
+
 
 Ext.CompositeElement = function(els, root){
     this.elements = [];
@@ -5672,1382 +5712,1404 @@ Ext.Element.select = function(selector, unique, root){
     }
 
     return (unique === true) ? new Ext.CompositeElement(els) : new Ext.CompositeElementLite(els);
-};
-
-
-Ext.select = Ext.Element.select;
-(function(){
-	var BEFOREREQUEST = &quot;beforerequest&quot;,
-		REQUESTCOMPLETE = &quot;requestcomplete&quot;,
-		REQUESTEXCEPTION = &quot;requestexception&quot;,
-        UNDEFINED = undefined,
-		LOAD = 'load',
-		POST = 'POST',
-		GET = 'GET',
-		WINDOW = window;
-	
-	
-	Ext.data.Connection = function(config){	
-	    Ext.apply(this, config);
-	    this.addEvents(
-	        
-	        BEFOREREQUEST,
-	        
-	        REQUESTCOMPLETE,
-	        
-	        REQUESTEXCEPTION
-	    );
-	    Ext.data.Connection.superclass.constructor.call(this);
-	};
-
-	// private
-    function handleResponse(response){
-        this.transId = false;
-        var options = response.argument.options;
-        response.argument = options ? options.argument : null;
-        this.fireEvent(REQUESTCOMPLETE, this, response, options);
-        if(options.success) options.success.call(options.scope, response, options);
-        if(options.callback) options.callback.call(options.scope, options, true, response);
-    }
-
-    // private
-    function handleFailure(response, e){
-        this.transId = false;
-        var options = response.argument.options;
-        response.argument = options ? options.argument : null;
-        this.fireEvent(REQUESTEXCEPTION, this, response, options, e);
-        if(options.failure) options.failure.call(options.scope, response, options);
-        if(options.callback) options.callback.call(options.scope, options, false, response);
-    }
-
-	// private
-    function doFormUpload(o, ps, url){
-        var id = Ext.id(),
-        	doc = document,
-        	frame = doc.createElement('iframe'),
-        	form = Ext.getDom(o.form),
-        	hiddens = [],
-        	hd;
-        	
-        frame.id = frame.name = id;         
-        frame.className = 'x-hidden';        
-        frame.src = Ext.SSL_SECURE_URL; // for IE        
-        doc.body.appendChild(frame);
-
-        if(Ext.isIE){
-        	doc.frames[id].name = id;
-        }
-        
-        form.target = id;
-        form.method = POST;
-        form.enctype = form.encoding = 'multipart/form-data';        
-        form.action = url || &quot;&quot;;
-        
-        // add dynamic params            
-        ps = Ext.urlDecode(ps, false);
-        for(var k in ps){
-            if(ps.hasOwnProperty(k)){
-                hd = doc.createElement('input');
-                hd.type = 'hidden';                    
-                hd.value = ps[hd.name = k];
-                form.appendChild(hd);
-                hiddens.push(hd);
-            }
-        }        
-
-        function cb(){
-            var me = this,
-            	// bogus response object
-            	r = {responseText : '',
-	                 responseXML : null,
-	                 argument : o.argument},
-            	doc,
-            	firstChild;
-
-            try { 
-                doc = frame.contentWindow.document || frame.contentDocument || WINDOW.frames[id].document;
-                if (doc) {
-	            	if (doc.body) {
-		            	if (/textarea/i.test((firstChild = doc.body.firstChild || {}).tagName)) { // json response wrapped in textarea	                    
-                        	r.responseText = firstChild.value;
-	                    } else {
-	                        r.responseText = doc.body.innerHTML;
-	                    }
-	            	} else {
-		            	r.responseXML = doc.XMLDocument || doc;
-		           	}
-                }
-            }
-            catch(e) {}
-
-            Ext.EventManager.removeListener(frame, LOAD, cb, me);
-
-            me.fireEvent(REQUESTCOMPLETE, me, r, o);
-
-            Ext.callback(o.success, o.scope, [r, o]);
-            Ext.callback(o.callback, o.scope, [o, true, r]);
-
-            if(!me.debugUploads){
-                setTimeout(function(){Ext.removeNode(frame);}, 100);
-            }
-        }
-
-        Ext.EventManager.on(frame, LOAD, cb, this);
-        form.submit();
-        
-        Ext.each(hiddens, function(h) {
-	        Ext.removeNode(h);
-        });
-    }
-    	    
-	Ext.extend(Ext.data.Connection, Ext.util.Observable, {
-	    
-	    
-	    
-	    
-	    
-	    timeout : 30000,
-	    
-	    autoAbort:false,
-	
-	    
-	    disableCaching: true,
-	    
-	    
-	    disableCachingParam: '_dc',
-        
-	    
-	    request : function(o){
-		    var me = this;
-	        if(me.fireEvent(BEFOREREQUEST, me, o)){
-                if (o.el) {
-                    if(!Ext.isEmpty(o.indicatorText)){
-                        me.indicatorText = '&lt;div class=&quot;loading-indicator&quot;&gt;'+o.indicatorText+&quot;&lt;/div&gt;&quot;;
-                    }
-                    if(me.indicatorText) {
-                        Ext.getDom(o.el).innerHTML = me.indicatorText;                        
-                    }
-                    o.success = (Ext.isFunction(o.success) ? o.success : function(){}).createInterceptor(function(response) {
-                        Ext.getDom(o.el).innerHTML = response.responseText;
-                    });
-                }
-                
-	            var p = o.params,
-	            	url = o.url || me.url,            	
-	            	method,
-	            	cb = {success: handleResponse,
-		                  failure: handleFailure,
-		                  scope: me,
-		                  argument: {options: o},
-		                  timeout : o.timeout || me.timeout
-		            },
-		            form,		            
-		            serForm;		            
-		          
-		             
-	            if (Ext.isFunction(p)) {
-	                p = p.call(o.scope||WINDOW, o);
-	            }
-	            	               	                    
-	            p = Ext.urlEncode(me.extraParams, typeof p == 'object' ? Ext.urlEncode(p) : p);	
-	            
-	            if (Ext.isFunction(url)) {
-	                url = url.call(o.scope || WINDOW, o);
-	            }
-	
-	            if(form = Ext.getDom(o.form)){
-	                url = url || form.action;
- 	                if(o.isUpload || /multipart\/form-data/i.test(form.getAttribute(&quot;enctype&quot;))) { 
- 	                    return doFormUpload.call(me, o, p, url);
- 	                }
-	                serForm = Ext.lib.Ajax.serializeForm(form);	                
-	                p = p ? (p + '&amp;' + serForm) : serForm;
-	            }
-	            
-	            method = o.method || me.method || ((p || o.xmlData || o.jsonData) ? POST : GET);
-	            
-	            if(method == GET &amp;&amp; (me.disableCaching || o.disableCaching !== false)) {// || o.disableCaching === true){
-	                var dcp = o.disableCachingParam || me.disableCachingParam;
-	                url += (url.indexOf('?') != -1 ? '&amp;' : '?') + dcp + '=' + (new Date().getTime());
-	            }
-	            
-	            o.headers = Ext.apply(o.headers || {}, me.defaultHeaders || {});
-	            
-				if(o.autoAbort === true || me.autoAbort) {
-					me.abort();
-				}
-				 
-	            if((method == GET || o.xmlData || o.jsonData) &amp;&amp; p){
-	                url += (/\?/.test(url) ? '&amp;' : '?') + p;  
-	                p = '';
-	            }
-	            
-	            return me.transId = Ext.lib.Ajax.request(method, url, cb, p, o);
-	        }else{	            
-	            return o.callback ? o.callback.apply(o.scope, [o,UNDEFINED,UNDEFINED]) : null;
-	        }
-	    },
-	
-	    
-	    isLoading : function(transId){
-		    return transId ? Ext.lib.Ajax.isCallInProgress(transId) : !! this.transId;	        
-	    },
-	
-	    
-	    abort : function(transId){
-	        if(transId || this.isLoading()){
-	            Ext.lib.Ajax.abort(transId || this.transId);
-	        }
-	    }
-	});
-})();
-
-
-Ext.Ajax = new Ext.data.Connection({
-    
-    
-    
-    
-    
-    
-
-    
-
-    
-    
-    
-    
-    
-    
-
-    
-    autoAbort : false,
-
-    
-    serializeForm : function(form){
-        return Ext.lib.Ajax.serializeForm(form);
-    }
-});
-
-Ext.UpdateManager = Ext.Updater = Ext.extend(Ext.util.Observable, 
-function() {
-	var BEFOREUPDATE = &quot;beforeupdate&quot;,
-		UPDATE = &quot;update&quot;,
-		FAILURE = &quot;failure&quot;;
-		
-	// private
-    function processSuccess(response){	    
-	    var me = this;
-        me.transaction = null;
-        if (response.argument.form &amp;&amp; response.argument.reset) {
-            try { // put in try/catch since some older FF releases had problems with this
-                response.argument.form.reset();
-            } catch(e){}
-        }
-        if (me.loadScripts) {
-            me.renderer.render(me.el, response, me,
-               updateComplete.createDelegate(me, [response]));
-        } else {
-            me.renderer.render(me.el, response, me);
-            updateComplete.call(me, response);
-        }
-    }
-    
-    // private
-    function updateComplete(response, type, success){
-        this.fireEvent(type || UPDATE, this.el, response);
-        if(Ext.isFunction(response.argument.callback)){
-            response.argument.callback.call(response.argument.scope, this.el, Ext.isEmpty(success) ? true : false, response, response.argument.options);
-        }
-    }
-
-    // private
-    function processFailure(response){	            
-        updateComplete.call(this, response, FAILURE, !!(this.transaction = null));
-    }
-	    
-	return {
-	    constructor: function(el, forceNew){
-		    var me = this;
-	        el = Ext.get(el);
-	        if(!forceNew &amp;&amp; el.updateManager){
-	            return el.updateManager;
-	        }
-	        
-	        me.el = el;
-	        
-	        me.defaultUrl = null;
-	
-	        me.addEvents(
-	            
-	            BEFOREUPDATE,
-	            
-	            UPDATE,
-	            
-	            FAILURE
-	        );
-	
-	        Ext.apply(me, Ext.Updater.defaults);
-	        
-	        
-	        
-	        
-	        
-	        
-	
-	        
-	        me.transaction = null;
-	        
-	        me.refreshDelegate = me.refresh.createDelegate(me);
-	        
-	        me.updateDelegate = me.update.createDelegate(me);
-	        
-	        me.formUpdateDelegate = (me.formUpdate || function(){}).createDelegate(me);	
-	        
-			
-	        me.renderer = me.renderer || me.getDefaultRenderer();
-	        
-	        Ext.Updater.superclass.constructor.call(me);
-	    },
-        
-		
-	    setRenderer : function(renderer){
-	        this.renderer = renderer;
-	    },	
-        
-	    
-	    getRenderer : function(){
-	       return this.renderer;
-	    },
-
-	    
-	    getDefaultRenderer: function() {
-	        return new Ext.Updater.BasicRenderer();
-	    },
-                
-	    
-	    setDefaultUrl : function(defaultUrl){
-	        this.defaultUrl = defaultUrl;
-	    },
-        
-	    
-	    getEl : function(){
-	        return this.el;
-	    },
-	
-		
-	    update : function(url, params, callback, discardUrl){
-		    var me = this,
-		    	cfg, 
-		    	callerScope;
-		    	
-	        if(me.fireEvent(BEFOREUPDATE, me.el, url, params) !== false){	            
-	            if(Ext.isObject(url)){ // must be config object
-	                cfg = url;
-	                url = cfg.url;
-	                params = params || cfg.params;
-	                callback = callback || cfg.callback;
-	                discardUrl = discardUrl || cfg.discardUrl;
-	                callerScope = cfg.scope;	                
-	                if(!Ext.isEmpty(cfg.nocache)){me.disableCaching = cfg.nocache;};
-	                if(!Ext.isEmpty(cfg.text)){me.indicatorText = '&lt;div class=&quot;loading-indicator&quot;&gt;'+cfg.text+&quot;&lt;/div&gt;&quot;;};
-	                if(!Ext.isEmpty(cfg.scripts)){me.loadScripts = cfg.scripts;};
-	                if(!Ext.isEmpty(cfg.timeout)){me.timeout = cfg.timeout;};
-	            }
-	            me.showLoading();
-	
-	            if(!discardUrl){
-	                me.defaultUrl = url;
-	            }
-	            if(Ext.isFunction(url)){
-	                url = url.call(me);
-	            }
-	
-	            var o = Ext.apply({}, {
-	                url : url,
-	                params: (Ext.isFunction(params) &amp;&amp; callerScope) ? params.createDelegate(callerScope) : params,
-	                success: processSuccess,
-	                failure: processFailure,
-	                scope: me,
-	                callback: undefined,
-	                timeout: (me.timeout*1000),
-	                disableCaching: me.disableCaching,
-	                argument: {
-	                    &quot;options&quot;: cfg,
-	                    &quot;url&quot;: url,
-	                    &quot;form&quot;: null,
-	                    &quot;callback&quot;: callback,
-	                    &quot;scope&quot;: callerScope || window,
-	                    &quot;params&quot;: params
-	                }
-	            }, cfg);
-	
-	            me.transaction = Ext.Ajax.request(o);
-	        }
-	    },	    	
-
-		
-	    formUpdate : function(form, url, reset, callback){
-		    var me = this;
-	        if(me.fireEvent(BEFOREUPDATE, me.el, form, url) !== false){
-	            if(Ext.isFunction(url)){
-	                url = url.call(me);
-	            }
-	            form = Ext.getDom(form)
-	            me.transaction = Ext.Ajax.request({
-	                form: form,
-	                url:url,
-	                success: processSuccess,
-	                failure: processFailure,
-	                scope: me,
-	                timeout: (me.timeout*1000),
-	                argument: {
-	                    &quot;url&quot;: url,
-	                    &quot;form&quot;: form,
-	                    &quot;callback&quot;: callback,
-	                    &quot;reset&quot;: reset
-	                }
-	            });
-	            me.showLoading.defer(1, me);
-	        }
-	    },
-                	
-	    
-	    startAutoRefresh : function(interval, url, params, callback, refreshNow){
-		    var me = this;
-	        if(refreshNow){
-	            me.update(url || me.defaultUrl, params, callback, true);
-	        }
-	        if(me.autoRefreshProcId){
-	            clearInterval(me.autoRefreshProcId);
-	        }
-	        me.autoRefreshProcId = setInterval(me.update.createDelegate(me, [url || me.defaultUrl, params, callback, true]), interval * 1000);
-	    },
-	
-	    
-	    stopAutoRefresh : function(){
-	        if(this.autoRefreshProcId){
-	            clearInterval(this.autoRefreshProcId);
-	            delete this.autoRefreshProcId;
-	        }
-	    },
-	
-	    
-	    isAutoRefreshing : function(){
-	       return !!this.autoRefreshProcId;
-	    },
-	
-	    
-	    showLoading : function(){
-	        if(this.showLoadIndicator){
-            	this.el.dom.innerHTML = this.indicatorText;
-	        }
-	    },
-	
-	    
-	    abort : function(){
-	        if(this.transaction){
-	            Ext.Ajax.abort(this.transaction);
-	        }
-	    },
-	
-	    
-	    isUpdating : function(){        
-	    	return this.transaction ? Ext.Ajax.isLoading(this.transaction) : false;        
-	    },
-	    
-	    
-	    refresh : function(callback){
-	        if(this.defaultUrl){
-	        	this.update(this.defaultUrl, null, callback, true);
-	    	}
-	    }
-    }
-}());
-
-
-Ext.Updater.defaults = {
-   
-    timeout : 30,    
-    
-    disableCaching : false,
-    
-    showLoadIndicator : true,
-    
-    indicatorText : '&lt;div class=&quot;loading-indicator&quot;&gt;Loading...&lt;/div&gt;',
-     
-    loadScripts : false,
-    
-    sslBlankUrl : (Ext.SSL_SECURE_URL || &quot;javascript:false&quot;)      
-};
-
-
-
-Ext.Updater.updateElement = function(el, url, params, options){
-    var um = Ext.get(el).getUpdater();
-    Ext.apply(um, options);
-    um.update(url, params, options ? options.callback : null);
-};
-
-
-Ext.Updater.BasicRenderer = function(){};
-
-Ext.Updater.BasicRenderer.prototype = {
-    
-     render : function(el, response, updateManager, callback){	     
-        el.update(response.responseText, updateManager.loadScripts, callback);
-    }
-};
-
-
-
-
-(function() {
-
-// create private copy of Ext's String.format() method
-// - to remove unnecessary dependency
-// - to resolve namespace conflict with M$-Ajax's implementation
-function xf(format) {
-    var args = Array.prototype.slice.call(arguments, 1);
-    return format.replace(/\{(\d+)\}/g, function(m, i) {
-        return args[i];
-    });
-}
-
-
-// private
-Date.formatCodeToRegex = function(character, currentGroup) {
-    // Note: currentGroup - position in regex result array (see notes for Date.parseCodes below)
-    var p = Date.parseCodes[character];
-
-    if (p) {
-      p = typeof p == 'function'? p() : p;
-      Date.parseCodes[character] = p; // reassign function result to prevent repeated execution
-    }
-
-    return p? Ext.applyIf({
-      c: p.c? xf(p.c, currentGroup || &quot;{0}&quot;) : p.c
-    }, p) : {
-        g:0,
-        c:null,
-        s:Ext.escapeRe(character) // treat unrecognised characters as literals
-    }
-}
-
-// private shorthand for Date.formatCodeToRegex since we'll be using it fairly often
-var $f = Date.formatCodeToRegex;
-
-Ext.apply(Date, {
-    
-    parseFunctions: {
-        &quot;M$&quot;: function(input, strict) {
-            // note: the timezone offset is ignored since the M$ Ajax server sends 
-            // a UTC milliseconds-since-Unix-epoch value
-            var re = new RegExp('\\/Date\\((\\d+)(?:[+-]\\d{4})?\\)\\/');
-            var r = (input || '').match(re);
-            return r? new Date(r[1] * 1) : null;
-        }
-    },
-    parseRegexes: [],
-
-    
-    formatFunctions: {
-        &quot;M$&quot;: function() {
-            // UTC milliseconds since Unix epoch (M$-AJAX serialized date format (MRSF))
-            return '\\/Date(' + this.getTime() + ')\\/';
-        }
-    },
-    daysInMonth : [31,28,31,30,31,30,31,31,30,31,30,31],
-    y2kYear : 50,
-
-    
-    MILLI : &quot;ms&quot;,
-
-    
-    SECOND : &quot;s&quot;,
-
-    
-    MINUTE : &quot;mi&quot;,
-
-    
-    HOUR : &quot;h&quot;,
-
-    
-    DAY : &quot;d&quot;,
-
-    
-    MONTH : &quot;mo&quot;,
-
-    
-    YEAR : &quot;y&quot;,
-
-    
-    dayNames : [
-        &quot;Sunday&quot;,
-        &quot;Monday&quot;,
-        &quot;Tuesday&quot;,
-        &quot;Wednesday&quot;,
-        &quot;Thursday&quot;,
-        &quot;Friday&quot;,
-        &quot;Saturday&quot;
-    ],
-
-    
-    monthNames : [
-        &quot;January&quot;,
-        &quot;February&quot;,
-        &quot;March&quot;,
-        &quot;April&quot;,
-        &quot;May&quot;,
-        &quot;June&quot;,
-        &quot;July&quot;,
-        &quot;August&quot;,
-        &quot;September&quot;,
-        &quot;October&quot;,
-        &quot;November&quot;,
-        &quot;December&quot;
-    ],
-
-    
-    monthNumbers : {
-        Jan:0,
-        Feb:1,
-        Mar:2,
-        Apr:3,
-        May:4,
-        Jun:5,
-        Jul:6,
-        Aug:7,
-        Sep:8,
-        Oct:9,
-        Nov:10,
-        Dec:11
-    },
-
-    
-    getShortMonthName : function(month) {
-        return Date.monthNames[month].substring(0, 3);
-    },
-
-    
-    getShortDayName : function(day) {
-        return Date.dayNames[day].substring(0, 3);
-    },
-
-    
-    getMonthNumber : function(name) {
-        // handle camel casing for english month names (since the keys for the Date.monthNumbers hash are case sensitive)
-        return Date.monthNumbers[name.substring(0, 1).toUpperCase() + name.substring(1, 3).toLowerCase()];
-    },
-
-    
-    formatCodes : {
-        d: &quot;String.leftPad(this.getDate(), 2, '0')&quot;,
-        D: &quot;Date.getShortDayName(this.getDay())&quot;, // get localised short day name
-        j: &quot;this.getDate()&quot;,
-        l: &quot;Date.dayNames[this.getDay()]&quot;,
-        N: &quot;(this.getDay() ? this.getDay() : 7)&quot;,
-        S: &quot;this.getSuffix()&quot;,
-        w: &quot;this.getDay()&quot;,
-        z: &quot;this.getDayOfYear()&quot;,
-        W: &quot;String.leftPad(this.getWeekOfYear(), 2, '0')&quot;,
-        F: &quot;Date.monthNames[this.getMonth()]&quot;,
-        m: &quot;String.leftPad(this.getMonth() + 1, 2, '0')&quot;,
-        M: &quot;Date.getShortMonthName(this.getMonth())&quot;, // get localised short month name
-        n: &quot;(this.getMonth() + 1)&quot;,
-        t: &quot;this.getDaysInMonth()&quot;,
-        L: &quot;(this.isLeapYear() ? 1 : 0)&quot;,
-        o: &quot;(this.getFullYear() + (this.getWeekOfYear() == 1 &amp;&amp; this.getMonth() &gt; 0 ? +1 : (this.getWeekOfYear() &gt;= 52 &amp;&amp; this.getMonth() &lt; 11 ? -1 : 0)))&quot;,
-        Y: &quot;this.getFullYear()&quot;,
-        y: &quot;('' + this.getFullYear()).substring(2, 4)&quot;,
-        a: &quot;(this.getHours() &lt; 12 ? 'am' : 'pm')&quot;,
-        A: &quot;(this.getHours() &lt; 12 ? 'AM' : 'PM')&quot;,
-        g: &quot;((this.getHours() % 12) ? this.getHours() % 12 : 12)&quot;,
-        G: &quot;this.getHours()&quot;,
-        h: &quot;String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0')&quot;,
-        H: &quot;String.leftPad(this.getHours(), 2, '0')&quot;,
-        i: &quot;String.leftPad(this.getMinutes(), 2, '0')&quot;,
-        s: &quot;String.leftPad(this.getSeconds(), 2, '0')&quot;,
-        u: &quot;String.leftPad(this.getMilliseconds(), 3, '0')&quot;,
-        O: &quot;this.getGMTOffset()&quot;,
-        P: &quot;this.getGMTOffset(true)&quot;,
-        T: &quot;this.getTimezone()&quot;,
-        Z: &quot;(this.getTimezoneOffset() * -60)&quot;,
-        
-        c: function() { // ISO-8601 -- GMT format
-            for (var c = &quot;Y-m-dTH:i:sP&quot;, code = [], i = 0, l = c.length; i &lt; l; ++i) {
-                var e = c.charAt(i);
-                code.push(e == &quot;T&quot; ? &quot;'T'&quot; : Date.getFormatCode(e)); // treat T as a character literal
-            }
-            return code.join(&quot; + &quot;);
-        },
-        
-        
-        U: &quot;Math.round(this.getTime() / 1000)&quot;
-    },
-    
-    
-    isValid : function(y, m, d, h, i, s, ms) {
-        // setup defaults
-        h = h || 0;
-        i = i || 0;
-        s = s || 0;
-        ms = ms || 0;
-            
-        var dt = new Date(y, m - 1, d, h, i, s, ms);
-        
-        return y == dt.getFullYear() &amp;&amp;
-            m == dt.getMonth() + 1 &amp;&amp;
-            d == dt.getDate() &amp;&amp;
-            h == dt.getHours() &amp;&amp;
-            i == dt.getMinutes() &amp;&amp;
-            s == dt.getSeconds() &amp;&amp;
-            ms == dt.getMilliseconds();
-    },
-
-    
-    parseDate : function(input, format, strict) {
-        var p = Date.parseFunctions;
-        if (p[format] == null) {
-            Date.createParser(format);
-        }
-        return p[format](input, strict);
-    },
-
-    // private
-    getFormatCode : function(character) {
-        var f = Date.formatCodes[character];
-
-        if (f) {
-          f = typeof f == 'function'? f() : f;
-          Date.formatCodes[character] = f; // reassign function result to prevent repeated execution
-        }
-
-        // note: unknown characters are treated as literals
-        return f || (&quot;'&quot; + String.escape(character) + &quot;'&quot;);
-    },
-
-    // private
-    createFormat : function(format) {
-        var code = [],
-            special = false,
-            ch = '';
-
-        for (var i = 0; i &lt; format.length; ++i) {
-            ch = format.charAt(i);
-            if (!special &amp;&amp; ch == &quot;\\&quot;) {
-                special = true;
-            } else if (special) {
-                special = false;
-                code.push(&quot;'&quot; + String.escape(ch) + &quot;'&quot;);
-            } else {
-                code.push(Date.getFormatCode(ch))
-            }
-        }
-        Date.formatFunctions[format] = new Function(&quot;return &quot; + code.join('+'));
-    },
-
-    // private
-    createParser : function() {
-        var code = [
-            &quot;var dt, y, m, d, h, i, s, ms, o, z, zz, u, v,&quot;,
-                &quot;results = String(input).match(Date.parseRegexes[{0}]);&quot;, // either null, or an array of matched strings
-
-            &quot;if(results){&quot;,
-                &quot;{1}&quot;,
-
-                &quot;if(u != null){&quot;, // i.e. unix time is defined
-                    &quot;v = new Date(u * 1000);&quot;, // give top priority to UNIX time
-                &quot;}else{&quot;,
-                    // create Date object representing midnight of the current day;
-                    // this will provide us with our date defaults
-                    // (note: clearTime() handles Daylight Saving Time automatically)
-                    &quot;dt = (new Date()).clearTime();&quot;,
-                
-                    // date calculations
-                    &quot;y = y &gt;= 0? y : dt.getFullYear();&quot;,
-                    &quot;m = m &gt;= 0? m : dt.getMonth();&quot;,
-                    &quot;d = d || dt.getDate();&quot;,
-
-                    // time calculations (dt.getXXX() methods return DST-adjusted h / i / s / ms)
-                    &quot;h = h || dt.getHours()&quot;,
-                    &quot;i = i || dt.getMinutes();&quot;,
-                    &quot;s = s || dt.getSeconds();&quot;,
-                    &quot;ms = ms || dt.getMilliseconds();&quot;,
-                    
-                    &quot;if(z &gt;= 0 &amp;&amp; y &gt;= 0){&quot;,
-                        // both the year and zero-based day of year are defined and &gt;= 0.
-                        // these 2 values alone provide sufficient info to create a full date object
-
-                        // create Date object representing January 1st for the given year
-                        &quot;v = new Date(y, 0, 1, h, i, s, ms);&quot;,
-                        
-                        // then add day of year, checking for Date &quot;rollover&quot; if necessary
-                        &quot;v = !strict? v : (strict === true &amp;&amp; (z &lt;= 364 || (v.isLeapYear() &amp;&amp; z &lt;= 365))? v.add(Date.DAY, z) : null);&quot;,
-                    &quot;}else if(strict === true &amp;&amp; !Date.isValid(y, m + 1, d, h, i, s, ms)){&quot;, // check for Date &quot;rollover&quot;
-                        &quot;v = null;&quot;, // invalid date, so return null
-                    &quot;}else{&quot;,
-                        // plain old Date object
-                        &quot;v = new Date(y, m, d, h, i, s, ms);&quot;,
-                    &quot;}&quot;,
-                &quot;}&quot;,
-            &quot;}&quot;,
-
-            &quot;if(v){&quot;,
-                // favour UTC offset over GMT offset
-                &quot;if(zz != null){&quot;,
-                    // reset to UTC, then add offset
-                    &quot;v = v.add(Date.SECOND, -v.getTimezoneOffset() * 60 - zz);&quot;,
-                &quot;}else if(o){&quot;,
-                    // reset to GMT, then add offset
-                    &quot;v = v.add(Date.MINUTE, -v.getTimezoneOffset() + (sn == '+'? -1 : 1) * (hr * 60 + mn));&quot;,
-                &quot;}&quot;,
-            &quot;}&quot;,
-            
-            &quot;return v;&quot;
-        ].join('\n');
-
-        return function(format) {
-            var regexNum = Date.parseRegexes.length,
-                currentGroup = 1,
-                calc = [],
-                regex = [],
-                special = false,
-                ch = &quot;&quot;;
-
-            for (var i = 0; i &lt; format.length; ++i) {
-                ch = format.charAt(i);
-                if (!special &amp;&amp; ch == &quot;\\&quot;) {
-                    special = true;
-                } else if (special) {
-                    special = false;
-                    regex.push(String.escape(ch));
-                } else {
-                    var obj = $f(ch, currentGroup);
-                    currentGroup += obj.g;
-                    regex.push(obj.s);
-                    if (obj.g &amp;&amp; obj.c) {
-                        calc.push(obj.c);
-                    }
-                }
-            }
-
-            Date.parseRegexes[regexNum] = new RegExp(&quot;^&quot; + regex.join('') + &quot;$&quot;, &quot;i&quot;);
-            Date.parseFunctions[format] = new Function(&quot;input&quot;, &quot;strict&quot;, xf(code, regexNum, calc.join('')));
-        }
-    }(),
-
-    // private
-    parseCodes : {
-        
-        d: {
-            g:1,
-            c:&quot;d = parseInt(results[{0}], 10);\n&quot;,
-            s:&quot;(\\d{2})&quot; // day of month with leading zeroes (01 - 31)
-        },
-        j: {
-            g:1,
-            c:&quot;d = parseInt(results[{0}], 10);\n&quot;,
-            s:&quot;(\\d{1,2})&quot; // day of month without leading zeroes (1 - 31)
-        },
-        D: function() {
-            for (var a = [], i = 0; i &lt; 7; a.push(Date.getShortDayName(i)), ++i); // get localised short day names
-            return {
-                g:0,
-                c:null,
-                s:&quot;(?:&quot; + a.join(&quot;|&quot;) +&quot;)&quot;
-            }
-        },
-        l: function() {
-            return {
-                g:0,
-                c:null,
-                s:&quot;(?:&quot; + Date.dayNames.join(&quot;|&quot;) + &quot;)&quot;
-            }
-        },
-        N: {
-            g:0,
-            c:null,
-            s:&quot;[1-7]&quot; // ISO-8601 day number (1 (monday) - 7 (sunday))
-        },
-        S: {
-            g:0,
-            c:null,
-            s:&quot;(?:st|nd|rd|th)&quot;
-        },
-        w: {
-            g:0,
-            c:null,
-            s:&quot;[0-6]&quot; // javascript day number (0 (sunday) - 6 (saturday))
-        },
-        z: {
-            g:1,
-            c:&quot;z = parseInt(results[{0}], 10);\n&quot;,
-            s:&quot;(\\d{1,3})&quot; // day of the year (0 - 364 (365 in leap years))
-        },
-        W: {
-            g:0,
-            c:null,
-            s:&quot;(?:\\d{2})&quot; // ISO-8601 week number (with leading zero)
-        },
-        F: function() {
-            return {
-                g:1,
-                c:&quot;m = parseInt(Date.getMonthNumber(results[{0}]), 10);\n&quot;, // get localised month number
-                s:&quot;(&quot; + Date.monthNames.join(&quot;|&quot;) + &quot;)&quot;
-            }
-        },
-        M: function() {
-            for (var a = [], i = 0; i &lt; 12; a.push(Date.getShortMonthName(i)), ++i); // get localised short month names
-            return Ext.applyIf({
-                s:&quot;(&quot; + a.join(&quot;|&quot;) + &quot;)&quot;
-            }, $f(&quot;F&quot;));
-        },
-        m: {
-            g:1,
-            c:&quot;m = parseInt(results[{0}], 10) - 1;\n&quot;,
-            s:&quot;(\\d{2})&quot; // month number with leading zeros (01 - 12)
-        },
-        n: {
-            g:1,
-            c:&quot;m = parseInt(results[{0}], 10) - 1;\n&quot;,
-            s:&quot;(\\d{1,2})&quot; // month number without leading zeros (1 - 12)
-        },
-        t: {
-            g:0,
-            c:null,
-            s:&quot;(?:\\d{2})&quot; // no. of days in the month (28 - 31)
-        },
-        L: {
-            g:0,
-            c:null,
-            s:&quot;(?:1|0)&quot;
-        },
-        o: function() {
-            return $f(&quot;Y&quot;);
-        },
-        Y: {
-            g:1,
-            c:&quot;y = parseInt(results[{0}], 10);\n&quot;,
-            s:&quot;(\\d{4})&quot; // 4-digit year
-        },
-        y: {
-            g:1,
-            c:&quot;var ty = parseInt(results[{0}], 10);\n&quot;
-                + &quot;y = ty &gt; Date.y2kYear ? 1900 + ty : 2000 + ty;\n&quot;, // 2-digit year
-            s:&quot;(\\d{1,2})&quot;
-        },
-        a: {
-            g:1,
-            c:&quot;if (results[{0}] == 'am') {\n&quot;
-                + &quot;if (h == 12) { h = 0; }\n&quot;
-                + &quot;} else { if (h &lt; 12) { h += 12; }}&quot;,
-            s:&quot;(am|pm)&quot;
-        },
-        A: {
-            g:1,
-            c:&quot;if (results[{0}] == 'AM') {\n&quot;
-                + &quot;if (h == 12) { h = 0; }\n&quot;
-                + &quot;} else { if (h &lt; 12) { h += 12; }}&quot;,
-            s:&quot;(AM|PM)&quot;
-        },
-        g: function() {
-            return $f(&quot;G&quot;);
-        },
-        G: {
-            g:1,
-            c:&quot;h = parseInt(results[{0}], 10);\n&quot;,
-            s:&quot;(\\d{1,2})&quot; // 24-hr format of an hour without leading zeroes (0 - 23)
-        },
-        h: function() {
-            return $f(&quot;H&quot;);
-        },
-        H: {
-            g:1,
-            c:&quot;h = parseInt(results[{0}], 10);\n&quot;,
-            s:&quot;(\\d{2})&quot; //  24-hr format of an hour with leading zeroes (00 - 23)
-        },
-        i: {
-            g:1,
-            c:&quot;i = parseInt(results[{0}], 10);\n&quot;,
-            s:&quot;(\\d{2})&quot; // minutes with leading zeros (00 - 59)
-        },
-        s: {
-            g:1,
-            c:&quot;s = parseInt(results[{0}], 10);\n&quot;,
-            s:&quot;(\\d{2})&quot; // seconds with leading zeros (00 - 59)
-        },
-        u: {
-            g:1,
-            c:&quot;ms = results[{0}]; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n&quot;,
-            s:&quot;(\\d+)&quot; // decimal fraction of a second (minimum = 1 digit, maximum = unlimited)
-        },
-        O: {
-            g:1,
-            c:[
-                &quot;o = results[{0}];&quot;,
-                &quot;var sn = o.substring(0,1),&quot;, // get + / - sign
-                    &quot;hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60),&quot;, // get hours (performs minutes-to-hour conversion also, just in case)
-                    &quot;mn = o.substring(3,5) % 60;&quot;, // get minutes
-                &quot;o = ((-12 &lt;= (hr*60 + mn)/60) &amp;&amp; ((hr*60 + mn)/60 &lt;= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n&quot; // -12hrs &lt;= GMT offset &lt;= 14hrs
-            ].join(&quot;\n&quot;),
-            s: &quot;([+\-]\\d{4})&quot; // GMT offset in hrs and mins
-        },
-        P: {
-            g:1,
-            c:[
-                &quot;o = results[{0}];&quot;,
-                &quot;var sn = o.substring(0,1),&quot;, // get + / - sign
-                    &quot;hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60),&quot;, // get hours (performs minutes-to-hour conversion also, just in case)
-                    &quot;mn = o.substring(4,6) % 60;&quot;, // get minutes
-                &quot;o = ((-12 &lt;= (hr*60 + mn)/60) &amp;&amp; ((hr*60 + mn)/60 &lt;= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n&quot; // -12hrs &lt;= GMT offset &lt;= 14hrs
-            ].join(&quot;\n&quot;),
-            s: &quot;([+\-]\\d{2}:\\d{2})&quot; // GMT offset in hrs and mins (with colon separator)
-        },
-        T: {
-            g:0,
-            c:null,
-            s:&quot;[A-Z]{1,4}&quot; // timezone abbrev. may be between 1 - 4 chars
-        },
-        Z: {
-            g:1,
-            c:&quot;zz = results[{0}] * 1;\n&quot; // -43200 &lt;= UTC offset &lt;= 50400
-                  + &quot;zz = (-43200 &lt;= zz &amp;&amp; zz &lt;= 50400)? zz : null;\n&quot;,
-            s:&quot;([+\-]?\\d{1,5})&quot; // leading '+' sign is optional for UTC offset
-        },
-        c: function() {
-            var calc = [],
-                arr = [
-                    $f(&quot;Y&quot;, 1), // year
-                    $f(&quot;m&quot;, 2), // month
-                    $f(&quot;d&quot;, 3), // day
-                    $f(&quot;h&quot;, 4), // hour
-                    $f(&quot;i&quot;, 5), // minute
-                    $f(&quot;s&quot;, 6), // second
-                    {c:&quot;ms = results[7] || '0'; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n&quot;}, // decimal fraction of a second (minimum = 1 digit, maximum = unlimited)
-                    {c:[ // allow either &quot;Z&quot; (i.e. UTC) or &quot;-0530&quot; or &quot;+08:00&quot; (i.e. UTC offset) timezone delimiters. assumes local timezone if no timezone is specified
-                        &quot;if(results[8]) {&quot;, // timezone specified
-                            &quot;if(results[8] == 'Z'){&quot;,
-                                &quot;zz = 0;&quot;, // UTC
-                            &quot;}else if (results[8].indexOf(':') &gt; -1){&quot;,
-                                $f(&quot;P&quot;, 8).c, // timezone offset with colon separator
-                            &quot;}else{&quot;,
-                                $f(&quot;O&quot;, 8).c, // timezone offset without colon separator
-                            &quot;}&quot;,
-                        &quot;}&quot;
-                    ].join('\n')}
-                ];
-
-            for (var i = 0, l = arr.length; i &lt; l; ++i) {
-                calc.push(arr[i].c);
-            }
-
-            return {
-                g:1,
-                c:calc.join(&quot;&quot;),
-                s:[
-                    arr[0].s, // year (required)
-                    &quot;(?:&quot;, &quot;-&quot;, arr[1].s, // month (optional)
-                        &quot;(?:&quot;, &quot;-&quot;, arr[2].s, // day (optional)
-                            &quot;(?:&quot;,
-                                &quot;(?:T| )?&quot;, // time delimiter -- either a &quot;T&quot; or a single blank space
-                                arr[3].s, &quot;:&quot;, arr[4].s,  // hour AND minute, delimited by a single colon (optional). MUST be preceded by either a &quot;T&quot; or a single blank space
-                                &quot;(?::&quot;, arr[5].s, &quot;)?&quot;, // seconds (optional)
-                                &quot;(?:(?:\\.|,)(\\d+))?&quot;, // decimal fraction of a second (e.g. &quot;,12345&quot; or &quot;.98765&quot;) (optional)
-                                &quot;(Z|(?:[-+]\\d{2}(?::)?\\d{2}))?&quot;, // &quot;Z&quot; (UTC) or &quot;-0530&quot; (UTC offset without colon delimiter) or &quot;+08:00&quot; (UTC offset with colon delimiter) (optional)
-                            &quot;)?&quot;,
-                        &quot;)?&quot;,
-                    &quot;)?&quot;
-                ].join(&quot;&quot;)
-            }
-        },
-        U: {
-            g:1,
-            c:&quot;u = parseInt(results[{0}], 10);\n&quot;,
-            s:&quot;(-?\\d+)&quot; // leading minus sign indicates seconds before UNIX epoch
-        }
-    }
-});
-
-}());
-
-Ext.apply(Date.prototype, {
-    // private
-    dateFormat : function(format) {
-        if (Date.formatFunctions[format] == null) {
-            Date.createFormat(format);
-        }
-        return Date.formatFunctions[format].call(this);
-    },
-
-    
-    getTimezone : function() {
-        // the following list shows the differences between date strings from different browsers on a WinXP SP2 machine from an Asian locale:
-        //
-        // Opera  : &quot;Thu, 25 Oct 2007 22:53:45 GMT+0800&quot; -- shortest (weirdest) date string of the lot
-        // Safari : &quot;Thu Oct 25 2007 22:55:35 GMT+0800 (Malay Peninsula Standard Time)&quot; -- value in parentheses always gives the correct timezone (same as FF)
-        // FF     : &quot;Thu Oct 25 2007 22:55:35 GMT+0800 (Malay Peninsula Standard Time)&quot; -- value in parentheses always gives the correct timezone
-        // IE     : &quot;Thu Oct 25 22:54:35 UTC+0800 2007&quot; -- (Asian system setting) look for 3-4 letter timezone abbrev
-        // IE     : &quot;Thu Oct 25 17:06:37 PDT 2007&quot; -- (American system setting) look for 3-4 letter timezone abbrev
-        //
-        // this crazy regex attempts to guess the correct timezone abbreviation despite these differences.
-        // step 1: (?:\((.*)\) -- find timezone in parentheses
-        // step 2: ([A-Z]{1,4})(?:[\-+][0-9]{4})?(?: -?\d+)?) -- if nothing was found in step 1, find timezone from timezone offset portion of date string
-        // step 3: remove all non uppercase characters found in step 1 and 2
-        return this.toString().replace(/^.* (?:\((.*)\)|([A-Z]{1,4})(?:[\-+][0-9]{4})?(?: -?\d+)?)$/, &quot;$1$2&quot;).replace(/[^A-Z]/g, &quot;&quot;);
-    },
-
-    
-    getGMTOffset : function(colon) {
-        return (this.getTimezoneOffset() &gt; 0 ? &quot;-&quot; : &quot;+&quot;)
-            + String.leftPad(Math.floor(Math.abs(this.getTimezoneOffset()) / 60), 2, &quot;0&quot;)
-            + (colon ? &quot;:&quot; : &quot;&quot;)
-            + String.leftPad(Math.abs(this.getTimezoneOffset() % 60), 2, &quot;0&quot;);
-    },
-
-    
-    getDayOfYear : function() {
-        var num = 0;
-        Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
-        for (var i = 0; i &lt; this.getMonth(); ++i) {
-            num += Date.daysInMonth[i];
-        }
-        return num + this.getDate() - 1;
-    },
-
-    
-    getWeekOfYear : function() {
-        // adapted from http://www.merlyn.demon.co.uk/weekcalc.htm
-        var ms1d = 864e5, // milliseconds in a day
-            ms7d = 7 * ms1d; // milliseconds in a week
-
-        return function() { // return a closure so constants get calculated only once
-            var DC3 = Date.UTC(this.getFullYear(), this.getMonth(), this.getDate() + 3) / ms1d, // an Absolute Day Number
-                AWN = Math.floor(DC3 / 7), // an Absolute Week Number
-                Wyr = new Date(AWN * ms7d).getUTCFullYear();
-
-            return AWN - Math.floor(Date.UTC(Wyr, 0, 7) / ms7d) + 1;
-        }
-    }(),
-
-    
-    isLeapYear : function() {
-        var year = this.getFullYear();
-        return !!((year &amp; 3) == 0 &amp;&amp; (year % 100 || (year % 400 == 0 &amp;&amp; year)));
-    },
-
-    
-    getFirstDayOfMonth : function() {
-        var day = (this.getDay() - (this.getDate() - 1)) % 7;
-        return (day &lt; 0) ? (day + 7) : day;
-    },
-
-    
-    getLastDayOfMonth : function() {
-        var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
-        return (day &lt; 0) ? (day + 7) : day;
-    },
-
-
-    
-    getFirstDateOfMonth : function() {
-        return new Date(this.getFullYear(), this.getMonth(), 1);
-    },
-
-    
-    getLastDateOfMonth : function() {
-        return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
-    },
-
-    
-    getDaysInMonth : function() {
-        Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
-        return Date.daysInMonth[this.getMonth()];
-    },
-
-    
-    getSuffix : function() {
-        switch (this.getDate()) {
-            case 1:
-            case 21:
-            case 31:
-                return &quot;st&quot;;
-            case 2:
-            case 22:
-                return &quot;nd&quot;;
-            case 3:
-            case 23:
-                return &quot;rd&quot;;
-            default:
-                return &quot;th&quot;;
-        }
-    },
-
-    
-    clone : function() {
-        return new Date(this.getTime());
-    },
-
-    
-    isDST : function() {
-        // adapted from http://extjs.com/forum/showthread.php?p=247172#post247172
-        // courtesy of @geoffrey.mcgill
-        return new Date(this.getFullYear(), 0, 1).getTimezoneOffset() != this.getTimezoneOffset();
-    },
-
-    
-    clearTime : function(clone) {
-        if (clone) {
-            return this.clone().clearTime();
-        }
-        
-        // get current date before clearing time
-        var d = this.getDate();
-
-        // clear time
-        this.setHours(0);
-        this.setMinutes(0);
-        this.setSeconds(0);
-        this.setMilliseconds(0);
-
-        if (this.getDate() != d) { // account for DST (i.e. day of month changed when setting hour = 0)
-            // note: DST adjustments are assumed to occur in multiples of 1 hour (this is almost always the case) 
-            // refer to http://www.timeanddate.com/time/aboutdst.html for the (rare) exceptions to this rule
-            
-            // increment hour until cloned date == current date
-            for (var hr = 1, c = this.add(Date.HOUR, hr); c.getDate() != d; hr++, c = this.add(Date.HOUR, hr));
-            
-            this.setDate(d);
-            this.setHours(c.getHours());
-        }
-
-        return this;
-    },
-
-    
-    add : function(interval, value) {
-        var d = this.clone();
-        if (!interval || value === 0) return d;
-
-        switch(interval.toLowerCase()) {
-            case Date.MILLI:
-                d.setMilliseconds(this.getMilliseconds() + value);
-                break;
-            case Date.SECOND:
-                d.setSeconds(this.getSeconds() + value);
-                break;
-            case Date.MINUTE:
-                d.setMinutes(this.getMinutes() + value);
-                break;
-            case Date.HOUR:
-                d.setHours(this.getHours() + value);
-                break;
-            case Date.DAY:
-                d.setDate(this.getDate() + value);
-                break;
-            case Date.MONTH:
-                var day = this.getDate();
-                if (day &gt; 28) {
-                    day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
-                }
-                d.setDate(day);
-                d.setMonth(this.getMonth() + value);
-                break;
-            case Date.YEAR:
-                d.setFullYear(this.getFullYear() + value);
-                break;
-        }
-        return d;
-    },
-
-    
-    between : function(start, end) {
-        var t = this.getTime();
-        return start.getTime() &lt;= t &amp;&amp; t &lt;= end.getTime();
-    }
-});
-
-
-
-Date.prototype.format = Date.prototype.dateFormat;
-
-
-// private
-if (Ext.isSafari &amp;&amp; (navigator.userAgent.match(/WebKit\/(\d+)/)[1] || NaN) &lt; 420) {
-    Ext.apply(Date.prototype, {
-        _xMonth : Date.prototype.setMonth,
-        _xDate  : Date.prototype.setDate,
-        
-        // Bug in Safari 1.3, 2.0 (WebKit build &lt; 420)
-        // Date.setMonth does not work consistently if iMonth is not 0-11
-        setMonth : function(num) {
-            if (num &lt;= -1) {
-                var n = Math.ceil(-num),
-                    back_year = Math.ceil(n / 12),
-                    month = (n % 12) ? 12 - n % 12 : 0;
-
-                this.setFullYear(this.getFullYear() - back_year);
-
-                return this._xMonth(month);
-            } else {
-                return this._xMonth(num);
-            }
-        },
-
-        // Bug in setDate() method (resolved in WebKit build 419.3, so to be safe we target Webkit builds &lt; 420)
-        // The parameter for Date.setDate() is converted to a signed byte integer in Safari
-        // http://brianary.blogspot.com/2006/03/safari-date-bug.html
-        setDate : function(d) {
-            // use setTime() to workaround setDate() bug
-            // subtract current day of month in milliseconds, then add desired day of month in milliseconds
-            return this.setTime(this.getTime() - (this.getDate() - d) * 864e5);
-        }
-    });
-}
-
-
-
-
-
-
-Ext.util.DelayedTask = function(fn, scope, args){
-    var me = this,
-    	NULL = null,
-    	id = NULL, 
-    	_delay, 
-    	_time,    	    	
-    	call = function(){
-	        var now = new Date().getTime();
-	        if(now - _time &gt;= _delay){
-	            clearInterval(id);
-	            id = NULL;
-	            fn.apply(scope, args || []);
-	        }
-	    };
-	    
-    
-    me.delay = function(delay, newFn, newScope, newArgs){
-        if(id &amp;&amp; delay != _delay){
-            this.cancel();
-        }
-        _delay = delay;
-        _time = new Date().getTime();
-        fn = newFn || fn;
-        scope = newScope || scope;
-        args = newArgs || args;
-        if(!id){
-            id = setInterval(call, _delay);
-        }
-    };
-
-    
-    me.cancel = function(){
-        if(id){
-            clearInterval(id);
-            id = NULL;
-        }
-    };
-};
+};
+
+
+Ext.select = Ext.Element.select;
+
+Ext.handleError = function(e) {
+    throw e;
+};
+
+
+Ext.Error = function(message) {
+    // Try to read the message from Ext.Error.lang
+    this.message = (this.lang[message]) ? this.lang[message] : message;
+}
+Ext.Error.prototype = new Error();
+Ext.apply(Ext.Error.prototype, {
+    // protected.  Extensions place their error-strings here.
+    lang: {},
+
+    name: 'Ext.Error',
+    
+    getName : function() {
+        return this.name;
+    },
+    
+    getMessage : function() {
+        return this.message;
+    },
+    
+    toJson : function() {
+        return Ext.encode(this);
+    }
+});
+
+
+(function(){
+    var BEFOREREQUEST = &quot;beforerequest&quot;,
+        REQUESTCOMPLETE = &quot;requestcomplete&quot;,
+        REQUESTEXCEPTION = &quot;requestexception&quot;,
+        UNDEFINED = undefined,
+        LOAD = 'load',
+        POST = 'POST',
+        GET = 'GET',
+        WINDOW = window;
+    
+    
+    Ext.data.Connection = function(config){    
+        Ext.apply(this, config);
+        this.addEvents(
+            
+            BEFOREREQUEST,
+            
+            REQUESTCOMPLETE,
+            
+            REQUESTEXCEPTION
+        );
+        Ext.data.Connection.superclass.constructor.call(this);
+    };
+
+    // private
+    function handleResponse(response){
+        this.transId = false;
+        var options = response.argument.options;
+        response.argument = options ? options.argument : null;
+        this.fireEvent(REQUESTCOMPLETE, this, response, options);
+        if(options.success) options.success.call(options.scope, response, options);
+        if(options.callback) options.callback.call(options.scope, options, true, response);
+    }
+
+    // private
+    function handleFailure(response, e){
+        this.transId = false;
+        var options = response.argument.options;
+        response.argument = options ? options.argument : null;
+        this.fireEvent(REQUESTEXCEPTION, this, response, options, e);
+        if(options.failure) options.failure.call(options.scope, response, options);
+        if(options.callback) options.callback.call(options.scope, options, false, response);
+    }
+
+    // private
+    function doFormUpload(o, ps, url){
+        var id = Ext.id(),
+            doc = document,
+            frame = doc.createElement('iframe'),
+            form = Ext.getDom(o.form),
+            hiddens = [],
+            hd;
+            
+        frame.id = frame.name = id;         
+        frame.className = 'x-hidden';        
+        frame.src = Ext.SSL_SECURE_URL; // for IE        
+        doc.body.appendChild(frame);
+
+        if(Ext.isIE){
+            doc.frames[id].name = id;
+        }
+        
+        form.target = id;
+        form.method = POST;
+        form.enctype = form.encoding = 'multipart/form-data';        
+        form.action = url || &quot;&quot;;
+        
+        // add dynamic params            
+        ps = Ext.urlDecode(ps, false);
+        for(var k in ps){
+            if(ps.hasOwnProperty(k)){
+                hd = doc.createElement('input');
+                hd.type = 'hidden';                    
+                hd.value = ps[hd.name = k];
+                form.appendChild(hd);
+                hiddens.push(hd);
+            }
+        }        
+
+        function cb(){
+            var me = this,
+                // bogus response object
+                r = {responseText : '',
+                     responseXML : null,
+                     argument : o.argument},
+                doc,
+                firstChild;
+
+            try { 
+                doc = frame.contentWindow.document || frame.contentDocument || WINDOW.frames[id].document;
+                if (doc) {
+                    if (doc.body) {
+                        if (/textarea/i.test((firstChild = doc.body.firstChild || {}).tagName)) { // json response wrapped in textarea                        
+                            r.responseText = firstChild.value;
+                        } else {
+                            r.responseText = doc.body.innerHTML;
+                        }
+                    } else {
+                        r.responseXML = doc.XMLDocument || doc;
+                       }
+                }
+            }
+            catch(e) {}
+
+            Ext.EventManager.removeListener(frame, LOAD, cb, me);
+
+            me.fireEvent(REQUESTCOMPLETE, me, r, o);
+
+            Ext.callback(o.success, o.scope, [r, o]);
+            Ext.callback(o.callback, o.scope, [o, true, r]);
+
+            if(!me.debugUploads){
+                setTimeout(function(){Ext.removeNode(frame);}, 100);
+            }
+        }
+
+        Ext.EventManager.on(frame, LOAD, cb, this);
+        form.submit();
+        
+        Ext.each(hiddens, function(h) {
+            Ext.removeNode(h);
+        });
+    }
+
+    Ext.extend(Ext.data.Connection, Ext.util.Observable, {
+        
+        
+        
+        
+        
+        timeout : 30000,
+        
+        autoAbort:false,
+    
+        
+        disableCaching: true,
+        
+        
+        disableCachingParam: '_dc',
+        
+        
+        request : function(o){
+            var me = this;
+            if(me.fireEvent(BEFOREREQUEST, me, o)){
+                if (o.el) {
+                    if(!Ext.isEmpty(o.indicatorText)){
+                        me.indicatorText = '&lt;div class=&quot;loading-indicator&quot;&gt;'+o.indicatorText+&quot;&lt;/div&gt;&quot;;
+                    }
+                    if(me.indicatorText) {
+                        Ext.getDom(o.el).innerHTML = me.indicatorText;                        
+                    }
+                    o.success = (Ext.isFunction(o.success) ? o.success : function(){}).createInterceptor(function(response) {
+                        Ext.getDom(o.el).innerHTML = response.responseText;
+                    });
+                }
+                
+                var p = o.params,
+                    url = o.url || me.url,                
+                    method,
+                    cb = {success: handleResponse,
+                          failure: handleFailure,
+                          scope: me,
+                          argument: {options: o},
+                          timeout : o.timeout || me.timeout
+                    },
+                    form,                    
+                    serForm;                    
+                  
+                     
+                if (Ext.isFunction(p)) {
+                    p = p.call(o.scope||WINDOW, o);
+                }
+                                                           
+                p = Ext.urlEncode(me.extraParams, typeof p == 'object' ? Ext.urlEncode(p) : p);    
+                
+                if (Ext.isFunction(url)) {
+                    url = url.call(o.scope || WINDOW, o);
+                }
+    
+                if(form = Ext.getDom(o.form)){
+                    url = url || form.action;
+                     if(o.isUpload || /multipart\/form-data/i.test(form.getAttribute(&quot;enctype&quot;))) { 
+                         return doFormUpload.call(me, o, p, url);
+                     }
+                    serForm = Ext.lib.Ajax.serializeForm(form);                    
+                    p = p ? (p + '&amp;' + serForm) : serForm;
+                }
+                
+                method = o.method || me.method || ((p || o.xmlData || o.jsonData) ? POST : GET);
+                
+                if(method === GET &amp;&amp; (me.disableCaching &amp;&amp; o.disableCaching !== false) || o.disableCaching === true){
+                    var dcp = o.disableCachingParam || me.disableCachingParam;
+                    url += (url.indexOf('?') != -1 ? '&amp;' : '?') + dcp + '=' + (new Date().getTime());
+                }
+                
+                o.headers = Ext.apply(o.headers || {}, me.defaultHeaders || {});
+                
+                if(o.autoAbort === true || me.autoAbort) {
+                    me.abort();
+                }
+                 
+                if((method == GET || o.xmlData || o.jsonData) &amp;&amp; p){
+                    url += (/\?/.test(url) ? '&amp;' : '?') + p;  
+                    p = '';
+                }
+                return me.transId = Ext.lib.Ajax.request(method, url, cb, p, o);
+            }else{                
+                return o.callback ? o.callback.apply(o.scope, [o,UNDEFINED,UNDEFINED]) : null;
+            }
+        },
+    
+        
+        isLoading : function(transId){
+            return transId ? Ext.lib.Ajax.isCallInProgress(transId) : !! this.transId;            
+        },
+    
+        
+        abort : function(transId){
+            if(transId || this.isLoading()){
+                Ext.lib.Ajax.abort(transId || this.transId);
+            }
+        }
+    });
+})();
+
+
+Ext.Ajax = new Ext.data.Connection({
+    
+    
+    
+    
+    
+    
+
+    
+
+    
+    
+    
+    
+    
+    
+
+    
+    autoAbort : false,
+
+    
+    serializeForm : function(form){
+        return Ext.lib.Ajax.serializeForm(form);
+    }
+});
+
+
+Ext.UpdateManager = Ext.Updater = Ext.extend(Ext.util.Observable, 
+function() {
+	var BEFOREUPDATE = &quot;beforeupdate&quot;,
+		UPDATE = &quot;update&quot;,
+		FAILURE = &quot;failure&quot;;
+		
+	// private
+    function processSuccess(response){	    
+	    var me = this;
+        me.transaction = null;
+        if (response.argument.form &amp;&amp; response.argument.reset) {
+            try { // put in try/catch since some older FF releases had problems with this
+                response.argument.form.reset();
+            } catch(e){}
+        }
+        if (me.loadScripts) {
+            me.renderer.render(me.el, response, me,
+               updateComplete.createDelegate(me, [response]));
+        } else {
+            me.renderer.render(me.el, response, me);
+            updateComplete.call(me, response);
+        }
+    }
+    
+    // private
+    function updateComplete(response, type, success){
+        this.fireEvent(type || UPDATE, this.el, response);
+        if(Ext.isFunction(response.argument.callback)){
+            response.argument.callback.call(response.argument.scope, this.el, Ext.isEmpty(success) ? true : false, response, response.argument.options);
+        }
+    }
+
+    // private
+    function processFailure(response){	            
+        updateComplete.call(this, response, FAILURE, !!(this.transaction = null));
+    }
+	    
+	return {
+	    constructor: function(el, forceNew){
+		    var me = this;
+	        el = Ext.get(el);
+	        if(!forceNew &amp;&amp; el.updateManager){
+	            return el.updateManager;
+	        }
+	        
+	        me.el = el;
+	        
+	        me.defaultUrl = null;
+	
+	        me.addEvents(
+	            
+	            BEFOREUPDATE,
+	            
+	            UPDATE,
+	            
+	            FAILURE
+	        );
+	
+	        Ext.apply(me, Ext.Updater.defaults);
+	        
+	        
+	        
+	        
+	        
+	        
+	
+	        
+	        me.transaction = null;
+	        
+	        me.refreshDelegate = me.refresh.createDelegate(me);
+	        
+	        me.updateDelegate = me.update.createDelegate(me);
+	        
+	        me.formUpdateDelegate = (me.formUpdate || function(){}).createDelegate(me);	
+	        
+			
+	        me.renderer = me.renderer || me.getDefaultRenderer();
+	        
+	        Ext.Updater.superclass.constructor.call(me);
+	    },
+        
+		
+	    setRenderer : function(renderer){
+	        this.renderer = renderer;
+	    },	
+        
+	    
+	    getRenderer : function(){
+	       return this.renderer;
+	    },
+
+	    
+	    getDefaultRenderer: function() {
+	        return new Ext.Updater.BasicRenderer();
+	    },
+                
+	    
+	    setDefaultUrl : function(defaultUrl){
+	        this.defaultUrl = defaultUrl;
+	    },
+        
+	    
+	    getEl : function(){
+	        return this.el;
+	    },
+	
+		
+	    update : function(url, params, callback, discardUrl){
+		    var me = this,
+		    	cfg, 
+		    	callerScope;
+		    	
+	        if(me.fireEvent(BEFOREUPDATE, me.el, url, params) !== false){	            
+	            if(Ext.isObject(url)){ // must be config object
+	                cfg = url;
+	                url = cfg.url;
+	                params = params || cfg.params;
+	                callback = callback || cfg.callback;
+	                discardUrl = discardUrl || cfg.discardUrl;
+	                callerScope = cfg.scope;	                
+	                if(!Ext.isEmpty(cfg.nocache)){me.disableCaching = cfg.nocache;};
+	                if(!Ext.isEmpty(cfg.text)){me.indicatorText = '&lt;div class=&quot;loading-indicator&quot;&gt;'+cfg.text+&quot;&lt;/div&gt;&quot;;};
+	                if(!Ext.isEmpty(cfg.scripts)){me.loadScripts = cfg.scripts;};
+	                if(!Ext.isEmpty(cfg.timeout)){me.timeout = cfg.timeout;};
+	            }
+	            me.showLoading();
+	
+	            if(!discardUrl){
+	                me.defaultUrl = url;
+	            }
+	            if(Ext.isFunction(url)){
+	                url = url.call(me);
+	            }
+	
+	            var o = Ext.apply({}, {
+	                url : url,
+	                params: (Ext.isFunction(params) &amp;&amp; callerScope) ? params.createDelegate(callerScope) : params,
+	                success: processSuccess,
+	                failure: processFailure,
+	                scope: me,
+	                callback: undefined,
+	                timeout: (me.timeout*1000),
+	                disableCaching: me.disableCaching,
+	                argument: {
+	                    &quot;options&quot;: cfg,
+	                    &quot;url&quot;: url,
+	                    &quot;form&quot;: null,
+	                    &quot;callback&quot;: callback,
+	                    &quot;scope&quot;: callerScope || window,
+	                    &quot;params&quot;: params
+	                }
+	            }, cfg);
+	
+	            me.transaction = Ext.Ajax.request(o);
+	        }
+	    },	    	
+
+		
+	    formUpdate : function(form, url, reset, callback){
+		    var me = this;
+	        if(me.fireEvent(BEFOREUPDATE, me.el, form, url) !== false){
+	            if(Ext.isFunction(url)){
+	                url = url.call(me);
+	            }
+	            form = Ext.getDom(form)
+	            me.transaction = Ext.Ajax.request({
+	                form: form,
+	                url:url,
+	                success: processSuccess,
+	                failure: processFailure,
+	                scope: me,
+	                timeout: (me.timeout*1000),
+	                argument: {
+	                    &quot;url&quot;: url,
+	                    &quot;form&quot;: form,
+	                    &quot;callback&quot;: callback,
+	                    &quot;reset&quot;: reset
+	                }
+	            });
+	            me.showLoading.defer(1, me);
+	        }
+	    },
+                	
+	    
+	    startAutoRefresh : function(interval, url, params, callback, refreshNow){
+		    var me = this;
+	        if(refreshNow){
+	            me.update(url || me.defaultUrl, params, callback, true);
+	        }
+	        if(me.autoRefreshProcId){
+	            clearInterval(me.autoRefreshProcId);
+	        }
+	        me.autoRefreshProcId = setInterval(me.update.createDelegate(me, [url || me.defaultUrl, params, callback, true]), interval * 1000);
+	    },
+	
+	    
+	    stopAutoRefresh : function(){
+	        if(this.autoRefreshProcId){
+	            clearInterval(this.autoRefreshProcId);
+	            delete this.autoRefreshProcId;
+	        }
+	    },
+	
+	    
+	    isAutoRefreshing : function(){
+	       return !!this.autoRefreshProcId;
+	    },
+	
+	    
+	    showLoading : function(){
+	        if(this.showLoadIndicator){
+            	this.el.dom.innerHTML = this.indicatorText;
+	        }
+	    },
+	
+	    
+	    abort : function(){
+	        if(this.transaction){
+	            Ext.Ajax.abort(this.transaction);
+	        }
+	    },
+	
+	    
+	    isUpdating : function(){        
+	    	return this.transaction ? Ext.Ajax.isLoading(this.transaction) : false;        
+	    },
+	    
+	    
+	    refresh : function(callback){
+	        if(this.defaultUrl){
+	        	this.update(this.defaultUrl, null, callback, true);
+	    	}
+	    }
+    }
+}());
+
+
+Ext.Updater.defaults = {
+   
+    timeout : 30,    
+    
+    disableCaching : false,
+    
+    showLoadIndicator : true,
+    
+    indicatorText : '&lt;div class=&quot;loading-indicator&quot;&gt;Loading...&lt;/div&gt;',
+     
+    loadScripts : false,
+    
+    sslBlankUrl : (Ext.SSL_SECURE_URL || &quot;javascript:false&quot;)      
+};
+
+
+
+Ext.Updater.updateElement = function(el, url, params, options){
+    var um = Ext.get(el).getUpdater();
+    Ext.apply(um, options);
+    um.update(url, params, options ? options.callback : null);
+};
+
+
+Ext.Updater.BasicRenderer = function(){};
+
+Ext.Updater.BasicRenderer.prototype = {
+    
+     render : function(el, response, updateManager, callback){	     
+        el.update(response.responseText, updateManager.loadScripts, callback);
+    }
+};
+
+
+
+
+(function() {
+
+// create private copy of Ext's String.format() method
+// - to remove unnecessary dependency
+// - to resolve namespace conflict with M$-Ajax's implementation
+function xf(format) {
+    var args = Array.prototype.slice.call(arguments, 1);
+    return format.replace(/\{(\d+)\}/g, function(m, i) {
+        return args[i];
+    });
+}
+
+
+// private
+Date.formatCodeToRegex = function(character, currentGroup) {
+    // Note: currentGroup - position in regex result array (see notes for Date.parseCodes below)
+    var p = Date.parseCodes[character];
+
+    if (p) {
+      p = typeof p == 'function'? p() : p;
+      Date.parseCodes[character] = p; // reassign function result to prevent repeated execution
+    }
+
+    return p? Ext.applyIf({
+      c: p.c? xf(p.c, currentGroup || &quot;{0}&quot;) : p.c
+    }, p) : {
+        g:0,
+        c:null,
+        s:Ext.escapeRe(character) // treat unrecognised characters as literals
+    }
+}
+
+// private shorthand for Date.formatCodeToRegex since we'll be using it fairly often
+var $f = Date.formatCodeToRegex;
+
+Ext.apply(Date, {
+    
+    parseFunctions: {
+        &quot;M$&quot;: function(input, strict) {
+            // note: the timezone offset is ignored since the M$ Ajax server sends
+            // a UTC milliseconds-since-Unix-epoch value
+            var re = new RegExp('\\/Date\\((\\d+)(?:[+-]\\d{4})?\\)\\/');
+            var r = (input || '').match(re);
+            return r? new Date(r[1] * 1) : null;
+        }
+    },
+    parseRegexes: [],
+
+    
+    formatFunctions: {
+        &quot;M$&quot;: function() {
+            // UTC milliseconds since Unix epoch (M$-AJAX serialized date format (MRSF))
+            return '\\/Date(' + this.getTime() + ')\\/';
+        }
+    },
+    daysInMonth : [31,28,31,30,31,30,31,31,30,31,30,31],
+    y2kYear : 50,
+
+    
+    MILLI : &quot;ms&quot;,
+
+    
+    SECOND : &quot;s&quot;,
+
+    
+    MINUTE : &quot;mi&quot;,
+
+    
+    HOUR : &quot;h&quot;,
+
+    
+    DAY : &quot;d&quot;,
+
+    
+    MONTH : &quot;mo&quot;,
+
+    
+    YEAR : &quot;y&quot;,
+
+    
+    defaults: {},
+
+    
+    dayNames : [
+        &quot;Sunday&quot;,
+        &quot;Monday&quot;,
+        &quot;Tuesday&quot;,
+        &quot;Wednesday&quot;,
+        &quot;Thursday&quot;,
+        &quot;Friday&quot;,
+        &quot;Saturday&quot;
+    ],
+
+    
+    monthNames : [
+        &quot;January&quot;,
+        &quot;February&quot;,
+        &quot;March&quot;,
+        &quot;April&quot;,
+        &quot;May&quot;,
+        &quot;June&quot;,
+        &quot;July&quot;,
+        &quot;August&quot;,
+        &quot;September&quot;,
+        &quot;October&quot;,
+        &quot;November&quot;,
+        &quot;December&quot;
+    ],
+
+    
+    monthNumbers : {
+        Jan:0,
+        Feb:1,
+        Mar:2,
+        Apr:3,
+        May:4,
+        Jun:5,
+        Jul:6,
+        Aug:7,
+        Sep:8,
+        Oct:9,
+        Nov:10,
+        Dec:11
+    },
+
+    
+    getShortMonthName : function(month) {
+        return Date.monthNames[month].substring(0, 3);
+    },
+
+    
+    getShortDayName : function(day) {
+        return Date.dayNames[day].substring(0, 3);
+    },
+
+    
+    getMonthNumber : function(name) {
+        // handle camel casing for english month names (since the keys for the Date.monthNumbers hash are case sensitive)
+        return Date.monthNumbers[name.substring(0, 1).toUpperCase() + name.substring(1, 3).toLowerCase()];
+    },
+
+    
+    formatCodes : {
+        d: &quot;String.leftPad(this.getDate(), 2, '0')&quot;,
+        D: &quot;Date.getShortDayName(this.getDay())&quot;, // get localised short day name
+        j: &quot;this.getDate()&quot;,
+        l: &quot;Date.dayNames[this.getDay()]&quot;,
+        N: &quot;(this.getDay() ? this.getDay() : 7)&quot;,
+        S: &quot;this.getSuffix()&quot;,
+        w: &quot;this.getDay()&quot;,
+        z: &quot;this.getDayOfYear()&quot;,
+        W: &quot;String.leftPad(this.getWeekOfYear(), 2, '0')&quot;,
+        F: &quot;Date.monthNames[this.getMonth()]&quot;,
+        m: &quot;String.leftPad(this.getMonth() + 1, 2, '0')&quot;,
+        M: &quot;Date.getShortMonthName(this.getMonth())&quot;, // get localised short month name
+        n: &quot;(this.getMonth() + 1)&quot;,
+        t: &quot;this.getDaysInMonth()&quot;,
+        L: &quot;(this.isLeapYear() ? 1 : 0)&quot;,
+        o: &quot;(this.getFullYear() + (this.getWeekOfYear() == 1 &amp;&amp; this.getMonth() &gt; 0 ? +1 : (this.getWeekOfYear() &gt;= 52 &amp;&amp; this.getMonth() &lt; 11 ? -1 : 0)))&quot;,
+        Y: &quot;this.getFullYear()&quot;,
+        y: &quot;('' + this.getFullYear()).substring(2, 4)&quot;,
+        a: &quot;(this.getHours() &lt; 12 ? 'am' : 'pm')&quot;,
+        A: &quot;(this.getHours() &lt; 12 ? 'AM' : 'PM')&quot;,
+        g: &quot;((this.getHours() % 12) ? this.getHours() % 12 : 12)&quot;,
+        G: &quot;this.getHours()&quot;,
+        h: &quot;String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0')&quot;,
+        H: &quot;String.leftPad(this.getHours(), 2, '0')&quot;,
+        i: &quot;String.leftPad(this.getMinutes(), 2, '0')&quot;,
+        s: &quot;String.leftPad(this.getSeconds(), 2, '0')&quot;,
+        u: &quot;String.leftPad(this.getMilliseconds(), 3, '0')&quot;,
+        O: &quot;this.getGMTOffset()&quot;,
+        P: &quot;this.getGMTOffset(true)&quot;,
+        T: &quot;this.getTimezone()&quot;,
+        Z: &quot;(this.getTimezoneOffset() * -60)&quot;,
+
+        c: function() { // ISO-8601 -- GMT format
+            for (var c = &quot;Y-m-dTH:i:sP&quot;, code = [], i = 0, l = c.length; i &lt; l; ++i) {
+                var e = c.charAt(i);
+                code.push(e == &quot;T&quot; ? &quot;'T'&quot; : Date.getFormatCode(e)); // treat T as a character literal
+            }
+            return code.join(&quot; + &quot;);
+        },
+        
+
+        U: &quot;Math.round(this.getTime() / 1000)&quot;
+    },
+
+    
+    isValid : function(y, m, d, h, i, s, ms) {
+        // setup defaults
+        h = h || 0;
+        i = i || 0;
+        s = s || 0;
+        ms = ms || 0;
+
+        var dt = new Date(y, m - 1, d, h, i, s, ms);
+
+        return y == dt.getFullYear() &amp;&amp;
+            m == dt.getMonth() + 1 &amp;&amp;
+            d == dt.getDate() &amp;&amp;
+            h == dt.getHours() &amp;&amp;
+            i == dt.getMinutes() &amp;&amp;
+            s == dt.getSeconds() &amp;&amp;
+            ms == dt.getMilliseconds();
+    },
+
+    
+    parseDate : function(input, format, strict) {
+        var p = Date.parseFunctions;
+        if (p[format] == null) {
+            Date.createParser(format);
+        }
+        return p[format](input, strict);
+    },
+
+    // private
+    getFormatCode : function(character) {
+        var f = Date.formatCodes[character];
+
+        if (f) {
+          f = typeof f == 'function'? f() : f;
+          Date.formatCodes[character] = f; // reassign function result to prevent repeated execution
+        }
+
+        // note: unknown characters are treated as literals
+        return f || (&quot;'&quot; + String.escape(character) + &quot;'&quot;);
+    },
+
+    // private
+    createFormat : function(format) {
+        var code = [],
+            special = false,
+            ch = '';
+
+        for (var i = 0; i &lt; format.length; ++i) {
+            ch = format.charAt(i);
+            if (!special &amp;&amp; ch == &quot;\\&quot;) {
+                special = true;
+            } else if (special) {
+                special = false;
+                code.push(&quot;'&quot; + String.escape(ch) + &quot;'&quot;);
+            } else {
+                code.push(Date.getFormatCode(ch))
+            }
+        }
+        Date.formatFunctions[format] = new Function(&quot;return &quot; + code.join('+'));
+    },
+
+    // private
+    createParser : function() {
+        var code = [
+            &quot;var dt, y, m, d, h, i, s, ms, o, z, zz, u, v,&quot;,
+                &quot;def = Date.defaults,&quot;,
+                &quot;results = String(input).match(Date.parseRegexes[{0}]);&quot;, // either null, or an array of matched strings
+
+            &quot;if(results){&quot;,
+                &quot;{1}&quot;,
+
+                &quot;if(u != null){&quot;, // i.e. unix time is defined
+                    &quot;v = new Date(u * 1000);&quot;, // give top priority to UNIX time
+                &quot;}else{&quot;,
+                    // create Date object representing midnight of the current day;
+                    // this will provide us with our date defaults
+                    // (note: clearTime() handles Daylight Saving Time automatically)
+                    &quot;dt = (new Date()).clearTime();&quot;,
+
+                    // date calculations (note: these calculations create a dependency on Ext.num())
+                    &quot;y = y &gt;= 0? y : Ext.num(def.y, dt.getFullYear());&quot;,
+                    &quot;m = m &gt;= 0? m : Ext.num(def.m - 1, dt.getMonth());&quot;,
+                    &quot;d = d || Ext.num(def.d, dt.getDate());&quot;,
+
+                    // time calculations (note: these calculations create a dependency on Ext.num())
+                    &quot;h  = h || Ext.num(def.h, dt.getHours());&quot;,
+                    &quot;i  = i || Ext.num(def.i, dt.getMinutes());&quot;,
+                    &quot;s  = s || Ext.num(def.s, dt.getSeconds());&quot;,
+                    &quot;ms = ms || Ext.num(def.ms, dt.getMilliseconds());&quot;,
+
+                    &quot;if(z &gt;= 0 &amp;&amp; y &gt;= 0){&quot;,
+                        // both the year and zero-based day of year are defined and &gt;= 0.
+                        // these 2 values alone provide sufficient info to create a full date object
+
+                        // create Date object representing January 1st for the given year
+                        &quot;v = new Date(y, 0, 1, h, i, s, ms);&quot;,
+
+                        // then add day of year, checking for Date &quot;rollover&quot; if necessary
+                        &quot;v = !strict? v : (strict === true &amp;&amp; (z &lt;= 364 || (v.isLeapYear() &amp;&amp; z &lt;= 365))? v.add(Date.DAY, z) : null);&quot;,
+                    &quot;}else if(strict === true &amp;&amp; !Date.isValid(y, m + 1, d, h, i, s, ms)){&quot;, // check for Date &quot;rollover&quot;
+                        &quot;v = null;&quot;, // invalid date, so return null
+                    &quot;}else{&quot;,
+                        // plain old Date object
+                        &quot;v = new Date(y, m, d, h, i, s, ms);&quot;,
+                    &quot;}&quot;,
+                &quot;}&quot;,
+            &quot;}&quot;,
+
+            &quot;if(v){&quot;,
+                // favour UTC offset over GMT offset
+                &quot;if(zz != null){&quot;,
+                    // reset to UTC, then add offset
+                    &quot;v = v.add(Date.SECOND, -v.getTimezoneOffset() * 60 - zz);&quot;,
+                &quot;}else if(o){&quot;,
+                    // reset to GMT, then add offset
+                    &quot;v = v.add(Date.MINUTE, -v.getTimezoneOffset() + (sn == '+'? -1 : 1) * (hr * 60 + mn));&quot;,
+                &quot;}&quot;,
+            &quot;}&quot;,
+
+            &quot;return v;&quot;
+        ].join('\n');
+
+        return function(format) {
+            var regexNum = Date.parseRegexes.length,
+                currentGroup = 1,
+                calc = [],
+                regex = [],
+                special = false,
+                ch = &quot;&quot;;
+
+            for (var i = 0; i &lt; format.length; ++i) {
+                ch = format.charAt(i);
+                if (!special &amp;&amp; ch == &quot;\\&quot;) {
+                    special = true;
+                } else if (special) {
+                    special = false;
+                    regex.push(String.escape(ch));
+                } else {
+                    var obj = $f(ch, currentGroup);
+                    currentGroup += obj.g;
+                    regex.push(obj.s);
+                    if (obj.g &amp;&amp; obj.c) {
+                        calc.push(obj.c);
+                    }
+                }
+            }
+
+            Date.parseRegexes[regexNum] = new RegExp(&quot;^&quot; + regex.join('') + &quot;$&quot;, &quot;i&quot;);
+            Date.parseFunctions[format] = new Function(&quot;input&quot;, &quot;strict&quot;, xf(code, regexNum, calc.join('')));
+        }
+    }(),
+
+    // private
+    parseCodes : {
+        
+        d: {
+            g:1,
+            c:&quot;d = parseInt(results[{0}], 10);\n&quot;,
+            s:&quot;(\\d{2})&quot; // day of month with leading zeroes (01 - 31)
+        },
+        j: {
+            g:1,
+            c:&quot;d = parseInt(results[{0}], 10);\n&quot;,
+            s:&quot;(\\d{1,2})&quot; // day of month without leading zeroes (1 - 31)
+        },
+        D: function() {
+            for (var a = [], i = 0; i &lt; 7; a.push(Date.getShortDayName(i)), ++i); // get localised short day names
+            return {
+                g:0,
+                c:null,
+                s:&quot;(?:&quot; + a.join(&quot;|&quot;) +&quot;)&quot;
+            }
+        },
+        l: function() {
+            return {
+                g:0,
+                c:null,
+                s:&quot;(?:&quot; + Date.dayNames.join(&quot;|&quot;) + &quot;)&quot;
+            }
+        },
+        N: {
+            g:0,
+            c:null,
+            s:&quot;[1-7]&quot; // ISO-8601 day number (1 (monday) - 7 (sunday))
+        },
+        S: {
+            g:0,
+            c:null,
+            s:&quot;(?:st|nd|rd|th)&quot;
+        },
+        w: {
+            g:0,
+            c:null,
+            s:&quot;[0-6]&quot; // javascript day number (0 (sunday) - 6 (saturday))
+        },
+        z: {
+            g:1,
+            c:&quot;z = parseInt(results[{0}], 10);\n&quot;,
+            s:&quot;(\\d{1,3})&quot; // day of the year (0 - 364 (365 in leap years))
+        },
+        W: {
+            g:0,
+            c:null,
+            s:&quot;(?:\\d{2})&quot; // ISO-8601 week number (with leading zero)
+        },
+        F: function() {
+            return {
+                g:1,
+                c:&quot;m = parseInt(Date.getMonthNumber(results[{0}]), 10);\n&quot;, // get localised month number
+                s:&quot;(&quot; + Date.monthNames.join(&quot;|&quot;) + &quot;)&quot;
+            }
+        },
+        M: function() {
+            for (var a = [], i = 0; i &lt; 12; a.push(Date.getShortMonthName(i)), ++i); // get localised short month names
+            return Ext.applyIf({
+                s:&quot;(&quot; + a.join(&quot;|&quot;) + &quot;)&quot;
+            }, $f(&quot;F&quot;));
+        },
+        m: {
+            g:1,
+            c:&quot;m = parseInt(results[{0}], 10) - 1;\n&quot;,
+            s:&quot;(\\d{2})&quot; // month number with leading zeros (01 - 12)
+        },
+        n: {
+            g:1,
+            c:&quot;m = parseInt(results[{0}], 10) - 1;\n&quot;,
+            s:&quot;(\\d{1,2})&quot; // month number without leading zeros (1 - 12)
+        },
+        t: {
+            g:0,
+            c:null,
+            s:&quot;(?:\\d{2})&quot; // no. of days in the month (28 - 31)
+        },
+        L: {
+            g:0,
+            c:null,
+            s:&quot;(?:1|0)&quot;
+        },
+        o: function() {
+            return $f(&quot;Y&quot;);
+        },
+        Y: {
+            g:1,
+            c:&quot;y = parseInt(results[{0}], 10);\n&quot;,
+            s:&quot;(\\d{4})&quot; // 4-digit year
+        },
+        y: {
+            g:1,
+            c:&quot;var ty = parseInt(results[{0}], 10);\n&quot;
+                + &quot;y = ty &gt; Date.y2kYear ? 1900 + ty : 2000 + ty;\n&quot;, // 2-digit year
+            s:&quot;(\\d{1,2})&quot;
+        },
+        a: {
+            g:1,
+            c:&quot;if (results[{0}] == 'am') {\n&quot;
+                + &quot;if (h == 12) { h = 0; }\n&quot;
+                + &quot;} else { if (h &lt; 12) { h += 12; }}&quot;,
+            s:&quot;(am|pm)&quot;
+        },
+        A: {
+            g:1,
+            c:&quot;if (results[{0}] == 'AM') {\n&quot;
+                + &quot;if (h == 12) { h = 0; }\n&quot;
+                + &quot;} else { if (h &lt; 12) { h += 12; }}&quot;,
+            s:&quot;(AM|PM)&quot;
+        },
+        g: function() {
+            return $f(&quot;G&quot;);
+        },
+        G: {
+            g:1,
+            c:&quot;h = parseInt(results[{0}], 10);\n&quot;,
+            s:&quot;(\\d{1,2})&quot; // 24-hr format of an hour without leading zeroes (0 - 23)
+        },
+        h: function() {
+            return $f(&quot;H&quot;);
+        },
+        H: {
+            g:1,
+            c:&quot;h = parseInt(results[{0}], 10);\n&quot;,
+            s:&quot;(\\d{2})&quot; //  24-hr format of an hour with leading zeroes (00 - 23)
+        },
+        i: {
+            g:1,
+            c:&quot;i = parseInt(results[{0}], 10);\n&quot;,
+            s:&quot;(\\d{2})&quot; // minutes with leading zeros (00 - 59)
+        },
+        s: {
+            g:1,
+            c:&quot;s = parseInt(results[{0}], 10);\n&quot;,
+            s:&quot;(\\d{2})&quot; // seconds with leading zeros (00 - 59)
+        },
+        u: {
+            g:1,
+            c:&quot;ms = results[{0}]; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n&quot;,
+            s:&quot;(\\d+)&quot; // decimal fraction of a second (minimum = 1 digit, maximum = unlimited)
+        },
+        O: {
+            g:1,
+            c:[
+                &quot;o = results[{0}];&quot;,
+                &quot;var sn = o.substring(0,1),&quot;, // get + / - sign
+                    &quot;hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60),&quot;, // get hours (performs minutes-to-hour conversion also, just in case)
+                    &quot;mn = o.substring(3,5) % 60;&quot;, // get minutes
+                &quot;o = ((-12 &lt;= (hr*60 + mn)/60) &amp;&amp; ((hr*60 + mn)/60 &lt;= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n&quot; // -12hrs &lt;= GMT offset &lt;= 14hrs
+            ].join(&quot;\n&quot;),
+            s: &quot;([+\-]\\d{4})&quot; // GMT offset in hrs and mins
+        },
+        P: {
+            g:1,
+            c:[
+                &quot;o = results[{0}];&quot;,
+                &quot;var sn = o.substring(0,1),&quot;, // get + / - sign
+                    &quot;hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60),&quot;, // get hours (performs minutes-to-hour conversion also, just in case)
+                    &quot;mn = o.substring(4,6) % 60;&quot;, // get minutes
+                &quot;o = ((-12 &lt;= (hr*60 + mn)/60) &amp;&amp; ((hr*60 + mn)/60 &lt;= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n&quot; // -12hrs &lt;= GMT offset &lt;= 14hrs
+            ].join(&quot;\n&quot;),
+            s: &quot;([+\-]\\d{2}:\\d{2})&quot; // GMT offset in hrs and mins (with colon separator)
+        },
+        T: {
+            g:0,
+            c:null,
+            s:&quot;[A-Z]{1,4}&quot; // timezone abbrev. may be between 1 - 4 chars
+        },
+        Z: {
+            g:1,
+            c:&quot;zz = results[{0}] * 1;\n&quot; // -43200 &lt;= UTC offset &lt;= 50400
+                  + &quot;zz = (-43200 &lt;= zz &amp;&amp; zz &lt;= 50400)? zz : null;\n&quot;,
+            s:&quot;([+\-]?\\d{1,5})&quot; // leading '+' sign is optional for UTC offset
+        },
+        c: function() {
+            var calc = [],
+                arr = [
+                    $f(&quot;Y&quot;, 1), // year
+                    $f(&quot;m&quot;, 2), // month
+                    $f(&quot;d&quot;, 3), // day
+                    $f(&quot;h&quot;, 4), // hour
+                    $f(&quot;i&quot;, 5), // minute
+                    $f(&quot;s&quot;, 6), // second
+                    {c:&quot;ms = results[7] || '0'; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n&quot;}, // decimal fraction of a second (minimum = 1 digit, maximum = unlimited)
+                    {c:[ // allow either &quot;Z&quot; (i.e. UTC) or &quot;-0530&quot; or &quot;+08:00&quot; (i.e. UTC offset) timezone delimiters. assumes local timezone if no timezone is specified
+                        &quot;if(results[8]) {&quot;, // timezone specified
+                            &quot;if(results[8] == 'Z'){&quot;,
+                                &quot;zz = 0;&quot;, // UTC
+                            &quot;}else if (results[8].indexOf(':') &gt; -1){&quot;,
+                                $f(&quot;P&quot;, 8).c, // timezone offset with colon separator
+                            &quot;}else{&quot;,
+                                $f(&quot;O&quot;, 8).c, // timezone offset without colon separator
+                            &quot;}&quot;,
+                        &quot;}&quot;
+                    ].join('\n')}
+                ];
+
+            for (var i = 0, l = arr.length; i &lt; l; ++i) {
+                calc.push(arr[i].c);
+            }
+
+            return {
+                g:1,
+                c:calc.join(&quot;&quot;),
+                s:[
+                    arr[0].s, // year (required)
+                    &quot;(?:&quot;, &quot;-&quot;, arr[1].s, // month (optional)
+                        &quot;(?:&quot;, &quot;-&quot;, arr[2].s, // day (optional)
+                            &quot;(?:&quot;,
+                                &quot;(?:T| )?&quot;, // time delimiter -- either a &quot;T&quot; or a single blank space
+                                arr[3].s, &quot;:&quot;, arr[4].s,  // hour AND minute, delimited by a single colon (optional). MUST be preceded by either a &quot;T&quot; or a single blank space
+                                &quot;(?::&quot;, arr[5].s, &quot;)?&quot;, // seconds (optional)
+                                &quot;(?:(?:\\.|,)(\\d+))?&quot;, // decimal fraction of a second (e.g. &quot;,12345&quot; or &quot;.98765&quot;) (optional)
+                                &quot;(Z|(?:[-+]\\d{2}(?::)?\\d{2}))?&quot;, // &quot;Z&quot; (UTC) or &quot;-0530&quot; (UTC offset without colon delimiter) or &quot;+08:00&quot; (UTC offset with colon delimiter) (optional)
+                            &quot;)?&quot;,
+                        &quot;)?&quot;,
+                    &quot;)?&quot;
+                ].join(&quot;&quot;)
+            }
+        },
+        U: {
+            g:1,
+            c:&quot;u = parseInt(results[{0}], 10);\n&quot;,
+            s:&quot;(-?\\d+)&quot; // leading minus sign indicates seconds before UNIX epoch
+        }
+    }
+});
+
+}());
+
+Ext.apply(Date.prototype, {
+    // private
+    dateFormat : function(format) {
+        if (Date.formatFunctions[format] == null) {
+            Date.createFormat(format);
+        }
+        return Date.formatFunctions[format].call(this);
+    },
+
+    
+    getTimezone : function() {
+        // the following list shows the differences between date strings from different browsers on a WinXP SP2 machine from an Asian locale:
+        //
+        // Opera  : &quot;Thu, 25 Oct 2007 22:53:45 GMT+0800&quot; -- shortest (weirdest) date string of the lot
+        // Safari : &quot;Thu Oct 25 2007 22:55:35 GMT+0800 (Malay Peninsula Standard Time)&quot; -- value in parentheses always gives the correct timezone (same as FF)
+        // FF     : &quot;Thu Oct 25 2007 22:55:35 GMT+0800 (Malay Peninsula Standard Time)&quot; -- value in parentheses always gives the correct timezone
+        // IE     : &quot;Thu Oct 25 22:54:35 UTC+0800 2007&quot; -- (Asian system setting) look for 3-4 letter timezone abbrev
+        // IE     : &quot;Thu Oct 25 17:06:37 PDT 2007&quot; -- (American system setting) look for 3-4 letter timezone abbrev
+        //
+        // this crazy regex attempts to guess the correct timezone abbreviation despite these differences.
+        // step 1: (?:\((.*)\) -- find timezone in parentheses
+        // step 2: ([A-Z]{1,4})(?:[\-+][0-9]{4})?(?: -?\d+)?) -- if nothing was found in step 1, find timezone from timezone offset portion of date string
+        // step 3: remove all non uppercase characters found in step 1 and 2
+        return this.toString().replace(/^.* (?:\((.*)\)|([A-Z]{1,4})(?:[\-+][0-9]{4})?(?: -?\d+)?)$/, &quot;$1$2&quot;).replace(/[^A-Z]/g, &quot;&quot;);
+    },
+
+    
+    getGMTOffset : function(colon) {
+        return (this.getTimezoneOffset() &gt; 0 ? &quot;-&quot; : &quot;+&quot;)
+            + String.leftPad(Math.floor(Math.abs(this.getTimezoneOffset()) / 60), 2, &quot;0&quot;)
+            + (colon ? &quot;:&quot; : &quot;&quot;)
+            + String.leftPad(Math.abs(this.getTimezoneOffset() % 60), 2, &quot;0&quot;);
+    },
+
+    
+    getDayOfYear : function() {
+        var num = 0;
+        Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
+        for (var i = 0; i &lt; this.getMonth(); ++i) {
+            num += Date.daysInMonth[i];
+        }
+        return num + this.getDate() - 1;
+    },
+
+    
+    getWeekOfYear : function() {
+        // adapted from http://www.merlyn.demon.co.uk/weekcalc.htm
+        var ms1d = 864e5, // milliseconds in a day
+            ms7d = 7 * ms1d; // milliseconds in a week
+
+        return function() { // return a closure so constants get calculated only once
+            var DC3 = Date.UTC(this.getFullYear(), this.getMonth(), this.getDate() + 3) / ms1d, // an Absolute Day Number
+                AWN = Math.floor(DC3 / 7), // an Absolute Week Number
+                Wyr = new Date(AWN * ms7d).getUTCFullYear();
+
+            return AWN - Math.floor(Date.UTC(Wyr, 0, 7) / ms7d) + 1;
+        }
+    }(),
+
+    
+    isLeapYear : function() {
+        var year = this.getFullYear();
+        return !!((year &amp; 3) == 0 &amp;&amp; (year % 100 || (year % 400 == 0 &amp;&amp; year)));
+    },
+
+    
+    getFirstDayOfMonth : function() {
+        var day = (this.getDay() - (this.getDate() - 1)) % 7;
+        return (day &lt; 0) ? (day + 7) : day;
+    },
+
+    
+    getLastDayOfMonth : function() {
+        var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
+        return (day &lt; 0) ? (day + 7) : day;
+    },
+
+
+    
+    getFirstDateOfMonth : function() {
+        return new Date(this.getFullYear(), this.getMonth(), 1);
+    },
+
+    
+    getLastDateOfMonth : function() {
+        return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
+    },
+
+    
+    getDaysInMonth : function() {
+        Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
+        return Date.daysInMonth[this.getMonth()];
+    },
+
+    
+    getSuffix : function() {
+        switch (this.getDate()) {
+            case 1:
+            case 21:
+            case 31:
+                return &quot;st&quot;;
+            case 2:
+            case 22:
+                return &quot;nd&quot;;
+            case 3:
+            case 23:
+                return &quot;rd&quot;;
+            default:
+                return &quot;th&quot;;
+        }
+    },
+
+    
+    clone : function() {
+        return new Date(this.getTime());
+    },
+
+    
+    isDST : function() {
+        // adapted from http://extjs.com/forum/showthread.php?p=247172#post247172
+        // courtesy of @geoffrey.mcgill
+        return new Date(this.getFullYear(), 0, 1).getTimezoneOffset() != this.getTimezoneOffset();
+    },
+
+    
+    clearTime : function(clone) {
+        if (clone) {
+            return this.clone().clearTime();
+        }
+
+        // get current date before clearing time
+        var d = this.getDate();
+
+        // clear time
+        this.setHours(0);
+        this.setMinutes(0);
+        this.setSeconds(0);
+        this.setMilliseconds(0);
+
+        if (this.getDate() != d) { // account for DST (i.e. day of month changed when setting hour = 0)
+            // note: DST adjustments are assumed to occur in multiples of 1 hour (this is almost always the case)
+            // refer to http://www.timeanddate.com/time/aboutdst.html for the (rare) exceptions to this rule
+
+            // increment hour until cloned date == current date
+            for (var hr = 1, c = this.add(Date.HOUR, hr); c.getDate() != d; hr++, c = this.add(Date.HOUR, hr));
+
+            this.setDate(d);
+            this.setHours(c.getHours());
+        }
+
+        return this;
+    },
+
+    
+    add : function(interval, value) {
+        var d = this.clone();
+        if (!interval || value === 0) return d;
+
+        switch(interval.toLowerCase()) {
+            case Date.MILLI:
+                d.setMilliseconds(this.getMilliseconds() + value);
+                break;
+            case Date.SECOND:
+                d.setSeconds(this.getSeconds() + value);
+                break;
+            case Date.MINUTE:
+                d.setMinutes(this.getMinutes() + value);
+                break;
+            case Date.HOUR:
+                d.setHours(this.getHours() + value);
+                break;
+            case Date.DAY:
+                d.setDate(this.getDate() + value);
+                break;
+            case Date.MONTH:
+                var day = this.getDate();
+                if (day &gt; 28) {
+                    day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
+                }
+                d.setDate(day);
+                d.setMonth(this.getMonth() + value);
+                break;
+            case Date.YEAR:
+                d.setFullYear(this.getFullYear() + value);
+                break;
+        }
+        return d;
+    },
+
+    
+    between : function(start, end) {
+        var t = this.getTime();
+        return start.getTime() &lt;= t &amp;&amp; t &lt;= end.getTime();
+    }
+});
+
+
+
+Date.prototype.format = Date.prototype.dateFormat;
+
+
+// private
+if (Ext.isSafari &amp;&amp; (navigator.userAgent.match(/WebKit\/(\d+)/)[1] || NaN) &lt; 420) {
+    Ext.apply(Date.prototype, {
+        _xMonth : Date.prototype.setMonth,
+        _xDate  : Date.prototype.setDate,
+
+        // Bug in Safari 1.3, 2.0 (WebKit build &lt; 420)
+        // Date.setMonth does not work consistently if iMonth is not 0-11
+        setMonth : function(num) {
+            if (num &lt;= -1) {
+                var n = Math.ceil(-num),
+                    back_year = Math.ceil(n / 12),
+                    month = (n % 12) ? 12 - n % 12 : 0;
+
+                this.setFullYear(this.getFullYear() - back_year);
+
+                return this._xMonth(month);
+            } else {
+                return this._xMonth(num);
+            }
+        },
+
+        // Bug in setDate() method (resolved in WebKit build 419.3, so to be safe we target Webkit builds &lt; 420)
+        // The parameter for Date.setDate() is converted to a signed byte integer in Safari
+        // http://brianary.blogspot.com/2006/03/safari-date-bug.html
+        setDate : function(d) {
+            // use setTime() to workaround setDate() bug
+            // subtract current day of month in milliseconds, then add desired day of month in milliseconds
+            return this.setTime(this.getTime() - (this.getDate() - d) * 864e5);
+        }
+    });
+}
+
+
+
+
+
+Ext.util.DelayedTask = function(fn, scope, args){
+    var me = this,
+    	id,    	
+    	call = function(){
+    		clearInterval(id);
+	        id = null;
+	        fn.apply(scope, args || []);
+	    };
+	    
+    
+    me.delay = function(delay, newFn, newScope, newArgs){
+        me.cancel();
+        fn = newFn || fn;
+        scope = newScope || scope;
+        args = newArgs || args;
+        id = setInterval(call, delay);
+    };
+
+    
+    me.cancel = function(){
+        if(id){
+            clearInterval(id);
+            id = null;
+        }
+    };
+};
 
 Ext.util.MixedCollection = function(allowFunctions, keyFn){
     this.items = [];
@@ -7228,8 +7290,8 @@ Ext.extend(Ext.util.MixedCollection, Ext.util.Observable, {
 
 
     item : function(key){
-        var item = typeof this.map[key] != &quot;undefined&quot; ? this.map[key] : this.items[key];
-        return typeof item != 'function' || this.allowFunctions ? item : null; // for prototype!
+        var item = typeof this.map[key] != &quot;undefined&quot; ? this.map[key] : (typeof key == 'number') ? this.items[key] : null;
+        return !Ext.isFunction(item) || this.allowFunctions ? item : null; // for prototype!
     },
 
 
@@ -7396,189 +7458,189 @@ Ext.extend(Ext.util.MixedCollection, Ext.util.Observable, {
     }
 });
 
-Ext.util.MixedCollection.prototype.get = Ext.util.MixedCollection.prototype.item;
-
-Ext.ComponentMgr = function(){
-    var all = new Ext.util.MixedCollection();
-    var types = {};
-    var ptypes = {};
-
-    return {
-        
-        register : function(c){
-            all.add(c);
-        },
-
-        
-        unregister : function(c){
-            all.remove(c);
-        },
-
-        
-        get : function(id){
-            return all.get(id);
-        },
-
-        
-        onAvailable : function(id, fn, scope){
-            all.on(&quot;add&quot;, function(index, o){
-                if(o.id == id){
-                    fn.call(scope || o, o);
-                    all.un(&quot;add&quot;, fn, scope);
-                }
-            });
-        },
-
-        
-        all : all,
-
-        
-        registerType : function(xtype, cls){
-            types[xtype] = cls;
-            cls.xtype = xtype;
-        },
-
-        
-        create : function(config, defaultType){
-            return config.render ? config : new types[config.xtype || defaultType](config);
-        },
-
-        
-        registerPlugin : function(ptype, cls){
-            ptypes[ptype] = cls;
-            cls.ptype = ptype;
-        },
-
-        
-        createPlugin : function(config, defaultType){
-            return new ptypes[config.ptype || defaultType](config);
-        }
-    };
-}();
-
-
-Ext.reg = Ext.ComponentMgr.registerType; // this will be called a lot internally, shorthand to keep the bytes down
-
-Ext.preg = Ext.ComponentMgr.registerPlugin;
-Ext.create = Ext.ComponentMgr.create;
-
-
-Ext.util.JSON = new (function(){
-    var useHasOwn = !!{}.hasOwnProperty,
-        isNative = Ext.USE_NATIVE_JSON &amp;&amp; JSON &amp;&amp; JSON.toString() == '[object JSON]';
-
-    // crashes Safari in some instances
-    //var validRE = /^(&quot;(\\.|[^&quot;\\\n\r])*?&quot;|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
-
-    var pad = function(n) {
-        return n &lt; 10 ? &quot;0&quot; + n : n;
-    };
-
-    var m = {
-        &quot;\b&quot;: '\\b',
-        &quot;\t&quot;: '\\t',
-        &quot;\n&quot;: '\\n',
-        &quot;\f&quot;: '\\f',
-        &quot;\r&quot;: '\\r',
-        '&quot;' : '\\&quot;',
-        &quot;\\&quot;: '\\\\'
-    };
-
-    var encodeString = function(s){
-        if (/[&quot;\\\x00-\x1f]/.test(s)) {
-            return '&quot;' + s.replace(/([\x00-\x1f\\&quot;])/g, function(a, b) {
-                var c = m[b];
-                if(c){
-                    return c;
-                }
-                c = b.charCodeAt();
-                return &quot;\\u00&quot; +
-                    Math.floor(c / 16).toString(16) +
-                    (c % 16).toString(16);
-            }) + '&quot;';
-        }
-        return '&quot;' + s + '&quot;';
-    };
-
-    var encodeArray = function(o){
-        var a = [&quot;[&quot;], b, i, l = o.length, v;
-            for (i = 0; i &lt; l; i += 1) {
-                v = o[i];
-                switch (typeof v) {
-                    case &quot;undefined&quot;:
-                    case &quot;function&quot;:
-                    case &quot;unknown&quot;:
-                        break;
-                    default:
-                        if (b) {
-                            a.push(',');
-                        }
-                        a.push(v === null ? &quot;null&quot; : Ext.util.JSON.encode(v));
-                        b = true;
-                }
-            }
-            a.push(&quot;]&quot;);
-            return a.join(&quot;&quot;);
-    };
-
-    this.encodeDate = function(o){
-        return '&quot;' + o.getFullYear() + &quot;-&quot; +
-                pad(o.getMonth() + 1) + &quot;-&quot; +
-                pad(o.getDate()) + &quot;T&quot; +
-                pad(o.getHours()) + &quot;:&quot; +
-                pad(o.getMinutes()) + &quot;:&quot; +
-                pad(o.getSeconds()) + '&quot;';
-    };
-
-    
-    this.encode = isNative ? JSON.stringify : function(o){
-        if(typeof o == &quot;undefined&quot; || o === null){
-            return &quot;null&quot;;
-        }else if(Ext.isArray(o)){
-            return encodeArray(o);
-        }else if(Ext.isDate(o)){
-            return Ext.util.JSON.encodeDate(o);
-        }else if(typeof o == &quot;string&quot;){
-            return encodeString(o);
-        }else if(typeof o == &quot;number&quot;){
-            return isFinite(o) ? String(o) : &quot;null&quot;;
-        }else if(typeof o == &quot;boolean&quot;){
-            return String(o);
-        }else {
-            var a = [&quot;{&quot;], b, i, v;
-            for (i in o) {
-                if(!useHasOwn || o.hasOwnProperty(i)) {
-                    v = o[i];
-                    switch (typeof v) {
-                    case &quot;undefined&quot;:
-                    case &quot;function&quot;:
-                    case &quot;unknown&quot;:
-                        break;
-                    default:
-                        if(b){
-                            a.push(',');
-                        }
-                        a.push(this.encode(i), &quot;:&quot;,
-                                v === null ? &quot;null&quot; : this.encode(v));
-                        b = true;
-                    }
-                }
-            }
-            a.push(&quot;}&quot;);
-            return a.join(&quot;&quot;);
-        }
-    };
-
-    
-    this.decode = isNative ? JSON.parse : function(json){
-        return eval(&quot;(&quot; + json + ')');    
-    };
-})();
-
-Ext.encode = Ext.util.JSON.encode;
-
-Ext.decode = Ext.util.JSON.decode;
-
+Ext.util.MixedCollection.prototype.get = Ext.util.MixedCollection.prototype.item;
+
+Ext.ComponentMgr = function(){
+    var all = new Ext.util.MixedCollection();
+    var types = {};
+    var ptypes = {};
+
+    return {
+        
+        register : function(c){
+            all.add(c);
+        },
+
+        
+        unregister : function(c){
+            all.remove(c);
+        },
+
+        
+        get : function(id){
+            return all.get(id);
+        },
+
+        
+        onAvailable : function(id, fn, scope){
+            all.on(&quot;add&quot;, function(index, o){
+                if(o.id == id){
+                    fn.call(scope || o, o);
+                    all.un(&quot;add&quot;, fn, scope);
+                }
+            });
+        },
+
+        
+        all : all,
+
+        
+        registerType : function(xtype, cls){
+            types[xtype] = cls;
+            cls.xtype = xtype;
+        },
+
+        
+        create : function(config, defaultType){
+            return config.render ? config : new types[config.xtype || defaultType](config);
+        },
+
+        
+        registerPlugin : function(ptype, cls){
+            ptypes[ptype] = cls;
+            cls.ptype = ptype;
+        },
+
+        
+        createPlugin : function(config, defaultType){
+            return new ptypes[config.ptype || defaultType](config);
+        }
+    };
+}();
+
+
+Ext.reg = Ext.ComponentMgr.registerType; // this will be called a lot internally, shorthand to keep the bytes down
+
+Ext.preg = Ext.ComponentMgr.registerPlugin;
+Ext.create = Ext.ComponentMgr.create;
+
+
+Ext.util.JSON = new (function(){
+    var useHasOwn = !!{}.hasOwnProperty,
+        isNative = Ext.USE_NATIVE_JSON &amp;&amp; JSON &amp;&amp; JSON.toString() == '[object JSON]';
+
+    // crashes Safari in some instances
+    //var validRE = /^(&quot;(\\.|[^&quot;\\\n\r])*?&quot;|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
+
+    var pad = function(n) {
+        return n &lt; 10 ? &quot;0&quot; + n : n;
+    };
+
+    var m = {
+        &quot;\b&quot;: '\\b',
+        &quot;\t&quot;: '\\t',
+        &quot;\n&quot;: '\\n',
+        &quot;\f&quot;: '\\f',
+        &quot;\r&quot;: '\\r',
+        '&quot;' : '\\&quot;',
+        &quot;\\&quot;: '\\\\'
+    };
+
+    var encodeString = function(s){
+        if (/[&quot;\\\x00-\x1f]/.test(s)) {
+            return '&quot;' + s.replace(/([\x00-\x1f\\&quot;])/g, function(a, b) {
+                var c = m[b];
+                if(c){
+                    return c;
+                }
+                c = b.charCodeAt();
+                return &quot;\\u00&quot; +
+                    Math.floor(c / 16).toString(16) +
+                    (c % 16).toString(16);
+            }) + '&quot;';
+        }
+        return '&quot;' + s + '&quot;';
+    };
+
+    var encodeArray = function(o){
+        var a = [&quot;[&quot;], b, i, l = o.length, v;
+            for (i = 0; i &lt; l; i += 1) {
+                v = o[i];
+                switch (typeof v) {
+                    case &quot;undefined&quot;:
+                    case &quot;function&quot;:
+                    case &quot;unknown&quot;:
+                        break;
+                    default:
+                        if (b) {
+                            a.push(',');
+                        }
+                        a.push(v === null ? &quot;null&quot; : Ext.util.JSON.encode(v));
+                        b = true;
+                }
+            }
+            a.push(&quot;]&quot;);
+            return a.join(&quot;&quot;);
+    };
+
+    this.encodeDate = function(o){
+        return '&quot;' + o.getFullYear() + &quot;-&quot; +
+                pad(o.getMonth() + 1) + &quot;-&quot; +
+                pad(o.getDate()) + &quot;T&quot; +
+                pad(o.getHours()) + &quot;:&quot; +
+                pad(o.getMinutes()) + &quot;:&quot; +
+                pad(o.getSeconds()) + '&quot;';
+    };
+
+    
+    this.encode = isNative ? JSON.stringify : function(o){
+        if(typeof o == &quot;undefined&quot; || o === null){
+            return &quot;null&quot;;
+        }else if(Ext.isArray(o)){
+            return encodeArray(o);
+        }else if(Object.prototype.toString.apply(o) === '[object Date]'){
+            return Ext.util.JSON.encodeDate(o);
+        }else if(typeof o == &quot;string&quot;){
+            return encodeString(o);
+        }else if(typeof o == &quot;number&quot;){
+            return isFinite(o) ? String(o) : &quot;null&quot;;
+        }else if(typeof o == &quot;boolean&quot;){
+            return String(o);
+        }else {
+            var a = [&quot;{&quot;], b, i, v;
+            for (i in o) {
+                if(!useHasOwn || o.hasOwnProperty(i)) {
+                    v = o[i];
+                    switch (typeof v) {
+                    case &quot;undefined&quot;:
+                    case &quot;function&quot;:
+                    case &quot;unknown&quot;:
+                        break;
+                    default:
+                        if(b){
+                            a.push(',');
+                        }
+                        a.push(this.encode(i), &quot;:&quot;,
+                                v === null ? &quot;null&quot; : this.encode(v));
+                        b = true;
+                    }
+                }
+            }
+            a.push(&quot;}&quot;);
+            return a.join(&quot;&quot;);
+        }
+    };
+
+    
+    this.decode = isNative ? JSON.parse : function(json){
+        return eval(&quot;(&quot; + json + ')');    
+    };
+})();
+
+Ext.encode = Ext.util.JSON.encode;
+
+Ext.decode = Ext.util.JSON.decode;
+
 
 Ext.util.Format = function(){
     var trimRe = /^\s+|\s+$/g;
@@ -7743,59 +7805,56 @@ Ext.util.Format = function(){
         
         number: function(v, format) {
             if(!format){
-                return v;
-            }
-            v *= 1;
-            if(typeof v != 'number' || isNaN(v)){
+		        return v;
+		    }
+		    v = Ext.num(v, NaN);
+            if (isNaN(v)){
                 return '';
             }
-            var comma = ',';
-            var dec = '.';
-            var i18n = false;
-            
-            if(format.substr(format.length - 2) == '/i'){
-                format = format.substr(0, format.length-2);
-                i18n = true;
-                comma = '.';
-                dec = ',';
-            }
-
-            var hasComma = format.indexOf(comma) != -1,
-                psplit = (i18n ? format.replace(/[^\d\,]/g,'') : format.replace(/[^\d\.]/g,'')).split(dec);
-
-            if (1 &lt; psplit.length) {
-                v = v.toFixed(psplit[1].length);
-            }
-            else if (2 &lt; psplit.length) {
-                throw('NumberFormatException: invalid format, formats should have no more than 1 period: ' + format);
-            }
-            else {
-                v = v.toFixed(0);
-            }
-
-            var fnum = v.toString();
-
-            if (hasComma) {
-                psplit = fnum.split('.');
-
-                var cnum = psplit[0],
-                    parr = [],
-                    j = cnum.length,
-                    m = Math.floor(j / 3),
-                    n = cnum.length % 3 || 3;
-
-                for (var i = 0; i &lt; j; i += n) {
-                    if (i != 0) {n = 3;}
-                    parr[parr.length] = cnum.substr(i, n);
-                    m -= 1;
-                }
-                fnum = parr.join(comma);
-                if (psplit[1]) {
-                    fnum += dec + psplit[1];
-                }
-            }
-
-            return format.replace(/[\d,?\.?]+/, fnum);
+		    var comma = ',',
+		        dec = '.',
+		        i18n = false,
+		        neg = v &lt; 0;
+		
+		    v = Math.abs(v);
+		    if(format.substr(format.length - 2) == '/i'){
+		        format = format.substr(0, format.length - 2);
+		        i18n = true;
+		        comma = '.';
+		        dec = ',';
+		    }
+		
+		    var hasComma = format.indexOf(comma) != -1, 
+		        psplit = (i18n ? format.replace(/[^\d\,]/g, '') : format.replace(/[^\d\.]/g, '')).split(dec);
+		
+		    if(1 &lt; psplit.length){
+		        v = v.toFixed(psplit[1].length);
+		    }else if(2 &lt; psplit.length){
+		        throw ('NumberFormatException: invalid format, formats should have no more than 1 period: ' + format);
+		    }else{
+		        v = v.toFixed(0);
+		    }
+		
+		    var fnum = v.toString();
+		    if(hasComma){
+		        psplit = fnum.split('.');
+		
+		        var cnum = psplit[0], parr = [], j = cnum.length, m = Math.floor(j / 3), n = cnum.length % 3 || 3;
+		
+		        for(var i = 0; i &lt; j; i += n){
+		            if(i != 0){
+		                n = 3;
+		            }
+		            parr[parr.length] = cnum.substr(i, n);
+		            m -= 1;
+		        }
+		        fnum = parr.join(comma);
+		        if(psplit[1]){
+		            fnum += dec + psplit[1];
+		        }
+		    }
+		
+		    return (neg ? '-' : '') + format.replace(/[\d,?\.?]+/, fnum);
         },
 
         
@@ -7815,180 +7874,180 @@ Ext.util.Format = function(){
             return v === undefined || v === null ? '' : v.replace(/\n/g, '&lt;br/&gt;');
         }
     }
-}();
-
-Ext.XTemplate = function(){
-    Ext.XTemplate.superclass.constructor.apply(this, arguments);
-
-    var me = this,
-    	s = me.html,
-    	re = /&lt;tpl\b[^&gt;]*&gt;((?:(?=([^&lt;]+))\2|&lt;(?!tpl\b[^&gt;]*&gt;))*?)&lt;\/tpl&gt;/,
-    	nameRe = /^&lt;tpl\b[^&gt;]*?for=&quot;(.*?)&quot;/,
-    	ifRe = /^&lt;tpl\b[^&gt;]*?if=&quot;(.*?)&quot;/,
-    	execRe = /^&lt;tpl\b[^&gt;]*?exec=&quot;(.*?)&quot;/,
-    	m,
-    	id = 0,
-    	tpls = [],
-    	VALUES = 'values',
-    	PARENT = 'parent',
-    	XINDEX = 'xindex',
-    	XCOUNT = 'xcount',
-    	RETURN = 'return ',
-    	WITHVALUES = 'with(values){ ';
-
-    s = ['&lt;tpl&gt;', s, '&lt;/tpl&gt;'].join('');
-
-    while(m = s.match(re)){
-       	var m2 = m[0].match(nameRe),
-			m3 = m[0].match(ifRe),
-       		m4 = m[0].match(execRe),
-       		exp = null,
-       		fn = null,
-       		exec = null,
-       		name = m2 &amp;&amp; m2[1] ? m2[1] : '';
-
-       if (m3) {
-           exp = m3 &amp;&amp; m3[1] ? m3[1] : null;
-           if(exp){
-               fn = new Function(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES + RETURN +(Ext.util.Format.htmlDecode(exp))+'; }');
-           }
-       }
-       if (m4) {
-           exp = m4 &amp;&amp; m4[1] ? m4[1] : null;
-           if(exp){
-               exec = new Function(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES +(Ext.util.Format.htmlDecode(exp))+'; }');
-           }
-       }
-       if(name){
-           switch(name){
-               case '.': name = new Function(VALUES, PARENT, WITHVALUES + RETURN + VALUES + '; }'); break;
-               case '..': name = new Function(VALUES, PARENT, WITHVALUES + RETURN + PARENT + '; }'); break;
-               default: name = new Function(VALUES, PARENT, WITHVALUES + RETURN + name + '; }');
-           }
-       }
-       tpls.push({
-            id: id,
-            target: name,
-            exec: exec,
-            test: fn,
-            body: m[1]||''
-        });
-       s = s.replace(m[0], '{xtpl'+ id + '}');
-       ++id;
-    }
-	Ext.each(tpls, function(t) {
-        me.compileTpl(t);
-    });
-    me.master = tpls[tpls.length-1];
-    me.tpls = tpls;
-};
-Ext.extend(Ext.XTemplate, Ext.Template, {
-    // private
-    re : /\{([\w-\.\#]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?(\s?[\+\-\*\\]\s?[\d\.\+\-\*\\\(\)]+)?\}/g,
-    // private
-    codeRe : /\{\[((?:\\\]|.|\n)*?)\]\}/g,
-
-    // private
-    applySubTemplate : function(id, values, parent, xindex, xcount){
-        var me = this,
-        	len,
-        	t = me.tpls[id],
-        	vs,
-        	buf = [];
-        if ((t.test &amp;&amp; !t.test.call(me, values, parent, xindex, xcount)) ||
-            (t.exec &amp;&amp; t.exec.call(me, values, parent, xindex, xcount))) {
-            return '';
-        }
-        vs = t.target ? t.target.call(me, values, parent) : values;
-        len = vs.len;
-        parent = t.target ? values : parent;
-        if(t.target &amp;&amp; Ext.isArray(vs)){
-	        Ext.each(vs, function(v, i) {
-                buf[buf.length] = t.compiled.call(me, v, parent, i+1, len);
-            });
-            return buf.join('');
-        }
-        return t.compiled.call(me, vs, parent, xindex, xcount);
-    },
-
-    // private
-    compileTpl : function(tpl){
-        var fm = Ext.util.Format,
-       		useF = this.disableFormats !== true,
-            sep = Ext.isGecko ? &quot;+&quot; : &quot;,&quot;,
-            body;
-
-        function fn(m, name, format, args, math){
-            if(name.substr(0, 4) == 'xtpl'){
-                return &quot;'&quot;+ sep +'this.applySubTemplate('+name.substr(4)+', values, parent, xindex, xcount)'+sep+&quot;'&quot;;
-            }
-            var v;
-            if(name === '.'){
-                v = 'values';
-            }else if(name === '#'){
-                v = 'xindex';
-            }else if(name.indexOf('.') != -1){
-                v = name;
-            }else{
-                v = &quot;values['&quot; + name + &quot;']&quot;;
-            }
-            if(math){
-                v = '(' + v + math + ')';
-            }
-            if (format &amp;&amp; useF) {
-                args = args ? ',' + args : &quot;&quot;;
-                if(format.substr(0, 5) != &quot;this.&quot;){
-                    format = &quot;fm.&quot; + format + '(';
-                }else{
-                    format = 'this.call(&quot;'+ format.substr(5) + '&quot;, ';
-                    args = &quot;, values&quot;;
-                }
-            } else {
-                args= ''; format = &quot;(&quot;+v+&quot; === undefined ? '' : &quot;;
-            }
-            return &quot;'&quot;+ sep + format + v + args + &quot;)&quot;+sep+&quot;'&quot;;
-        };
-
-        function codeFn(m, code){
-            return &quot;'&quot;+ sep +'('+code+')'+sep+&quot;'&quot;;
-        };
-
-        // branched to use + in gecko and [].join() in others
-        if(Ext.isGecko){
-            body = &quot;tpl.compiled = function(values, parent, xindex, xcount){ return '&quot; +
-                   tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, &quot;\\'&quot;).replace(this.re, fn).replace(this.codeRe, codeFn) +
-                    &quot;';};&quot;;
-        }else{
-            body = [&quot;tpl.compiled = function(values, parent, xindex, xcount){ return ['&quot;];
-            body.push(tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, &quot;\\'&quot;).replace(this.re, fn).replace(this.codeRe, codeFn));
-            body.push(&quot;'].join('');};&quot;);
-            body = body.join('');
-        }
-        eval(body);
-        return this;
-    },
-
-    
-    applyTemplate : function(values){
-        return this.master.compiled.call(this, values, {}, 1, 1);
-    },
-
-    
-    compile : function(){return this;}
-
-    
-    
-    
-
-});
-
-Ext.XTemplate.prototype.apply = Ext.XTemplate.prototype.applyTemplate;
-
-
-Ext.XTemplate.from = function(el){
-    el = Ext.getDom(el);
-    return new Ext.XTemplate(el.value || el.innerHTML);
-};
+}();
+
+Ext.XTemplate = function(){
+    Ext.XTemplate.superclass.constructor.apply(this, arguments);
+
+    var me = this,
+    	s = me.html,
+    	re = /&lt;tpl\b[^&gt;]*&gt;((?:(?=([^&lt;]+))\2|&lt;(?!tpl\b[^&gt;]*&gt;))*?)&lt;\/tpl&gt;/,
+    	nameRe = /^&lt;tpl\b[^&gt;]*?for=&quot;(.*?)&quot;/,
+    	ifRe = /^&lt;tpl\b[^&gt;]*?if=&quot;(.*?)&quot;/,
+    	execRe = /^&lt;tpl\b[^&gt;]*?exec=&quot;(.*?)&quot;/,
+    	m,
+    	id = 0,
+    	tpls = [],
+    	VALUES = 'values',
+    	PARENT = 'parent',
+    	XINDEX = 'xindex',
+    	XCOUNT = 'xcount',
+    	RETURN = 'return ',
+    	WITHVALUES = 'with(values){ ';
+
+    s = ['&lt;tpl&gt;', s, '&lt;/tpl&gt;'].join('');
+
+    while(m = s.match(re)){
+       	var m2 = m[0].match(nameRe),
+			m3 = m[0].match(ifRe),
+       		m4 = m[0].match(execRe),
+       		exp = null,
+       		fn = null,
+       		exec = null,
+       		name = m2 &amp;&amp; m2[1] ? m2[1] : '';
+
+       if (m3) {
+           exp = m3 &amp;&amp; m3[1] ? m3[1] : null;
+           if(exp){
+               fn = new Function(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES + RETURN +(Ext.util.Format.htmlDecode(exp))+'; }');
+           }
+       }
+       if (m4) {
+           exp = m4 &amp;&amp; m4[1] ? m4[1] : null;
+           if(exp){
+               exec = new Function(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES +(Ext.util.Format.htmlDecode(exp))+'; }');
+           }
+       }
+       if(name){
+           switch(name){
+               case '.': name = new Function(VALUES, PARENT, WITHVALUES + RETURN + VALUES + '; }'); break;
+               case '..': name = new Function(VALUES, PARENT, WITHVALUES + RETURN + PARENT + '; }'); break;
+               default: name = new Function(VALUES, PARENT, WITHVALUES + RETURN + name + '; }');
+           }
+       }
+       tpls.push({
+            id: id,
+            target: name,
+            exec: exec,
+            test: fn,
+            body: m[1]||''
+        });
+       s = s.replace(m[0], '{xtpl'+ id + '}');
+       ++id;
+    }
+	Ext.each(tpls, function(t) {
+        me.compileTpl(t);
+    });
+    me.master = tpls[tpls.length-1];
+    me.tpls = tpls;
+};
+Ext.extend(Ext.XTemplate, Ext.Template, {
+    // private
+    re : /\{([\w-\.\#]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?(\s?[\+\-\*\\]\s?[\d\.\+\-\*\\\(\)]+)?\}/g,
+    // private
+    codeRe : /\{\[((?:\\\]|.|\n)*?)\]\}/g,
+
+    // private
+    applySubTemplate : function(id, values, parent, xindex, xcount){
+        var me = this,
+        	len,
+        	t = me.tpls[id],
+        	vs,
+        	buf = [];
+        if ((t.test &amp;&amp; !t.test.call(me, values, parent, xindex, xcount)) ||
+            (t.exec &amp;&amp; t.exec.call(me, values, parent, xindex, xcount))) {
+            return '';
+        }
+        vs = t.target ? t.target.call(me, values, parent) : values;
+        len = vs.length;
+        parent = t.target ? values : parent;
+        if(t.target &amp;&amp; Ext.isArray(vs)){
+	        Ext.each(vs, function(v, i) {
+                buf[buf.length] = t.compiled.call(me, v, parent, i+1, len);
+            });
+            return buf.join('');
+        }
+        return t.compiled.call(me, vs, parent, xindex, xcount);
+    },
+
+    // private
+    compileTpl : function(tpl){
+        var fm = Ext.util.Format,
+       		useF = this.disableFormats !== true,
+            sep = Ext.isGecko ? &quot;+&quot; : &quot;,&quot;,
+            body;
+
+        function fn(m, name, format, args, math){
+            if(name.substr(0, 4) == 'xtpl'){
+                return &quot;'&quot;+ sep +'this.applySubTemplate('+name.substr(4)+', values, parent, xindex, xcount)'+sep+&quot;'&quot;;
+            }
+            var v;
+            if(name === '.'){
+                v = 'values';
+            }else if(name === '#'){
+                v = 'xindex';
+            }else if(name.indexOf('.') != -1){
+                v = name;
+            }else{
+                v = &quot;values['&quot; + name + &quot;']&quot;;
+            }
+            if(math){
+                v = '(' + v + math + ')';
+            }
+            if (format &amp;&amp; useF) {
+                args = args ? ',' + args : &quot;&quot;;
+                if(format.substr(0, 5) != &quot;this.&quot;){
+                    format = &quot;fm.&quot; + format + '(';
+                }else{
+                    format = 'this.call(&quot;'+ format.substr(5) + '&quot;, ';
+                    args = &quot;, values&quot;;
+                }
+            } else {
+                args= ''; format = &quot;(&quot;+v+&quot; === undefined ? '' : &quot;;
+            }
+            return &quot;'&quot;+ sep + format + v + args + &quot;)&quot;+sep+&quot;'&quot;;
+        };
+
+        function codeFn(m, code){
+            return &quot;'&quot;+ sep +'('+code+')'+sep+&quot;'&quot;;
+        };
+
+        // branched to use + in gecko and [].join() in others
+        if(Ext.isGecko){
+            body = &quot;tpl.compiled = function(values, parent, xindex, xcount){ return '&quot; +
+                   tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, &quot;\\'&quot;).replace(this.re, fn).replace(this.codeRe, codeFn) +
+                    &quot;';};&quot;;
+        }else{
+            body = [&quot;tpl.compiled = function(values, parent, xindex, xcount){ return ['&quot;];
+            body.push(tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, &quot;\\'&quot;).replace(this.re, fn).replace(this.codeRe, codeFn));
+            body.push(&quot;'].join('');};&quot;);
+            body = body.join('');
+        }
+        eval(body);
+        return this;
+    },
+
+    
+    applyTemplate : function(values){
+        return this.master.compiled.call(this, values, {}, 1, 1);
+    },
+
+    
+    compile : function(){return this;}
+
+    
+    
+    
+
+});
+
+Ext.XTemplate.prototype.apply = Ext.XTemplate.prototype.applyTemplate;
+
+
+Ext.XTemplate.from = function(el){
+    el = Ext.getDom(el);
+    return new Ext.XTemplate(el.value || el.innerHTML);
+};
 
 Ext.util.CSS = function(){
 	var rules = null;
@@ -8108,234 +8167,234 @@ Ext.util.CSS = function(){
    		return false;
    	}
    };	
-}();
-
-Ext.util.ClickRepeater = function(el, config)
-{
-    this.el = Ext.get(el);
-    this.el.unselectable();
-
-    Ext.apply(this, config);
-
-    this.addEvents(
-    
-        &quot;mousedown&quot;,
-    
-        &quot;click&quot;,
-    
-        &quot;mouseup&quot;
-    );
-
-    this.el.on(&quot;mousedown&quot;, this.handleMouseDown, this);
-    if(this.preventDefault || this.stopDefault){
-        this.el.on(&quot;click&quot;, function(e){
-            if(this.preventDefault){
-                e.preventDefault();
-            }
-            if(this.stopDefault){
-                e.stopEvent();
-            }
-        }, this);
-    }
-
-    // allow inline handler
-    if(this.handler){
-        this.on(&quot;click&quot;, this.handler,  this.scope || this);
-    }
-
-    Ext.util.ClickRepeater.superclass.constructor.call(this);
-};
-
-Ext.extend(Ext.util.ClickRepeater, Ext.util.Observable, {
-    interval : 20,
-    delay: 250,
-    preventDefault : true,
-    stopDefault : false,
-    timer : 0,
-
-    // private
-    destroy : function() {
-        Ext.destroy(this.el);
-        this.purgeListeners();
-    },
-    
-    // private
-    handleMouseDown : function(){
-        clearTimeout(this.timer);
-        this.el.blur();
-        if(this.pressClass){
-            this.el.addClass(this.pressClass);
-        }
-        this.mousedownTime = new Date();
-
-        Ext.getDoc().on(&quot;mouseup&quot;, this.handleMouseUp, this);
-        this.el.on(&quot;mouseout&quot;, this.handleMouseOut, this);
-
-        this.fireEvent(&quot;mousedown&quot;, this);
-        this.fireEvent(&quot;click&quot;, this);
-
-//      Do not honor delay or interval if acceleration wanted.
-        if (this.accelerate) {
-            this.delay = 400;
-	    }
-        this.timer = this.click.defer(this.delay || this.interval, this);
-    },
-
-    // private
-    click : function(){
-        this.fireEvent(&quot;click&quot;, this);
-        this.timer = this.click.defer(this.accelerate ?
-            this.easeOutExpo(this.mousedownTime.getElapsed(),
-                400,
-                -390,
-                12000) :
-            this.interval, this);
-    },
-
-    easeOutExpo : function (t, b, c, d) {
-        return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
-    },
-
-    // private
-    handleMouseOut : function(){
-        clearTimeout(this.timer);
-        if(this.pressClass){
-            this.el.removeClass(this.pressClass);
-        }
-        this.el.on(&quot;mouseover&quot;, this.handleMouseReturn, this);
-    },
-
-    // private
-    handleMouseReturn : function(){
-        this.el.un(&quot;mouseover&quot;, this.handleMouseReturn, this);
-        if(this.pressClass){
-            this.el.addClass(this.pressClass);
-        }
-        this.click();
-    },
-
-    // private
-    handleMouseUp : function(){
-        clearTimeout(this.timer);
-        this.el.un(&quot;mouseover&quot;, this.handleMouseReturn, this);
-        this.el.un(&quot;mouseout&quot;, this.handleMouseOut, this);
-        Ext.getDoc().un(&quot;mouseup&quot;, this.handleMouseUp, this);
-        this.el.removeClass(this.pressClass);
-        this.fireEvent(&quot;mouseup&quot;, this);
-    }
-});
-
-Ext.KeyNav = function(el, config){
-    this.el = Ext.get(el);
-    Ext.apply(this, config);
-    if(!this.disabled){
-        this.disabled = true;
-        this.enable();
-    }
-};
-
-Ext.KeyNav.prototype = {
-    
-    disabled : false,
-    
-    defaultEventAction: &quot;stopEvent&quot;,
-    
-    forceKeyDown : false,
-
-    // private
-    prepareEvent : function(e){
-        var k = e.getKey();
-        var h = this.keyToHandler[k];
-        if(Ext.isSafari2 &amp;&amp; h &amp;&amp; k &gt;= 37 &amp;&amp; k &lt;= 40){
-            e.stopEvent();
-        }
-    },
-
-    // private
-    relay : function(e){
-        var k = e.getKey();
-        var h = this.keyToHandler[k];
-        if(h &amp;&amp; this[h]){
-            if(this.doRelay(e, this[h], h) !== true){
-                e[this.defaultEventAction]();
-            }
-        }
-    },
-
-    // private
-    doRelay : function(e, h, hname){
-        return h.call(this.scope || this, e);
-    },
-
-    // possible handlers
-    enter : false,
-    left : false,
-    right : false,
-    up : false,
-    down : false,
-    tab : false,
-    esc : false,
-    pageUp : false,
-    pageDown : false,
-    del : false,
-    home : false,
-    end : false,
-
-    // quick lookup hash
-    keyToHandler : {
-        37 : &quot;left&quot;,
-        39 : &quot;right&quot;,
-        38 : &quot;up&quot;,
-        40 : &quot;down&quot;,
-        33 : &quot;pageUp&quot;,
-        34 : &quot;pageDown&quot;,
-        46 : &quot;del&quot;,
-        36 : &quot;home&quot;,
-        35 : &quot;end&quot;,
-        13 : &quot;enter&quot;,
-        27 : &quot;esc&quot;,
-        9  : &quot;tab&quot;
-    },
-
-	
-	enable: function(){
-		if(this.disabled){
-            // ie won't do special keys on keypress, no one else will repeat keys with keydown
-            // the EventObject will normalize Safari automatically
-            if(this.isKeyDown()){
-                this.el.on(&quot;keydown&quot;, this.relay,  this);
-            }else{
-                this.el.on(&quot;keydown&quot;, this.prepareEvent,  this);
-                this.el.on(&quot;keypress&quot;, this.relay,  this);
-            }
-		    this.disabled = false;
-		}
-	},
-
-	
-	disable: function(){
-		if(!this.disabled){
-		    if(this.isKeyDown()){
-                this.el.un(&quot;keydown&quot;, this.relay, this);
-            }else{
-                this.el.un(&quot;keydown&quot;, this.prepareEvent, this);
-                this.el.un(&quot;keypress&quot;, this.relay, this);
-            }
-		    this.disabled = true;
-		}
-	},
-    
-    
-    setDisabled : function(disabled){
-        this[disabled ? &quot;disable&quot; : &quot;enable&quot;]();
-    },
-    
-    // private
-    isKeyDown: function(){
-        return this.forceKeyDown || Ext.isIE || Ext.isSafari3 || Ext.isChrome || Ext.isAir;
-    }
-};
-
+}();
+
+Ext.util.ClickRepeater = function(el, config)
+{
+    this.el = Ext.get(el);
+    this.el.unselectable();
+
+    Ext.apply(this, config);
+
+    this.addEvents(
+    
+        &quot;mousedown&quot;,
+    
+        &quot;click&quot;,
+    
+        &quot;mouseup&quot;
+    );
+
+    this.el.on(&quot;mousedown&quot;, this.handleMouseDown, this);
+    if(this.preventDefault || this.stopDefault){
+        this.el.on(&quot;click&quot;, function(e){
+            if(this.preventDefault){
+                e.preventDefault();
+            }
+            if(this.stopDefault){
+                e.stopEvent();
+            }
+        }, this);
+    }
+
+    // allow inline handler
+    if(this.handler){
+        this.on(&quot;click&quot;, this.handler,  this.scope || this);
+    }
+
+    Ext.util.ClickRepeater.superclass.constructor.call(this);
+};
+
+Ext.extend(Ext.util.ClickRepeater, Ext.util.Observable, {
+    interval : 20,
+    delay: 250,
+    preventDefault : true,
+    stopDefault : false,
+    timer : 0,
+
+    // private
+    destroy : function() {
+        Ext.destroy(this.el);
+        this.purgeListeners();
+    },
+    
+    // private
+    handleMouseDown : function(){
+        clearTimeout(this.timer);
+        this.el.blur();
+        if(this.pressClass){
+            this.el.addClass(this.pressClass);
+        }
+        this.mousedownTime = new Date();
+
+        Ext.getDoc().on(&quot;mouseup&quot;, this.handleMouseUp, this);
+        this.el.on(&quot;mouseout&quot;, this.handleMouseOut, this);
+
+        this.fireEvent(&quot;mousedown&quot;, this);
+        this.fireEvent(&quot;click&quot;, this);
+
+//      Do not honor delay or interval if acceleration wanted.
+        if (this.accelerate) {
+            this.delay = 400;
+	    }
+        this.timer = this.click.defer(this.delay || this.interval, this);
+    },
+
+    // private
+    click : function(){
+        this.fireEvent(&quot;click&quot;, this);
+        this.timer = this.click.defer(this.accelerate ?
+            this.easeOutExpo(this.mousedownTime.getElapsed(),
+                400,
+                -390,
+                12000) :
+            this.interval, this);
+    },
+
+    easeOutExpo : function (t, b, c, d) {
+        return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
+    },
+
+    // private
+    handleMouseOut : function(){
+        clearTimeout(this.timer);
+        if(this.pressClass){
+            this.el.removeClass(this.pressClass);
+        }
+        this.el.on(&quot;mouseover&quot;, this.handleMouseReturn, this);
+    },
+
+    // private
+    handleMouseReturn : function(){
+        this.el.un(&quot;mouseover&quot;, this.handleMouseReturn, this);
+        if(this.pressClass){
+            this.el.addClass(this.pressClass);
+        }
+        this.click();
+    },
+
+    // private
+    handleMouseUp : function(){
+        clearTimeout(this.timer);
+        this.el.un(&quot;mouseover&quot;, this.handleMouseReturn, this);
+        this.el.un(&quot;mouseout&quot;, this.handleMouseOut, this);
+        Ext.getDoc().un(&quot;mouseup&quot;, this.handleMouseUp, this);
+        this.el.removeClass(this.pressClass);
+        this.fireEvent(&quot;mouseup&quot;, this);
+    }
+});
+
+Ext.KeyNav = function(el, config){
+    this.el = Ext.get(el);
+    Ext.apply(this, config);
+    if(!this.disabled){
+        this.disabled = true;
+        this.enable();
+    }
+};
+
+Ext.KeyNav.prototype = {
+    
+    disabled : false,
+    
+    defaultEventAction: &quot;stopEvent&quot;,
+    
+    forceKeyDown : false,
+
+    // private
+    prepareEvent : function(e){
+        var k = e.getKey();
+        var h = this.keyToHandler[k];
+        if(Ext.isSafari2 &amp;&amp; h &amp;&amp; k &gt;= 37 &amp;&amp; k &lt;= 40){
+            e.stopEvent();
+        }
+    },
+
+    // private
+    relay : function(e){
+        var k = e.getKey();
+        var h = this.keyToHandler[k];
+        if(h &amp;&amp; this[h]){
+            if(this.doRelay(e, this[h], h) !== true){
+                e[this.defaultEventAction]();
+            }
+        }
+    },
+
+    // private
+    doRelay : function(e, h, hname){
+        return h.call(this.scope || this, e);
+    },
+
+    // possible handlers
+    enter : false,
+    left : false,
+    right : false,
+    up : false,
+    down : false,
+    tab : false,
+    esc : false,
+    pageUp : false,
+    pageDown : false,
+    del : false,
+    home : false,
+    end : false,
+
+    // quick lookup hash
+    keyToHandler : {
+        37 : &quot;left&quot;,
+        39 : &quot;right&quot;,
+        38 : &quot;up&quot;,
+        40 : &quot;down&quot;,
+        33 : &quot;pageUp&quot;,
+        34 : &quot;pageDown&quot;,
+        46 : &quot;del&quot;,
+        36 : &quot;home&quot;,
+        35 : &quot;end&quot;,
+        13 : &quot;enter&quot;,
+        27 : &quot;esc&quot;,
+        9  : &quot;tab&quot;
+    },
+
+	
+	enable: function(){
+		if(this.disabled){
+            // ie won't do special keys on keypress, no one else will repeat keys with keydown
+            // the EventObject will normalize Safari automatically
+            if(this.isKeyDown()){
+                this.el.on(&quot;keydown&quot;, this.relay,  this);
+            }else{
+                this.el.on(&quot;keydown&quot;, this.prepareEvent,  this);
+                this.el.on(&quot;keypress&quot;, this.relay,  this);
+            }
+		    this.disabled = false;
+		}
+	},
+
+	
+	disable: function(){
+		if(!this.disabled){
+		    if(this.isKeyDown()){
+                this.el.un(&quot;keydown&quot;, this.relay, this);
+            }else{
+                this.el.un(&quot;keydown&quot;, this.prepareEvent, this);
+                this.el.un(&quot;keypress&quot;, this.relay, this);
+            }
+		    this.disabled = true;
+		}
+	},
+    
+    
+    setDisabled : function(disabled){
+        this[disabled ? &quot;disable&quot; : &quot;enable&quot;]();
+    },
+    
+    // private
+    isKeyDown: function(){
+        return this.forceKeyDown || Ext.isIE || Ext.isSafari3 || Ext.isChrome || Ext.isAir;
+    }
+};
+
 
 Ext.KeyMap = function(el, config, eventName){
     this.el  = Ext.get(el);
@@ -8471,1867 +8530,1867 @@ Ext.KeyMap.prototype = {
     setDisabled : function(disabled){
         this[disabled ? &quot;disable&quot; : &quot;enable&quot;]();
     }
-};
-
-Ext.util.TextMetrics = function(){
-    var shared;
-    return {
-        
-        measure : function(el, text, fixedWidth){
-            if(!shared){
-                shared = Ext.util.TextMetrics.Instance(el, fixedWidth);
-            }
-            shared.bind(el);
-            shared.setFixedWidth(fixedWidth || 'auto');
-            return shared.getSize(text);
-        },
-
-        
-        createInstance : function(el, fixedWidth){
-            return Ext.util.TextMetrics.Instance(el, fixedWidth);
-        }
-    };
-}();
-
-Ext.util.TextMetrics.Instance = function(bindTo, fixedWidth){
-    var ml = new Ext.Element(document.createElement('div'));
-    document.body.appendChild(ml.dom);
-    ml.position('absolute');
-    ml.setLeftTop(-1000, -1000);
-    ml.hide();
-
-    if(fixedWidth){
-        ml.setWidth(fixedWidth);
-    }
-
-    var instance = {
-        
-        getSize : function(text){
-            ml.update(text);
-            var s = ml.getSize();
-            ml.update('');
-            return s;
-        },
-
-        
-        bind : function(el){
-            ml.setStyle(
-                Ext.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height', 'text-transform', 'letter-spacing')
-            );
-        },
-
-        
-        setFixedWidth : function(width){
-            ml.setWidth(width);
-        },
-
-        
-        getWidth : function(text){
-            ml.dom.style.width = 'auto';
-            return this.getSize(text).width;
-        },
-
-        
-        getHeight : function(text){
-            return this.getSize(text).height;
-        }
-    };
-
-    instance.bind(bindTo);
-
-    return instance;
-};
-
-Ext.Element.addMethods({
-    
-    getTextWidth : function(text, min, max){
-        return (Ext.util.TextMetrics.measure(this.dom, Ext.value(text, this.dom.innerHTML, true)).width).constrain(min || 0, max || 1000000);
-    }
-});
-
-
-
-(function() {
-
-var Event=Ext.EventManager;
-var Dom=Ext.lib.Dom;
-
-
-Ext.dd.DragDrop = function(id, sGroup, config) {
-    if(id) {
-        this.init(id, sGroup, config);
-    }
-};
-
-Ext.dd.DragDrop.prototype = {
-
-    
-
-    
-    id: null,
-
-    
-    config: null,
-
-    
-    dragElId: null,
-
-    
-    handleElId: null,
-
-    
-    invalidHandleTypes: null,
-
-    
-    invalidHandleIds: null,
-
-    
-    invalidHandleClasses: null,
-
-    
-    startPageX: 0,
-
-    
-    startPageY: 0,
-
-    
-    groups: null,
-
-    
-    locked: false,
-
-    
-    lock: function() { this.locked = true; },
-
-    
-    moveOnly: false,
-
-    
-    unlock: function() { this.locked = false; },
-
-    
-    isTarget: true,
-
-    
-    padding: null,
-
-    
-    _domRef: null,
-
-    
-    __ygDragDrop: true,
-
-    
-    constrainX: false,
-
-    
-    constrainY: false,
-
-    
-    minX: 0,
-
-    
-    maxX: 0,
-
-    
-    minY: 0,
-
-    
-    maxY: 0,
-
-    
-    maintainOffset: false,
-
-    
-    xTicks: null,
-
-    
-    yTicks: null,
-
-    
-    primaryButtonOnly: true,
-
-    
-    available: false,
-
-    
-    hasOuterHandles: false,
-
-    
-    b4StartDrag: function(x, y) { },
-
-    
-    startDrag: function(x, y) {  },
-
-    
-    b4Drag: function(e) { },
-
-    
-    onDrag: function(e) {  },
-
-    
-    onDragEnter: function(e, id) {  },
-
-    
-    b4DragOver: function(e) { },
-
-    
-    onDragOver: function(e, id) {  },
-
-    
-    b4DragOut: function(e) { },
-
-    
-    onDragOut: function(e, id) {  },
-
-    
-    b4DragDrop: function(e) { },
-
-    
-    onDragDrop: function(e, id) {  },
-
-    
-    onInvalidDrop: function(e) {  },
-
-    
-    b4EndDrag: function(e) { },
-
-    
-    endDrag: function(e) {  },
-
-    
-    b4MouseDown: function(e) {  },
-
-    
-    onMouseDown: function(e) {  },
-
-    
-    onMouseUp: function(e) {  },
-
-    
-    onAvailable: function () {
-    },
-
-    
-    defaultPadding : {left:0, right:0, top:0, bottom:0},
-
-    
-    constrainTo : function(constrainTo, pad, inContent){
-        if(typeof pad == &quot;number&quot;){
-            pad = {left: pad, right:pad, top:pad, bottom:pad};
-        }
-        pad = pad || this.defaultPadding;
-        var b = Ext.get(this.getEl()).getBox();
-        var ce = Ext.get(constrainTo);
-        var s = ce.getScroll();
-        var c, cd = ce.dom;
-        if(cd == document.body){
-            c = { x: s.left, y: s.top, width: Ext.lib.Dom.getViewWidth(), height: Ext.lib.Dom.getViewHeight()};
-        }else{
-            var xy = ce.getXY();
-            c = {x : xy[0]+s.left, y: xy[1]+s.top, width: cd.clientWidth, height: cd.clientHeight};
-        }
-
-
-        var topSpace = b.y - c.y;
-        var leftSpace = b.x - c.x;
-
-        this.resetConstraints();
-        this.setXConstraint(leftSpace - (pad.left||0), // left
-                c.width - leftSpace - b.width - (pad.right||0), //right
-				this.xTickSize
-        );
-        this.setYConstraint(topSpace - (pad.top||0), //top
-                c.height - topSpace - b.height - (pad.bottom||0), //bottom
-				this.yTickSize
-        );
-    },
-
-    
-    getEl: function() {
-        if (!this._domRef) {
-            this._domRef = Ext.getDom(this.id);
-        }
-
-        return this._domRef;
-    },
-
-    
-    getDragEl: function() {
-        return Ext.getDom(this.dragElId);
-    },
-
-    
-    init: function(id, sGroup, config) {
-        this.initTarget(id, sGroup, config);
-        Event.on(this.id, &quot;mousedown&quot;, this.handleMouseDown, this);
-        // Event.on(this.id, &quot;selectstart&quot;, Event.preventDefault);
-    },
-
-    
-    initTarget: function(id, sGroup, config) {
-
-        // configuration attributes
-        this.config = config || {};
-
-        // create a local reference to the drag and drop manager
-        this.DDM = Ext.dd.DDM;
-        // initialize the groups array
-        this.groups = {};
-
-        // assume that we have an element reference instead of an id if the
-        // parameter is not a string
-        if (typeof id !== &quot;string&quot;) {
-            id = Ext.id(id);
-        }
-
-        // set the id
-        this.id = id;
-
-        // add to an interaction group
-        this.addToGroup((sGroup) ? sGroup : &quot;default&quot;);
-
-        // We don't want to register this as the handle with the manager
-        // so we just set the id rather than calling the setter.
-        this.handleElId = id;
-
-        // the linked element is the element that gets dragged by default
-        this.setDragElId(id);
-
-        // by default, clicked anchors will not start drag operations.
-        this.invalidHandleTypes = { A: &quot;A&quot; };
-        this.invalidHandleIds = {};
-        this.invalidHandleClasses = [];
-
-        this.applyConfig();
-
-        this.handleOnAvailable();
-    },
-
-    
-    applyConfig: function() {
-
-        // configurable properties:
-        //    padding, isTarget, maintainOffset, primaryButtonOnly
-        this.padding           = this.config.padding || [0, 0, 0, 0];
-        this.isTarget          = (this.config.isTarget !== false);
-        this.maintainOffset    = (this.config.maintainOffset);
-        this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
-
-    },
-
-    
-    handleOnAvailable: function() {
-        this.available = true;
-        this.resetConstraints();
-        this.onAvailable();
-    },
-
-     
-    setPadding: function(iTop, iRight, iBot, iLeft) {
-        // this.padding = [iLeft, iRight, iTop, iBot];
-        if (!iRight &amp;&amp; 0 !== iRight) {
-            this.padding = [iTop, iTop, iTop, iTop];
-        } else if (!iBot &amp;&amp; 0 !== iBot) {
-            this.padding = [iTop, iRight, iTop, iRight];
-        } else {
-            this.padding = [iTop, iRight, iBot, iLeft];
-        }
-    },
-
-    
-    setInitPosition: function(diffX, diffY) {
-        var el = this.getEl();
-
-        if (!this.DDM.verifyEl(el)) {
-            return;
-        }
-
-        var dx = diffX || 0;
-        var dy = diffY || 0;
-
-        var p = Dom.getXY( el );
-
-        this.initPageX = p[0] - dx;
-        this.initPageY = p[1] - dy;
-
-        this.lastPageX = p[0];
-        this.lastPageY = p[1];
-
-
-        this.setStartPosition(p);
-    },
-
-    
-    setStartPosition: function(pos) {
-        var p = pos || Dom.getXY( this.getEl() );
-        this.deltaSetXY = null;
-
-        this.startPageX = p[0];
-        this.startPageY = p[1];
-    },
-
-    
-    addToGroup: function(sGroup) {
-        this.groups[sGroup] = true;
-        this.DDM.regDragDrop(this, sGroup);
-    },
-
-    
-    removeFromGroup: function(sGroup) {
-        if (this.groups[sGroup]) {
-            delete this.groups[sGroup];
-        }
-
-        this.DDM.removeDDFromGroup(this, sGroup);
-    },
-
-    
-    setDragElId: function(id) {
-        this.dragElId = id;
-    },
-
-    
-    setHandleElId: function(id) {
-        if (typeof id !== &quot;string&quot;) {
-            id = Ext.id(id);
-        }
-        this.handleElId = id;
-        this.DDM.regHandle(this.id, id);
-    },
-
-    
-    setOuterHandleElId: function(id) {
-        if (typeof id !== &quot;string&quot;) {
-            id = Ext.id(id);
-        }
-        Event.on(id, &quot;mousedown&quot;,
-                this.handleMouseDown, this);
-        this.setHandleElId(id);
-
-        this.hasOuterHandles = true;
-    },
-
-    
-    unreg: function() {
-        Event.un(this.id, &quot;mousedown&quot;,
-                this.handleMouseDown);
-        this._domRef = null;
-        this.DDM._remove(this);
-    },
-
-    destroy : function(){
-        this.unreg();
-    },
-
-    
-    isLocked: function() {
-        return (this.DDM.isLocked() || this.locked);
-    },
-
-    
-    handleMouseDown: function(e, oDD){
-        if (this.primaryButtonOnly &amp;&amp; e.button != 0) {
-            return;
-        }
-
-        if (this.isLocked()) {
-            return;
-        }
-
-        this.DDM.refreshCache(this.groups);
-
-        var pt = new Ext.lib.Point(Ext.lib.Event.getPageX(e), Ext.lib.Event.getPageY(e));
-        if (!this.hasOuterHandles &amp;&amp; !this.DDM.isOverTarget(pt, this) )  {
-        } else {
-            if (this.clickValidator(e)) {
-
-                // set the initial element position
-                this.setStartPosition();
-
-
-                this.b4MouseDown(e);
-                this.onMouseDown(e);
-
-                this.DDM.handleMouseDown(e, this);
-
-                this.DDM.stopEvent(e);
-            } else {
-
-
-            }
-        }
-    },
-
-    clickValidator: function(e) {
-        var target = e.getTarget();
-        return ( this.isValidHandleChild(target) &amp;&amp;
-                    (this.id == this.handleElId ||
-                        this.DDM.handleWasClicked(target, this.id)) );
-    },
-
-    
-    addInvalidHandleType: function(tagName) {
-        var type = tagName.toUpperCase();
-        this.invalidHandleTypes[type] = type;
-    },
-
-    
-    addInvalidHandleId: function(id) {
-        if (typeof id !== &quot;string&quot;) {
-            id = Ext.id(id);
-        }
-        this.invalidHandleIds[id] = id;
-    },
-
-    
-    addInvalidHandleClass: function(cssClass) {
-        this.invalidHandleClasses.push(cssClass);
-    },
-
-    
-    removeInvalidHandleType: function(tagName) {
-        var type = tagName.toUpperCase();
-        // this.invalidHandleTypes[type] = null;
-        delete this.invalidHandleTypes[type];
-    },
-
-    
-    removeInvalidHandleId: function(id) {
-        if (typeof id !== &quot;string&quot;) {
-            id = Ext.id(id);
-        }
-        delete this.invalidHandleIds[id];
-    },
-
-    
-    removeInvalidHandleClass: function(cssClass) {
-        for (var i=0, len=this.invalidHandleClasses.length; i&lt;len; ++i) {
-            if (this.invalidHandleClasses[i] == cssClass) {
-                delete this.invalidHandleClasses[i];
-            }
-        }
-    },
-
-    
-    isValidHandleChild: function(node) {
-
-        var valid = true;
-        // var n = (node.nodeName == &quot;#text&quot;) ? node.parentNode : node;
-        var nodeName;
-        try {
-            nodeName = node.nodeName.toUpperCase();
-        } catch(e) {
-            nodeName = node.nodeName;
-        }
-        valid = valid &amp;&amp; !this.invalidHandleTypes[nodeName];
-        valid = valid &amp;&amp; !this.invalidHandleIds[node.id];
-
-        for (var i=0, len=this.invalidHandleClasses.length; valid &amp;&amp; i&lt;len; ++i) {
-            valid = !Ext.fly(node).hasClass(this.invalidHandleClasses[i]);
-        }
-
-
-        return valid;
-
-    },
-
-    
-    setXTicks: function(iStartX, iTickSize) {
-        this.xTicks = [];
-        this.xTickSize = iTickSize;
-
-        var tickMap = {};
-
-        for (var i = this.initPageX; i &gt;= this.minX; i = i - iTickSize) {
-            if (!tickMap[i]) {
-                this.xTicks[this.xTicks.length] = i;
-                tickMap[i] = true;
-            }
-        }
-
-        for (i = this.initPageX; i &lt;= this.maxX; i = i + iTickSize) {
-            if (!tickMap[i]) {
-                this.xTicks[this.xTicks.length] = i;
-                tickMap[i] = true;
-            }
-        }
-
-        this.xTicks.sort(this.DDM.numericSort) ;
-    },
-
-    
-    setYTicks: function(iStartY, iTickSize) {
-        this.yTicks = [];
-        this.yTickSize = iTickSize;
-
-        var tickMap = {};
-
-        for (var i = this.initPageY; i &gt;= this.minY; i = i - iTickSize) {
-            if (!tickMap[i]) {
-                this.yTicks[this.yTicks.length] = i;
-                tickMap[i] = true;
-            }
-        }
-
-        for (i = this.initPageY; i &lt;= this.maxY; i = i + iTickSize) {
-            if (!tickMap[i]) {
-                this.yTicks[this.yTicks.length] = i;
-                tickMap[i] = true;
-            }
-        }
-
-        this.yTicks.sort(this.DDM.numericSort) ;
-    },
-
-    
-    setXConstraint: function(iLeft, iRight, iTickSize) {
-        this.leftConstraint = iLeft;
-        this.rightConstraint = iRight;
-
-        this.minX = this.initPageX - iLeft;
-        this.maxX = this.initPageX + iRight;
-        if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
-
-        this.constrainX = true;
-    },
-
-    
-    clearConstraints: function() {
-        this.constrainX = false;
-        this.constrainY = false;
-        this.clearTicks();
-    },
-
-    
-    clearTicks: function() {
-        this.xTicks = null;
-        this.yTicks = null;
-        this.xTickSize = 0;
-        this.yTickSize = 0;
-    },
-
-    
-    setYConstraint: function(iUp, iDown, iTickSize) {
-        this.topConstraint = iUp;
-        this.bottomConstraint = iDown;
-
-        this.minY = this.initPageY - iUp;
-        this.maxY = this.initPageY + iDown;
-        if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
-
-        this.constrainY = true;
-
-    },
-
-    
-    resetConstraints: function() {
-
-
-        // Maintain offsets if necessary
-        if (this.initPageX || this.initPageX === 0) {
-            // figure out how much this thing has moved
-            var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
-            var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
-
-            this.setInitPosition(dx, dy);
-
-        // This is the first time we have detected the element's position
-        } else {
-            this.setInitPosition();
-        }
-
-        if (this.constrainX) {
-            this.setXConstraint( this.leftConstraint,
-                                 this.rightConstraint,
-                                 this.xTickSize        );
-        }
-
-        if (this.constrainY) {
-            this.setYConstraint( this.topConstraint,
-                                 this.bottomConstraint,
-                                 this.yTickSize         );
-        }
-    },
-
-    
-    getTick: function(val, tickArray) {
-
-        if (!tickArray) {
-            // If tick interval is not defined, it is effectively 1 pixel,
-            // so we return the value passed to us.
-            return val;
-        } else if (tickArray[0] &gt;= val) {
-            // The value is lower than the first tick, so we return the first
-            // tick.
-            return tickArray[0];
-        } else {
-            for (var i=0, len=tickArray.length; i&lt;len; ++i) {
-                var next = i + 1;
-                if (tickArray[next] &amp;&amp; tickArray[next] &gt;= val) {
-                    var diff1 = val - tickArray[i];
-                    var diff2 = tickArray[next] - val;
-                    return (diff2 &gt; diff1) ? tickArray[i] : tickArray[next];
-                }
-            }
-
-            // The value is larger than the last tick, so we return the last
-            // tick.
-            return tickArray[tickArray.length - 1];
-        }
-    },
-
-    
-    toString: function() {
-        return (&quot;DragDrop &quot; + this.id);
-    }
-
-};
-
-})();
-
-
-// Only load the library once.  Rewriting the manager class would orphan
-// existing drag and drop instances.
-if (!Ext.dd.DragDropMgr) {
-
-
-Ext.dd.DragDropMgr = function() {
-
-    var Event = Ext.EventManager;
-
-    return {
-
-        
-        ids: {},
-
-        
-        handleIds: {},
-
-        
-        dragCurrent: null,
-
-        
-        dragOvers: {},
-
-        
-        deltaX: 0,
-
-        
-        deltaY: 0,
-
-        
-        preventDefault: true,
-
-        
-        stopPropagation: true,
-
-        
-        initialized: false,
-
-        
-        locked: false,
-
-        
-        init: function() {
-            this.initialized = true;
-        },
-
-        
-        POINT: 0,
-
-        
-        INTERSECT: 1,
-
-        
-        mode: 0,
-
-        
-        _execOnAll: function(sMethod, args) {
-            for (var i in this.ids) {
-                for (var j in this.ids[i]) {
-                    var oDD = this.ids[i][j];
-                    if (! this.isTypeOfDD(oDD)) {
-                        continue;
-                    }
-                    oDD[sMethod].apply(oDD, args);
-                }
-            }
-        },
-
-        
-        _onLoad: function() {
-
-            this.init();
-
-
-            Event.on(document, &quot;mouseup&quot;,   this.handleMouseUp, this, true);
-            Event.on(document, &quot;mousemove&quot;, this.handleMouseMove, this, true);
-            Event.on(window,   &quot;unload&quot;,    this._onUnload, this, true);
-            Event.on(window,   &quot;resize&quot;,    this._onResize, this, true);
-            // Event.on(window,   &quot;mouseout&quot;,    this._test);
-
-        },
-
-        
-        _onResize: function(e) {
-            this._execOnAll(&quot;resetConstraints&quot;, []);
-        },
-
-        
-        lock: function() { this.locked = true; },
-
-        
-        unlock: function() { this.locked = false; },
-
-        
-        isLocked: function() { return this.locked; },
-
-        
-        locationCache: {},
-
-        
-        useCache: true,
-
-        
-        clickPixelThresh: 3,
-
-        
-        clickTimeThresh: 350,
-
-        
-        dragThreshMet: false,
-
-        
-        clickTimeout: null,
-
-        
-        startX: 0,
-
-        
-        startY: 0,
-
-        
-        regDragDrop: function(oDD, sGroup) {
-            if (!this.initialized) { this.init(); }
-
-            if (!this.ids[sGroup]) {
-                this.ids[sGroup] = {};
-            }
-            this.ids[sGroup][oDD.id] = oDD;
-        },
-
-        
-        removeDDFromGroup: function(oDD, sGroup) {
-            if (!this.ids[sGroup]) {
-                this.ids[sGroup] = {};
-            }
-
-            var obj = this.ids[sGroup];
-            if (obj &amp;&amp; obj[oDD.id]) {
-                delete obj[oDD.id];
-            }
-        },
-
-        
-        _remove: function(oDD) {
-            for (var g in oDD.groups) {
-                if (g &amp;&amp; this.ids[g] &amp;&amp; this.ids[g][oDD.id]) {
-                    delete this.ids[g][oDD.id];
-                }
-            }
-            delete this.handleIds[oDD.id];
-        },
-
-        
-        regHandle: function(sDDId, sHandleId) {
-            if (!this.handleIds[sDDId]) {
-                this.handleIds[sDDId] = {};
-            }
-            this.handleIds[sDDId][sHandleId] = sHandleId;
-        },
-
-        
-        isDragDrop: function(id) {
-            return ( this.getDDById(id) ) ? true : false;
-        },
-
-        
-        getRelated: function(p_oDD, bTargetsOnly) {
-            var oDDs = [];
-            for (var i in p_oDD.groups) {
-                for (var j in this.ids[i]) {
-                    var dd = this.ids[i][j];
-                    if (! this.isTypeOfDD(dd)) {
-                        continue;
-                    }
-                    if (!bTargetsOnly || dd.isTarget) {
-                        oDDs[oDDs.length] = dd;
-                    }
-                }
-            }
-
-            return oDDs;
-        },
-
-        
-        isLegalTarget: function (oDD, oTargetDD) {
-            var targets = this.getRelated(oDD, true);
-            for (var i=0, len=targets.length;i&lt;len;++i) {
-                if (targets[i].id == oTargetDD.id) {
-                    return true;
-                }
-            }
-
-            return false;
-        },
-
-        
-        isTypeOfDD: function (oDD) {
-            return (oDD &amp;&amp; oDD.__ygDragDrop);
-        },
-
-        
-        isHandle: function(sDDId, sHandleId) {
-            return ( this.handleIds[sDDId] &amp;&amp;
-                            this.handleIds[sDDId][sHandleId] );
-        },
-
-        
-        getDDById: function(id) {
-            for (var i in this.ids) {
-                if (this.ids[i][id]) {
-                    return this.ids[i][id];
-                }
-            }
-            return null;
-        },
-
-        
-        handleMouseDown: function(e, oDD) {
-            if(Ext.QuickTips){
-                Ext.QuickTips.disable();
-            }
-            if(this.dragCurrent){
-                // the original browser mouseup wasn't handled (e.g. outside FF browser window)
-                // so clean up first to avoid breaking the next drag
-                this.handleMouseUp(e);
-            }
-            
-            this.currentTarget = e.getTarget();
-            this.dragCurrent = oDD;
-
-            var el = oDD.getEl();
-
-            // track start position
-            this.startX = e.getPageX();
-            this.startY = e.getPageY();
-
-            this.deltaX = this.startX - el.offsetLeft;
-            this.deltaY = this.startY - el.offsetTop;
-
-            this.dragThreshMet = false;
-
-            this.clickTimeout = setTimeout(
-                    function() {
-                        var DDM = Ext.dd.DDM;
-                        DDM.startDrag(DDM.startX, DDM.startY);
-                    },
-                    this.clickTimeThresh );
-        },
-
-        
-        startDrag: function(x, y) {
-            clearTimeout(this.clickTimeout);
-            if (this.dragCurrent) {
-                this.dragCurrent.b4StartDrag(x, y);
-                this.dragCurrent.startDrag(x, y);
-            }
-            this.dragThreshMet = true;
-        },
-
-        
-        handleMouseUp: function(e) {
-
-            if(Ext.QuickTips){
-                Ext.QuickTips.enable();
-            }
-            if (! this.dragCurrent) {
-                return;
-            }
-
-            clearTimeout(this.clickTimeout);
-
-            if (this.dragThreshMet) {
-                this.fireEvents(e, true);
-            } else {
-            }
-
-            this.stopDrag(e);
-
-            this.stopEvent(e);
-        },
-
-        
-        stopEvent: function(e){
-            if(this.stopPropagation) {
-                e.stopPropagation();
-            }
-
-            if (this.preventDefault) {
-                e.preventDefault();
-            }
-        },
-
-        
-        stopDrag: function(e) {
-            // Fire the drag end event for the item that was dragged
-            if (this.dragCurrent) {
-                if (this.dragThreshMet) {
-                    this.dragCurrent.b4EndDrag(e);
-                    this.dragCurrent.endDrag(e);
-                }
-
-                this.dragCurrent.onMouseUp(e);
-            }
-
-            this.dragCurrent = null;
-            this.dragOvers = {};
-        },
-
-        
-        handleMouseMove: function(e) {
-            if (! this.dragCurrent) {
-                return true;
-            }
-            // var button = e.which || e.button;
-
-            // check for IE mouseup outside of page boundary
-            if (Ext.isIE &amp;&amp; (e.button !== 0 &amp;&amp; e.button !== 1 &amp;&amp; e.button !== 2)) {
-                this.stopEvent(e);
-                return this.handleMouseUp(e);
-            }
-
-            if (!this.dragThreshMet) {
-                var diffX = Math.abs(this.startX - e.getPageX());
-                var diffY = Math.abs(this.startY - e.getPageY());
-                if (diffX &gt; this.clickPixelThresh ||
-                            diffY &gt; this.clickPixelThresh) {
-                    this.startDrag(this.startX, this.startY);
-                }
-            }
-
-            if (this.dragThreshMet) {
-                this.dragCurrent.b4Drag(e);
-                this.dragCurrent.onDrag(e);
-                if(!this.dragCurrent.moveOnly){
-                    this.fireEvents(e, false);
-                }
-            }
-
-            this.stopEvent(e);
-
-            return true;
-        },
-
-        
-        fireEvents: function(e, isDrop) {
-            var dc = this.dragCurrent;
-
-            // If the user did the mouse up outside of the window, we could
-            // get here even though we have ended the drag.
-            if (!dc || dc.isLocked()) {
-                return;
-            }
-
-            var pt = e.getPoint();
-
-            // cache the previous dragOver array
-            var oldOvers = [];
-
-            var outEvts   = [];
-            var overEvts  = [];
-            var dropEvts  = [];
-            var enterEvts = [];
-
-            // Check to see if the object(s) we were hovering over is no longer
-            // being hovered over so we can fire the onDragOut event
-            for (var i in this.dragOvers) {
-
-                var ddo = this.dragOvers[i];
-
-                if (! this.isTypeOfDD(ddo)) {
-                    continue;
-                }
-
-                if (! this.isOverTarget(pt, ddo, this.mode)) {
-                    outEvts.push( ddo );
-                }
-
-                oldOvers[i] = true;
-                delete this.dragOvers[i];
-            }
-
-            for (var sGroup in dc.groups) {
-
-                if (&quot;string&quot; != typeof sGroup) {
-                    continue;
-                }
-
-                for (i in this.ids[sGroup]) {
-                    var oDD = this.ids[sGroup][i];
-                    if (! this.isTypeOfDD(oDD)) {
-                        continue;
-                    }
-
-                    if (oDD.isTarget &amp;&amp; !oDD.isLocked() &amp;&amp; ((oDD != dc) || (dc.ignoreSelf === false))) {
-                        if (this.isOverTarget(pt, oDD, this.mode)) {
-                            // look for drop interactions
-                            if (isDrop) {
-                                dropEvts.push( oDD );
-                            // look for drag enter and drag over interactions
-                            } else {
-
-                                // initial drag over: dragEnter fires
-                                if (!oldOvers[oDD.id]) {
-                                    enterEvts.push( oDD );
-                                // subsequent drag overs: dragOver fires
-                                } else {
-                                    overEvts.push( oDD );
-                                }
-
-                                this.dragOvers[oDD.id] = oDD;
-                            }
-                        }
-                    }
-                }
-            }
-
-            if (this.mode) {
-                if (outEvts.length) {
-                    dc.b4DragOut(e, outEvts);
-                    dc.onDragOut(e, outEvts);
-                }
-
-                if (enterEvts.length) {
-                    dc.onDragEnter(e, enterEvts);
-                }
-
-                if (overEvts.length) {
-                    dc.b4DragOver(e, overEvts);
-                    dc.onDragOver(e, overEvts);
-                }
-
-                if (dropEvts.length) {
-                    dc.b4DragDrop(e, dropEvts);
-                    dc.onDragDrop(e, dropEvts);
-                }
-
-            } else {
-                // fire dragout events
-                var len = 0;
-                for (i=0, len=outEvts.length; i&lt;len; ++i) {
-                    dc.b4DragOut(e, outEvts[i].id);
-                    dc.onDragOut(e, outEvts[i].id);
-                }
-
-                // fire enter events
-                for (i=0,len=enterEvts.length; i&lt;len; ++i) {
-                    // dc.b4DragEnter(e, oDD.id);
-                    dc.onDragEnter(e, enterEvts[i].id);
-                }
-
-                // fire over events
-                for (i=0,len=overEvts.length; i&lt;len; ++i) {
-                    dc.b4DragOver(e, overEvts[i].id);
-                    dc.onDragOver(e, overEvts[i].id);
-                }
-
-                // fire drop events
-                for (i=0, len=dropEvts.length; i&lt;len; ++i) {
-                    dc.b4DragDrop(e, dropEvts[i].id);
-                    dc.onDragDrop(e, dropEvts[i].id);
-                }
-
-            }
-
-            // notify about a drop that did not find a target
-            if (isDrop &amp;&amp; !dropEvts.length) {
-                dc.onInvalidDrop(e);
-            }
-
-        },
-
-        
-        getBestMatch: function(dds) {
-            var winner = null;
-            // Return null if the input is not what we expect
-            //if (!dds || !dds.length || dds.length == 0) {
-               // winner = null;
-            // If there is only one item, it wins
-            //} else if (dds.length == 1) {
-
-            var len = dds.length;
-
-            if (len == 1) {
-                winner = dds[0];
-            } else {
-                // Loop through the targeted items
-                for (var i=0; i&lt;len; ++i) {
-                    var dd = dds[i];
-                    // If the cursor is over the object, it wins.  If the
-                    // cursor is over multiple matches, the first one we come
-                    // to wins.
-                    if (dd.cursorIsOver) {
-                        winner = dd;
-                        break;
-                    // Otherwise the object with the most overlap wins
-                    } else {
-                        if (!winner ||
-                            winner.overlap.getArea() &lt; dd.overlap.getArea()) {
-                            winner = dd;
-                        }
-                    }
-                }
-            }
-
-            return winner;
-        },
-
-        
-        refreshCache: function(groups) {
-            for (var sGroup in groups) {
-                if (&quot;string&quot; != typeof sGroup) {
-                    continue;
-                }
-                for (var i in this.ids[sGroup]) {
-                    var oDD = this.ids[sGroup][i];
-
-                    if (this.isTypeOfDD(oDD)) {
-                    // if (this.isTypeOfDD(oDD) &amp;&amp; oDD.isTarget) {
-                        var loc = this.getLocation(oDD);
-                        if (loc) {
-                            this.locationCache[oDD.id] = loc;
-                        } else {
-                            delete this.locationCache[oDD.id];
-                            // this will unregister the drag and drop object if
-                            // the element is not in a usable state
-                            // oDD.unreg();
-                        }
-                    }
-                }
-            }
-        },
-
-        
-        verifyEl: function(el) {
-            if (el) {
-                var parent;
-                if(Ext.isIE){
-                    try{
-                        parent = el.offsetParent;
-                    }catch(e){}
-                }else{
-                    parent = el.offsetParent;
-                }
-                if (parent) {
-                    return true;
-                }
-            }
-
-            return false;
-        },
-
-        
-        getLocation: function(oDD) {
-            if (! this.isTypeOfDD(oDD)) {
-                return null;
-            }
-
-            var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
-
-            try {
-                pos= Ext.lib.Dom.getXY(el);
-            } catch (e) { }
-
-            if (!pos) {
-                return null;
-            }
-
-            x1 = pos[0];
-            x2 = x1 + el.offsetWidth;
-            y1 = pos[1];
-            y2 = y1 + el.offsetHeight;
-
-            t = y1 - oDD.padding[0];
-            r = x2 + oDD.padding[1];
-            b = y2 + oDD.padding[2];
-            l = x1 - oDD.padding[3];
-
-            return new Ext.lib.Region( t, r, b, l );
-        },
-
-        
-        isOverTarget: function(pt, oTarget, intersect) {
-            // use cache if available
-            var loc = this.locationCache[oTarget.id];
-            if (!loc || !this.useCache) {
-                loc = this.getLocation(oTarget);
-                this.locationCache[oTarget.id] = loc;
-
-            }
-
-            if (!loc) {
-                return false;
-            }
-
-            oTarget.cursorIsOver = loc.contains( pt );
-
-            // DragDrop is using this as a sanity check for the initial mousedown
-            // in this case we are done.  In POINT mode, if the drag obj has no
-            // contraints, we are also done. Otherwise we need to evaluate the
-            // location of the target as related to the actual location of the
-            // dragged element.
-            var dc = this.dragCurrent;
-            if (!dc || !dc.getTargetCoord ||
-                    (!intersect &amp;&amp; !dc.constrainX &amp;&amp; !dc.constrainY)) {
-                return oTarget.cursorIsOver;
-            }
-
-            oTarget.overlap = null;
-
-            // Get the current location of the drag element, this is the
-            // location of the mouse event less the delta that represents
-            // where the original mousedown happened on the element.  We
-            // need to consider constraints and ticks as well.
-            var pos = dc.getTargetCoord(pt.x, pt.y);
-
-            var el = dc.getDragEl();
-            var curRegion = new Ext.lib.Region( pos.y,
-                                                   pos.x + el.offsetWidth,
-                                                   pos.y + el.offsetHeight,
-                                                   pos.x );
-
-            var overlap = curRegion.intersect(loc);
-
-            if (overlap) {
-                oTarget.overlap = overlap;
-                return (intersect) ? true : oTarget.cursorIsOver;
-            } else {
-                return false;
-            }
-        },
-
-        
-        _onUnload: function(e, me) {
-            Ext.dd.DragDropMgr.unregAll();
-        },
-
-        
-        unregAll: function() {
-
-            if (this.dragCurrent) {
-                this.stopDrag();
-                this.dragCurrent = null;
-            }
-
-            this._execOnAll(&quot;unreg&quot;, []);
-
-            for (var i in this.elementCache) {
-                delete this.elementCache[i];
-            }
-
-            this.elementCache = {};
-            this.ids = {};
-        },
-
-        
-        elementCache: {},
-
-        
-        getElWrapper: function(id) {
-            var oWrapper = this.elementCache[id];
-            if (!oWrapper || !oWrapper.el) {
-                oWrapper = this.elementCache[id] =
-                    new this.ElementWrapper(Ext.getDom(id));
-            }
-            return oWrapper;
-        },
-
-        
-        getElement: function(id) {
-            return Ext.getDom(id);
-        },
-
-        
-        getCss: function(id) {
-            var el = Ext.getDom(id);
-            return (el) ? el.style : null;
-        },
-
-        
-        ElementWrapper: function(el) {
-                
-                this.el = el || null;
-                
-                this.id = this.el &amp;&amp; el.id;
-                
-                this.css = this.el &amp;&amp; el.style;
-            },
-
-        
-        getPosX: function(el) {
-            return Ext.lib.Dom.getX(el);
-        },
-
-        
-        getPosY: function(el) {
-            return Ext.lib.Dom.getY(el);
-        },
-
-        
-        swapNode: function(n1, n2) {
-            if (n1.swapNode) {
-                n1.swapNode(n2);
-            } else {
-                var p = n2.parentNode;
-                var s = n2.nextSibling;
-
-                if (s == n1) {
-                    p.insertBefore(n1, n2);
-                } else if (n2 == n1.nextSibling) {
-                    p.insertBefore(n2, n1);
-                } else {
-                    n1.parentNode.replaceChild(n2, n1);
-                    p.insertBefore(n1, s);
-                }
-            }
-        },
-
-        
-        getScroll: function () {
-            var t, l, dde=document.documentElement, db=document.body;
-            if (dde &amp;&amp; (dde.scrollTop || dde.scrollLeft)) {
-                t = dde.scrollTop;
-                l = dde.scrollLeft;
-            } else if (db) {
-                t = db.scrollTop;
-                l = db.scrollLeft;
-            } else {
-
-            }
-            return { top: t, left: l };
-        },
-
-        
-        getStyle: function(el, styleProp) {
-            return Ext.fly(el).getStyle(styleProp);
-        },
-
-        
-        getScrollTop: function () { return this.getScroll().top; },
-
-        
-        getScrollLeft: function () { return this.getScroll().left; },
-
-        
-        moveToEl: function (moveEl, targetEl) {
-            var aCoord = Ext.lib.Dom.getXY(targetEl);
-            Ext.lib.Dom.setXY(moveEl, aCoord);
-        },
-
-        
-        numericSort: function(a, b) { return (a - b); },
-
-        
-        _timeoutCount: 0,
-
-        
-        _addListeners: function() {
-            var DDM = Ext.dd.DDM;
-            if ( Ext.lib.Event &amp;&amp; document ) {
-                DDM._onLoad();
-            } else {
-                if (DDM._timeoutCount &gt; 2000) {
-                } else {
-                    setTimeout(DDM._addListeners, 10);
-                    if (document &amp;&amp; document.body) {
-                        DDM._timeoutCount += 1;
-                    }
-                }
-            }
-        },
-
-        
-        handleWasClicked: function(node, id) {
-            if (this.isHandle(id, node.id)) {
-                return true;
-            } else {
-                // check to see if this is a text node child of the one we want
-                var p = node.parentNode;
-
-                while (p) {
-                    if (this.isHandle(id, p.id)) {
-                        return true;
-                    } else {
-                        p = p.parentNode;
-                    }
-                }
-            }
-
-            return false;
-        }
-
-    };
-
-}();
-
-// shorter alias, save a few bytes
-Ext.dd.DDM = Ext.dd.DragDropMgr;
-Ext.dd.DDM._addListeners();
-
-}
-
-
-Ext.dd.DD = function(id, sGroup, config) {
-    if (id) {
-        this.init(id, sGroup, config);
-    }
-};
-
-Ext.extend(Ext.dd.DD, Ext.dd.DragDrop, {
-
-    
-    scroll: true,
-
-    
-    autoOffset: function(iPageX, iPageY) {
-        var x = iPageX - this.startPageX;
-        var y = iPageY - this.startPageY;
-        this.setDelta(x, y);
-    },
-
-    
-    setDelta: function(iDeltaX, iDeltaY) {
-        this.deltaX = iDeltaX;
-        this.deltaY = iDeltaY;
-    },
-
-    
-    setDragElPos: function(iPageX, iPageY) {
-        // the first time we do this, we are going to check to make sure
-        // the element has css positioning
-
-        var el = this.getDragEl();
-        this.alignElWithMouse(el, iPageX, iPageY);
-    },
-
-    
-    alignElWithMouse: function(el, iPageX, iPageY) {
-        var oCoord = this.getTargetCoord(iPageX, iPageY);
-        var fly = el.dom ? el : Ext.fly(el, '_dd');
-        if (!this.deltaSetXY) {
-            var aCoord = [oCoord.x, oCoord.y];
-            fly.setXY(aCoord);
-            var newLeft = fly.getLeft(true);
-            var newTop  = fly.getTop(true);
-            this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ];
-        } else {
-            fly.setLeftTop(oCoord.x + this.deltaSetXY[0], oCoord.y + this.deltaSetXY[1]);
-        }
-
-        this.cachePosition(oCoord.x, oCoord.y);
-        this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
-        return oCoord;
-    },
-
-    
-    cachePosition: function(iPageX, iPageY) {
-        if (iPageX) {
-            this.lastPageX = iPageX;
-            this.lastPageY = iPageY;
-        } else {
-            var aCoord = Ext.lib.Dom.getXY(this.getEl());
-            this.lastPageX = aCoord[0];
-            this.lastPageY = aCoord[1];
-        }
-    },
-
-    
-    autoScroll: function(x, y, h, w) {
-
-        if (this.scroll) {
-            // The client height
-            var clientH = Ext.lib.Dom.getViewHeight();
-
-            // The client width
-            var clientW = Ext.lib.Dom.getViewWidth();
-
-            // The amt scrolled down
-            var st = this.DDM.getScrollTop();
-
-            // The amt scrolled right
-            var sl = this.DDM.getScrollLeft();
-
-            // Location of the bottom of the element
-            var bot = h + y;
-
-            // Location of the right of the element
-            var right = w + x;
-
-            // The distance from the cursor to the bottom of the visible area,
-            // adjusted so that we don't scroll if the cursor is beyond the
-            // element drag constraints
-            var toBot = (clientH + st - y - this.deltaY);
-
-            // The distance from the cursor to the right of the visible area
-            var toRight = (clientW + sl - x - this.deltaX);
-
-
-            // How close to the edge the cursor must be before we scroll
-            // var thresh = (document.all) ? 100 : 40;
-            var thresh = 40;
-
-            // How many pixels to scroll per autoscroll op.  This helps to reduce
-            // clunky scrolling. IE is more sensitive about this ... it needs this
-            // value to be higher.
-            var scrAmt = (document.all) ? 80 : 30;
-
-            // Scroll down if we are near the bottom of the visible page and the
-            // obj extends below the crease
-            if ( bot &gt; clientH &amp;&amp; toBot &lt; thresh ) {
-                window.scrollTo(sl, st + scrAmt);
-            }
-
-            // Scroll up if the window is scrolled down and the top of the object
-            // goes above the top border
-            if ( y &lt; st &amp;&amp; st &gt; 0 &amp;&amp; y - st &lt; thresh ) {
-                window.scrollTo(sl, st - scrAmt);
-            }
-
-            // Scroll right if the obj is beyond the right border and the cursor is
-            // near the border.
-            if ( right &gt; clientW &amp;&amp; toRight &lt; thresh ) {
-                window.scrollTo(sl + scrAmt, st);
-            }
-
-            // Scroll left if the window has been scrolled to the right and the obj
-            // extends past the left border
-            if ( x &lt; sl &amp;&amp; sl &gt; 0 &amp;&amp; x - sl &lt; thresh ) {
-                window.scrollTo(sl - scrAmt, st);
-            }
-        }
-    },
-
-    
-    getTargetCoord: function(iPageX, iPageY) {
-
-
-        var x = iPageX - this.deltaX;
-        var y = iPageY - this.deltaY;
-
-        if (this.constrainX) {
-            if (x &lt; this.minX) { x = this.minX; }
-            if (x &gt; this.maxX) { x = this.maxX; }
-        }
-
-        if (this.constrainY) {
-            if (y &lt; this.minY) { y = this.minY; }
-            if (y &gt; this.maxY) { y = this.maxY; }
-        }
-
-        x = this.getTick(x, this.xTicks);
-        y = this.getTick(y, this.yTicks);
-
-
-        return {x:x, y:y};
-    },
-
-    
-    applyConfig: function() {
-        Ext.dd.DD.superclass.applyConfig.call(this);
-        this.scroll = (this.config.scroll !== false);
-    },
-
-    
-    b4MouseDown: function(e) {
-        // this.resetConstraints();
-        this.autoOffset(e.getPageX(),
-                            e.getPageY());
-    },
-
-    
-    b4Drag: function(e) {
-        this.setDragElPos(e.getPageX(),
-                            e.getPageY());
-    },
-
-    toString: function() {
-        return (&quot;DD &quot; + this.id);
-    }
-
-    //////////////////////////////////////////////////////////////////////////
-    // Debugging ygDragDrop events that can be overridden
-    //////////////////////////////////////////////////////////////////////////
-    
-
-});
-
-Ext.dd.DDProxy = function(id, sGroup, config) {
-    if (id) {
-        this.init(id, sGroup, config);
-        this.initFrame();
-    }
-};
-
-
-Ext.dd.DDProxy.dragElId = &quot;ygddfdiv&quot;;
-
-Ext.extend(Ext.dd.DDProxy, Ext.dd.DD, {
-
-    
-    resizeFrame: true,
-
-    
-    centerFrame: false,
-
-    
-    createFrame: function() {
-        var self = this;
-        var body = document.body;
-
-        if (!body || !body.firstChild) {
-            setTimeout( function() { self.createFrame(); }, 50 );
-            return;
-        }
-
-        var div = this.getDragEl();
-
-        if (!div) {
-            div    = document.createElement(&quot;div&quot;);
-            div.id = this.dragElId;
-            var s  = div.style;
-
-            s.position   = &quot;absolute&quot;;
-            s.visibility = &quot;hidden&quot;;
-            s.cursor     = &quot;move&quot;;
-            s.border     = &quot;2px solid #aaa&quot;;
-            s.zIndex     = 999;
-
-            // appendChild can blow up IE if invoked prior to the window load event
-            // while rendering a table.  It is possible there are other scenarios
-            // that would cause this to happen as well.
-            body.insertBefore(div, body.firstChild);
-        }
-    },
-
-    
-    initFrame: function() {
-        this.createFrame();
-    },
-
-    applyConfig: function() {
-        Ext.dd.DDProxy.superclass.applyConfig.call(this);
-
-        this.resizeFrame = (this.config.resizeFrame !== false);
-        this.centerFrame = (this.config.centerFrame);
-        this.setDragElId(this.config.dragElId || Ext.dd.DDProxy.dragElId);
-    },
-
-    
-    showFrame: function(iPageX, iPageY) {
-        var el = this.getEl();
-        var dragEl = this.getDragEl();
-        var s = dragEl.style;
-
-        this._resizeProxy();
-
-        if (this.centerFrame) {
-            this.setDelta( Math.round(parseInt(s.width,  10)/2),
-                           Math.round(parseInt(s.height, 10)/2) );
-        }
-
-        this.setDragElPos(iPageX, iPageY);
-
-        Ext.fly(dragEl).show();
-    },
-
-    
-    _resizeProxy: function() {
-        if (this.resizeFrame) {
-            var el = this.getEl();
-            Ext.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
-        }
-    },
-
-    // overrides Ext.dd.DragDrop
-    b4MouseDown: function(e) {
-        var x = e.getPageX();
-        var y = e.getPageY();
-        this.autoOffset(x, y);
-        this.setDragElPos(x, y);
-    },
-
-    // overrides Ext.dd.DragDrop
-    b4StartDrag: function(x, y) {
-        // show the drag frame
-        this.showFrame(x, y);
-    },
-
-    // overrides Ext.dd.DragDrop
-    b4EndDrag: function(e) {
-        Ext.fly(this.getDragEl()).hide();
-    },
-
-    // overrides Ext.dd.DragDrop
-    // By default we try to move the element to the last location of the frame.
-    // This is so that the default behavior mirrors that of Ext.dd.DD.
-    endDrag: function(e) {
-
-        var lel = this.getEl();
-        var del = this.getDragEl();
-
-        // Show the drag frame briefly so we can get its position
-        del.style.visibility = &quot;&quot;;
-
-        this.beforeMove();
-        // Hide the linked element before the move to get around a Safari
-        // rendering bug.
-        lel.style.visibility = &quot;hidden&quot;;
-        Ext.dd.DDM.moveToEl(lel, del);
-        del.style.visibility = &quot;hidden&quot;;
-        lel.style.visibility = &quot;&quot;;
-
-        this.afterDrag();
-    },
-
-    beforeMove : function(){
-
-    },
-
-    afterDrag : function(){
-
-    },
-
-    toString: function() {
-        return (&quot;DDProxy &quot; + this.id);
-    }
-
-});
-
-Ext.dd.DDTarget = function(id, sGroup, config) {
-    if (id) {
-        this.initTarget(id, sGroup, config);
-    }
-};
-
-// Ext.dd.DDTarget.prototype = new Ext.dd.DragDrop();
-Ext.extend(Ext.dd.DDTarget, Ext.dd.DragDrop, {
-    toString: function() {
-        return (&quot;DDTarget &quot; + this.id);
-    }
-});
-
+};
+
+Ext.util.TextMetrics = function(){
+    var shared;
+    return {
+        
+        measure : function(el, text, fixedWidth){
+            if(!shared){
+                shared = Ext.util.TextMetrics.Instance(el, fixedWidth);
+            }
+            shared.bind(el);
+            shared.setFixedWidth(fixedWidth || 'auto');
+            return shared.getSize(text);
+        },
+
+        
+        createInstance : function(el, fixedWidth){
+            return Ext.util.TextMetrics.Instance(el, fixedWidth);
+        }
+    };
+}();
+
+Ext.util.TextMetrics.Instance = function(bindTo, fixedWidth){
+    var ml = new Ext.Element(document.createElement('div'));
+    document.body.appendChild(ml.dom);
+    ml.position('absolute');
+    ml.setLeftTop(-1000, -1000);
+    ml.hide();
+
+    if(fixedWidth){
+        ml.setWidth(fixedWidth);
+    }
+
+    var instance = {
+        
+        getSize : function(text){
+            ml.update(text);
+            var s = ml.getSize();
+            ml.update('');
+            return s;
+        },
+
+        
+        bind : function(el){
+            ml.setStyle(
+                Ext.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height', 'text-transform', 'letter-spacing')
+            );
+        },
+
+        
+        setFixedWidth : function(width){
+            ml.setWidth(width);
+        },
+
+        
+        getWidth : function(text){
+            ml.dom.style.width = 'auto';
+            return this.getSize(text).width;
+        },
+
+        
+        getHeight : function(text){
+            return this.getSize(text).height;
+        }
+    };
+
+    instance.bind(bindTo);
+
+    return instance;
+};
+
+Ext.Element.addMethods({
+    
+    getTextWidth : function(text, min, max){
+        return (Ext.util.TextMetrics.measure(this.dom, Ext.value(text, this.dom.innerHTML, true)).width).constrain(min || 0, max || 1000000);
+    }
+});
+
+
+
+(function() {
+
+var Event=Ext.EventManager;
+var Dom=Ext.lib.Dom;
+
+
+Ext.dd.DragDrop = function(id, sGroup, config) {
+    if(id) {
+        this.init(id, sGroup, config);
+    }
+};
+
+Ext.dd.DragDrop.prototype = {
+
+    
+
+    
+    id: null,
+
+    
+    config: null,
+
+    
+    dragElId: null,
+
+    
+    handleElId: null,
+
+    
+    invalidHandleTypes: null,
+
+    
+    invalidHandleIds: null,
+
+    
+    invalidHandleClasses: null,
+
+    
+    startPageX: 0,
+
+    
+    startPageY: 0,
+
+    
+    groups: null,
+
+    
+    locked: false,
+
+    
+    lock: function() { this.locked = true; },
+
+    
+    moveOnly: false,
+
+    
+    unlock: function() { this.locked = false; },
+
+    
+    isTarget: true,
+
+    
+    padding: null,
+
+    
+    _domRef: null,
+
+    
+    __ygDragDrop: true,
+
+    
+    constrainX: false,
+
+    
+    constrainY: false,
+
+    
+    minX: 0,
+
+    
+    maxX: 0,
+
+    
+    minY: 0,
+
+    
+    maxY: 0,
+
+    
+    maintainOffset: false,
+
+    
+    xTicks: null,
+
+    
+    yTicks: null,
+
+    
+    primaryButtonOnly: true,
+
+    
+    available: false,
+
+    
+    hasOuterHandles: false,
+
+    
+    b4StartDrag: function(x, y) { },
+
+    
+    startDrag: function(x, y) {  },
+
+    
+    b4Drag: function(e) { },
+
+    
+    onDrag: function(e) {  },
+
+    
+    onDragEnter: function(e, id) {  },
+
+    
+    b4DragOver: function(e) { },
+
+    
+    onDragOver: function(e, id) {  },
+
+    
+    b4DragOut: function(e) { },
+
+    
+    onDragOut: function(e, id) {  },
+
+    
+    b4DragDrop: function(e) { },
+
+    
+    onDragDrop: function(e, id) {  },
+
+    
+    onInvalidDrop: function(e) {  },
+
+    
+    b4EndDrag: function(e) { },
+
+    
+    endDrag: function(e) {  },
+
+    
+    b4MouseDown: function(e) {  },
+
+    
+    onMouseDown: function(e) {  },
+
+    
+    onMouseUp: function(e) {  },
+
+    
+    onAvailable: function () {
+    },
+
+    
+    defaultPadding : {left:0, right:0, top:0, bottom:0},
+
+    
+    constrainTo : function(constrainTo, pad, inContent){
+        if(typeof pad == &quot;number&quot;){
+            pad = {left: pad, right:pad, top:pad, bottom:pad};
+        }
+        pad = pad || this.defaultPadding;
+        var b = Ext.get(this.getEl()).getBox();
+        var ce = Ext.get(constrainTo);
+        var s = ce.getScroll();
+        var c, cd = ce.dom;
+        if(cd == document.body){
+            c = { x: s.left, y: s.top, width: Ext.lib.Dom.getViewWidth(), height: Ext.lib.Dom.getViewHeight()};
+        }else{
+            var xy = ce.getXY();
+            c = {x : xy[0]+s.left, y: xy[1]+s.top, width: cd.clientWidth, height: cd.clientHeight};
+        }
+
+
+        var topSpace = b.y - c.y;
+        var leftSpace = b.x - c.x;
+
+        this.resetConstraints();
+        this.setXConstraint(leftSpace - (pad.left||0), // left
+                c.width - leftSpace - b.width - (pad.right||0), //right
+				this.xTickSize
+        );
+        this.setYConstraint(topSpace - (pad.top||0), //top
+                c.height - topSpace - b.height - (pad.bottom||0), //bottom
+				this.yTickSize
+        );
+    },
+
+    
+    getEl: function() {
+        if (!this._domRef) {
+            this._domRef = Ext.getDom(this.id);
+        }
+
+        return this._domRef;
+    },
+
+    
+    getDragEl: function() {
+        return Ext.getDom(this.dragElId);
+    },
+
+    
+    init: function(id, sGroup, config) {
+        this.initTarget(id, sGroup, config);
+        Event.on(this.id, &quot;mousedown&quot;, this.handleMouseDown, this);
+        // Event.on(this.id, &quot;selectstart&quot;, Event.preventDefault);
+    },
+
+    
+    initTarget: function(id, sGroup, config) {
+
+        // configuration attributes
+        this.config = config || {};
+
+        // create a local reference to the drag and drop manager
+        this.DDM = Ext.dd.DDM;
+        // initialize the groups array
+        this.groups = {};
+
+        // assume that we have an element reference instead of an id if the
+        // parameter is not a string
+        if (typeof id !== &quot;string&quot;) {
+            id = Ext.id(id);
+        }
+
+        // set the id
+        this.id = id;
+
+        // add to an interaction group
+        this.addToGroup((sGroup) ? sGroup : &quot;default&quot;);
+
+        // We don't want to register this as the handle with the manager
+        // so we just set the id rather than calling the setter.
+        this.handleElId = id;
+
+        // the linked element is the element that gets dragged by default
+        this.setDragElId(id);
+
+        // by default, clicked anchors will not start drag operations.
+        this.invalidHandleTypes = { A: &quot;A&quot; };
+        this.invalidHandleIds = {};
+        this.invalidHandleClasses = [];
+
+        this.applyConfig();
+
+        this.handleOnAvailable();
+    },
+
+    
+    applyConfig: function() {
+
+        // configurable properties:
+        //    padding, isTarget, maintainOffset, primaryButtonOnly
+        this.padding           = this.config.padding || [0, 0, 0, 0];
+        this.isTarget          = (this.config.isTarget !== false);
+        this.maintainOffset    = (this.config.maintainOffset);
+        this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
+
+    },
+
+    
+    handleOnAvailable: function() {
+        this.available = true;
+        this.resetConstraints();
+        this.onAvailable();
+    },
+
+     
+    setPadding: function(iTop, iRight, iBot, iLeft) {
+        // this.padding = [iLeft, iRight, iTop, iBot];
+        if (!iRight &amp;&amp; 0 !== iRight) {
+            this.padding = [iTop, iTop, iTop, iTop];
+        } else if (!iBot &amp;&amp; 0 !== iBot) {
+            this.padding = [iTop, iRight, iTop, iRight];
+        } else {
+            this.padding = [iTop, iRight, iBot, iLeft];
+        }
+    },
+
+    
+    setInitPosition: function(diffX, diffY) {
+        var el = this.getEl();
+
+        if (!this.DDM.verifyEl(el)) {
+            return;
+        }
+
+        var dx = diffX || 0;
+        var dy = diffY || 0;
+
+        var p = Dom.getXY( el );
+
+        this.initPageX = p[0] - dx;
+        this.initPageY = p[1] - dy;
+
+        this.lastPageX = p[0];
+        this.lastPageY = p[1];
+
+
+        this.setStartPosition(p);
+    },
+
+    
+    setStartPosition: function(pos) {
+        var p = pos || Dom.getXY( this.getEl() );
+        this.deltaSetXY = null;
+
+        this.startPageX = p[0];
+        this.startPageY = p[1];
+    },
+
+    
+    addToGroup: function(sGroup) {
+        this.groups[sGroup] = true;
+        this.DDM.regDragDrop(this, sGroup);
+    },
+
+    
+    removeFromGroup: function(sGroup) {
+        if (this.groups[sGroup]) {
+            delete this.groups[sGroup];
+        }
+
+        this.DDM.removeDDFromGroup(this, sGroup);
+    },
+
+    
+    setDragElId: function(id) {
+        this.dragElId = id;
+    },
+
+    
+    setHandleElId: function(id) {
+        if (typeof id !== &quot;string&quot;) {
+            id = Ext.id(id);
+        }
+        this.handleElId = id;
+        this.DDM.regHandle(this.id, id);
+    },
+
+    
+    setOuterHandleElId: function(id) {
+        if (typeof id !== &quot;string&quot;) {
+            id = Ext.id(id);
+        }
+        Event.on(id, &quot;mousedown&quot;,
+                this.handleMouseDown, this);
+        this.setHandleElId(id);
+
+        this.hasOuterHandles = true;
+    },
+
+    
+    unreg: function() {
+        Event.un(this.id, &quot;mousedown&quot;,
+                this.handleMouseDown);
+        this._domRef = null;
+        this.DDM._remove(this);
+    },
+
+    destroy : function(){
+        this.unreg();
+    },
+
+    
+    isLocked: function() {
+        return (this.DDM.isLocked() || this.locked);
+    },
+
+    
+    handleMouseDown: function(e, oDD){
+        if (this.primaryButtonOnly &amp;&amp; e.button != 0) {
+            return;
+        }
+
+        if (this.isLocked()) {
+            return;
+        }
+
+        this.DDM.refreshCache(this.groups);
+
+        var pt = new Ext.lib.Point(Ext.lib.Event.getPageX(e), Ext.lib.Event.getPageY(e));
+        if (!this.hasOuterHandles &amp;&amp; !this.DDM.isOverTarget(pt, this) )  {
+        } else {
+            if (this.clickValidator(e)) {
+
+                // set the initial element position
+                this.setStartPosition();
+
+
+                this.b4MouseDown(e);
+                this.onMouseDown(e);
+
+                this.DDM.handleMouseDown(e, this);
+
+                this.DDM.stopEvent(e);
+            } else {
+
+
+            }
+        }
+    },
+
+    clickValidator: function(e) {
+        var target = e.getTarget();
+        return ( this.isValidHandleChild(target) &amp;&amp;
+                    (this.id == this.handleElId ||
+                        this.DDM.handleWasClicked(target, this.id)) );
+    },
+
+    
+    addInvalidHandleType: function(tagName) {
+        var type = tagName.toUpperCase();
+        this.invalidHandleTypes[type] = type;
+    },
+
+    
+    addInvalidHandleId: function(id) {
+        if (typeof id !== &quot;string&quot;) {
+            id = Ext.id(id);
+        }
+        this.invalidHandleIds[id] = id;
+    },
+
+    
+    addInvalidHandleClass: function(cssClass) {
+        this.invalidHandleClasses.push(cssClass);
+    },
+
+    
+    removeInvalidHandleType: function(tagName) {
+        var type = tagName.toUpperCase();
+        // this.invalidHandleTypes[type] = null;
+        delete this.invalidHandleTypes[type];
+    },
+
+    
+    removeInvalidHandleId: function(id) {
+        if (typeof id !== &quot;string&quot;) {
+            id = Ext.id(id);
+        }
+        delete this.invalidHandleIds[id];
+    },
+
+    
+    removeInvalidHandleClass: function(cssClass) {
+        for (var i=0, len=this.invalidHandleClasses.length; i&lt;len; ++i) {
+            if (this.invalidHandleClasses[i] == cssClass) {
+                delete this.invalidHandleClasses[i];
+            }
+        }
+    },
+
+    
+    isValidHandleChild: function(node) {
+
+        var valid = true;
+        // var n = (node.nodeName == &quot;#text&quot;) ? node.parentNode : node;
+        var nodeName;
+        try {
+            nodeName = node.nodeName.toUpperCase();
+        } catch(e) {
+            nodeName = node.nodeName;
+        }
+        valid = valid &amp;&amp; !this.invalidHandleTypes[nodeName];
+        valid = valid &amp;&amp; !this.invalidHandleIds[node.id];
+
+        for (var i=0, len=this.invalidHandleClasses.length; valid &amp;&amp; i&lt;len; ++i) {
+            valid = !Ext.fly(node).hasClass(this.invalidHandleClasses[i]);
+        }
+
+
+        return valid;
+
+    },
+
+    
+    setXTicks: function(iStartX, iTickSize) {
+        this.xTicks = [];
+        this.xTickSize = iTickSize;
+
+        var tickMap = {};
+
+        for (var i = this.initPageX; i &gt;= this.minX; i = i - iTickSize) {
+            if (!tickMap[i]) {
+                this.xTicks[this.xTicks.length] = i;
+                tickMap[i] = true;
+            }
+        }
+
+        for (i = this.initPageX; i &lt;= this.maxX; i = i + iTickSize) {
+            if (!tickMap[i]) {
+                this.xTicks[this.xTicks.length] = i;
+                tickMap[i] = true;
+            }
+        }
+
+        this.xTicks.sort(this.DDM.numericSort) ;
+    },
+
+    
+    setYTicks: function(iStartY, iTickSize) {
+        this.yTicks = [];
+        this.yTickSize = iTickSize;
+
+        var tickMap = {};
+
+        for (var i = this.initPageY; i &gt;= this.minY; i = i - iTickSize) {
+            if (!tickMap[i]) {
+                this.yTicks[this.yTicks.length] = i;
+                tickMap[i] = true;
+            }
+        }
+
+        for (i = this.initPageY; i &lt;= this.maxY; i = i + iTickSize) {
+            if (!tickMap[i]) {
+                this.yTicks[this.yTicks.length] = i;
+                tickMap[i] = true;
+            }
+        }
+
+        this.yTicks.sort(this.DDM.numericSort) ;
+    },
+
+    
+    setXConstraint: function(iLeft, iRight, iTickSize) {
+        this.leftConstraint = iLeft;
+        this.rightConstraint = iRight;
+
+        this.minX = this.initPageX - iLeft;
+        this.maxX = this.initPageX + iRight;
+        if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
+
+        this.constrainX = true;
+    },
+
+    
+    clearConstraints: function() {
+        this.constrainX = false;
+        this.constrainY = false;
+        this.clearTicks();
+    },
+
+    
+    clearTicks: function() {
+        this.xTicks = null;
+        this.yTicks = null;
+        this.xTickSize = 0;
+        this.yTickSize = 0;
+    },
+
+    
+    setYConstraint: function(iUp, iDown, iTickSize) {
+        this.topConstraint = iUp;
+        this.bottomConstraint = iDown;
+
+        this.minY = this.initPageY - iUp;
+        this.maxY = this.initPageY + iDown;
+        if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
+
+        this.constrainY = true;
+
+    },
+
+    
+    resetConstraints: function() {
+
+
+        // Maintain offsets if necessary
+        if (this.initPageX || this.initPageX === 0) {
+            // figure out how much this thing has moved
+            var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
+            var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
+
+            this.setInitPosition(dx, dy);
+
+        // This is the first time we have detected the element's position
+        } else {
+            this.setInitPosition();
+        }
+
+        if (this.constrainX) {
+            this.setXConstraint( this.leftConstraint,
+                                 this.rightConstraint,
+                                 this.xTickSize        );
+        }
+
+        if (this.constrainY) {
+            this.setYConstraint( this.topConstraint,
+                                 this.bottomConstraint,
+                                 this.yTickSize         );
+        }
+    },
+
+    
+    getTick: function(val, tickArray) {
+
+        if (!tickArray) {
+            // If tick interval is not defined, it is effectively 1 pixel,
+            // so we return the value passed to us.
+            return val;
+        } else if (tickArray[0] &gt;= val) {
+            // The value is lower than the first tick, so we return the first
+            // tick.
+            return tickArray[0];
+        } else {
+            for (var i=0, len=tickArray.length; i&lt;len; ++i) {
+                var next = i + 1;
+                if (tickArray[next] &amp;&amp; tickArray[next] &gt;= val) {
+                    var diff1 = val - tickArray[i];
+                    var diff2 = tickArray[next] - val;
+                    return (diff2 &gt; diff1) ? tickArray[i] : tickArray[next];
+                }
+            }
+
+            // The value is larger than the last tick, so we return the last
+            // tick.
+            return tickArray[tickArray.length - 1];
+        }
+    },
+
+    
+    toString: function() {
+        return (&quot;DragDrop &quot; + this.id);
+    }
+
+};
+
+})();
+
+
+// Only load the library once.  Rewriting the manager class would orphan
+// existing drag and drop instances.
+if (!Ext.dd.DragDropMgr) {
+
+
+Ext.dd.DragDropMgr = function() {
+
+    var Event = Ext.EventManager;
+
+    return {
+
+        
+        ids: {},
+
+        
+        handleIds: {},
+
+        
+        dragCurrent: null,
+
+        
+        dragOvers: {},
+
+        
+        deltaX: 0,
+
+        
+        deltaY: 0,
+
+        
+        preventDefault: true,
+
+        
+        stopPropagation: true,
+
+        
+        initialized: false,
+
+        
+        locked: false,
+
+        
+        init: function() {
+            this.initialized = true;
+        },
+
+        
+        POINT: 0,
+
+        
+        INTERSECT: 1,
+
+        
+        mode: 0,
+
+        
+        _execOnAll: function(sMethod, args) {
+            for (var i in this.ids) {
+                for (var j in this.ids[i]) {
+                    var oDD = this.ids[i][j];
+                    if (! this.isTypeOfDD(oDD)) {
+                        continue;
+                    }
+                    oDD[sMethod].apply(oDD, args);
+                }
+            }
+        },
+
+        
+        _onLoad: function() {
+
+            this.init();
+
+
+            Event.on(document, &quot;mouseup&quot;,   this.handleMouseUp, this, true);
+            Event.on(document, &quot;mousemove&quot;, this.handleMouseMove, this, true);
+            Event.on(window,   &quot;unload&quot;,    this._onUnload, this, true);
+            Event.on(window,   &quot;resize&quot;,    this._onResize, this, true);
+            // Event.on(window,   &quot;mouseout&quot;,    this._test);
+
+        },
+
+        
+        _onResize: function(e) {
+            this._execOnAll(&quot;resetConstraints&quot;, []);
+        },
+
+        
+        lock: function() { this.locked = true; },
+
+        
+        unlock: function() { this.locked = false; },
+
+        
+        isLocked: function() { return this.locked; },
+
+        
+        locationCache: {},
+
+        
+        useCache: true,
+
+        
+        clickPixelThresh: 3,
+
+        
+        clickTimeThresh: 350,
+
+        
+        dragThreshMet: false,
+
+        
+        clickTimeout: null,
+
+        
+        startX: 0,
+
+        
+        startY: 0,
+
+        
+        regDragDrop: function(oDD, sGroup) {
+            if (!this.initialized) { this.init(); }
+
+            if (!this.ids[sGroup]) {
+                this.ids[sGroup] = {};
+            }
+            this.ids[sGroup][oDD.id] = oDD;
+        },
+
+        
+        removeDDFromGroup: function(oDD, sGroup) {
+            if (!this.ids[sGroup]) {
+                this.ids[sGroup] = {};
+            }
+
+            var obj = this.ids[sGroup];
+            if (obj &amp;&amp; obj[oDD.id]) {
+                delete obj[oDD.id];
+            }
+        },
+
+        
+        _remove: function(oDD) {
+            for (var g in oDD.groups) {
+                if (g &amp;&amp; this.ids[g] &amp;&amp; this.ids[g][oDD.id]) {
+                    delete this.ids[g][oDD.id];
+                }
+            }
+            delete this.handleIds[oDD.id];
+        },
+
+        
+        regHandle: function(sDDId, sHandleId) {
+            if (!this.handleIds[sDDId]) {
+                this.handleIds[sDDId] = {};
+            }
+            this.handleIds[sDDId][sHandleId] = sHandleId;
+        },
+
+        
+        isDragDrop: function(id) {
+            return ( this.getDDById(id) ) ? true : false;
+        },
+
+        
+        getRelated: function(p_oDD, bTargetsOnly) {
+            var oDDs = [];
+            for (var i in p_oDD.groups) {
+                for (var j in this.ids[i]) {
+                    var dd = this.ids[i][j];
+                    if (! this.isTypeOfDD(dd)) {
+                        continue;
+                    }
+                    if (!bTargetsOnly || dd.isTarget) {
+                        oDDs[oDDs.length] = dd;
+                    }
+                }
+            }
+
+            return oDDs;
+        },
+
+        
+        isLegalTarget: function (oDD, oTargetDD) {
+            var targets = this.getRelated(oDD, true);
+            for (var i=0, len=targets.length;i&lt;len;++i) {
+                if (targets[i].id == oTargetDD.id) {
+                    return true;
+                }
+            }
+
+            return false;
+        },
+
+        
+        isTypeOfDD: function (oDD) {
+            return (oDD &amp;&amp; oDD.__ygDragDrop);
+        },
+
+        
+        isHandle: function(sDDId, sHandleId) {
+            return ( this.handleIds[sDDId] &amp;&amp;
+                            this.handleIds[sDDId][sHandleId] );
+        },
+
+        
+        getDDById: function(id) {
+            for (var i in this.ids) {
+                if (this.ids[i][id]) {
+                    return this.ids[i][id];
+                }
+            }
+            return null;
+        },
+
+        
+        handleMouseDown: function(e, oDD) {
+            if(Ext.QuickTips){
+                Ext.QuickTips.disable();
+            }
+            if(this.dragCurrent){
+                // the original browser mouseup wasn't handled (e.g. outside FF browser window)
+                // so clean up first to avoid breaking the next drag
+                this.handleMouseUp(e);
+            }
+            
+            this.currentTarget = e.getTarget();
+            this.dragCurrent = oDD;
+
+            var el = oDD.getEl();
+
+            // track start position
+            this.startX = e.getPageX();
+            this.startY = e.getPageY();
+
+            this.deltaX = this.startX - el.offsetLeft;
+            this.deltaY = this.startY - el.offsetTop;
+
+            this.dragThreshMet = false;
+
+            this.clickTimeout = setTimeout(
+                    function() {
+                        var DDM = Ext.dd.DDM;
+                        DDM.startDrag(DDM.startX, DDM.startY);
+                    },
+                    this.clickTimeThresh );
+        },
+
+        
+        startDrag: function(x, y) {
+            clearTimeout(this.clickTimeout);
+            if (this.dragCurrent) {
+                this.dragCurrent.b4StartDrag(x, y);
+                this.dragCurrent.startDrag(x, y);
+            }
+            this.dragThreshMet = true;
+        },
+
+        
+        handleMouseUp: function(e) {
+
+            if(Ext.QuickTips){
+                Ext.QuickTips.enable();
+            }
+            if (! this.dragCurrent) {
+                return;
+            }
+
+            clearTimeout(this.clickTimeout);
+
+            if (this.dragThreshMet) {
+                this.fireEvents(e, true);
+            } else {
+            }
+
+            this.stopDrag(e);
+
+            this.stopEvent(e);
+        },
+
+        
+        stopEvent: function(e){
+            if(this.stopPropagation) {
+                e.stopPropagation();
+            }
+
+            if (this.preventDefault) {
+                e.preventDefault();
+            }
+        },
+
+        
+        stopDrag: function(e) {
+            // Fire the drag end event for the item that was dragged
+            if (this.dragCurrent) {
+                if (this.dragThreshMet) {
+                    this.dragCurrent.b4EndDrag(e);
+                    this.dragCurrent.endDrag(e);
+                }
+
+                this.dragCurrent.onMouseUp(e);
+            }
+
+            this.dragCurrent = null;
+            this.dragOvers = {};
+        },
+
+        
+        handleMouseMove: function(e) {
+            if (! this.dragCurrent) {
+                return true;
+            }
+            // var button = e.which || e.button;
+
+            // check for IE mouseup outside of page boundary
+            if (Ext.isIE &amp;&amp; (e.button !== 0 &amp;&amp; e.button !== 1 &amp;&amp; e.button !== 2)) {
+                this.stopEvent(e);
+                return this.handleMouseUp(e);
+            }
+
+            if (!this.dragThreshMet) {
+                var diffX = Math.abs(this.startX - e.getPageX());
+                var diffY = Math.abs(this.startY - e.getPageY());
+                if (diffX &gt; this.clickPixelThresh ||
+                            diffY &gt; this.clickPixelThresh) {
+                    this.startDrag(this.startX, this.startY);
+                }
+            }
+
+            if (this.dragThreshMet) {
+                this.dragCurrent.b4Drag(e);
+                this.dragCurrent.onDrag(e);
+                if(!this.dragCurrent.moveOnly){
+                    this.fireEvents(e, false);
+                }
+            }
+
+            this.stopEvent(e);
+
+            return true;
+        },
+
+        
+        fireEvents: function(e, isDrop) {
+            var dc = this.dragCurrent;
+
+            // If the user did the mouse up outside of the window, we could
+            // get here even though we have ended the drag.
+            if (!dc || dc.isLocked()) {
+                return;
+            }
+
+            var pt = e.getPoint();
+
+            // cache the previous dragOver array
+            var oldOvers = [];
+
+            var outEvts   = [];
+            var overEvts  = [];
+            var dropEvts  = [];
+            var enterEvts = [];
+
+            // Check to see if the object(s) we were hovering over is no longer
+            // being hovered over so we can fire the onDragOut event
+            for (var i in this.dragOvers) {
+
+                var ddo = this.dragOvers[i];
+
+                if (! this.isTypeOfDD(ddo)) {
+                    continue;
+                }
+
+                if (! this.isOverTarget(pt, ddo, this.mode)) {
+                    outEvts.push( ddo );
+                }
+
+                oldOvers[i] = true;
+                delete this.dragOvers[i];
+            }
+
+            for (var sGroup in dc.groups) {
+
+                if (&quot;string&quot; != typeof sGroup) {
+                    continue;
+                }
+
+                for (i in this.ids[sGroup]) {
+                    var oDD = this.ids[sGroup][i];
+                    if (! this.isTypeOfDD(oDD)) {
+                        continue;
+                    }
+
+                    if (oDD.isTarget &amp;&amp; !oDD.isLocked() &amp;&amp; ((oDD != dc) || (dc.ignoreSelf === false))) {
+                        if (this.isOverTarget(pt, oDD, this.mode)) {
+                            // look for drop interactions
+                            if (isDrop) {
+                                dropEvts.push( oDD );
+                            // look for drag enter and drag over interactions
+                            } else {
+
+                                // initial drag over: dragEnter fires
+                                if (!oldOvers[oDD.id]) {
+                                    enterEvts.push( oDD );
+                                // subsequent drag overs: dragOver fires
+                                } else {
+                                    overEvts.push( oDD );
+                                }
+
+                                this.dragOvers[oDD.id] = oDD;
+                            }
+                        }
+                    }
+                }
+            }
+
+            if (this.mode) {
+                if (outEvts.length) {
+                    dc.b4DragOut(e, outEvts);
+                    dc.onDragOut(e, outEvts);
+                }
+
+                if (enterEvts.length) {
+                    dc.onDragEnter(e, enterEvts);
+                }
+
+                if (overEvts.length) {
+                    dc.b4DragOver(e, overEvts);
+                    dc.onDragOver(e, overEvts);
+                }
+
+                if (dropEvts.length) {
+                    dc.b4DragDrop(e, dropEvts);
+                    dc.onDragDrop(e, dropEvts);
+                }
+
+            } else {
+                // fire dragout events
+                var len = 0;
+                for (i=0, len=outEvts.length; i&lt;len; ++i) {
+                    dc.b4DragOut(e, outEvts[i].id);
+                    dc.onDragOut(e, outEvts[i].id);
+                }
+
+                // fire enter events
+                for (i=0,len=enterEvts.length; i&lt;len; ++i) {
+                    // dc.b4DragEnter(e, oDD.id);
+                    dc.onDragEnter(e, enterEvts[i].id);
+                }
+
+                // fire over events
+                for (i=0,len=overEvts.length; i&lt;len; ++i) {
+                    dc.b4DragOver(e, overEvts[i].id);
+                    dc.onDragOver(e, overEvts[i].id);
+                }
+
+                // fire drop events
+                for (i=0, len=dropEvts.length; i&lt;len; ++i) {
+                    dc.b4DragDrop(e, dropEvts[i].id);
+                    dc.onDragDrop(e, dropEvts[i].id);
+                }
+
+            }
+
+            // notify about a drop that did not find a target
+            if (isDrop &amp;&amp; !dropEvts.length) {
+                dc.onInvalidDrop(e);
+            }
+
+        },
+
+        
+        getBestMatch: function(dds) {
+            var winner = null;
+            // Return null if the input is not what we expect
+            //if (!dds || !dds.length || dds.length == 0) {
+               // winner = null;
+            // If there is only one item, it wins
+            //} else if (dds.length == 1) {
+
+            var len = dds.length;
+
+            if (len == 1) {
+                winner = dds[0];
+            } else {
+                // Loop through the targeted items
+                for (var i=0; i&lt;len; ++i) {
+                    var dd = dds[i];
+                    // If the cursor is over the object, it wins.  If the
+                    // cursor is over multiple matches, the first one we come
+                    // to wins.
+                    if (dd.cursorIsOver) {
+                        winner = dd;
+                        break;
+                    // Otherwise the object with the most overlap wins
+                    } else {
+                        if (!winner ||
+                            winner.overlap.getArea() &lt; dd.overlap.getArea()) {
+                            winner = dd;
+                        }
+                    }
+                }
+            }
+
+            return winner;
+        },
+
+        
+        refreshCache: function(groups) {
+            for (var sGroup in groups) {
+                if (&quot;string&quot; != typeof sGroup) {
+                    continue;
+                }
+                for (var i in this.ids[sGroup]) {
+                    var oDD = this.ids[sGroup][i];
+
+                    if (this.isTypeOfDD(oDD)) {
+                    // if (this.isTypeOfDD(oDD) &amp;&amp; oDD.isTarget) {
+                        var loc = this.getLocation(oDD);
+                        if (loc) {
+                            this.locationCache[oDD.id] = loc;
+                        } else {
+                            delete this.locationCache[oDD.id];
+                            // this will unregister the drag and drop object if
+                            // the element is not in a usable state
+                            // oDD.unreg();
+                        }
+                    }
+                }
+            }
+        },
+
+        
+        verifyEl: function(el) {
+            if (el) {
+                var parent;
+                if(Ext.isIE){
+                    try{
+                        parent = el.offsetParent;
+                    }catch(e){}
+                }else{
+                    parent = el.offsetParent;
+                }
+                if (parent) {
+                    return true;
+                }
+            }
+
+            return false;
+        },
+
+        
+        getLocation: function(oDD) {
+            if (! this.isTypeOfDD(oDD)) {
+                return null;
+            }
+
+            var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
+
+            try {
+                pos= Ext.lib.Dom.getXY(el);
+            } catch (e) { }
+
+            if (!pos) {
+                return null;
+            }
+
+            x1 = pos[0];
+            x2 = x1 + el.offsetWidth;
+            y1 = pos[1];
+            y2 = y1 + el.offsetHeight;
+
+            t = y1 - oDD.padding[0];
+            r = x2 + oDD.padding[1];
+            b = y2 + oDD.padding[2];
+            l = x1 - oDD.padding[3];
+
+            return new Ext.lib.Region( t, r, b, l );
+        },
+
+        
+        isOverTarget: function(pt, oTarget, intersect) {
+            // use cache if available
+            var loc = this.locationCache[oTarget.id];
+            if (!loc || !this.useCache) {
+                loc = this.getLocation(oTarget);
+                this.locationCache[oTarget.id] = loc;
+
+            }
+
+            if (!loc) {
+                return false;
+            }
+
+            oTarget.cursorIsOver = loc.contains( pt );
+
+            // DragDrop is using this as a sanity check for the initial mousedown
+            // in this case we are done.  In POINT mode, if the drag obj has no
+            // contraints, we are also done. Otherwise we need to evaluate the
+            // location of the target as related to the actual location of the
+            // dragged element.
+            var dc = this.dragCurrent;
+            if (!dc || !dc.getTargetCoord ||
+                    (!intersect &amp;&amp; !dc.constrainX &amp;&amp; !dc.constrainY)) {
+                return oTarget.cursorIsOver;
+            }
+
+            oTarget.overlap = null;
+
+            // Get the current location of the drag element, this is the
+            // location of the mouse event less the delta that represents
+            // where the original mousedown happened on the element.  We
+            // need to consider constraints and ticks as well.
+            var pos = dc.getTargetCoord(pt.x, pt.y);
+
+            var el = dc.getDragEl();
+            var curRegion = new Ext.lib.Region( pos.y,
+                                                   pos.x + el.offsetWidth,
+                                                   pos.y + el.offsetHeight,
+                                                   pos.x );
+
+            var overlap = curRegion.intersect(loc);
+
+            if (overlap) {
+                oTarget.overlap = overlap;
+                return (intersect) ? true : oTarget.cursorIsOver;
+            } else {
+                return false;
+            }
+        },
+
+        
+        _onUnload: function(e, me) {
+            Ext.dd.DragDropMgr.unregAll();
+        },
+
+        
+        unregAll: function() {
+
+            if (this.dragCurrent) {
+                this.stopDrag();
+                this.dragCurrent = null;
+            }
+
+            this._execOnAll(&quot;unreg&quot;, []);
+
+            for (var i in this.elementCache) {
+                delete this.elementCache[i];
+            }
+
+            this.elementCache = {};
+            this.ids = {};
+        },
+
+        
+        elementCache: {},
+
+        
+        getElWrapper: function(id) {
+            var oWrapper = this.elementCache[id];
+            if (!oWrapper || !oWrapper.el) {
+                oWrapper = this.elementCache[id] =
+                    new this.ElementWrapper(Ext.getDom(id));
+            }
+            return oWrapper;
+        },
+
+        
+        getElement: function(id) {
+            return Ext.getDom(id);
+        },
+
+        
+        getCss: function(id) {
+            var el = Ext.getDom(id);
+            return (el) ? el.style : null;
+        },
+
+        
+        ElementWrapper: function(el) {
+                
+                this.el = el || null;
+                
+                this.id = this.el &amp;&amp; el.id;
+                
+                this.css = this.el &amp;&amp; el.style;
+            },
+
+        
+        getPosX: function(el) {
+            return Ext.lib.Dom.getX(el);
+        },
+
+        
+        getPosY: function(el) {
+            return Ext.lib.Dom.getY(el);
+        },
+
+        
+        swapNode: function(n1, n2) {
+            if (n1.swapNode) {
+                n1.swapNode(n2);
+            } else {
+                var p = n2.parentNode;
+                var s = n2.nextSibling;
+
+                if (s == n1) {
+                    p.insertBefore(n1, n2);
+                } else if (n2 == n1.nextSibling) {
+                    p.insertBefore(n2, n1);
+                } else {
+                    n1.parentNode.replaceChild(n2, n1);
+                    p.insertBefore(n1, s);
+                }
+            }
+        },
+
+        
+        getScroll: function () {
+            var t, l, dde=document.documentElement, db=document.body;
+            if (dde &amp;&amp; (dde.scrollTop || dde.scrollLeft)) {
+                t = dde.scrollTop;
+                l = dde.scrollLeft;
+            } else if (db) {
+                t = db.scrollTop;
+                l = db.scrollLeft;
+            } else {
+
+            }
+            return { top: t, left: l };
+        },
+
+        
+        getStyle: function(el, styleProp) {
+            return Ext.fly(el).getStyle(styleProp);
+        },
+
+        
+        getScrollTop: function () { return this.getScroll().top; },
+
+        
+        getScrollLeft: function () { return this.getScroll().left; },
+
+        
+        moveToEl: function (moveEl, targetEl) {
+            var aCoord = Ext.lib.Dom.getXY(targetEl);
+            Ext.lib.Dom.setXY(moveEl, aCoord);
+        },
+
+        
+        numericSort: function(a, b) { return (a - b); },
+
+        
+        _timeoutCount: 0,
+
+        
+        _addListeners: function() {
+            var DDM = Ext.dd.DDM;
+            if ( Ext.lib.Event &amp;&amp; document ) {
+                DDM._onLoad();
+            } else {
+                if (DDM._timeoutCount &gt; 2000) {
+                } else {
+                    setTimeout(DDM._addListeners, 10);
+                    if (document &amp;&amp; document.body) {
+                        DDM._timeoutCount += 1;
+                    }
+                }
+            }
+        },
+
+        
+        handleWasClicked: function(node, id) {
+            if (this.isHandle(id, node.id)) {
+                return true;
+            } else {
+                // check to see if this is a text node child of the one we want
+                var p = node.parentNode;
+
+                while (p) {
+                    if (this.isHandle(id, p.id)) {
+                        return true;
+                    } else {
+                        p = p.parentNode;
+                    }
+                }
+            }
+
+            return false;
+        }
+
+    };
+
+}();
+
+// shorter alias, save a few bytes
+Ext.dd.DDM = Ext.dd.DragDropMgr;
+Ext.dd.DDM._addListeners();
+
+}
+
+
+Ext.dd.DD = function(id, sGroup, config) {
+    if (id) {
+        this.init(id, sGroup, config);
+    }
+};
+
+Ext.extend(Ext.dd.DD, Ext.dd.DragDrop, {
+
+    
+    scroll: true,
+
+    
+    autoOffset: function(iPageX, iPageY) {
+        var x = iPageX - this.startPageX;
+        var y = iPageY - this.startPageY;
+        this.setDelta(x, y);
+    },
+
+    
+    setDelta: function(iDeltaX, iDeltaY) {
+        this.deltaX = iDeltaX;
+        this.deltaY = iDeltaY;
+    },
+
+    
+    setDragElPos: function(iPageX, iPageY) {
+        // the first time we do this, we are going to check to make sure
+        // the element has css positioning
+
+        var el = this.getDragEl();
+        this.alignElWithMouse(el, iPageX, iPageY);
+    },
+
+    
+    alignElWithMouse: function(el, iPageX, iPageY) {
+        var oCoord = this.getTargetCoord(iPageX, iPageY);
+        var fly = el.dom ? el : Ext.fly(el, '_dd');
+        if (!this.deltaSetXY) {
+            var aCoord = [oCoord.x, oCoord.y];
+            fly.setXY(aCoord);
+            var newLeft = fly.getLeft(true);
+            var newTop  = fly.getTop(true);
+            this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ];
+        } else {
+            fly.setLeftTop(oCoord.x + this.deltaSetXY[0], oCoord.y + this.deltaSetXY[1]);
+        }
+
+        this.cachePosition(oCoord.x, oCoord.y);
+        this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
+        return oCoord;
+    },
+
+    
+    cachePosition: function(iPageX, iPageY) {
+        if (iPageX) {
+            this.lastPageX = iPageX;
+            this.lastPageY = iPageY;
+        } else {
+            var aCoord = Ext.lib.Dom.getXY(this.getEl());
+            this.lastPageX = aCoord[0];
+            this.lastPageY = aCoord[1];
+        }
+    },
+
+    
+    autoScroll: function(x, y, h, w) {
+
+        if (this.scroll) {
+            // The client height
+            var clientH = Ext.lib.Dom.getViewHeight();
+
+            // The client width
+            var clientW = Ext.lib.Dom.getViewWidth();
+
+            // The amt scrolled down
+            var st = this.DDM.getScrollTop();
+
+            // The amt scrolled right
+            var sl = this.DDM.getScrollLeft();
+
+            // Location of the bottom of the element
+            var bot = h + y;
+
+            // Location of the right of the element
+            var right = w + x;
+
+            // The distance from the cursor to the bottom of the visible area,
+            // adjusted so that we don't scroll if the cursor is beyond the
+            // element drag constraints
+            var toBot = (clientH + st - y - this.deltaY);
+
+            // The distance from the cursor to the right of the visible area
+            var toRight = (clientW + sl - x - this.deltaX);
+
+
+            // How close to the edge the cursor must be before we scroll
+            // var thresh = (document.all) ? 100 : 40;
+            var thresh = 40;
+
+            // How many pixels to scroll per autoscroll op.  This helps to reduce
+            // clunky scrolling. IE is more sensitive about this ... it needs this
+            // value to be higher.
+            var scrAmt = (document.all) ? 80 : 30;
+
+            // Scroll down if we are near the bottom of the visible page and the
+            // obj extends below the crease
+            if ( bot &gt; clientH &amp;&amp; toBot &lt; thresh ) {
+                window.scrollTo(sl, st + scrAmt);
+            }
+
+            // Scroll up if the window is scrolled down and the top of the object
+            // goes above the top border
+            if ( y &lt; st &amp;&amp; st &gt; 0 &amp;&amp; y - st &lt; thresh ) {
+                window.scrollTo(sl, st - scrAmt);
+            }
+
+            // Scroll right if the obj is beyond the right border and the cursor is
+            // near the border.
+            if ( right &gt; clientW &amp;&amp; toRight &lt; thresh ) {
+                window.scrollTo(sl + scrAmt, st);
+            }
+
+            // Scroll left if the window has been scrolled to the right and the obj
+            // extends past the left border
+            if ( x &lt; sl &amp;&amp; sl &gt; 0 &amp;&amp; x - sl &lt; thresh ) {
+                window.scrollTo(sl - scrAmt, st);
+            }
+        }
+    },
+
+    
+    getTargetCoord: function(iPageX, iPageY) {
+
+
+        var x = iPageX - this.deltaX;
+        var y = iPageY - this.deltaY;
+
+        if (this.constrainX) {
+            if (x &lt; this.minX) { x = this.minX; }
+            if (x &gt; this.maxX) { x = this.maxX; }
+        }
+
+        if (this.constrainY) {
+            if (y &lt; this.minY) { y = this.minY; }
+            if (y &gt; this.maxY) { y = this.maxY; }
+        }
+
+        x = this.getTick(x, this.xTicks);
+        y = this.getTick(y, this.yTicks);
+
+
+        return {x:x, y:y};
+    },
+
+    
+    applyConfig: function() {
+        Ext.dd.DD.superclass.applyConfig.call(this);
+        this.scroll = (this.config.scroll !== false);
+    },
+
+    
+    b4MouseDown: function(e) {
+        // this.resetConstraints();
+        this.autoOffset(e.getPageX(),
+                            e.getPageY());
+    },
+
+    
+    b4Drag: function(e) {
+        this.setDragElPos(e.getPageX(),
+                            e.getPageY());
+    },
+
+    toString: function() {
+        return (&quot;DD &quot; + this.id);
+    }
+
+    //////////////////////////////////////////////////////////////////////////
+    // Debugging ygDragDrop events that can be overridden
+    //////////////////////////////////////////////////////////////////////////
+    
+
+});
+
+Ext.dd.DDProxy = function(id, sGroup, config) {
+    if (id) {
+        this.init(id, sGroup, config);
+        this.initFrame();
+    }
+};
+
+
+Ext.dd.DDProxy.dragElId = &quot;ygddfdiv&quot;;
+
+Ext.extend(Ext.dd.DDProxy, Ext.dd.DD, {
+
+    
+    resizeFrame: true,
+
+    
+    centerFrame: false,
+
+    
+    createFrame: function() {
+        var self = this;
+        var body = document.body;
+
+        if (!body || !body.firstChild) {
+            setTimeout( function() { self.createFrame(); }, 50 );
+            return;
+        }
+
+        var div = this.getDragEl();
+
+        if (!div) {
+            div    = document.createElement(&quot;div&quot;);
+            div.id = this.dragElId;
+            var s  = div.style;
+
+            s.position   = &quot;absolute&quot;;
+            s.visibility = &quot;hidden&quot;;
+            s.cursor     = &quot;move&quot;;
+            s.border     = &quot;2px solid #aaa&quot;;
+            s.zIndex     = 999;
+
+            // appendChild can blow up IE if invoked prior to the window load event
+            // while rendering a table.  It is possible there are other scenarios
+            // that would cause this to happen as well.
+            body.insertBefore(div, body.firstChild);
+        }
+    },
+
+    
+    initFrame: function() {
+        this.createFrame();
+    },
+
+    applyConfig: function() {
+        Ext.dd.DDProxy.superclass.applyConfig.call(this);
+
+        this.resizeFrame = (this.config.resizeFrame !== false);
+        this.centerFrame = (this.config.centerFrame);
+        this.setDragElId(this.config.dragElId || Ext.dd.DDProxy.dragElId);
+    },
+
+    
+    showFrame: function(iPageX, iPageY) {
+        var el = this.getEl();
+        var dragEl = this.getDragEl();
+        var s = dragEl.style;
+
+        this._resizeProxy();
+
+        if (this.centerFrame) {
+            this.setDelta( Math.round(parseInt(s.width,  10)/2),
+                           Math.round(parseInt(s.height, 10)/2) );
+        }
+
+        this.setDragElPos(iPageX, iPageY);
+
+        Ext.fly(dragEl).show();
+    },
+
+    
+    _resizeProxy: function() {
+        if (this.resizeFrame) {
+            var el = this.getEl();
+            Ext.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
+        }
+    },
+
+    // overrides Ext.dd.DragDrop
+    b4MouseDown: function(e) {
+        var x = e.getPageX();
+        var y = e.getPageY();
+        this.autoOffset(x, y);
+        this.setDragElPos(x, y);
+    },
+
+    // overrides Ext.dd.DragDrop
+    b4StartDrag: function(x, y) {
+        // show the drag frame
+        this.showFrame(x, y);
+    },
+
+    // overrides Ext.dd.DragDrop
+    b4EndDrag: function(e) {
+        Ext.fly(this.getDragEl()).hide();
+    },
+
+    // overrides Ext.dd.DragDrop
+    // By default we try to move the element to the last location of the frame.
+    // This is so that the default behavior mirrors that of Ext.dd.DD.
+    endDrag: function(e) {
+
+        var lel = this.getEl();
+        var del = this.getDragEl();
+
+        // Show the drag frame briefly so we can get its position
+        del.style.visibility = &quot;&quot;;
+
+        this.beforeMove();
+        // Hide the linked element before the move to get around a Safari
+        // rendering bug.
+        lel.style.visibility = &quot;hidden&quot;;
+        Ext.dd.DDM.moveToEl(lel, del);
+        del.style.visibility = &quot;hidden&quot;;
+        lel.style.visibility = &quot;&quot;;
+
+        this.afterDrag();
+    },
+
+    beforeMove : function(){
+
+    },
+
+    afterDrag : function(){
+
+    },
+
+    toString: function() {
+        return (&quot;DDProxy &quot; + this.id);
+    }
+
+});
+
+Ext.dd.DDTarget = function(id, sGroup, config) {
+    if (id) {
+        this.initTarget(id, sGroup, config);
+    }
+};
+
+// Ext.dd.DDTarget.prototype = new Ext.dd.DragDrop();
+Ext.extend(Ext.dd.DDTarget, Ext.dd.DragDrop, {
+    toString: function() {
+        return (&quot;DDTarget &quot; + this.id);
+    }
+});
+
 
 Ext.dd.DragTracker = function(config){
     Ext.apply(this, config);
@@ -10393,6 +10452,13 @@ Ext.extend(Ext.dd.DragTracker, Ext.util.Observable,  {
     },
 
     onMouseMove: function(e, target){
+        // HACK: IE hack to see if button was released outside of window. */
+        if(this.active &amp;&amp; Ext.isIE &amp;&amp; !e.browserEvent.button){
+            e.preventDefault();
+            this.onMouseUp(e);
+            return;
+        }
+
         e.preventDefault();
         var xy = e.getXY(), s = this.startXY;
         this.lastXY = xy;
@@ -10498,7 +10564,7 @@ Ext.extend(Ext.dd.DragTracker, Ext.util.Observable,  {
             return [dr.left, dr.top];
         }
     }
-});
+});
 
 Ext.dd.ScrollManager = function(){
     var ddm = Ext.dd.DragDropMgr;
@@ -10645,7 +10711,7 @@ Ext.dd.ScrollManager = function(){
             }
         }
     };
-}();
+}();
 
 Ext.dd.Registry = function(){
     var elements = {}; 
@@ -10727,7 +10793,7 @@ Ext.dd.Registry = function(){
             return t ? elements[t.id] || handles[t.id] : null;
         }
     };
-}();
+}();
 
 Ext.dd.StatusProxy = function(config){
     Ext.apply(this, config);
@@ -10780,7 +10846,7 @@ Ext.dd.StatusProxy.prototype = {
         }
         var el = this.ghost.dom.firstChild; 
         if(el){
-            Ext.fly(el).setStyle(Ext.isIE ? 'styleFloat' : 'cssFloat', 'none');
+            Ext.fly(el).setStyle('float', 'none');
         }
     },
 
@@ -10848,7 +10914,7 @@ Ext.dd.StatusProxy.prototype = {
         this.callback = null;
         this.scope = null;
     }
-};
+};
 
 Ext.dd.DragSource = function(el, config){
     this.el = Ext.get(el);
@@ -11095,7 +11161,7 @@ Ext.extend(Ext.dd.DragSource, Ext.dd.DDProxy, {
     autoOffset : function(x, y) {
         this.setDelta(-12, -20);
     }    
-});
+});
 
 Ext.dd.DropTarget = function(el, config){
     this.el = Ext.get(el);
@@ -11149,7 +11215,7 @@ Ext.extend(Ext.dd.DropTarget, Ext.dd.DDTarget, {
     notifyDrop : function(dd, e, data){
         return false;
     }
-});
+});
 
 Ext.dd.DragZone = function(el, config){
     Ext.dd.DragZone.superclass.constructor.call(this, el, config);
@@ -11187,7 +11253,7 @@ Ext.extend(Ext.dd.DragZone, Ext.dd.DragSource, {
     getRepairXY : function(e){
         return Ext.Element.fly(this.dragData.ddel).getXY();  
     }
-});
+});
 
 Ext.dd.DropZone = function(el, config){
     Ext.dd.DropZone.superclass.constructor.call(this, el, config);
@@ -11278,52 +11344,120 @@ Ext.extend(Ext.dd.DropZone, Ext.dd.DropTarget, {
     triggerCacheRefresh : function(){
         Ext.dd.DDM.refreshCache(this.groups);
     }  
-});
-
-Ext.data.Api = (function() {
-
-    return {
-        
-        CREATE  : 'create',
-        
-        READ    : 'load',
-        
-        UPDATE  : 'save',
-        
-        DESTROY : 'destroy',
-
-        
-        getVerbs : function(){
-            return [this.CREATE, this.READ, this.UPDATE, this.DESTROY];
-        },
-        
-        isVerb : function(action, crud) {
-            var found = false;
-            crud = crud || this.getVerbs();
-            for (var n=0,len=crud.length;n&lt;len;n++) {
-                if (crud[n] == action) {
-                   found = true;
-                   break;
-                }
-            }
-            return found;
-        },
-        
-        isValid : function(api){
-            var invalid = [];
-            var crud = this.getVerbs(); // &lt;-- cache a copy of teh verbs.
-            for (var action in api) {
-                if (!this.isVerb(action, crud)) {   // &lt;-- send cache of verbs into isVerb.  This call is only reason for isVerb to accept 2nd param.
-                    invalid.push(action);
-                }
-            }
-            return (!invalid.length) ? true : invalid;
-        }
-    }
-})();
-
-
-
+});
+
+Ext.data.Api = (function() {
+
+    // private validActions.  validActions is essentially an inverted hash of Ext.data.Api.actions, where value becomes the key.
+    // Some methods in this singleton (eg: getActions, getVerb) will loop through actions with the code &lt;code&gt;for (var verb in this.actions)&lt;/code&gt;
+    // For efficiency, some methods will first check this hash for a match.  Those methods which do acces validActions will cache their result here.
+    // We cannot pre-define this hash since the developer may over-ride the actions at runtime.
+    var validActions = {};
+
+    return {
+        
+        actions : {
+            create  : 'create',
+            read    : 'read',
+            update  : 'update',
+            destroy : 'destroy'
+        },
+
+        
+        restActions : {
+            create  : 'POST',
+            read    : 'GET',
+            update  : 'PUT',
+            destroy : 'DELETE'
+        },
+
+        
+        isAction : function(action) {
+            return (Ext.data.Api.actions[action]) ? true : false;
+        },
+
+        
+        getVerb : function(name) {
+            if (validActions[name]) {
+                return validActions[name];  // &lt;-- found in cache.  return immediately.
+            }
+            for (var verb in this.actions) {
+                if (this.actions[verb] === name) {
+                    validActions[name] = verb;
+                    break;
+                }
+            }
+            return (validActions[name] !== undefined) ? validActions[name] : null;
+        },
+
+        
+        isValid : function(api){
+            var invalid = [];
+            var crud = this.actions; // &lt;-- cache a copy of the actions.
+            for (var action in api) {
+                if (!(action in crud)) {
+                    invalid.push(action);
+                }
+            }
+            return (!invalid.length) ? true : invalid;
+        },
+
+        
+        hasUniqueUrl : function(proxy, verb) {
+            var url = (proxy.api[verb]) ? proxy.api[verb].url : null;
+            var unique = true;
+            for (var action in proxy.api) {
+                if ((unique = (action === verb) ? true : (proxy.api[action].url != url) ? true : false) === false) {
+                    break;
+                }
+            }
+            return unique;
+        },
+
+        
+        prepare : function(proxy) {
+            if (!proxy.api) {
+                proxy.api = {}; // &lt;-- No api?  create a blank one.
+            }
+            for (var verb in this.actions) {
+                var action = this.actions[verb];
+                proxy.api[action] = proxy.api[action] || proxy.url || proxy.directFn;
+                if (typeof(proxy.api[action]) == 'string') {
+                    proxy.api[action] = {
+                        url: proxy.api[action]
+                    };
+                }
+            }
+        },
+
+        
+        restify : function(proxy) {
+            proxy.restful = true;
+            for (var verb in this.restActions) {
+                proxy.api[this.actions[verb]].method = this.restActions[verb];
+            }
+        }
+    };
+})();
+
+
+
+Ext.data.Api.Error = Ext.extend(Ext.Error, {
+    constructor : function(message, arg) {
+        this.arg = arg;
+        Ext.Error.call(this, message);
+    },
+    name: 'Ext.data.Api'
+});
+Ext.apply(Ext.data.Api.Error.prototype, {
+    lang: {
+        '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.',
+        'invalid': 'received an invalid API-configuration.  Please ensure your proxy API-configuration contains only the actions defined in Ext.data.Api.actions',
+        'invalid-url': 'Invalid url.  Please review your proxy configuration.',
+        'execute': 'Attempted to execute an unknown action.  Valid API actions are defined in Ext.data.Api.actions&quot;'
+    }
+});
+
 
 
 Ext.data.SortTypes = {
@@ -11374,1163 +11508,1246 @@ Ext.data.SortTypes = {
         if(isNaN(val)) val = 0;
     	return val;
     }
-};
-
-Ext.data.Record = function(data, id){
-    // if no id, call the auto id method
-    this.id = (id || id === 0) ? id : Ext.data.Record.id(this);
-    this.data = data;
-};
-
-
-Ext.data.Record.create = function(o){
-    var f = Ext.extend(Ext.data.Record, {});
-    var p = f.prototype;
-    p.fields = new Ext.util.MixedCollection(false, function(field){
-        return field.name;
-    });
-    for(var i = 0, len = o.length; i &lt; len; i++){
-        p.fields.add(new Ext.data.Field(o[i]));
-    }
-    f.getField = function(name){
-        return p.fields.get(name);
-    };
-    return f;
-};
-
-Ext.data.Record.PREFIX = 'ext-record';
-Ext.data.Record.AUTO_ID = 1;
-Ext.data.Record.EDIT = 'edit';
-Ext.data.Record.REJECT = 'reject';
-Ext.data.Record.COMMIT = 'commit';
-
-
-
-Ext.data.Record.id = function(rec) {
-    rec.phantom = true;
-    return [Ext.data.Record.PREFIX, '-', Ext.data.Record.AUTO_ID++].join('');
-}
-
-Ext.data.Record.prototype = {
-    
-    
-    
-    
-    dirty : false,
-    editing : false,
-    error: null,
-    
-    modified: null,
-    
-    phantom : false,
-
-    // private
-    join : function(store){
-        
-        this.store = store;
-    },
-
-    
-    set : function(name, value){
-        if(String(this.data[name]) == String(value)){
-            return;
-        }
-        this.dirty = true;
-        if(!this.modified){
-            this.modified = {};
-        }
-        if(typeof this.modified[name] == 'undefined'){
-            this.modified[name] = this.data[name];
-        }
-        this.data[name] = value;
-        if(!this.editing){
-            this.afterEdit();
-        }
-    },
-
-    // private
-    afterEdit: function(){
-        if(this.store){
-            this.store.afterEdit(this);
-        }
-    },
-
-    // private
-    afterReject: function(){
-        if(this.store){
-            this.store.afterReject(this);
-        }
-    },
-
-    // private
-    afterCommit: function(){
-        if(this.store){
-            this.store.afterCommit(this);
-        }
-    },
-
-    
-    get : function(name){
-        return this.data[name];
-    },
-
-    
-    beginEdit : function(){
-        this.editing = true;
-        this.modified = this.modified || {};
-    },
-
-    
-    cancelEdit : function(){
-        this.editing = false;
-        delete this.modified;
-    },
-
-    
-    endEdit : function(){
-        this.editing = false;
-        if(this.dirty){
-            this.afterEdit();
-        }
-    },
-
-    
-    reject : function(silent){
-        var m = this.modified;
-        for(var n in m){
-            if(typeof m[n] != &quot;function&quot;){
-                this.data[n] = m[n];
-            }
-        }
-        this.dirty = false;
-        delete this.modified;
-        this.editing = false;
-        if(silent !== true){
-            this.afterReject();
-        }
-    },
-
-    
-    commit : function(silent){
-        this.dirty = false;
-        delete this.modified;
-        this.editing = false;
-        if(silent !== true){
-            this.afterCommit();
-        }
-    },
-
-    
-    getChanges : function(){
-        var m = this.modified, cs = {};
-        for(var n in m){
-            if(m.hasOwnProperty(n)){
-                cs[n] = this.data[n];
-            }
-        }
-        return cs;
-    },
-
-    // private
-    hasError : function(){
-        return this.error != null;
-    },
-
-    // private
-    clearError : function(){
-        this.error = null;
-    },
-
-    
-    copy : function(newId) {
-        return new this.constructor(Ext.apply({}, this.data), newId || this.id);
-    },
-
-    
-    isModified : function(fieldName){
-        return !!(this.modified &amp;&amp; this.modified.hasOwnProperty(fieldName));
-    },
-
-    
-    isValid : function() {
-        return this.fields.find(function(f) {
-            return (f.allowBlank == false &amp;&amp; Ext.isEmpty(this.data[f.name])) ? true : false;
-        },this) ? false : true;
-    },
-
-    
-    markDirty : function(){
-        this.dirty = true;
-        if(!this.modified){
-            this.modified = {};
-        }
-        this.fields.each(function(f) {
-            this.modified[f.name] = this.data[f.name];
-        },this);
-    }
-};
-
-Ext.StoreMgr = Ext.apply(new Ext.util.MixedCollection(), {
-    
-
-    
-    register : function(){
-        for(var i = 0, s; s = arguments[i]; i++){
-            this.add(s);
-        }
-    },
-
-    
-    unregister : function(){
-        for(var i = 0, s; s = arguments[i]; i++){
-            this.remove(this.lookup(s));
-        }
-    },
-
-    
-    lookup : function(id){
-        return typeof id == &quot;object&quot; ? (id.events ? id : Ext.create(id, 'store')) : this.get(id);
-    },
-
-    // getKey implementation for MixedCollection
-    getKey : function(o){
-         return o.storeId;
-    }
-});
-
-Ext.data.Store = function(config){
-    this.data = new Ext.util.MixedCollection(false);
-    this.data.getKey = function(o){
-        return o.id;
-    };
-    
-    this.baseParams = {};
-
-    // temporary removed-records cache
-    this.removed = [];
-
-    
-    this.paramNames = {
-        &quot;start&quot; : &quot;start&quot;,
-        &quot;limit&quot; : &quot;limit&quot;,
-        &quot;sort&quot; : &quot;sort&quot;,
-        &quot;dir&quot; : &quot;dir&quot;
-    };
-
-    if(config &amp;&amp; config.data){
-        this.inlineData = config.data;
-        delete config.data;
-    }
-
-    Ext.apply(this, config);
-
-    if(this.url &amp;&amp; !this.proxy){
-        this.proxy = new Ext.data.HttpProxy({url: this.url});
-    }
-
-    if(this.reader){ // reader passed
-        if(!this.recordType){
-            this.recordType = this.reader.recordType;
-        }
-        if(this.reader.onMetaChange){
-            this.reader.onMetaChange = this.onMetaChange.createDelegate(this);
-        }
-        if (this.writer) { // writer passed
-            this.writer.meta = this.reader.meta;
-            this.pruneModifiedRecords = true;
-        }
-    }
-
-    
-    if(this.recordType){
-        
-        this.fields = this.recordType.prototype.fields;
-    }
-    this.modified = [];
-
-    this.addEvents(
-        
-        'datachanged',
-        
-        'metachange',
-        
-        'add',
-        
-        'remove',
-        
-        'update',
-        
-        'clear',
-        
-        'before'+Ext.data.Api.READ,
-        
-        Ext.data.Api.READ,
-        
-        Ext.data.Api.READ+'exception',
-        
-        'beforewrite',
-        
-        'write',
-        
-        'writeexception'
-    );
-
-    if(this.proxy){
-        this.relayEvents(this.proxy,  [Ext.data.Api.READ+&quot;exception&quot;]);
-    }
-    // With a writer installed into the Store, we want to listen to add/remove events to remotely create/destroy records.
-    if (this.writer) {
-        this.relayEvents(this.proxy, [&quot;writeexception&quot;]);
-        this.on('add', this.createRecords.createDelegate(this));
-        this.on('remove', this.destroyRecord.createDelegate(this));
-        this.on('update', this.updateRecord.createDelegate(this));
-    }
-
-    this.sortToggle = {};
-    if(this.sortField){
-        this.setDefaultSort(this.sortField, this.sortDir);
-    }else if(this.sortInfo){
-        this.setDefaultSort(this.sortInfo.field, this.sortInfo.direction);
-    }
-
-    Ext.data.Store.superclass.constructor.call(this);
-
-    if(this.id){
-        this.storeId = this.id;
-        delete this.id;
-    }
-    if(this.storeId){
-        Ext.StoreMgr.register(this);
-    }
-    if(this.inlineData){
-        this.loadData(this.inlineData);
-        delete this.inlineData;
-    }else if(this.autoLoad){
-        this.load.defer(10, this, [
-            typeof this.autoLoad == 'object' ?
-                this.autoLoad : undefined]);
-    }
-};
-Ext.extend(Ext.data.Store, Ext.util.Observable, {
-    
-    
-    
-    
-    
-    
-    
-    writer : undefined,
-    
-    
-    
-    remoteSort : false,
-
-    
-    autoDestroy : false,
-
-    
-    pruneModifiedRecords : false,
-
-    
-   lastOptions : null,
-
-    
-    batchSave : false,
-
-    
-    destroy : function(){
-        if(this.storeId){
-            Ext.StoreMgr.unregister(this);
-        }
-        this.data = null;
-        this.purgeListeners();
-    },
-
-    
-    add : function(records){
-        records = [].concat(records);
-        if(records.length &lt; 1){
-            return;
-        }
-        for(var i = 0, len = records.length; i &lt; len; i++){
-            records[i].join(this);
-        }
-        var index = this.data.length;
-        this.data.addAll(records);
-        if(this.snapshot){
-            this.snapshot.addAll(records);
-        }
-        this.fireEvent(&quot;add&quot;, this, records, index);
-    },
-
-    
-    addSorted : function(record){
-        var index = this.findInsertIndex(record);
-        this.insert(index, record);
-    },
-
-    
-    remove : function(record){
-        var index = this.data.indexOf(record);
-        this.data.removeAt(index);
-        if(this.pruneModifiedRecords){
-            this.modified.remove(record);
-        }
-        if(this.snapshot){
-            this.snapshot.remove(record);
-        }
-        this.fireEvent(&quot;remove&quot;, this, record, index);
-    },
-
-    
-    removeAt : function(index){
-        this.remove(this.getAt(index));
-    },
-
-    
-    removeAll : function(){
-        this.data.clear();
-        if(this.snapshot){
-            this.snapshot.clear();
-        }
-        if(this.pruneModifiedRecords){
-            this.modified = [];
-        }
-        this.fireEvent(&quot;clear&quot;, this);
-    },
-
-    
-    insert : function(index, records){
-        records = [].concat(records);
-        for(var i = 0, len = records.length; i &lt; len; i++){
-            this.data.insert(index, records[i]);
-            records[i].join(this);
-        }
-        this.fireEvent(&quot;add&quot;, this, records, index);
-    },
-
-    
-    indexOf : function(record){
-        return this.data.indexOf(record);
-    },
-
-    
-    indexOfId : function(id){
-        return this.data.indexOfKey(id);
-    },
-
-    
-    getById : function(id){
-        return this.data.key(id);
-    },
-
-    
-    getAt : function(index){
-        return this.data.itemAt(index);
-    },
-
-    
-    getRange : function(start, end){
-        return this.data.getRange(start, end);
-    },
-
-    // private
-    storeOptions : function(o){
-        o = Ext.apply({}, o);
-        delete o.callback;
-        delete o.scope;
-        this.lastOptions = o;
-    },
-
-    
-    load : function(options) {
-        options = options || {};
-        this.storeOptions(options);
-        if(this.sortInfo &amp;&amp; this.remoteSort){
-            var pn = this.paramNames;
-            options.params = options.params || {};
-            options.params[pn[&quot;sort&quot;]] = this.sortInfo.field;
-            options.params[pn[&quot;dir&quot;]] = this.sortInfo.direction;
-        }
-        try {
-            return this.execute(Ext.data.Api.READ, null, options); // &lt;-- null represents rs.  No rs for load actions.
-        } catch(e) {
-            this.handleException(e);
-            return false;
-        }
-    },
-
-    
-    updateRecord : function(store, record, action) {
-        if (action == Ext.data.Record.EDIT &amp;&amp; this.batchSave !== true &amp;&amp; (!record.phantom || (record.phantom &amp;&amp; record.isValid))) {
-            this.save();
-        }
-    },
-
-    
-    createRecords : function(store, rs, index) {
-        for (var i = 0, len = rs.length; i &lt; len; i++) {
-            if (rs[i].phantom &amp;&amp; rs[i].isValid()) {
-                rs[i].markDirty();  // &lt;-- Mark new records dirty
-                this.modified.push(rs[i]);  // &lt;-- add to modified
-            }
-        }
-        if (this.batchSave === false) {
-            this.save();
-        }
-    },
-
-    
-    destroyRecord : function(store, record, index) {
-        if (this.modified.indexOf(record) != -1) {	// &lt;-- handled already if @cfg pruneModifiedRecords == true
-            this.modified.remove(record);
-        }
-        if (!record.phantom) {
-            this.removed.push(record);
-
-            // since the record has already been removed from the store but the server request has not yet been executed,
-            // must keep track of the last known index this record existed.  If a server error occurs, the record can be
-            // put back into the store.  @see Store#createCallback where the record is returned when response status === false
-            record.lastIndex = index;
-
-            if (this.batchSave === false) {
-                this.save();
-            }
-        }
-    },
-
-    
-    execute : function(action, rs, options) {
-        // blow up if action not Ext.data.CREATE, READ, UPDATE, DESTROY
-        if (!Ext.data.Api.isVerb(action)) {
-            throw new Error('Store#execute attempted to execute an unknown action &quot;' + action + '&quot;.  Valid API actions are &quot;' + Ext.data.Api.getVerbs().join(', '));
-        }
-
-        // make sure options has a params key
-        options = Ext.applyIf(options||{}, {
-            params: {}
-        });
-
-        // have to separate before-events since load has a different signature than create,destroy and save events since load does not
-        // include the rs (record resultset) parameter.  Capture return values from the beforeaction into doRequest flag.
-        var doRequest = true;
-        if (action === Ext.data.Api.READ) {// TODO: define actions as CONSTANTS
-            doRequest = this.fireEvent('before'+action, this, options);
-        }
-        else {
-            // if rs has just a single recoractiond, shift it off so that Writer writes data as &quot;{}&quot; rather than &quot;[{}]&quot;
-            rs = (rs.length &gt; 1) ? rs : rs.shift();
-
-            // Write the action to options.params
-            if (doRequest = this.fireEvent('beforewrite', this, action, rs, options) !== false) {
-                this.writer.write(action, options.params, rs);
-            }
-        }
-        if (doRequest !== false) {
-            // Send request to proxy.  The big Ext.apply as 3rd arg here is simply building the request-params
-            // and applying the xaction parameter.
-            // @TODO: let writer write xaction param as well rather than here in store.  DataWriter needs to expose more hooks.
-            this.proxy.request(action, rs, Ext.apply(options.params || {}, this.baseParams, {xaction: action}), this.reader, this.createCallback(action, rs), this, options);
-        }
-        return doRequest;
-    },
-
-    
-    save : function() {
-        if (!this.writer) {
-            throw new Error('Store#save called without a DataWriter installed!  Unable to execute remote-actions.  See docs for Ext.data.Api, Ext.data.DataWriter, Ext.data.JsonWriter.');
-        }
-
-        // First check for removed records.  Records in this.removed are guaranteed non-phantoms.  @see Store#remove
-        if (this.removed.length) {
-            try {
-                this.execute(Ext.data.Api.DESTROY, this.removed);
-            } catch (e) {
-                this.handleException(e);
-            }
-        }
-
-        // Check for modified records.  Bail-out if empty...
-        var rs = this.getModifiedRecords();
-        if (!rs.length) {
-            return true;
-        }
-
-        // Next check for phantoms within rs.  splice-off and execute create.
-        var phantoms = [];
-        for (var i = rs.length-1; i &gt;= 0; i--) {
-            if (rs[i].phantom === true) {
-                var rec = rs.splice(i, 1).shift();
-                if (rec.isValid()) {
-                    phantoms.push(rec);
-                }
-            }
-            else if (!rs[i].isValid()) { // &lt;-- while we're here, splice-off any !isValid real records
-                rs.splice(i,1);
-            }
-        }
-        // If we have valid phantoms, create them...
-        if (phantoms.length) {
-            try {
-                this.execute(Ext.data.Api.CREATE, phantoms);
-            } catch (e) {
-                this.handleException(e);
-            }
-        }
-
-        // And finally, if we're still here after splicing-off phantoms and !isValid real records, update the rest...
-        if (rs.length) {
-            try {
-                this.execute(Ext.data.Api.UPDATE, rs);
-            } catch (e) {
-                this.handleException(e);
-            }
-        }
-        return true;
-    },
-
-    // private callback-handler for remote CRUD actions
-    // Do not override -- override loadRecords, onCreateRecords, onDestroyRecords and onUpdateRecords instead.
-    createCallback : function(action, rs) {
-        return (action == Ext.data.Api.READ) ? this.loadRecords : function(data, response, success) {
-            switch (action) {
-                case Ext.data.Api.CREATE:
-                    this.onCreateRecords(success, rs, data);
-                    break;
-                case Ext.data.Api.DESTROY:
-                    this.onDestroyRecords(success, rs, data);
-                    break;
-                case Ext.data.Api.UPDATE:
-                    this.onUpdateRecords(success, rs, data);
-                    break;
-            }
-            // fire catch-all &quot;write&quot; event for CREATE, DESTROY, UPDATE
-            this.fireEvent('write', this, action, data, response, rs);
-        }
-    },
-
-    // protected onCreateRecord proxy callback for create action
-    onCreateRecords : function(success, rs, data) {
-        if (success === true) {
-            try {
-                this.reader.realize(rs, data);
-            }
-            catch (e) {
-                this.handleException(e);
-                if (Ext.isArray(rs)) {
-                    // Recurse to run back into the try {}.  DataReader#realize splices-off the rs until empty.
-                    this.onCreateRecords(success, rs, data);
-                }
-            }
-        }
-    },
-
-    // protected, onUpdateRecords proxy callback for update action
-    onUpdateRecords : function(success, rs, data) {
-        if (success === true) {
-            try {
-                this.reader.update(rs, data);
-            }
-            catch (e) {
-                this.handleException(e);
-                if (Ext.isArray(rs)) {
-                    // Recurse to run back into the try {}.  DataReader#update splices-off the rs until empty.
-                    this.onUpdateRecords(success, rs, data);
-                }
-            }
-        }
-    },
-
-    // protected onDestroyRecords proxy callback for destroy action
-    onDestroyRecords : function(success, rs, data) {
-        this.removed = [];
-        if (success === true) {
-            // nothing to do so far...invert the logic?
-        } else {
-            // put records back into store if remote destroy fails.
-            // @TODO: Might want to let developer decide.
-            if (rs instanceof Ext.data.Record) {
-                rs = [rs];
-            }
-            for (var i=0,len=rs.length;i&lt;len;i++) {
-                this.insert(rs[i].lastIndex, rs[i]);    // &lt;-- lastIndex set in Store#destroyRecord
-            }
-        }
-    },
-
-    // protected handleException.  Possibly temporary until Ext framework has an exception-handler.
-    handleException : function(e) {
-        if (typeof(console) == 'object' &amp;&amp; typeof(console.error) == 'function') {
-            console.error(e);
-        }
-        else {
-            alert(e);   // &lt;-- ugh.  fix this before official release.
-        }
-    },
-
-    
-    reload : function(options){
-        this.load(Ext.applyIf(options||{}, this.lastOptions));
-    },
-
-    // private
-    // Called as a callback by the Reader during a load operation.
-    loadRecords : function(o, options, success){
-        if(!o || success === false){
-            if(success !== false){
-                this.fireEvent(Ext.data.Api.READ, this, [], options);
-            }
-            if(options.callback){
-                options.callback.call(options.scope || this, [], options, false);
-            }
-            return;
-        }
-        var r = o.records, t = o.totalRecords || r.length;
-        if(!options || options.add !== true){
-            if(this.pruneModifiedRecords){
-                this.modified = [];
-            }
-            for(var i = 0, len = r.length; i &lt; len; i++){
-                r[i].join(this);
-            }
-            if(this.snapshot){
-                this.data = this.snapshot;
-                delete this.snapshot;
-            }
-            this.data.clear();
-            this.data.addAll(r);
-            this.totalLength = t;
-            this.applySort();
-            this.fireEvent(&quot;datachanged&quot;, this);
-        }else{
-            this.totalLength = Math.max(t, this.data.length+r.length);
-            this.add(r);
-        }
-        this.fireEvent(Ext.data.Api.READ, this, r, options);
-        if(options.callback){
-            options.callback.call(options.scope || this, r, options, true);
-        }
-    },
-
-    
-    loadData : function(o, append){
-        var r = this.reader.readRecords(o);
-        this.loadRecords(r, {add: append}, true);
-    },
-
-    
-    getCount : function(){
-        return this.data.length || 0;
-    },
-
-    
-    getTotalCount : function(){
-        return this.totalLength || 0;
-    },
-
-    
-    getSortState : function(){
-        return this.sortInfo;
-    },
-
-    // private
-    applySort : function(){
-        if(this.sortInfo &amp;&amp; !this.remoteSort){
-            var s = this.sortInfo, f = s.field;
-            this.sortData(f, s.direction);
-        }
-    },
-
-    // private
-    sortData : function(f, direction){
-        direction = direction || 'ASC';
-        var st = this.fields.get(f).sortType;
-        var fn = function(r1, r2){
-            var v1 = st(r1.data[f]), v2 = st(r2.data[f]);
-            return v1 &gt; v2 ? 1 : (v1 &lt; v2 ? -1 : 0);
-        };
-        this.data.sort(direction, fn);
-        if(this.snapshot &amp;&amp; this.snapshot != this.data){
-            this.snapshot.sort(direction, fn);
-        }
-    },
-
-    
-    setDefaultSort : function(field, dir){
-        dir = dir ? dir.toUpperCase() : &quot;ASC&quot;;
-        this.sortInfo = {field: field, direction: dir};
-        this.sortToggle[field] = dir;
-    },
-
-    
-    sort : function(fieldName, dir){
-        var f = this.fields.get(fieldName);
-        if(!f){
-            return false;
-        }
-        if(!dir){
-            if(this.sortInfo &amp;&amp; this.sortInfo.field == f.name){ // toggle sort dir
-                dir = (this.sortToggle[f.name] || &quot;ASC&quot;).toggle(&quot;ASC&quot;, &quot;DESC&quot;);
-            }else{
-                dir = f.sortDir;
-            }
-        }
-        var st = (this.sortToggle) ? this.sortToggle[f.name] : null;
-        var si = (this.sortInfo) ? this.sortInfo : null;
-
-        this.sortToggle[f.name] = dir;
-        this.sortInfo = {field: f.name, direction: dir};
-        if(!this.remoteSort){
-            this.applySort();
-            this.fireEvent(&quot;datachanged&quot;, this);
-        }else{
-            if (!this.load(this.lastOptions)) {
-                if (st) {
-                    this.sortToggle[f.name] = st;
-                }
-                if (si) {
-                    this.sortInfo = si;
-                }
-            }
-        }
-    },
-
-    
-    each : function(fn, scope){
-        this.data.each(fn, scope);
-    },
-
-    
-    getModifiedRecords : function(){
-        return this.modified;
-    },
-
-    // private
-    createFilterFn : function(property, value, anyMatch, caseSensitive){
-        if(Ext.isEmpty(value, false)){
-            return false;
-        }
-        value = this.data.createValueMatcher(value, anyMatch, caseSensitive);
-        return function(r){
-            return value.test(r.data[property]);
-        };
-    },
-
-    
-    sum : function(property, start, end){
-        var rs = this.data.items, v = 0;
-        start = start || 0;
-        end = (end || end === 0) ? end : rs.length-1;
-
-        for(var i = start; i &lt;= end; i++){
-            v += (rs[i].data[property] || 0);
-        }
-        return v;
-    },
-
-    
-    filter : function(property, value, anyMatch, caseSensitive){
-        var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
-        return fn ? this.filterBy(fn) : this.clearFilter();
-    },
-
-    
-    filterBy : function(fn, scope){
-        this.snapshot = this.snapshot || this.data;
-        this.data = this.queryBy(fn, scope||this);
-        this.fireEvent(&quot;datachanged&quot;, this);
-    },
-
-    
-    query : function(property, value, anyMatch, caseSensitive){
-        var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
-        return fn ? this.queryBy(fn) : this.data.clone();
-    },
-
-    
-    queryBy : function(fn, scope){
-        var data = this.snapshot || this.data;
-        return data.filterBy(fn, scope||this);
-    },
-
-    
-    find : function(property, value, start, anyMatch, caseSensitive){
-        var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
-        return fn ? this.data.findIndexBy(fn, null, start) : -1;
-    },
-
-    
-    findBy : function(fn, scope, start){
-        return this.data.findIndexBy(fn, scope, start);
-    },
-
-    
-    collect : function(dataIndex, allowNull, bypassFilter){
-        var d = (bypassFilter === true &amp;&amp; this.snapshot) ?
-                this.snapshot.items : this.data.items;
-        var v, sv, r = [], l = {};
-        for(var i = 0, len = d.length; i &lt; len; i++){
-            v = d[i].data[dataIndex];
-            sv = String(v);
-            if((allowNull || !Ext.isEmpty(v)) &amp;&amp; !l[sv]){
-                l[sv] = true;
-                r[r.length] = v;
-            }
-        }
-        return r;
-    },
-
-    
-    clearFilter : function(suppressEvent){
-        if(this.isFiltered()){
-            this.data = this.snapshot;
-            delete this.snapshot;
-            if(suppressEvent !== true){
-                this.fireEvent(&quot;datachanged&quot;, this);
-            }
-        }
-    },
-
-    
-    isFiltered : function(){
-        return this.snapshot &amp;&amp; this.snapshot != this.data;
-    },
-
-    // private
-    afterEdit : function(record){
-        if(this.modified.indexOf(record) == -1){
-            this.modified.push(record);
-        }
-        this.fireEvent(&quot;update&quot;, this, record, Ext.data.Record.EDIT);
-    },
-
-    // private
-    afterReject : function(record){
-        this.modified.remove(record);
-        this.fireEvent(&quot;update&quot;, this, record, Ext.data.Record.REJECT);
-    },
-
-    // private
-    afterCommit : function(record){
-        this.modified.remove(record);
-        this.fireEvent(&quot;update&quot;, this, record, Ext.data.Record.COMMIT);
-    },
-
-    
-    commitChanges : function(){
-        var m = this.modified.slice(0);
-        this.modified = [];
-        for(var i = 0, len = m.length; i &lt; len; i++){
-            m[i].commit();
-        }
-    },
-
-    
-    rejectChanges : function(){
-        var m = this.modified.slice(0);
-        this.modified = [];
-        for(var i = 0, len = m.length; i &lt; len; i++){
-            m[i].reject();
-        }
-    },
-
-    // private
-    onMetaChange : function(meta, rtype, o){
-        this.recordType = rtype;
-        this.fields = rtype.prototype.fields;
-        delete this.snapshot;
-        this.sortInfo = meta.sortInfo;
-        this.modified = [];
-        this.fireEvent('metachange', this, this.reader.meta);
-    },
-
-    // private
-    findInsertIndex : function(record){
-        this.suspendEvents();
-        var data = this.data.clone();
-        this.data.add(record);
-        this.applySort();
-        var index = this.data.indexOf(record);
-        this.data = data;
-        this.resumeEvents();
-        return index;
-    },
-
-    
-    setBaseParam : function (name, value){
-        this.baseParams = this.baseParams || {};
-        this.baseParams[name] = value;
-    }
-});
-
-Ext.reg('store', Ext.data.Store);
+};
+
+Ext.data.Record = function(data, id){
+    // if no id, call the auto id method
+    this.id = (id || id === 0) ? id : Ext.data.Record.id(this);
+    this.data = data || {};
+};
+
+
+Ext.data.Record.create = function(o){
+    var f = Ext.extend(Ext.data.Record, {});
+    var p = f.prototype;
+    p.fields = new Ext.util.MixedCollection(false, function(field){
+        return field.name;
+    });
+    for(var i = 0, len = o.length; i &lt; len; i++){
+        p.fields.add(new Ext.data.Field(o[i]));
+    }
+    f.getField = function(name){
+        return p.fields.get(name);
+    };
+    return f;
+};
+
+Ext.data.Record.PREFIX = 'ext-record';
+Ext.data.Record.AUTO_ID = 1;
+Ext.data.Record.EDIT = 'edit';
+Ext.data.Record.REJECT = 'reject';
+Ext.data.Record.COMMIT = 'commit';
+
+
+
+Ext.data.Record.id = function(rec) {
+    rec.phantom = true;
+    return [Ext.data.Record.PREFIX, '-', Ext.data.Record.AUTO_ID++].join('');
+}
+
+Ext.data.Record.prototype = {
+    
+    
+    
+    
+    dirty : false,
+    editing : false,
+    error: null,
+    
+    modified: null,
+    
+    phantom : false,
+
+    // private
+    join : function(store){
+        
+        this.store = store;
+    },
+
+    
+    set : function(name, value){
+        if(String(this.data[name]) == String(value)){
+            return;
+        }
+        this.dirty = true;
+        if(!this.modified){
+            this.modified = {};
+        }
+        if(typeof this.modified[name] == 'undefined'){
+            this.modified[name] = this.data[name];
+        }
+        this.data[name] = value;
+        if(!this.editing){
+            this.afterEdit();
+        }
+    },
+
+    // private
+    afterEdit: function(){
+        if(this.store){
+            this.store.afterEdit(this);
+        }
+    },
+
+    // private
+    afterReject: function(){
+        if(this.store){
+            this.store.afterReject(this);
+        }
+    },
+
+    // private
+    afterCommit: function(){
+        if(this.store){
+            this.store.afterCommit(this);
+        }
+    },
+
+    
+    get : function(name){
+        return this.data[name];
+    },
+
+    
+    beginEdit : function(){
+        this.editing = true;
+        this.modified = this.modified || {};
+    },
+
+    
+    cancelEdit : function(){
+        this.editing = false;
+        delete this.modified;
+    },
+
+    
+    endEdit : function(){
+        this.editing = false;
+        if(this.dirty){
+            this.afterEdit();
+        }
+    },
+
+    
+    reject : function(silent){
+        var m = this.modified;
+        for(var n in m){
+            if(typeof m[n] != &quot;function&quot;){
+                this.data[n] = m[n];
+            }
+        }
+        this.dirty = false;
+        delete this.modified;
+        this.editing = false;
+        if(silent !== true){
+            this.afterReject();
+        }
+    },
+
+    
+    commit : function(silent){
+        this.dirty = false;
+        delete this.modified;
+        this.editing = false;
+        if(silent !== true){
+            this.afterCommit();
+        }
+    },
+
+    
+    getChanges : function(){
+        var m = this.modified, cs = {};
+        for(var n in m){
+            if(m.hasOwnProperty(n)){
+                cs[n] = this.data[n];
+            }
+        }
+        return cs;
+    },
+
+    // private
+    hasError : function(){
+        return this.error != null;
+    },
+
+    // private
+    clearError : function(){
+        this.error = null;
+    },
+
+    
+    copy : function(newId) {
+        return new this.constructor(Ext.apply({}, this.data), newId || this.id);
+    },
+
+    
+    isModified : function(fieldName){
+        return !!(this.modified &amp;&amp; this.modified.hasOwnProperty(fieldName));
+    },
+
+    
+    isValid : function() {
+        return this.fields.find(function(f) {
+            return (f.allowBlank == false &amp;&amp; Ext.isEmpty(this.data[f.name])) ? true : false;
+        },this) ? false : true;
+    },
+
+    
+    markDirty : function(){
+        this.dirty = true;
+        if(!this.modified){
+            this.modified = {};
+        }
+        this.fields.each(function(f) {
+            this.modified[f.name] = this.data[f.name];
+        },this);
+    }
+};
+
+Ext.StoreMgr = Ext.apply(new Ext.util.MixedCollection(), {
+    
+
+    
+    register : function(){
+        for(var i = 0, s; s = arguments[i]; i++){
+            this.add(s);
+        }
+    },
+
+    
+    unregister : function(){
+        for(var i = 0, s; s = arguments[i]; i++){
+            this.remove(this.lookup(s));
+        }
+    },
+
+    
+    lookup : function(id){
+        if(Ext.isArray(id)){
+            var fields = ['field1'], expand = !Ext.isArray(id[0]);
+            if(!expand){
+                for(var i = 2, len = id[0].length; i &lt;= len; ++i){
+                    fields.push('field' + i);
+                }
+            }
+            return new Ext.data.ArrayStore({
+                fields: fields,
+                data: id,
+                expandData: expand,
+                autoDestroy: true,
+                autoCreated: true
+
+            });
+        }
+        return Ext.isObject(id) ? (id.events ? id : Ext.create(id, 'store')) : this.get(id);
+    },
+
+    // getKey implementation for MixedCollection
+    getKey : function(o){
+         return o.storeId;
+    }
+});
+
+Ext.data.Store = function(config){
+    this.data = new Ext.util.MixedCollection(false);
+    this.data.getKey = function(o){
+        return o.id;
+    };
+    
+    this.baseParams = {};
+
+    // temporary removed-records cache
+    this.removed = [];
+
+    
+    this.paramNames = {
+        &quot;start&quot; : &quot;start&quot;,
+        &quot;limit&quot; : &quot;limit&quot;,
+        &quot;sort&quot; : &quot;sort&quot;,
+        &quot;dir&quot; : &quot;dir&quot;
+    };
+
+    if(config &amp;&amp; config.data){
+        this.inlineData = config.data;
+        delete config.data;
+    }
+
+    Ext.apply(this, config);
+
+    if(this.url &amp;&amp; !this.proxy){
+        this.proxy = new Ext.data.HttpProxy({url: this.url});
+    }
+    // If Store is RESTful, so too is the DataProxy
+    if (this.restful === true) {
+        // When operating RESTfully, a unique transaction is generated for each record.
+        this.batch = false;
+        Ext.data.Api.restify(this.proxy);
+    }
+
+    if(this.reader){ // reader passed
+        if(!this.recordType){
+            this.recordType = this.reader.recordType;
+        }
+        if(this.reader.onMetaChange){
+            this.reader.onMetaChange = this.onMetaChange.createDelegate(this);
+        }
+        if (this.writer) { // writer passed
+            this.writer.meta = this.reader.meta;
+            this.pruneModifiedRecords = true;
+        }
+    }
+
+    
+
+    if(this.recordType){
+        
+        this.fields = this.recordType.prototype.fields;
+    }
+    this.modified = [];
+
+    this.addEvents(
+        
+        'datachanged',
+        
+        'metachange',
+        
+        'add',
+        
+        'remove',
+        
+        'update',
+        
+        'clear',
+        
+        'exception',
+        
+        'beforeload',
+        
+        'load',
+        
+        'loadexception',
+        
+        'beforewrite',
+        
+        'write'
+    );
+
+    if(this.proxy){
+        this.relayEvents(this.proxy,  [&quot;loadexception&quot;, &quot;exception&quot;]);
+    }
+    // With a writer set for the Store, we want to listen to add/remove events to remotely create/destroy records.
+    if (this.writer) {
+        this.on('add', this.createRecords.createDelegate(this));
+        this.on('remove', this.destroyRecord.createDelegate(this));
+        this.on('update', this.updateRecord.createDelegate(this));
+    }
+
+    this.sortToggle = {};
+    if(this.sortField){
+        this.setDefaultSort(this.sortField, this.sortDir);
+    }else if(this.sortInfo){
+        this.setDefaultSort(this.sortInfo.field, this.sortInfo.direction);
+    }
+
+    Ext.data.Store.superclass.constructor.call(this);
+
+    if(this.id){
+        this.storeId = this.id;
+        delete this.id;
+    }
+    if(this.storeId){
+        Ext.StoreMgr.register(this);
+    }
+    if(this.inlineData){
+        this.loadData(this.inlineData);
+        delete this.inlineData;
+    }else if(this.autoLoad){
+        this.load.defer(10, this, [
+            typeof this.autoLoad == 'object' ?
+                this.autoLoad : undefined]);
+    }
+};
+Ext.extend(Ext.data.Store, Ext.util.Observable, {
+    
+    
+    
+    
+    
+    
+    
+    writer : undefined,
+    
+    
+    
+    remoteSort : false,
+
+    
+    autoDestroy : false,
+
+    
+    pruneModifiedRecords : false,
+
+    
+    lastOptions : null,
+
+    
+    autoSave : true,
+
+    
+    batch : true,
+
+    
+    restful: false,
+
+    
+    destroy : function(){
+        if(this.storeId){
+            Ext.StoreMgr.unregister(this);
+        }
+        this.data = null;
+        Ext.destroy(this.proxy);
+        this.reader = this.writer = null;
+        this.purgeListeners();
+    },
+
+    
+    add : function(records){
+        records = [].concat(records);
+        if(records.length &lt; 1){
+            return;
+        }
+        for(var i = 0, len = records.length; i &lt; len; i++){
+            records[i].join(this);
+        }
+        var index = this.data.length;
+        this.data.addAll(records);
+        if(this.snapshot){
+            this.snapshot.addAll(records);
+        }
+        this.fireEvent(&quot;add&quot;, this, records, index);
+    },
+
+    
+    addSorted : function(record){
+        var index = this.findInsertIndex(record);
+        this.insert(index, record);
+    },
+
+    
+    remove : function(record){
+        var index = this.data.indexOf(record);
+        if(index &gt; -1){
+            this.data.removeAt(index);
+            if(this.pruneModifiedRecords){
+                this.modified.remove(record);
+            }
+            if(this.snapshot){
+                this.snapshot.remove(record);
+            }
+            this.fireEvent(&quot;remove&quot;, this, record, index);
+        }
+    },
+
+    
+    removeAt : function(index){
+        this.remove(this.getAt(index));
+    },
+
+    
+    removeAll : function(){
+        this.data.clear();
+        if(this.snapshot){
+            this.snapshot.clear();
+        }
+        if(this.pruneModifiedRecords){
+            this.modified = [];
+        }
+        this.fireEvent(&quot;clear&quot;, this);
+    },
+
+    
+    insert : function(index, records){
+        records = [].concat(records);
+        for(var i = 0, len = records.length; i &lt; len; i++){
+            this.data.insert(index, records[i]);
+            records[i].join(this);
+        }
+        this.fireEvent(&quot;add&quot;, this, records, index);
+    },
+
+    
+    indexOf : function(record){
+        return this.data.indexOf(record);
+    },
+
+    
+    indexOfId : function(id){
+        return this.data.indexOfKey(id);
+    },
+
+    
+    getById : function(id){
+        return this.data.key(id);
+    },
+
+    
+    getAt : function(index){
+        return this.data.itemAt(index);
+    },
+
+    
+    getRange : function(start, end){
+        return this.data.getRange(start, end);
+    },
+
+    // private
+    storeOptions : function(o){
+        o = Ext.apply({}, o);
+        delete o.callback;
+        delete o.scope;
+        this.lastOptions = o;
+    },
+
+    
+    load : function(options) {
+        options = options || {};
+        this.storeOptions(options);
+        if(this.sortInfo &amp;&amp; this.remoteSort){
+            var pn = this.paramNames;
+            options.params = options.params || {};
+            options.params[pn[&quot;sort&quot;]] = this.sortInfo.field;
+            options.params[pn[&quot;dir&quot;]] = this.sortInfo.direction;
+        }
+        try {
+            return this.execute(&quot;read&quot;, null, options); // &lt;-- null represents rs.  No rs for load actions.
+        } catch(e) {
+            this.handleException(e);
+            return false;
+        }
+    },
+
+    
+    updateRecord : function(store, record, action) {
+        if (action == Ext.data.Record.EDIT &amp;&amp; this.autoSave === true &amp;&amp; (!record.phantom || (record.phantom &amp;&amp; record.isValid))) {
+            this.save();
+        }
+    },
+
+    
+    createRecords : function(store, rs, index) {
+        for (var i = 0, len = rs.length; i &lt; len; i++) {
+            if (rs[i].phantom &amp;&amp; rs[i].isValid()) {
+                rs[i].markDirty();  // &lt;-- Mark new records dirty
+                this.modified.push(rs[i]);  // &lt;-- add to modified
+            }
+        }
+        if (this.autoSave === true) {
+            this.save();
+        }
+    },
+
+    
+    destroyRecord : function(store, record, index) {
+        if (this.modified.indexOf(record) != -1) {  // &lt;-- handled already if @cfg pruneModifiedRecords == true
+            this.modified.remove(record);
+        }
+        if (!record.phantom) {
+            this.removed.push(record);
+
+            // since the record has already been removed from the store but the server request has not yet been executed,
+            // must keep track of the last known index this record existed.  If a server error occurs, the record can be
+            // put back into the store.  @see Store#createCallback where the record is returned when response status === false
+            record.lastIndex = index;
+
+            if (this.autoSave === true) {
+                this.save();
+            }
+        }
+    },
+
+    
+    execute : function(action, rs, options) {
+        // blow up if action not Ext.data.CREATE, READ, UPDATE, DESTROY
+        if (!Ext.data.Api.isAction(action)) {
+            throw new Ext.data.Api.Error('execute', action);
+        }
+        // make sure options has a params key
+        options = Ext.applyIf(options||{}, {
+            params: {}
+        });
+
+        // have to separate before-events since load has a different signature than create,destroy and save events since load does not
+        // include the rs (record resultset) parameter.  Capture return values from the beforeaction into doRequest flag.
+        var doRequest = true;
+
+        if (action === &quot;read&quot;) {
+            doRequest = this.fireEvent('beforeload', this, options);
+        }
+        else {
+            // if Writer is configured as listful, force single-recoord rs to be [{}} instead of {}
+            if (this.writer.listful === true &amp;&amp; this.restful !== true) {
+                rs = (Ext.isArray(rs)) ? rs : [rs];
+            }
+            // if rs has just a single record, shift it off so that Writer writes data as &quot;{}&quot; rather than &quot;[{}]&quot;
+            else if (Ext.isArray(rs) &amp;&amp; rs.length == 1) {
+                rs = rs.shift();
+            }
+            // Write the action to options.params
+            if ((doRequest = this.fireEvent('beforewrite', this, action, rs, options)) !== false) {
+                this.writer.write(action, options.params, rs);
+            }
+        }
+        if (doRequest !== false) {
+            // Send request to proxy.
+            var params = Ext.apply(options.params || {}, this.baseParams);
+            if (this.writer &amp;&amp; this.proxy.url &amp;&amp; !this.proxy.restful &amp;&amp; !Ext.data.Api.hasUniqueUrl(this.proxy, action)) {
+                params.xaction = action;
+            }
+            // Note:  Up until this point we've been dealing with &quot;action&quot; as a key from Ext.data.Api.actions.  We'll flip it now
+            // and send the value into DataProxy#request, since it's the value which maps to the DataProxy#api
+            this.proxy.request(Ext.data.Api.actions[action], rs, params, this.reader, this.createCallback(action, rs), this, options);
+        }
+        return doRequest;
+    },
+
+    
+    save : function() {
+        if (!this.writer) {
+            throw new Ext.data.Store.Error('writer-undefined');
+        }
+
+        // DESTROY:  First check for removed records.  Records in this.removed are guaranteed non-phantoms.  @see Store#remove
+        if (this.removed.length) {
+            this.doTransaction(&quot;destroy&quot;, this.removed);
+        }
+
+        // Check for modified records.  Bail-out if empty...
+        var rs = this.getModifiedRecords();
+        if (!rs.length) {
+            return true;
+        }
+
+        // CREATE:  Next check for phantoms within rs.  splice-off and execute create.
+        var phantoms = [];
+        for (var i = rs.length-1; i &gt;= 0; i--) {
+            if (rs[i].phantom === true) {
+                var rec = rs.splice(i, 1).shift();
+                if (rec.isValid()) {
+                    phantoms.push(rec);
+                }
+            } else if (!rs[i].isValid()) { // &lt;-- while we're here, splice-off any !isValid real records
+                rs.splice(i,1);
+            }
+        }
+        // If we have valid phantoms, create them...
+        if (phantoms.length) {
+            this.doTransaction('create', phantoms);
+        }
+
+        // UPDATE:  And finally, if we're still here after splicing-off phantoms and !isValid real records, update the rest...
+        if (rs.length) {
+            this.doTransaction('update', rs);
+        }
+        return true;
+    },
+
+    // private.  Simply wraps call to Store#execute in try/catch.  Defers to Store#handleException on error.  Loops if batch: false
+    doTransaction : function(action, rs) {
+        if (this.batch === false) {
+            for (var i = 0, len = rs.length; i &lt; len; i++) {
+                transaction.call(this, rs[i]);
+            }
+        } else {
+            transaction.call(this, rs);
+        }
+        function transaction(records) {
+            try {
+                this.execute(action, records);
+            } catch (e) {
+                this.handleException(e);
+            }
+        }
+    },
+
+    // @private callback-handler for remote CRUD actions
+    // Do not override -- override loadRecords, onCreateRecords, onDestroyRecords and onUpdateRecords instead.
+    createCallback : function(action, rs) {
+        var actions = Ext.data.Api.actions;
+        return (action == &quot;read&quot;) ? this.loadRecords : function(data, response, success) {
+            // If success === false here, exception will have been called in DataProxy
+            if (success === true) {
+                this.fireEvent('write', this, action, data, response, rs);
+            } else {
+                this.clearModified(rs);  // &lt;-- If not cleared, they'll keep getting posted with the same data which caused the server error.
+            }
+            // calls: onCreateRecords | onUpdateRecords | onDestroyRecords
+            this['on' + Ext.util.Format.capitalize(action) + 'Records'](success, rs, data);
+        };
+    },
+
+    // Clears records from modified array after an exception event.
+    // NOTE:  records are left marked dirty.  Do we want to commit them even though they were not updated/realized?
+    clearModified : function(rs) {
+        if (Ext.isArray(rs)) {
+            for (var n=rs.length-1;n&gt;=0;n--) {
+                this.modified.splice(this.modified.indexOf(rs[n]), 1);
+            }
+        } else {
+            this.modified.splice(this.modified.indexOf(rs), 1);
+        }
+    },
+
+    // remap record ids in MixedCollection after records have been realized.  @see Store#onCreateRecords, @see DataReader#realize
+    reMap : function(record) {
+        if (Ext.isArray(record)) {
+            for (var i = 0, len = record.length; i &lt; len; i++) {
+                this.reMap(record[i]);
+            }
+        } else {
+            delete this.data.map[record._phid];
+            this.data.map[record.id] = record;
+            var index = this.data.keys.indexOf(record._phid);
+            this.data.keys.splice(index, 1, record.id);
+            delete record._phid;
+        }
+    },
+
+    // @protected onCreateRecord proxy callback for create action
+    onCreateRecords : function(success, rs, data) {
+        if (success === true) {
+            try {
+                this.reader.realize(rs, data);
+                this.reMap(rs);
+            }
+            catch (e) {
+                this.handleException(e);
+                if (Ext.isArray(rs)) {
+                    // Recurse to run back into the try {}.  DataReader#realize splices-off the rs until empty.
+                    this.onCreateRecords(success, rs, data);
+                }
+            }
+        }
+    },
+
+    // @protected, onUpdateRecords proxy callback for update action
+    onUpdateRecords : function(success, rs, data) {
+        if (success === true) {
+            try {
+                this.reader.update(rs, data);
+            } catch (e) {
+                this.handleException(e);
+                if (Ext.isArray(rs)) {
+                    // Recurse to run back into the try {}.  DataReader#update splices-off the rs until empty.
+                    this.onUpdateRecords(success, rs, data);
+                }
+            }
+        }
+    },
+
+    // @protected onDestroyRecords proxy callback for destroy action
+    onDestroyRecords : function(success, rs, data) {
+        // splice each rec out of this.removed
+        rs = (rs instanceof Ext.data.Record) ? [rs] : rs;
+        for (var i=0,len=rs.length;i&lt;len;i++) {
+            this.removed.splice(this.removed.indexOf(rs[i]), 1);
+        }
+        if (success === false) {
+            // put records back into store if remote destroy fails.
+            // @TODO: Might want to let developer decide.
+            for (i=rs.length-1;i&gt;=0;i--) {
+                this.insert(rs[i].lastIndex, rs[i]);    // &lt;-- lastIndex set in Store#destroyRecord
+            }
+        }
+    },
+
+    // protected handleException.  Possibly temporary until Ext framework has an exception-handler.
+    handleException : function(e) {
+        // @see core/Error.js
+        Ext.handleError(e);
+    },
+
+    
+    reload : function(options){
+        this.load(Ext.applyIf(options||{}, this.lastOptions));
+    },
+
+    // private
+    // Called as a callback by the Reader during a load operation.
+    loadRecords : function(o, options, success){
+        if(!o || success === false){
+            if(success !== false){
+                this.fireEvent(&quot;load&quot;, this, [], options);
+            }
+            if(options.callback){
+                options.callback.call(options.scope || this, [], options, false, o);
+            }
+            return;
+        }
+        var r = o.records, t = o.totalRecords || r.length;
+        if(!options || options.add !== true){
+            if(this.pruneModifiedRecords){
+                this.modified = [];
+            }
+            for(var i = 0, len = r.length; i &lt; len; i++){
+                r[i].join(this);
+            }
+            if(this.snapshot){
+                this.data = this.snapshot;
+                delete this.snapshot;
+            }
+            this.data.clear();
+            this.data.addAll(r);
+            this.totalLength = t;
+            this.applySort();
+            this.fireEvent(&quot;datachanged&quot;, this);
+        }else{
+            this.totalLength = Math.max(t, this.data.length+r.length);
+            this.add(r);
+        }
+        this.fireEvent(&quot;load&quot;, this, r, options);
+        if(options.callback){
+            options.callback.call(options.scope || this, r, options, true);
+        }
+    },
+
+    
+    loadData : function(o, append){
+        var r = this.reader.readRecords(o);
+        this.loadRecords(r, {add: append}, true);
+    },
+
+    
+    getCount : function(){
+        return this.data.length || 0;
+    },
+
+    
+    getTotalCount : function(){
+        return this.totalLength || 0;
+    },
+
+    
+    getSortState : function(){
+        return this.sortInfo;
+    },
+
+    // private
+    applySort : function(){
+        if(this.sortInfo &amp;&amp; !this.remoteSort){
+            var s = this.sortInfo, f = s.field;
+            this.sortData(f, s.direction);
+        }
+    },
+
+    // private
+    sortData : function(f, direction){
+        direction = direction || 'ASC';
+        var st = this.fields.get(f).sortType;
+        var fn = function(r1, r2){
+            var v1 = st(r1.data[f]), v2 = st(r2.data[f]);
+            return v1 &gt; v2 ? 1 : (v1 &lt; v2 ? -1 : 0);
+        };
+        this.data.sort(direction, fn);
+        if(this.snapshot &amp;&amp; this.snapshot != this.data){
+            this.snapshot.sort(direction, fn);
+        }
+    },
+
+    
+    setDefaultSort : function(field, dir){
+        dir = dir ? dir.toUpperCase() : &quot;ASC&quot;;
+        this.sortInfo = {field: field, direction: dir};
+        this.sortToggle[field] = dir;
+    },
+
+    
+    sort : function(fieldName, dir){
+        var f = this.fields.get(fieldName);
+        if(!f){
+            return false;
+        }
+        if(!dir){
+            if(this.sortInfo &amp;&amp; this.sortInfo.field == f.name){ // toggle sort dir
+                dir = (this.sortToggle[f.name] || &quot;ASC&quot;).toggle(&quot;ASC&quot;, &quot;DESC&quot;);
+            }else{
+                dir = f.sortDir;
+            }
+        }
+        var st = (this.sortToggle) ? this.sortToggle[f.name] : null;
+        var si = (this.sortInfo) ? this.sortInfo : null;
+
+        this.sortToggle[f.name] = dir;
+        this.sortInfo = {field: f.name, direction: dir};
+        if(!this.remoteSort){
+            this.applySort();
+            this.fireEvent(&quot;datachanged&quot;, this);
+        }else{
+            if (!this.load(this.lastOptions)) {
+                if (st) {
+                    this.sortToggle[f.name] = st;
+                }
+                if (si) {
+                    this.sortInfo = si;
+                }
+            }
+        }
+    },
+
+    
+    each : function(fn, scope){
+        this.data.each(fn, scope);
+    },
+
+    
+    getModifiedRecords : function(){
+        return this.modified;
+    },
+
+    // private
+    createFilterFn : function(property, value, anyMatch, caseSensitive){
+        if(Ext.isEmpty(value, false)){
+            return false;
+        }
+        value = this.data.createValueMatcher(value, anyMatch, caseSensitive);
+        return function(r){
+            return value.test(r.data[property]);
+        };
+    },
+
+    
+    sum : function(property, start, end){
+        var rs = this.data.items, v = 0;
+        start = start || 0;
+        end = (end || end === 0) ? end : rs.length-1;
+
+        for(var i = start; i &lt;= end; i++){
+            v += (rs[i].data[property] || 0);
+        }
+        return v;
+    },
+
+    
+    filter : function(property, value, anyMatch, caseSensitive){
+        var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
+        return fn ? this.filterBy(fn) : this.clearFilter();
+    },
+
+    
+    filterBy : function(fn, scope){
+        this.snapshot = this.snapshot || this.data;
+        this.data = this.queryBy(fn, scope||this);
+        this.fireEvent(&quot;datachanged&quot;, this);
+    },
+
+    
+    query : function(property, value, anyMatch, caseSensitive){
+        var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
+        return fn ? this.queryBy(fn) : this.data.clone();
+    },
+
+    
+    queryBy : function(fn, scope){
+        var data = this.snapshot || this.data;
+        return data.filterBy(fn, scope||this);
+    },
+
+    
+    find : function(property, value, start, anyMatch, caseSensitive){
+        var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
+        return fn ? this.data.findIndexBy(fn, null, start) : -1;
+    },
+
+    
+    findBy : function(fn, scope, start){
+        return this.data.findIndexBy(fn, scope, start);
+    },
+
+    
+    collect : function(dataIndex, allowNull, bypassFilter){
+        var d = (bypassFilter === true &amp;&amp; this.snapshot) ?
+                this.snapshot.items : this.data.items;
+        var v, sv, r = [], l = {};
+        for(var i = 0, len = d.length; i &lt; len; i++){
+            v = d[i].data[dataIndex];
+            sv = String(v);
+            if((allowNull || !Ext.isEmpty(v)) &amp;&amp; !l[sv]){
+                l[sv] = true;
+                r[r.length] = v;
+            }
+        }
+        return r;
+    },
+
+    
+    clearFilter : function(suppressEvent){
+        if(this.isFiltered()){
+            this.data = this.snapshot;
+            delete this.snapshot;
+            if(suppressEvent !== true){
+                this.fireEvent(&quot;datachanged&quot;, this);
+            }
+        }
+    },
+
+    
+    isFiltered : function(){
+        return this.snapshot &amp;&amp; this.snapshot != this.data;
+    },
+
+    // private
+    afterEdit : function(record){
+        if(this.modified.indexOf(record) == -1){
+            this.modified.push(record);
+        }
+        this.fireEvent(&quot;update&quot;, this, record, Ext.data.Record.EDIT);
+    },
+
+    // private
+    afterReject : function(record){
+        this.modified.remove(record);
+        this.fireEvent(&quot;update&quot;, this, record, Ext.data.Record.REJECT);
+    },
+
+    // private
+    afterCommit : function(record){
+        this.modified.remove(record);
+        this.fireEvent(&quot;update&quot;, this, record, Ext.data.Record.COMMIT);
+    },
+
+    
+    commitChanges : function(){
+        var m = this.modified.slice(0);
+        this.modified = [];
+        for(var i = 0, len = m.length; i &lt; len; i++){
+            m[i].commit();
+        }
+    },
+
+    
+    rejectChanges : function(){
+        var m = this.modified.slice(0);
+        this.modified = [];
+        for(var i = 0, len = m.length; i &lt; len; i++){
+            m[i].reject();
+        }
+    },
+
+    // private
+    onMetaChange : function(meta, rtype, o){
+        this.recordType = rtype;
+        this.fields = rtype.prototype.fields;
+        delete this.snapshot;
+        if(meta.sortInfo){
+            this.sortInfo = meta.sortInfo;
+        }else if(this.sortInfo  &amp;&amp; !this.fields.get(this.sortInfo.field)){
+            delete this.sortInfo;
+        }
+        this.modified = [];
+        this.fireEvent('metachange', this, this.reader.meta);
+    },
+
+    // private
+    findInsertIndex : function(record){
+        this.suspendEvents();
+        var data = this.data.clone();
+        this.data.add(record);
+        this.applySort();
+        var index = this.data.indexOf(record);
+        this.data = data;
+        this.resumeEvents();
+        return index;
+    },
+
+    
+    setBaseParam : function (name, value){
+        this.baseParams = this.baseParams || {};
+        this.baseParams[name] = value;
+    }
+});
+
+Ext.reg('store', Ext.data.Store);
+
+
+Ext.data.Store.Error = Ext.extend(Ext.Error, {
+    name: 'Ext.data.Store'
+});
+Ext.apply(Ext.data.Store.Error.prototype, {
+    lang: {
+        &quot;writer-undefined&quot; : &quot;Attempted to execute a write-action without a DataWriter installed.&quot;
+    }
+});
+
+
 
 Ext.data.DirectStore = function(c){
-	Ext.data.DirectStore.superclass.constructor.call(this, Ext.apply(c, {
+    // each transaction upon a singe record will generatie a distinct Direct transaction since Direct queues them into one Ajax request.
+    c.batchTransactions = false;
+
+    Ext.data.DirectStore.superclass.constructor.call(this, Ext.apply(c, {
         proxy: (typeof(c.proxy) == 'undefined') ? new Ext.data.DirectProxy(Ext.copyTo({}, c, 'paramOrder,paramsAsHash,directFn,api')) : c.proxy,
         reader: (typeof(c.reader) == 'undefined' &amp;&amp; typeof(c.fields) == 'object') ? new Ext.data.JsonReader(Ext.copyTo({}, c, 'totalProperty,root,idProperty'), c.fields) : c.reader
     }));
 };
-Ext.extend(Ext.data.DirectStore, Ext.data.Store);
-Ext.reg('directstore', Ext.data.DirectStore);
-
-
-Ext.data.JsonStore = Ext.extend(Ext.data.Store, {
-    constructor: function(config){
-        Ext.data.JsonStore.superclass.constructor.call(this, Ext.apply(config, {
-            reader: new Ext.data.JsonReader(config)
-        }));
-    }
-    
-    
-});
-Ext.reg('jsonstore', Ext.data.JsonStore);
+Ext.extend(Ext.data.DirectStore, Ext.data.Store, {});
+Ext.reg('directstore', Ext.data.DirectStore);
+
+
+Ext.data.JsonStore = Ext.extend(Ext.data.Store, {
+    
+    constructor: function(config){
+        Ext.data.JsonStore.superclass.constructor.call(this, Ext.apply(config, {
+            reader: new Ext.data.JsonReader(config)
+        }));
+    }
+});
+Ext.reg('jsonstore', Ext.data.JsonStore);
 
 Ext.data.XmlStore = Ext.extend(Ext.data.Store, {
+    
     constructor: function(config){
         Ext.data.XmlStore.superclass.constructor.call(this, Ext.apply(config, {
             reader: new Ext.data.XmlReader(config)
         }));
     }
-    
-    
-});
-Ext.reg('xmlstore', Ext.data.XmlStore);
-
-Ext.data.ArrayStore = Ext.extend(Ext.data.Store, {
-    constructor: function(config){
-        Ext.data.ArrayStore.superclass.constructor.call(this, Ext.apply(config, {
-            reader: new Ext.data.ArrayReader(config)
-        }));
-    },
-
-    loadData : function(data, append){
-        if(this.expandData === true){
-            var r = [];
-            for(var i = 0, len = data.length; i &lt; len; i++){
-                r[r.length] = [data[i]];
-            }
-            data = r;
-        }
-        Ext.data.ArrayStore.superclass.loadData.call(this, data, append);
-    }
 });
-Ext.reg('arraystore', Ext.data.ArrayStore);
-
-// backwards compat
-Ext.data.SimpleStore = Ext.data.ArrayStore;
-Ext.reg('simplestore', Ext.data.SimpleStore);
-
-Ext.data.Field = function(config){
-    if(typeof config == &quot;string&quot;){
-        config = {name: config};
-    }
-    Ext.apply(this, config);
-
-    if(!this.type){
-        this.type = &quot;auto&quot;;
-    }
-
-    var st = Ext.data.SortTypes;
-    // named sortTypes are supported, here we look them up
-    if(typeof this.sortType == &quot;string&quot;){
-        this.sortType = st[this.sortType];
-    }
-
-    // set default sortType for strings and dates
-    if(!this.sortType){
-        switch(this.type){
-            case &quot;string&quot;:
-                this.sortType = st.asUCString;
-                break;
-            case &quot;date&quot;:
-                this.sortType = st.asDate;
-                break;
-            default:
-                this.sortType = st.none;
-        }
-    }
-
-    // define once
-    var stripRe = /[\$,%]/g;
-
-    // prebuilt conversion function for this field, instead of
-    // switching every time we're reading a value
-    if(!this.convert){
-        var cv, dateFormat = this.dateFormat;
-        switch(this.type){
-            case &quot;&quot;:
-            case &quot;auto&quot;:
-            case undefined:
-                cv = function(v){ return v; };
-                break;
-            case &quot;string&quot;:
-                cv = function(v){ return (v === undefined || v === null) ? '' : String(v); };
-                break;
-            case &quot;int&quot;:
-                cv = function(v){
-                    return v !== undefined &amp;&amp; v !== null &amp;&amp; v !== '' ?
-                           parseInt(String(v).replace(stripRe, &quot;&quot;), 10) : '';
-                    };
-                break;
-            case &quot;float&quot;:
-                cv = function(v){
-                    return v !== undefined &amp;&amp; v !== null &amp;&amp; v !== '' ?
-                           parseFloat(String(v).replace(stripRe, &quot;&quot;), 10) : '';
-                    };
-                break;
-            case &quot;bool&quot;:
-            case &quot;boolean&quot;:
-                cv = function(v){ return v === true || v === &quot;true&quot; || v == 1; };
-                break;
-            case &quot;date&quot;:
-                cv = function(v){
-                    if(!v){
-                        return '';
-                    }
-                    if(Ext.isDate(v)){
-                        return v;
-                    }
-                    if(dateFormat){
-                        if(dateFormat == &quot;timestamp&quot;){
-                            return new Date(v*1000);
-                        }
-                        if(dateFormat == &quot;time&quot;){
-                            return new Date(parseInt(v, 10));
-                        }
-                        return Date.parseDate(v, dateFormat);
-                    }
-                    var parsed = Date.parse(v);
-                    return parsed ? new Date(parsed) : null;
-                };
-             break;
-
-        }
-        this.convert = cv;
-    }
-};
-
-Ext.data.Field.prototype = {
-    
-    
-    
-    
-    dateFormat: null,
-    
-    defaultValue: &quot;&quot;,
-    
-    mapping: null,
-    
-    sortType : null,
-    
-    sortDir : &quot;ASC&quot;,
-	
-	allowBlank : true
-};
+Ext.reg('xmlstore', Ext.data.XmlStore);
+
+Ext.data.ArrayStore = Ext.extend(Ext.data.Store, {
+    
+    constructor: function(config){
+        Ext.data.ArrayStore.superclass.constructor.call(this, Ext.apply(config, {
+            reader: new Ext.data.ArrayReader(config)
+        }));
+    },
+
+    loadData : function(data, append){
+        if(this.expandData === true){
+            var r = [];
+            for(var i = 0, len = data.length; i &lt; len; i++){
+                r[r.length] = [data[i]];
+            }
+            data = r;
+        }
+        Ext.data.ArrayStore.superclass.loadData.call(this, data, append);
+    }
+});
+Ext.reg('arraystore', Ext.data.ArrayStore);
+
+// backwards compat
+Ext.data.SimpleStore = Ext.data.ArrayStore;
+Ext.reg('simplestore', Ext.data.SimpleStore);
+
+Ext.data.Field = function(config){
+    if(typeof config == &quot;string&quot;){
+        config = {name: config};
+    }
+    Ext.apply(this, config);
+
+    if(!this.type){
+        this.type = &quot;auto&quot;;
+    }
+
+    var st = Ext.data.SortTypes;
+    // named sortTypes are supported, here we look them up
+    if(typeof this.sortType == &quot;string&quot;){
+        this.sortType = st[this.sortType];
+    }
+
+    // set default sortType for strings and dates
+    if(!this.sortType){
+        switch(this.type){
+            case &quot;string&quot;:
+                this.sortType = st.asUCString;
+                break;
+            case &quot;date&quot;:
+                this.sortType = st.asDate;
+                break;
+            default:
+                this.sortType = st.none;
+        }
+    }
+
+    // define once
+    var stripRe = /[\$,%]/g;
+
+    // prebuilt conversion function for this field, instead of
+    // switching every time we're reading a value
+    if(!this.convert){
+        var cv, dateFormat = this.dateFormat;
+        switch(this.type){
+            case &quot;&quot;:
+            case &quot;auto&quot;:
+            case undefined:
+                cv = function(v){ return v; };
+                break;
+            case &quot;string&quot;:
+                cv = function(v){ return (v === undefined || v === null) ? '' : String(v); };
+                break;
+            case &quot;int&quot;:
+                cv = function(v){
+                    return v !== undefined &amp;&amp; v !== null &amp;&amp; v !== '' ?
+                           parseInt(String(v).replace(stripRe, &quot;&quot;), 10) : '';
+                    };
+                break;
+            case &quot;float&quot;:
+                cv = function(v){
+                    return v !== undefined &amp;&amp; v !== null &amp;&amp; v !== '' ?
+                           parseFloat(String(v).replace(stripRe, &quot;&quot;), 10) : '';
+                    };
+                break;
+            case &quot;bool&quot;:
+            case &quot;boolean&quot;:
+                cv = function(v){ return v === true || v === &quot;true&quot; || v == 1; };
+                break;
+            case &quot;date&quot;:
+                cv = function(v){
+                    if(!v){
+                        return '';
+                    }
+                    if(Ext.isDate(v)){
+                        return v;
+                    }
+                    if(dateFormat){
+                        if(dateFormat == &quot;timestamp&quot;){
+                            return new Date(v*1000);
+                        }
+                        if(dateFormat == &quot;time&quot;){
+                            return new Date(parseInt(v, 10));
+                        }
+                        return Date.parseDate(v, dateFormat);
+                    }
+                    var parsed = Date.parse(v);
+                    return parsed ? new Date(parsed) : null;
+                };
+             break;
+
+        }
+        this.convert = cv;
+    }
+};
+
+Ext.data.Field.prototype = {
+    
+    
+    
+    
+    dateFormat: null,
+    
+    defaultValue: &quot;&quot;,
+    
+    mapping: null,
+    
+    sortType : null,
+    
+    sortDir : &quot;ASC&quot;,
+	
+	allowBlank : true
+};
 
 Ext.data.DataReader = function(meta, recordType){
     
     this.meta = meta;
+    
     this.recordType = Ext.isArray(recordType) ?
         Ext.data.Record.create(recordType) : recordType;
 };
@@ -12553,14 +12770,18 @@ Ext.data.DataReader.prototype = {
             }
         }
         else {
+            // If rs is NOT an array but data IS, see if data contains just 1 record.  If so extract it and carry on.
+            if (Ext.isArray(data) &amp;&amp; data.length == 1) {
+                data = data.shift();
+            }
             if (!this.isData(data)) {
-                // TODO: create custom Exception class to return record in thrown exception.  Allow exception-handler the choice
-                // to commit or not rather than blindly rs.commit() here.
+                // TODO: Let exception-handler choose to commit or not rather than blindly rs.commit() here.
                 rs.commit();
-                throw new Error(&quot;DataReader#realize was called with invalid remote-data.  Please see the docs for DataReader#realize and review your DataReader configuration.&quot;);
+                throw new Ext.data.DataReader.Error('realize', rs);
             }
             var values = this.extractValues(data, rs.fields.items, rs.fields.items.length);
             rs.phantom = false; // &lt;-- That's what it's all about
+            rs._phid = rs.id;  // &lt;-- copy phantom-id -&gt; _phid, so we can remap in Store#onCreateRecords
             rs.id = data[this.meta.idProperty];
             rs.data = values;
             rs.commit();
@@ -12582,13 +12803,17 @@ Ext.data.DataReader.prototype = {
             }
         }
         else {
+                     // If rs is NOT an array but data IS, see if data contains just 1 record.  If so extract it and carry on.
+            if (Ext.isArray(data) &amp;&amp; data.length == 1) {
+                data = data.shift();
+            }
             if (!this.isData(data)) {
                 // TODO: create custom Exception class to return record in thrown exception.  Allow exception-handler the choice
                 // to commit or not rather than blindly rs.commit() here.
                 rs.commit();
-                throw new Error(&quot;DataReader#update received invalid data from server.  Please see docs for DataReader#update&quot;);
+                throw new Ext.data.DataReader.Error('update', rs);
             }
-            rs.data = this.extractValues(data, rs.fields.items, rs.fields.items.length);
+            rs.data = this.extractValues(Ext.apply(rs.data, data), rs.fields.items, rs.fields.items.length);
             rs.commit();
         }
     },
@@ -12599,180 +12824,195 @@ Ext.data.DataReader.prototype = {
     }
 };
 
-Ext.data.DataWriter = function(config){
-    
-    Ext.apply(this, config);
-};
-
-Ext.data.DataWriter.prototype = {
-
-    meta : {},
-    
-    writeAllFields : false,
-
-    
-    write : function(action, params, rs) {
-        var data = null;
-        switch (action) {
-            case Ext.data.Api.CREATE:
-               data = this.create(rs);
-               break;
-            case Ext.data.Api.UPDATE:
-               data = this.update(rs);
-               break;
-            case Ext.data.Api.DESTROY:
-               data = this.destroy(rs);
-               break;
-        }
-        this.render(action, rs, params, data);
-    },
-
-    
-    render : Ext.emptyFn,
-
-    
-    update : function(rs) {
-        var params = {};
-        if (Ext.isArray(rs)) {
-            var data = [];
-            var ids = [];
-            for (var n=0,len=rs.length;n&lt;len;n++) {
-                ids.push(rs[n].id);
-                data.push(this.updateRecord(rs[n]));
-            }
-            params[this.meta.idProperty] = ids;
-            params[this.meta.root] = data;
-        }
-        else if (rs instanceof Ext.data.Record) {
-            params[this.meta.idProperty] = rs.id;
-            params[this.meta.root] = this.updateRecord(rs);
-        }
-        return params;
-    },
-
-    
-    updateRecord : Ext.emptyFn,
-
-    
-    create : function(rs) {
-        var params = {};
-        if (Ext.isArray(rs)) {
-            var data = [];
-            for (var n=0,len=rs.length;n&lt;len;n++) {
-                data.push(this.createRecord(rs[n]));
-            }
-            params[this.meta.root] = data;
-        }
-        else if (rs instanceof Ext.data.Record) {
-            params[this.meta.root] = this.createRecord(rs);
-        }
-        return params;
-    },
-
-    
-    createRecord : Ext.emptyFn,
 
-    
-    destroy : function(rs) {
-        var params = {};
-        if (Ext.isArray(rs)) {
-            var data = [];
-            var ids = [];
-            for (var i=0,len=rs.length;i&lt;len;i++) {
-                data.push(this.destroyRecord(rs[i]));
-            }
-            params[this.meta.root] = data;
-        } else if (rs instanceof Ext.data.Record) {
-            params[this.meta.root] = this.destroyRecord(rs);
-        }
-        return params;
+Ext.data.DataReader.Error = Ext.extend(Ext.Error, {
+    constructor : function(message, arg) {
+        this.arg = arg;
+        Ext.Error.call(this, message);
     },
-
-    
-    destroyRecord : Ext.emptyFn,
-
-    
-    toHash : function(rec) {
-        var map = rec.fields.map;
-        var data = {};
-        var raw = (this.writeAllFields === false &amp;&amp; rec.phantom === false) ? rec.getChanges() : rec.data;
-        for (var k in raw) {
-            data[(map[k].mapping) ? map[k].mapping : map[k].name] = raw[k];
-        }
-        data[this.meta.idProperty] = rec.id;
-        return data;
+    name: 'Ext.data.DataReader'
+});
+Ext.apply(Ext.data.DataReader.Error.prototype, {
+    lang : {
+        'update': &quot;#update received invalid data from server.  Please see docs for DataReader#update and review your DataReader configuration.&quot;,
+        'realize': &quot;#realize was called with invalid remote-data.  Please see the docs for DataReader#realize and review your DataReader configuration.&quot;,
+        'invalid-response': &quot;#readResponse received an invalid response from the server.&quot;
     }
-};
-
-Ext.data.JsonWriter = Ext.extend(Ext.data.DataWriter, {
-    
-    returnJson : true,
+});
 
-    
-    render : function(action, rs, params, data) {
-        Ext.apply(params, data);
-        if (this.returnJson) {
-            if (Ext.isArray(rs) &amp;&amp; data[this.meta.idProperty]) {
-                params[this.meta.idProperty] = Ext.encode(params[this.meta.idProperty]);
-            }
-            params[this.meta.root] = Ext.encode(params[this.meta.root]);
-        }
-    },
-    
-    createRecord : function(rec) {
-        return this.toHash(rec);
-    },
-    
-    updateRecord : function(rec) {
-        return this.toHash(rec);
 
-    },
-    
-    destroyRecord : function(rec) {
-        return rec.id
-    }
-});
+
+
+Ext.data.DataWriter = function(config){
+    
+    Ext.apply(this, config);
+};
+
+Ext.data.DataWriter.prototype = {
+
+    
+    writeAllFields : false,
+    
+    listful : false,    // &lt;-- listful is actually not used internally here in DataWriter.  @see Ext.data.Store#execute.
+
+    
+    write : function(action, params, rs) {
+        this.render(action, rs, params, this[action](rs));
+    },
+
+    
+    render : Ext.emptyFn,
+
+    
+    update : function(rs) {
+        var params = {};
+        if (Ext.isArray(rs)) {
+            var data = [];
+            var ids = [];
+            for (var n=0,len=rs.length;n&lt;len;n++) {
+                ids.push(rs[n].id);
+                data.push(this.updateRecord(rs[n]));
+            }
+            params[this.meta.idProperty] = ids;
+            params[this.meta.root] = data;
+        }
+        else if (rs instanceof Ext.data.Record) {
+            params[this.meta.idProperty] = rs.id;
+            params[this.meta.root] = this.updateRecord(rs);
+        }
+        return params;
+    },
+
+    
+    updateRecord : Ext.emptyFn,
+
+    
+    create : function(rs) {
+        var params = {};
+        if (Ext.isArray(rs)) {
+            var data = [];
+            for (var n=0,len=rs.length;n&lt;len;n++) {
+                data.push(this.createRecord(rs[n]));
+            }
+            params[this.meta.root] = data;
+        }
+        else if (rs instanceof Ext.data.Record) {
+            params[this.meta.root] = this.createRecord(rs);
+        }
+        return params;
+    },
+
+    
+    createRecord : Ext.emptyFn,
+
+    
+    destroy : function(rs) {
+        var params = {};
+        if (Ext.isArray(rs)) {
+            var data = [];
+            var ids = [];
+            for (var i=0,len=rs.length;i&lt;len;i++) {
+                data.push(this.destroyRecord(rs[i]));
+            }
+            params[this.meta.root] = data;
+        } else if (rs instanceof Ext.data.Record) {
+            params[this.meta.root] = this.destroyRecord(rs);
+        }
+        return params;
+    },
+
+    
+    destroyRecord : Ext.emptyFn,
+
+    
+    toHash : function(rec) {
+        var map = rec.fields.map;
+        var data = {};
+        var raw = (this.writeAllFields === false &amp;&amp; rec.phantom === false) ? rec.getChanges() : rec.data;
+        for (var k in raw) {
+            data[(map[k].mapping) ? map[k].mapping : map[k].name] = raw[k];
+        }
+        data[this.meta.idProperty] = rec.id;
+        return data;
+    }
+};
+
+Ext.data.JsonWriter = Ext.extend(Ext.data.DataWriter, {
+    
+    returnJson : true,
+
+    
+    render : function(action, rs, params, data) {
+        Ext.apply(params, data);
+        if (this.returnJson) {
+            if (Ext.isArray(rs) &amp;&amp; data[this.meta.idProperty]) {
+                params[this.meta.idProperty] = Ext.encode(params[this.meta.idProperty]);
+            }
+            params[this.meta.root] = Ext.encode(params[this.meta.root]);
+        }
+    },
+    
+    createRecord : function(rec) {
+        return this.toHash(rec);
+    },
+    
+    updateRecord : function(rec) {
+        return this.toHash(rec);
+
+    },
+    
+    destroyRecord : function(rec) {
+        return rec.id
+    }
+});
 
 Ext.data.DataProxy = function(conn){
     // make sure we have a config object here to support ux proxies.
     // All proxies should now send config into superclass constructor.
     conn = conn || {};
 
-    Ext.apply(this, conn);
+    // This line caused a bug when people use custom Connection object having its own request method.
+    // http://extjs.com/forum/showthread.php?t=67194.  Have to set DataProxy config
+    //Ext.applyIf(this, conn);
 
-    
+    this.api     = conn.api;
+    this.url     = conn.url;
+    this.restful = conn.restful;
+    this.listeners = conn.listeners;
 
-    // Verify valid api or define if not set.
-    if (conn.api) {
-       var valid = Ext.data.Api.isValid(conn.api);
-       if (valid !== true) {
-           throw new Error('Ext.data.DataProxy#constructor recieved an invalid API-configuration &quot;' + valid.join(', ') + '&quot;.  Please ensure your proxy API-configuration contains only the actions &quot;' + Ext.data.Api.getVerbs().join(', '));
-       }
-    }
-    else {
-        this.api = {};
-        this.api[Ext.data.Api.CREATE]     = undefined;
-        this.api[Ext.data.Api.READ]       = undefined;
-        this.api[Ext.data.Api.UPDATE]     = undefined;
-        this.api[Ext.data.Api.DESTROY]    = undefined;
+    // deprecated
+    this.prettyUrls = conn.prettyUrls;
+
+    
+    // Prepare the proxy api.  Ensures all API-actions are defined with the Object-form.
+    try {
+        Ext.data.Api.prepare(this);
+    } catch (e) {
+        if (e instanceof Ext.data.Api.Error) {
+            e.toConsole();
+        }
     }
 
     this.addEvents(
         
-        'before'+Ext.data.READ,
+        'exception',
+        
+        'beforeload',
         
-        Ext.data.READ,
+        'load',
+        
+        'loadexception',
         
         'beforewrite',
         
         'write'
-
-
     );
     Ext.data.DataProxy.superclass.constructor.call(this);
 };
 
 Ext.extend(Ext.data.DataProxy, Ext.util.Observable, {
+    
+    restful: false,
 
     
     setApi : function() {
@@ -12782,31 +13022,41 @@ Ext.extend(Ext.data.DataProxy, Ext.util.Observable, {
                 this.api = arguments[0];
             }
             else {
-                throw new Error('Ext.data.DataProxy#setApi received invalid API action(s) &quot;' + valid.join(', ') + '&quot;.  Valid API actions are: ' + Ext.data.Api.getVerbs().join(', '));
+                throw new Ext.data.Api.Error('invalid', valid);
             }
         }
         else if (arguments.length == 2) {
-            if (!Ext.data.Api.isVerb(arguments[0])) {
-                throw new Error('Ext.data.DataProxy#setApi received an invalid API action &quot;' + arguments[0] + '&quot;.  Valid API actions are: ' + Ext.data.Api.getVerbs().join(', '))
+            if (!Ext.data.Api.isAction(arguments[0])) {
+                throw new Ext.data.Api.Error('invalid', arguments[0]);
             }
             this.api[arguments[0]] = arguments[1];
         }
+        Ext.data.Api.prepare(this);
+    },
+
+    
+    isApiAction : function(action) {
+        return (this.api[action]) ? true : false;
     },
 
     
     request : function(action, rs, params, reader, callback, scope, options) {
+        if (!this.api[action]) {
+            throw new Ext.data.DataProxy.Error('action-undefined', action);
+        }
         params = params || {};
-        if ((action == Ext.data.Api.READ) ? this.fireEvent(&quot;before&quot;+action, this, params, options) : this.fireEvent(&quot;beforewrite&quot;, this, action, params, options) !== false) {
+        if ((action === Ext.data.Api.actions.read) ? this.fireEvent(&quot;beforeload&quot;, this, params) : this.fireEvent(&quot;beforewrite&quot;, this, action, rs, params) !== false) {
             this.doRequest.apply(this, arguments);
         }
         else {
-            callback.call(scope || this, null, arg, false);
+            callback.call(scope || this, null, options, false);
         }
     },
 
+
     
     load : function(params, reader, callback, scope, arg) {
-        this.doRequest(Ext.data.READ, null, params, reader, callback, scope, arg);
+        this.doRequest(Ext.data.Api.actions.read, null, params, reader, callback, scope, arg);
     },
 
     
@@ -12814,38 +13064,77 @@ Ext.extend(Ext.data.DataProxy, Ext.util.Observable, {
         // default implementation of doRequest for backwards compatibility with 2.0 proxies.
         // If we're executing here, the action is probably &quot;load&quot;.
         // Call with the pre-3.0 method signature.
-        this[action](params, reader, callback, scope, options);
+        // WARNING:  Potentially infinitely recursive:  See load above which calls this.doRequest
+        this.load(params, reader, callback, scope, options);
+    },
+
+    
+    buildUrl : function(action, record) {
+        record = record || null;
+        var url = (this.api[action]) ? this.api[action]['url'] : this.url;
+        if (!url) {
+            throw new Ext.data.Api.Error('invalid-url', action);
+        }
+        // prettyUrls is deprectated in favor of restful-config
+        if ((this.prettyUrls === true || this.restful === true) &amp;&amp; record instanceof Ext.data.Record &amp;&amp; !record.phantom) {
+            url += '/' + record.id;
+        }
+        return url;
+    },
+
+    
+    destroy: function(){
+        this.purgeListeners();
     }
 });
 
+
+Ext.data.DataProxy.Error = Ext.extend(Ext.Error, {
+    constructor : function(message, arg) {
+        this.arg = arg;
+        Ext.Error.call(this, message);
+    },
+    name: 'Ext.data.DataProxy'
+});
+Ext.apply(Ext.data.DataProxy.Error.prototype, {
+    lang: {
+        'action-undefined': &quot;DataProxy attempted to execute an API-action but found an undefined url / function.  Please review your Proxy url/api-configuration.&quot;,
+        'api-invalid': 'Recieved an invalid API-configuration.  Please ensure your proxy API-configuration contains only the actions from Ext.data.Api.actions.'
+    }
+});
+
+
 Ext.data.MemoryProxy = function(data){
-    Ext.data.MemoryProxy.superclass.constructor.call(this);
+    // Must define a dummy api with &quot;read&quot; action to satisfy DataProxy#doRequest and Ext.data.Api#prepare *before* calling super
+    var api = {};
+    api[Ext.data.Api.actions.read] = true;
+    Ext.data.MemoryProxy.superclass.constructor.call(this, {
+        api: api
+    });
     this.data = data;
-
-    // Define the proxy api to satisfy DataProxy#doRequest
-    this.api = {
-        load: true
-    };
 };
 
 Ext.extend(Ext.data.MemoryProxy, Ext.data.DataProxy, {
     
 
        
-    doRequest : function(action, rs, params, reader, writer, callback, scope, arg) {
+    doRequest : function(action, rs, params, reader, callback, scope, arg) {
         // No implementation for CRUD in MemoryProxy.  Assumes all actions are 'load'
         params = params || {};
         var result;
         try {
             result = reader.readRecords(this.data);
         }catch(e){
-            this.fireEvent(&quot;loadexception&quot;, this, arg, null, e);
+            // @deprecated loadexception
+            this.fireEvent(&quot;loadexception&quot;, this, null, arg, e);
+
+            this.fireEvent('exception', this, 'response', action, arg, null, e);
             callback.call(scope, null, arg, false);
             return;
         }
         callback.call(scope, result, arg, true);
     }
-});
+});
 
 Ext.data.HttpProxy = function(conn){
     Ext.data.HttpProxy.superclass.constructor.call(this, conn);
@@ -12861,22 +13150,19 @@ Ext.data.HttpProxy = function(conn){
 
     this.useAjax = !conn || !conn.events;
 
-    //private.  A hash containing active requests, keyed on action [Ext.data.Api.CREATE|READ|UPDATE|DESTROY]
+    //private.  A hash containing active requests, keyed on action [Ext.data.Api.actions.create|read|update|destroy]
+    var actions = Ext.data.Api.actions
     this.activeRequest = {};
-    var verbs = Ext.data.Api.getVerbs();
-    for (var n=0,len=verbs.length;n&lt;len;n++) {
-        this.activeRequest[verbs[n]] = undefined; // &lt;-- initialize availale activeRequest verbs.
+    for (var verb in actions) {
+        this.activeRequest[actions[verb]] = undefined;
     }
-
-    
 };
 
 Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {
     
-    prettyUrls : false,
 
     
-    getConnection : function(){
+    getConnection : function() {
         return this.useAjax ? Ext.Ajax : this.conn;
     },
 
@@ -12885,29 +13171,15 @@ Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {
         this.conn.url = url;
         if (makePermanent === true) {
             this.url = url;
+            Ext.data.Api.prepare(this);
         }
     },
 
     
-    buildUrl : function(action, record) {
-        record = record || null;
-        var url = (this.api[action]) ? this.api[action] : this.url;
-
-        if (!url) {
-            throw new Error('HttpProxy tried to build an url for the action &quot;' + action + '&quot; but could not find an api definition for this action or an url to fall-back to.  Please review your proxy configuration.');
-        }
-
-        if (this.prettyUrls === true &amp;&amp; record instanceof Ext.data.Record &amp;&amp; !record.phantom) {
-            url += '/' + record.id;
-        }
-        return url;
-    },
-
-    
     doRequest : function(action, rs, params, reader, cb, scope, arg) {
         var  o = {
             params : params || {},
-            method: (action === Ext.data.Api.READ) ? &quot;GET&quot; : &quot;POST&quot;,
+            method: (this.api[action]) ? this.api[action]['method'] : undefined,
             request: {
                 callback : cb,
                 scope : scope,
@@ -12917,73 +13189,116 @@ Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {
             callback : this.createCallback(action, rs),
             scope: this
         };
+        // Set the connection url.  If this.conn.url is not null here,
+        // the user may have overridden the url during a beforeaction event-handler.
+        // this.conn.url is nullified after each request.
+        if (this.conn.url === null) {
+            this.conn.url = this.buildUrl(action, rs);
+        }
+        else if (this.restful === true &amp;&amp; rs instanceof Ext.data.Record &amp;&amp; !rs.phantom) {
+            this.conn.url += '/' + rs.id;
+        }
         if(this.useAjax){
-            // Set the connection url.  If this.conn.url is not null here,
-            // the user may have overridden the url during a beforeaction event-handler.
-            // this.conn.url is nullified after each request.
-            if (this.conn.url === null) {
-                this.conn.url = this.buildUrl(action, rs);
-            }
-            else if (this.prettyUrls === true &amp;&amp; rs instanceof Ext.data.Record &amp;&amp; !rs.phantom) {
-                this.conn.url += '/' + rs.id;
-            }
 
             Ext.applyIf(o, this.conn);
 
             // If a currently running request is found for this action, abort it.
             if (this.activeRequest[action]) {
-                Ext.Ajax.abort(this.activeRequest[action]);
+                // Disabled aborting activeRequest while implementing REST.  activeRequest[action] will have to become an array
+                //Ext.Ajax.abort(this.activeRequest[action]);
             }
             this.activeRequest[action] = Ext.Ajax.request(o);
-
-            // request is sent, nullify the connection url in preparation for the next request
-            this.conn.url = null;
-
         }else{
             this.conn.request(o);
         }
+        // request is sent, nullify the connection url in preparation for the next request