Upgrade to ExtJS 3.1.1 - Released 02/08/2010
[extjs.git] / ext-all-debug.js
index d38b19f..8eb0f03 100644 (file)
@@ -1,6 +1,6 @@
 /*!
- * Ext JS Library 3.0.3
- * Copyright(c) 2006-2009 Ext JS, LLC
+ * Ext JS Library 3.1.1
+ * Copyright(c) 2006-2010 Ext JS, LLC
  * licensing@extjs.com
  * http://www.extjs.com/license
  */
@@ -167,9 +167,11 @@ Ext.DomHelper = function(){
         if(Ext.isString(o)){\r
             b = o;\r
         } else if (Ext.isArray(o)) {\r
-            Ext.each(o, function(v) {\r
-                b += createHtml(v);\r
-            });\r
+            for (var i=0; i < o.length; i++) {\r
+                if(o[i]) {\r
+                    b += createHtml(o[i]);\r
+                }\r
+            };\r
         } else {\r
             b += '<' + (o.tag = o.tag || 'div');\r
             Ext.iterate(o, function(attr, val){\r
@@ -974,6 +976,7 @@ All selectors, attribute filters and pseudos below can be combined infinitely in
     <li> <b>E:has(S)</b> an E element that has a descendent that matches simple selector S</li>\r
     <li> <b>E:next(S)</b> an E element whose next sibling matches simple selector S</li>\r
     <li> <b>E:prev(S)</b> an E element whose previous sibling matches simple selector S</li>\r
+    <li> <b>E:any(S1|S2|S2)</b> an E element which matches any of the simple selectors S1, S2 or S3//\\</li>\r
 </ul>\r
 <h4>CSS Value Selectors:</h4>\r
 <ul class="list">\r
@@ -998,19 +1001,20 @@ Ext.DomQuery = function(){
        nthRe = /(\d*)n\+?(\d*)/, \r
        nthRe2 = /\D/,\r
        // This is for IE MSXML which does not support expandos.\r
-           // IE runs the same speed using setAttribute, however FF slows way down\r
-           // and Safari completely fails so they need to continue to use expandos.\r
-           isIE = window.ActiveXObject ? true : false,\r
-        isOpera = Ext.isOpera,\r
-           key = 30803;\r
-           \r
+       // IE runs the same speed using setAttribute, however FF slows way down\r
+       // and Safari completely fails so they need to continue to use expandos.\r
+       isIE = window.ActiveXObject ? true : false,\r
+       key = 30803;\r
+    \r
     // this eval is stop the compressor from\r
-       // renaming the variable to something shorter\r
-       eval("var batch = 30803;");     \r
+    // renaming the variable to something shorter\r
+    eval("var batch = 30803;");        \r
 \r
-    function child(p, index){\r
+    // Retrieve the child node from a particular\r
+    // parent at the specified index.\r
+    function child(parent, index){\r
         var i = 0,\r
-               n = p.firstChild;\r
+            n = parent.firstChild;\r
         while(n){\r
             if(n.nodeType == 1){\r
                if(++i == index){\r
@@ -1020,53 +1024,65 @@ Ext.DomQuery = function(){
             n = n.nextSibling;\r
         }\r
         return null;\r
-    };\r
+    }\r
 \r
-    function next(n){\r
+    // retrieve the next element node\r
+    function next(n){  \r
         while((n = n.nextSibling) && n.nodeType != 1);\r
         return n;\r
-    };\r
+    }\r
 \r
+    // retrieve the previous element node \r
     function prev(n){\r
         while((n = n.previousSibling) && n.nodeType != 1);\r
         return n;\r
-    };\r
+    }\r
+\r
+    // Mark each child node with a nodeIndex skipping and\r
+    // removing empty text nodes.\r
+    function children(parent){\r
+        var n = parent.firstChild,\r
+           nodeIndex = -1,\r
+           nextNode;\r
+       while(n){\r
+           nextNode = n.nextSibling;\r
+           // clean worthless empty nodes.\r
+           if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){\r
+               parent.removeChild(n);\r
+           }else{\r
+               // add an expando nodeIndex\r
+               n.nodeIndex = ++nodeIndex;\r
+           }\r
+           n = nextNode;\r
+       }\r
+       return this;\r
+    }\r
+\r
 \r
-    function children(d){\r
-        var n = d.firstChild, ni = -1,\r
-               nx;\r
-           while(n){\r
-               nx = n.nextSibling;\r
-               if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){\r
-                   d.removeChild(n);\r
-               }else{\r
-                   n.nodeIndex = ++ni;\r
-               }\r
-               n = nx;\r
-           }\r
-           return this;\r
-       };\r
-\r
-    function byClassName(c, a, v){\r
-        if(!v){\r
-            return c;\r
-        }\r
-        var r = [], ri = -1, cn;\r
-        for(var i = 0, ci; ci = c[i]; i++){\r
-            if((' '+ci.className+' ').indexOf(v) != -1){\r
-                r[++ri] = ci;\r
+    // nodeSet - array of nodes\r
+    // cls - CSS Class\r
+    function byClassName(nodeSet, cls){\r
+        if(!cls){\r
+            return nodeSet;\r
+        }\r
+        var result = [], ri = -1;\r
+        for(var i = 0, ci; ci = nodeSet[i]; i++){\r
+            if((' '+ci.className+' ').indexOf(cls) != -1){\r
+                result[++ri] = ci;\r
             }\r
         }\r
-        return r;\r
+        return result;\r
     };\r
 \r
     function attrValue(n, attr){\r
+       // if its an array, use the first node.\r
         if(!n.tagName && typeof n.length != "undefined"){\r
             n = n[0];\r
         }\r
         if(!n){\r
             return null;\r
         }\r
+\r
         if(attr == "for"){\r
             return n.htmlFor;\r
         }\r
@@ -1077,15 +1093,23 @@ Ext.DomQuery = function(){
 \r
     };\r
 \r
+\r
+    // ns - nodes\r
+    // mode - false, /, >, +, ~\r
+    // tagName - defaults to "*"\r
     function getNodes(ns, mode, tagName){\r
         var result = [], ri = -1, cs;\r
         if(!ns){\r
             return result;\r
         }\r
         tagName = tagName || "*";\r
+       // convert to array\r
         if(typeof ns.getElementsByTagName != "undefined"){\r
             ns = [ns];\r
         }\r
+       \r
+       // no mode specified, grab all elements by tagName\r
+       // at any depth\r
         if(!mode){\r
             for(var i = 0, ni; ni = ns[i]; i++){\r
                 cs = ni.getElementsByTagName(tagName);\r
@@ -1093,16 +1117,20 @@ Ext.DomQuery = function(){
                     result[++ri] = ci;\r
                 }\r
             }\r
-        }else if(mode == "/" || mode == ">"){\r
+       // Direct Child mode (/ or >)\r
+       // E > F or E/F all direct children elements of E that have the tag     \r
+        } else if(mode == "/" || mode == ">"){\r
             var utag = tagName.toUpperCase();\r
             for(var i = 0, ni, cn; ni = ns[i]; i++){\r
-                cn = isOpera ? ni.childNodes : (ni.children || ni.childNodes);\r
+                cn = ni.childNodes;\r
                 for(var j = 0, cj; cj = cn[j]; j++){\r
                     if(cj.nodeName == utag || cj.nodeName == tagName  || tagName == '*'){\r
                         result[++ri] = cj;\r
                     }\r
                 }\r
             }\r
+       // Immediately Preceding mode (+)\r
+       // E + F all elements with the tag F that are immediately preceded by an element with the tag E\r
         }else if(mode == "+"){\r
             var utag = tagName.toUpperCase();\r
             for(var i = 0, n; n = ns[i]; i++){\r
@@ -1111,6 +1139,8 @@ Ext.DomQuery = function(){
                     result[++ri] = n;\r
                 }\r
             }\r
+       // Sibling mode (~)\r
+       // E ~ F all elements with the tag F that are preceded by a sibling element with the tag E\r
         }else if(mode == "~"){\r
             var utag = tagName.toUpperCase();\r
             for(var i = 0, n; n = ns[i]; i++){\r
@@ -1122,7 +1152,7 @@ Ext.DomQuery = function(){
             }\r
         }\r
         return result;\r
-    };\r
+    }\r
 \r
     function concat(a, b){\r
         if(b.slice){\r
@@ -1141,69 +1171,81 @@ Ext.DomQuery = function(){
         if(!tagName){\r
             return cs;\r
         }\r
-        var r = [], ri = -1;\r
+        var result = [], ri = -1;\r
         tagName = tagName.toLowerCase();\r
         for(var i = 0, ci; ci = cs[i]; i++){\r
-            if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){\r
-                r[++ri] = ci;\r
+            if(ci.nodeType == 1 && ci.tagName.toLowerCase() == tagName){\r
+                result[++ri] = ci;\r
             }\r
         }\r
-        return r;\r
-    };\r
+        return result;\r
+    }\r
 \r
-    function byId(cs, attr, id){\r
+    function byId(cs, id){\r
         if(cs.tagName || cs == document){\r
             cs = [cs];\r
         }\r
         if(!id){\r
             return cs;\r
         }\r
-        var r = [], ri = -1;\r
-        for(var i = 0,ci; ci = cs[i]; i++){\r
+        var result = [], ri = -1;\r
+        for(var i = 0, ci; ci = cs[i]; i++){\r
             if(ci && ci.id == id){\r
-                r[++ri] = ci;\r
-                return r;\r
+                result[++ri] = ci;\r
+                return result;\r
             }\r
         }\r
-        return r;\r
-    };\r
+        return result;\r
+    }\r
 \r
+    // operators are =, !=, ^=, $=, *=, %=, |= and ~=\r
+    // custom can be "{"\r
     function byAttribute(cs, attr, value, op, custom){\r
-        var r = [], \r
-               ri = -1, \r
-               st = custom=="{",\r
-               f = Ext.DomQuery.operators[op];\r
+        var result = [], \r
+            ri = -1, \r
+            useGetStyle = custom == "{",           \r
+            fn = Ext.DomQuery.operators[op],       \r
+            a,     \r
+            innerHTML;\r
         for(var i = 0, ci; ci = cs[i]; i++){\r
+           // skip non-element nodes.\r
             if(ci.nodeType != 1){\r
                 continue;\r
             }\r
-            var a;\r
-            if(st){\r
-                a = Ext.DomQuery.getStyle(ci, attr);\r
-            }\r
-            else if(attr == "class" || attr == "className"){\r
-                a = ci.className;\r
-            }else if(attr == "for"){\r
-                a = ci.htmlFor;\r
-            }else if(attr == "href"){\r
-                a = ci.getAttribute("href", 2);\r
+           \r
+            innerHTML = ci.innerHTML;\r
+            // we only need to change the property names if we're dealing with html nodes, not XML\r
+            if(innerHTML !== null && innerHTML !== undefined){\r
+                if(useGetStyle){\r
+                    a = Ext.DomQuery.getStyle(ci, attr);\r
+                } else if (attr == "class" || attr == "className"){\r
+                    a = ci.className;\r
+                } else if (attr == "for"){\r
+                    a = ci.htmlFor;\r
+                } else if (attr == "href"){\r
+                   // getAttribute href bug\r
+                   // http://www.glennjones.net/Post/809/getAttributehrefbug.htm\r
+                    a = ci.getAttribute("href", 2);\r
+                } else{\r
+                    a = ci.getAttribute(attr);\r
+                }\r
             }else{\r
                 a = ci.getAttribute(attr);\r
             }\r
-            if((f && f(a, value)) || (!f && a)){\r
-                r[++ri] = ci;\r
+            if((fn && fn(a, value)) || (!fn && a)){\r
+                result[++ri] = ci;\r
             }\r
         }\r
-        return r;\r
-    };\r
+        return result;\r
+    }\r
 \r
     function byPseudo(cs, name, value){\r
         return Ext.DomQuery.pseudos[name](cs, value);\r
-    };\r
+    }\r
 \r
     function nodupIEXml(cs){\r
         var d = ++key, \r
-               r;\r
+            r;\r
         cs[0].setAttribute("_nodup", d);\r
         r = [cs[0]];\r
         for(var i = 1, len = cs.length; i < len; i++){\r
@@ -1254,7 +1296,7 @@ Ext.DomQuery = function(){
 \r
     function quickDiffIEXml(c1, c2){\r
         var d = ++key,\r
-               r = [];\r
+            r = [];\r
         for(var i = 0, len = c1.length; i < len; i++){\r
             c1[i].setAttribute("_qdiff", d);\r
         }        \r
@@ -1276,7 +1318,7 @@ Ext.DomQuery = function(){
         if(!len1){\r
             return c2;\r
         }\r
-        if(isIE && c1[0].selectSingleNode){\r
+        if(isIE && typeof c1[0].selectSingleNode != "undefined"){\r
             return quickDiffIEXml(c1, c2);\r
         }        \r
         for(var i = 0; i < len1; i++){\r
@@ -1296,7 +1338,7 @@ Ext.DomQuery = function(){
            return d.getElementById(id);\r
         }\r
         ns = getNodes(ns, mode, "*");\r
-        return byId(ns, null, id);\r
+        return byId(ns, id);\r
     }\r
 \r
     return {\r
@@ -1313,72 +1355,80 @@ Ext.DomQuery = function(){
         compile : function(path, type){\r
             type = type || "select";\r
 \r
+           // setup fn preamble\r
             var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"],\r
-               q = path, mode, lq,\r
-               tk = Ext.DomQuery.matchers,\r
-               tklen = tk.length,\r
-               mm,\r
+               mode,           \r
+               lastPath,\r
+               matchers = Ext.DomQuery.matchers,\r
+               matchersLn = matchers.length,\r
+               modeMatch,\r
                // accept leading mode switch\r
-               lmode = q.match(modeRe);\r
+               lmode = path.match(modeRe);\r
             \r
             if(lmode && lmode[1]){\r
                 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';\r
-                q = q.replace(lmode[1], "");\r
+                path = path.replace(lmode[1], "");\r
             }\r
+           \r
             // strip leading slashes\r
             while(path.substr(0, 1)=="/"){\r
                 path = path.substr(1);\r
             }\r
 \r
-            while(q && lq != q){\r
-                lq = q;\r
-                var tm = q.match(tagTokenRe);\r
+            while(path && lastPath != path){\r
+                lastPath = path;\r
+                var tokenMatch = path.match(tagTokenRe);\r
                 if(type == "select"){\r
-                    if(tm){\r
-                        if(tm[1] == "#"){\r
-                            fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';\r
+                    if(tokenMatch){\r
+                       // ID Selector\r
+                        if(tokenMatch[1] == "#"){\r
+                            fn[fn.length] = 'n = quickId(n, mode, root, "'+tokenMatch[2]+'");';                        \r
                         }else{\r
-                            fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';\r
+                            fn[fn.length] = 'n = getNodes(n, mode, "'+tokenMatch[2]+'");';\r
                         }\r
-                        q = q.replace(tm[0], "");\r
-                    }else if(q.substr(0, 1) != '@'){\r
+                        path = path.replace(tokenMatch[0], "");\r
+                    }else if(path.substr(0, 1) != '@'){\r
                         fn[fn.length] = 'n = getNodes(n, mode, "*");';\r
                     }\r
+               // type of "simple"\r
                 }else{\r
-                    if(tm){\r
-                        if(tm[1] == "#"){\r
-                            fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';\r
+                    if(tokenMatch){\r
+                        if(tokenMatch[1] == "#"){\r
+                            fn[fn.length] = 'n = byId(n, "'+tokenMatch[2]+'");';\r
                         }else{\r
-                            fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';\r
+                            fn[fn.length] = 'n = byTag(n, "'+tokenMatch[2]+'");';\r
                         }\r
-                        q = q.replace(tm[0], "");\r
+                        path = path.replace(tokenMatch[0], "");\r
                     }\r
                 }\r
-                while(!(mm = q.match(modeRe))){\r
+                while(!(modeMatch = path.match(modeRe))){\r
                     var matched = false;\r
-                    for(var j = 0; j < tklen; j++){\r
-                        var t = tk[j];\r
-                        var m = q.match(t.re);\r
+                    for(var j = 0; j < matchersLn; j++){\r
+                        var t = matchers[j];\r
+                        var m = path.match(t.re);\r
                         if(m){\r
                             fn[fn.length] = t.select.replace(tplRe, function(x, i){\r
-                                                    return m[i];\r
-                                                });\r
-                            q = q.replace(m[0], "");\r
+                               return m[i];\r
+                           });\r
+                            path = path.replace(m[0], "");\r
                             matched = true;\r
                             break;\r
                         }\r
                     }\r
                     // prevent infinite loop on bad selector\r
                     if(!matched){\r
-                        throw 'Error parsing selector, parsing failed at "' + q + '"';\r
+                        throw 'Error parsing selector, parsing failed at "' + path + '"';\r
                     }\r
                 }\r
-                if(mm[1]){\r
-                    fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';\r
-                    q = q.replace(mm[1], "");\r
+                if(modeMatch[1]){\r
+                    fn[fn.length] = 'mode="'+modeMatch[1].replace(trimRe, "")+'";';\r
+                    path = path.replace(modeMatch[1], "");\r
                 }\r
             }\r
+           // close fn out\r
             fn[fn.length] = "return nodup(n);\n}";\r
+           \r
+           // eval fn and return it\r
             eval(fn.join(""));\r
             return f;\r
         },\r
@@ -1386,37 +1436,60 @@ Ext.DomQuery = function(){
         /**\r
          * Selects a group of elements.\r
          * @param {String} selector The selector/xpath query (can be a comma separated list of selectors)\r
-         * @param {Node} root (optional) The start of the query (defaults to document).\r
+         * @param {Node/String} root (optional) The start of the query (defaults to document).\r
          * @return {Array} An Array of DOM elements which match the selector. If there are\r
          * no matches, and empty Array is returned.\r
          */\r
-        select : function(path, root, type){\r
-            if(!root || root == document){\r
-                root = document;\r
-            }\r
+       jsSelect: function(path, root, type){\r
+           // set root to doc if not specified.\r
+           root = root || document;\r
+           \r
             if(typeof root == "string"){\r
                 root = document.getElementById(root);\r
             }\r
             var paths = path.split(","),\r
                results = [];\r
-            for(var i = 0, len = paths.length; i < len; i++){\r
-                var p = paths[i].replace(trimRe, "");\r
-                if(!cache[p]){\r
-                    cache[p] = Ext.DomQuery.compile(p);\r
-                    if(!cache[p]){\r
-                        throw p + " is not a valid selector";\r
+               \r
+           // loop over each selector\r
+            for(var i = 0, len = paths.length; i < len; i++){          \r
+                var subPath = paths[i].replace(trimRe, "");\r
+               // compile and place in cache\r
+                if(!cache[subPath]){\r
+                    cache[subPath] = Ext.DomQuery.compile(subPath);\r
+                    if(!cache[subPath]){\r
+                        throw subPath + " is not a valid selector";\r
                     }\r
                 }\r
-                var result = cache[p](root);\r
+                var result = cache[subPath](root);\r
                 if(result && result != document){\r
                     results = results.concat(result);\r
                 }\r
             }\r
+           \r
+           // if there were multiple selectors, make sure dups\r
+           // are eliminated\r
             if(paths.length > 1){\r
                 return nodup(results);\r
             }\r
             return results;\r
         },\r
+       isXml: function(el) {\r
+           var docEl = (el ? el.ownerDocument || el : 0).documentElement;\r
+           return docEl ? docEl.nodeName !== "HTML" : false;\r
+       },\r
+        select : document.querySelectorAll ? function(path, root, type) {\r
+           root = root || document;\r
+           if (!Ext.DomQuery.isXml(root)) {\r
+               try {\r
+                   var cs = root.querySelectorAll(path);\r
+                   return Ext.toArray(cs);\r
+               }\r
+               catch (ex) {}           \r
+           }       \r
+           return Ext.DomQuery.jsSelect.call(this, path, root, type);\r
+       } : function(path, root, type) {\r
+           return Ext.DomQuery.jsSelect.call(this, path, root, type);\r
+       },\r
 \r
         /**\r
          * Selects a single element.\r
@@ -1440,9 +1513,15 @@ Ext.DomQuery = function(){
             if(!valueCache[path]){\r
                 valueCache[path] = Ext.DomQuery.compile(path, "select");\r
             }\r
-            var n = valueCache[path](root),\r
-               v;\r
+            var n = valueCache[path](root), v;\r
             n = n[0] ? n[0] : n;\r
+                   \r
+           // overcome a limitation of maximum textnode size\r
+           // Rumored to potentially crash IE6 but has not been confirmed.\r
+           // http://reference.sitepoint.com/javascript/Node/normalize\r
+           // https://developer.mozilla.org/En/DOM/Node.normalize          \r
+            if (typeof n.normalize == 'function') n.normalize();\r
+            \r
             v = (n && n.firstChild ? n.firstChild.nodeValue : null);\r
             return ((v === null||v === undefined||v==='') ? defaultValue : v);\r
         },\r
@@ -1494,10 +1573,12 @@ Ext.DomQuery = function(){
 \r
         /**\r
          * Collection of matching regular expressions and code snippets.\r
+         * Each capture group within () will be replace the {} in the select\r
+         * statement as specified by their index.\r
          */\r
         matchers : [{\r
                 re: /^\.([\w-]+)/,\r
-                select: 'n = byClassName(n, null, " {1} ");'\r
+                select: 'n = byClassName(n, " {1} ");'\r
             }, {\r
                 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,\r
                 select: 'n = byPseudo(n, "{1}", "{2}");'\r
@@ -1506,7 +1587,7 @@ Ext.DomQuery = function(){
                 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'\r
             }, {\r
                 re: /^#([\w-]+)/,\r
-                select: 'n = byId(n, null, "{1}");'\r
+                select: 'n = byId(n, "{1}");'\r
             },{\r
                 re: /^@([\w-]+)/,\r
                 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'\r
@@ -1762,7 +1843,70 @@ var externalLinks = Ext.select("a:external");
  * @method query\r
  */\r
 Ext.query = Ext.DomQuery.select;\r
-(function(){
+/**
+ * @class Ext.util.DelayedTask
+ * <p> The DelayedTask class provides a convenient way to "buffer" the execution of a method,
+ * performing setTimeout where a new timeout cancels the old timeout. When called, the
+ * task will wait the specified time period before executing. If durng that time period,
+ * the task is called again, the original call will be cancelled. This continues so that
+ * the function is only called a single time for each iteration.</p>
+ * <p>This method is especially useful for things like detecting whether a user has finished
+ * typing in a text field. An example would be performing validation on a keypress. You can
+ * use this class to buffer the keypress events for a certain number of milliseconds, and
+ * perform only if they stop for that amount of time.  Usage:</p><pre><code>
+var task = new Ext.util.DelayedTask(function(){
+    alert(Ext.getDom('myInputField').value.length);
+});
+// Wait 500ms before calling our function. If the user presses another key 
+// during that 500ms, it will be cancelled and we'll wait another 500ms.
+Ext.get('myInputField').on('keypress', function(){
+    task.{@link #delay}(500); 
+});
+ * </code></pre> 
+ * <p>Note that we are using a DelayedTask here to illustrate a point. The configuration
+ * option <tt>buffer</tt> for {@link Ext.util.Observable#addListener addListener/on} will
+ * also setup a delayed task for you to buffer events.</p> 
+ * @constructor The parameters to this constructor serve as defaults and are not required.
+ * @param {Function} fn (optional) The default function to call.
+ * @param {Object} scope The default scope (The <code><b>this</b></code> reference) in which the
+ * function is called. If not specified, <code>this</code> will refer to the browser window.
+ * @param {Array} args (optional) The default Array of arguments.
+ */
+Ext.util.DelayedTask = function(fn, scope, args){
+    var me = this,
+       id,     
+       call = function(){
+               clearInterval(id);
+               id = null;
+               fn.apply(scope, args || []);
+           };
+           
+    /**
+     * Cancels any pending timeout and queues a new one
+     * @param {Number} delay The milliseconds to delay
+     * @param {Function} newFn (optional) Overrides function passed to constructor
+     * @param {Object} newScope (optional) Overrides scope passed to constructor. Remember that if no scope
+     * is specified, <code>this</code> will refer to the browser window.
+     * @param {Array} newArgs (optional) Overrides args passed to constructor
+     */
+    me.delay = function(delay, newFn, newScope, newArgs){
+        me.cancel();
+        fn = newFn || fn;
+        scope = newScope || scope;
+        args = newArgs || args;
+        id = setInterval(call, delay);
+    };
+
+    /**
+     * Cancel the last queued timeout
+     */
+    me.cancel = function(){
+        if(id){
+            clearInterval(id);
+            id = null;
+        }
+    };
+};(function(){
 
 var EXTUTIL = Ext.util,
     TOARRAY = Ext.toArray,
@@ -2044,9 +2188,11 @@ this.addEvents('storeloaded', 'storecleared');
         var me = this;
         me.events = me.events || {};
         if (Ext.isString(o)) {
-            EACH(arguments, function(a) {
-                me.events[a] = me.events[a] || TRUE;
-            });
+            var a = arguments,
+                i = a.length;
+            while(i--) {
+                me.events[a[i]] = me.events[a[i]] || TRUE;
+            }
         } else {
             Ext.applyIf(me.events, o);
         }
@@ -2127,26 +2273,28 @@ function createTargeted(h, o, scope){
     };
 };
 
-function createBuffered(h, o, scope){
-    var task = new EXTUTIL.DelayedTask();
+function createBuffered(h, o, l, scope){
+    l.task = new EXTUTIL.DelayedTask();
     return function(){
-        task.delay(o.buffer, h, scope, TOARRAY(arguments));
+        l.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){
+function createDelayed(h, o, l, scope){
     return function(){
-        var args = TOARRAY(arguments);
-        (function(){
-            h.apply(scope, args);
-        }).defer(o.delay || 10);
+        var task = new EXTUTIL.DelayedTask();
+        if(!l.tasks) {
+            l.tasks = [];
+        }
+        l.tasks.push(task);
+        task.delay(o.delay || 10, h, scope, TOARRAY(arguments));
     };
 };
 
@@ -2181,29 +2329,33 @@ EXTUTIL.Event.prototype = {
             h = createTargeted(h, o, scope);
         }
         if(o.delay){
-            h = createDelayed(h, o, scope);
+            h = createDelayed(h, o, l, scope);
         }
         if(o.single){
             h = createSingle(h, this, fn, scope);
         }
         if(o.buffer){
-            h = createBuffered(h, o, scope);
+            h = createBuffered(h, o, l, 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 && (s == scope || s == this.obj)){
-                ret = i;
-                return FALSE;
+        var list = this.listeners,
+            i = list.length,
+            l,
+            s;
+        while(i--) {
+            l = list[i];
+            if(l) {
+                s = l.scope;
+                if(l.fn == fn && (s == scope || s == this.obj)){
+                    return i;
+                }
             }
-        },
-        this);
-        return ret;
+        }
+        return -1;
     },
 
     isListening : function(fn, scope){
@@ -2212,62 +2364,88 @@ EXTUTIL.Event.prototype = {
 
     removeListener : function(fn, scope){
         var index,
+            l,
+            k,
             me = this,
             ret = FALSE;
         if((index = me.findListener(fn, scope)) != -1){
             if (me.firing) {
                 me.listeners = me.listeners.slice(0);
             }
+            l = me.listeners[index];
+            if(l.task) {
+                l.task.cancel();
+                delete l.task;
+            }
+            k = l.tasks && l.tasks.length;
+            if(k) {
+                while(k--) {
+                    l.tasks[k].cancel();
+                }
+                delete l.tasks;
+            }
             me.listeners.splice(index, 1);
             ret = TRUE;
         }
         return ret;
     },
 
+    // Iterate to stop any buffered/delayed events
     clearListeners : function(){
-        this.listeners = [];
+        var me = this,
+            l = me.listeners,
+            i = l.length;
+        while(i--) {
+            me.removeListener(l[i].fn, l[i].scope);
+        }
     },
 
     fire : function(){
         var me = this,
             args = TOARRAY(arguments),
-            ret = TRUE;
+            listeners = me.listeners,
+            len = listeners.length,
+            i = 0,
+            l;
 
-        EACH(me.listeners, function(l) {
+        if(len > 0){
             me.firing = TRUE;
-            if (l.fireFn.apply(l.scope || me.obj || window, args) === FALSE) {
-                return ret = me.firing = FALSE;
+            for (; i < len; i++) {
+                l = listeners[i];
+                if(l && l.fireFn.apply(l.scope || me.obj || window, args) === FALSE) {
+                    return (me.firing = FALSE);
+                }
             }
-        });
+        }
         me.firing = FALSE;
-        return ret;
+        return TRUE;
     }
 };
 })();/**\r
  * @class Ext.util.Observable\r
  */\r
-Ext.apply(Ext.util.Observable.prototype, function(){    \r
+Ext.apply(Ext.util.Observable.prototype, function(){\r
     // this is considered experimental (along with beforeMethod, afterMethod, removeMethodListener?)\r
     // allows for easier interceptor and sequences, including cancelling and overwriting the return value of the call\r
     // private\r
     function getMethodEvent(method){\r
         var e = (this.methodEvents = this.methodEvents ||\r
         {})[method], returnValue, v, cancel, obj = this;\r
-        \r
+\r
         if (!e) {\r
             this.methodEvents[method] = e = {};\r
             e.originalFn = this[method];\r
             e.methodName = method;\r
             e.before = [];\r
             e.after = [];\r
-            \r
+\r
             var makeCall = function(fn, scope, args){\r
                 if (!Ext.isEmpty(v = fn.apply(scope || obj, args))) {\r
                     if (Ext.isObject(v)) {\r
                         returnValue = !Ext.isEmpty(v.returnValue) ? v.returnValue : v;\r
                         cancel = !!v.cancel;\r
                     }\r
-                    else \r
+                    else\r
                         if (v === false) {\r
                             cancel = true;\r
                         }\r
@@ -2276,19 +2454,19 @@ Ext.apply(Ext.util.Observable.prototype, function(){
                         }\r
                 }\r
             };\r
-            \r
+\r
             this[method] = function(){\r
                 var args = Ext.toArray(arguments);\r
                 returnValue = v = undefined;\r
                 cancel = false;\r
-                \r
+\r
                 Ext.each(e.before, function(b){\r
                     makeCall(b.fn, b.scope, args);\r
                     if (cancel) {\r
                         return returnValue;\r
                     }\r
                 });\r
-                \r
+\r
                 if (!Ext.isEmpty(v = e.originalFn.apply(obj, args))) {\r
                     returnValue = v;\r
                 }\r
@@ -2303,26 +2481,26 @@ Ext.apply(Ext.util.Observable.prototype, function(){
         }\r
         return e;\r
     }\r
-    \r
+\r
     return {\r
         // these are considered experimental\r
         // allows for easier interceptor and sequences, including cancelling and overwriting the return value of the call\r
-        // adds an "interceptor" called before the original method\r
-        beforeMethod: function(method, fn, scope){\r
+        // adds an 'interceptor' called before the original method\r
+        beforeMethod : function(method, fn, scope){\r
             getMethodEvent.call(this, method).before.push({\r
                 fn: fn,\r
                 scope: scope\r
             });\r
         },\r
-        \r
-        // adds a "sequence" called after the original method\r
-        afterMethod: function(method, fn, scope){\r
+\r
+        // adds a 'sequence' called after the original method\r
+        afterMethod : function(method, fn, scope){\r
             getMethodEvent.call(this, method).after.push({\r
                 fn: fn,\r
                 scope: scope\r
             });\r
         },\r
-        \r
+\r
         removeMethodListener: function(method, fn, scope){\r
             var e = getMethodEvent.call(this, method), found = false;\r
             Ext.each(e.before, function(b, i, arr){\r
@@ -2341,13 +2519,13 @@ Ext.apply(Ext.util.Observable.prototype, function(){
                 });\r
             }\r
         },\r
-        \r
+\r
         /**\r
          * Relays selected events from the specified Observable as if the events were fired by <tt><b>this</b></tt>.\r
          * @param {Object} o The Observable whose events this object is to relay.\r
          * @param {Array} events Array of event names to relay.\r
          */\r
-        relayEvents: function(o, events){\r
+        relayEvents : function(o, events){\r
             var me = this;\r
             function createHandler(ename){\r
                 return function(){\r
@@ -2359,7 +2537,7 @@ Ext.apply(Ext.util.Observable.prototype, function(){
                 o.on(ename, createHandler(ename), me);\r
             });\r
         },\r
-        \r
+\r
         /**\r
          * <p>Enables events fired by this Observable to bubble up an owner hierarchy by calling\r
          * <code>this.getBubbleTarget()</code> if present. There is no implementation in the Observable base class.</p>\r
@@ -2368,13 +2546,13 @@ Ext.apply(Ext.util.Observable.prototype, function(){
          * access the required target more quickly.</p>\r
          * <p>Example:</p><pre><code>\r
 Ext.override(Ext.form.Field, {\r
-//  Add functionality to Field's initComponent to enable the change event to bubble\r
-    initComponent: Ext.form.Field.prototype.initComponent.createSequence(function() {\r
+    //  Add functionality to Field&#39;s initComponent to enable the change event to bubble\r
+    initComponent : Ext.form.Field.prototype.initComponent.createSequence(function() {\r
         this.enableBubble('change');\r
     }),\r
 \r
-//  We know that we want Field's events to bubble directly to the FormPanel.\r
-    getBubbleTarget: function() {\r
+    //  We know that we want Field&#39;s events to bubble directly to the FormPanel.\r
+    getBubbleTarget : function() {\r
         if (!this.formPanel) {\r
             this.formPanel = this.findParentByType('form');\r
         }\r
@@ -2389,15 +2567,15 @@ var myForm = new Ext.formPanel({
     }],\r
     listeners: {\r
         change: function() {\r
-//          Title goes red if form has been modified.\r
-            myForm.header.setStyle("color", "red");\r
+            // Title goes red if form has been modified.\r
+            myForm.header.setStyle('color', 'red');\r
         }\r
     }\r
 });\r
 </code></pre>\r
-         * @param {Object} events The event name to bubble, or an Array of event names.\r
+         * @param {String/Array} events The event name to bubble, or an Array of event names.\r
          */\r
-        enableBubble: function(events){\r
+        enableBubble : function(events){\r
             var me = this;\r
             if(!Ext.isEmpty(events)){\r
                 events = Ext.isArray(events) ? events : Ext.toArray(arguments);\r
@@ -2421,9 +2599,9 @@ var myForm = new Ext.formPanel({
  * to the supplied function with the event name + standard signature of the event\r
  * <b>before</b> the event is fired. If the supplied function returns false,\r
  * the event will not fire.\r
- * @param {Observable} o The Observable to capture\r
- * @param {Function} fn The function to call\r
- * @param {Object} scope (optional) The scope (this object) for the fn\r
+ * @param {Observable} o The Observable to capture events from.\r
+ * @param {Function} fn The function to call when an event is fired.\r
+ * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to the Observable firing the event.\r
  * @static\r
  */\r
 Ext.util.Observable.capture = function(o, fn, scope){\r
@@ -2438,3603 +2616,3921 @@ Ext.util.Observable.capture = function(o, fn, scope){
  * <p>Usage:</p><pre><code>\r
 Ext.util.Observable.observeClass(Ext.data.Connection);\r
 Ext.data.Connection.on('beforerequest', function(con, options) {\r
-    console.log("Ajax request made to " + options.url);\r
+    console.log('Ajax request made to ' + options.url);\r
 });</code></pre>\r
  * @param {Function} c The class constructor to make observable.\r
+ * @param {Object} listeners An object containing a series of listeners to add. See {@link #addListener}. \r
  * @static\r
  */\r
-Ext.util.Observable.observeClass = function(c){\r
-    Ext.apply(c, new Ext.util.Observable());\r
-    c.prototype.fireEvent = function(){\r
-        return (c.fireEvent.apply(c, arguments) !== false) &&\r
-        (Ext.util.Observable.prototype.fireEvent.apply(this, arguments) !== false);\r
-    };\r
-};/**
- * @class Ext.EventManager
- * Registers event handlers that want to receive a normalized EventObject instead of the standard browser event and provides
- * several useful events directly.
- * See {@link Ext.EventObject} for more details on normalized event objects.
- * @singleton
- */
-Ext.EventManager = function(){
-    var docReadyEvent, 
-        docReadyProcId, 
-        docReadyState = false,        
-        E = Ext.lib.Event,
-        D = Ext.lib.Dom,
-        DOC = document,
-        WINDOW = window,
-        IEDEFERED = "ie-deferred-loader",
-        DOMCONTENTLOADED = "DOMContentLoaded",
-        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 == "mousewheel" && el.addEventListener){ // workaround for jQuery
-            var args = ["DOMMouseScroll", wrap, false];
-            el.addEventListener.apply(el, args);
-            E.on(window, 'unload', function(){
-                el.removeEventListener.apply(el, args);                
-            });
-        }
-        if(ename == "mousedown" && 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 = "complete";
-            
-        docReadyEvent = new Ext.util.Event();
-        if (Ext.isGecko || Ext.isOpera) {
-            DOC.addEventListener(DOMCONTENTLOADED, fireDocReady, false);
-        } else if (Ext.isIE){
-            DOC.write("<s"+'cript id=' + IEDEFERED + ' defer="defer" src="/'+'/:"></s'+"cript>");            
-            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, "load", 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 "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
-        }
-        function h(e){
-            // prevent errors while unload occurring
-            if(!Ext){// !window[xname]){  ==> 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 = {
-        /**
-         * Appends an event handler to an element.  The shorthand version {@link #on} is equivalent.  Typically you will
-         * use {@link Ext.Element#addListener} directly on an Element in favor of calling this version.
-         * @param {String/HTMLElement} el The html element or id to assign the event handler to.
-         * @param {String} eventName The name of the event to listen for.
-         * @param {Function} handler The handler function the event invokes. This function is passed
-         * the following parameters:<ul>
-         * <li>evt : EventObject<div class="sub-desc">The {@link Ext.EventObject EventObject} describing the event.</div></li>
-         * <li>t : Element<div class="sub-desc">The {@link Ext.Element Element} which was the target of the event.
-         * Note that this may be filtered by using the <tt>delegate</tt> option.</div></li>
-         * <li>o : Object<div class="sub-desc">The options object from the addListener call.</div></li>
-         * </ul>
-         * @param {Object} scope (optional) The scope (<b><code>this</code></b> reference) in which the handler function is executed. <b>Defaults to the Element</b>.
-         * @param {Object} options (optional) An object containing handler configuration properties.
-         * This may contain any of the following properties:<ul>
-         * <li>scope : Object<div class="sub-desc">The scope (<b><code>this</code></b> reference) in which the handler function is executed. <b>Defaults to the Element</b>.</div></li>
-         * <li>delegate : String<div class="sub-desc">A simple selector to filter the target or look for a descendant of the target</div></li>
-         * <li>stopEvent : Boolean<div class="sub-desc">True to stop the event. That is stop propagation, and prevent the default action.</div></li>
-         * <li>preventDefault : Boolean<div class="sub-desc">True to prevent the default action</div></li>
-         * <li>stopPropagation : Boolean<div class="sub-desc">True to prevent event propagation</div></li>
-         * <li>normalized : Boolean<div class="sub-desc">False to pass a browser event to the handler function instead of an Ext.EventObject</div></li>
-         * <li>delay : Number<div class="sub-desc">The number of milliseconds to delay the invocation of the handler after te event fires.</div></li>
-         * <li>single : Boolean<div class="sub-desc">True to add a handler to handle just the next firing of the event, and then remove itself.</div></li>
-         * <li>buffer : Number<div class="sub-desc">Causes the handler to be scheduled to run in an {@link Ext.util.DelayedTask} delayed
-         * by the specified number of milliseconds. If the event fires again within that time, the original
-         * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</div></li>
-         * <li>target : Element<div class="sub-desc">Only call the handler if the event was fired on the target Element, <i>not</i> if the event was bubbled up from a child node.</div></li>
-         * </ul><br>
-         * <p>See {@link Ext.Element#addListener} for examples of how to use these options.</p>
-         */
-        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);
-            }
-        },
-        
-        /**
-         * Removes an event handler from an element.  The shorthand version {@link #un} is equivalent.  Typically
-         * you will use {@link Ext.Element#removeListener} directly on an Element in favor of calling this version.
-         * @param {String/HTMLElement} el The id or html element from which to remove the listener.
-         * @param {String} eventName The name of the event.
-         * @param {Function} fn The handler function to remove. <b>This must be a reference to the function passed into the {@link #addListener} call.</b>
-         * @param {Object} scope If a scope (<b><code>this</code></b> reference) was specified when the listener was added,
-         * then this must refer to the same object.
-         */
-        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) && v[0] == fn && (!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 == "mousewheel" && el.addEventListener && wrap){
-                el.removeEventListener("DOMMouseScroll", wrap, false);
-            }
-                        
-            if(eventName == "mousedown" && el == DOC && wrap){ // fix stopped mousedowns on the document
-                Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);
-            }
-        },
-        
-        /**
-         * Removes all event handers from an element.  Typically you will use {@link Ext.Element#removeAllListeners}
-         * directly on an Element in favor of calling this version.
-         * @param {String/HTMLElement} el The id or html element from which to remove all event handlers.
-         */
-        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;       
-        },
-
-        /**
-         * Adds a listener to be notified when the document is ready (before onload and before images are loaded). Can be
-         * accessed shorthanded as Ext.onReady().
-         * @param {Function} fn The method the event invokes.
-         * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the handler function executes. Defaults to the browser window.
-         * @param {boolean} options (optional) Options object as passed to {@link Ext.Element#addListener}. It is recommended that the options
-         * <code>{single: true}</code> be used so that the handler is removed on first invocation.
-         */
-        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   
-    };
-     /**
-     * Appends an event handler to an element.  Shorthand for {@link #addListener}.
-     * @param {String/HTMLElement} el The html element or id to assign the event handler to
-     * @param {String} eventName The name of the event to listen for.
-     * @param {Function} handler The handler function the event invokes.
-     * @param {Object} scope (optional) (<code>this</code> reference) in which the handler function executes. <b>Defaults to the Element</b>.
-     * @param {Object} options (optional) An object containing standard {@link #addListener} options
-     * @member Ext.EventManager
-     * @method on
-     */
-    pub.on = pub.addListener;
-    /**
-     * Removes an event handler from an element.  Shorthand for {@link #removeListener}.
-     * @param {String/HTMLElement} el The id or html element from which to remove the listener.
-     * @param {String} eventName The name of the event.
-     * @param {Function} fn The handler function to remove. <b>This must be a reference to the function passed into the {@link #on} call.</b>
-     * @param {Object} scope If a scope (<b><code>this</code></b> reference) was specified when the listener was added,
-     * then this must refer to the same object.
-     * @member Ext.EventManager
-     * @method un
-     */
-    pub.un = pub.removeListener;
-
-    pub.stoppedMouseDownEvent = new Ext.util.Event();
-    return pub;
-}();
-/**
-  * Adds a listener to be notified when the document is ready (before onload and before images are loaded). Shorthand of {@link Ext.EventManager#onDocumentReady}.
-  * @param {Function} fn The method the event invokes.
-  * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the handler function executes. Defaults to the browser window.
-  * @param {boolean} options (optional) Options object as passed to {@link Ext.Element#addListener}. It is recommended that the options
-  * <code>{single: true}</code> be used so that the handler is removed on first invocation.
-  * @member Ext
-  * @method onReady
- */
-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 ? "ext-ie " + (Ext.isIE6 ? 'ext-ie6' : (Ext.isIE7 ? 'ext-ie7' : 'ext-ie8'))
-                : Ext.isGecko ? "ext-gecko " + (Ext.isGecko2 ? 'ext-gecko2' : 'ext-gecko3')
-                : Ext.isOpera ? "ext-opera"
-                : Ext.isWebKit ? "ext-webkit" : ""];
-
-        if(Ext.isSafari){
-            cls.push("ext-safari " + (Ext.isSafari2 ? 'ext-safari2' : (Ext.isSafari3 ? 'ext-safari3' : 'ext-safari4')));
-        }else if(Ext.isChrome){
-            cls.push("ext-chrome");
-        }
-
-        if(Ext.isMac){
-            cls.push("ext-mac");
-        }
-        if(Ext.isLinux){
-            cls.push("ext-linux");
-        }
-
-        if(Ext.isStrict || Ext.isBorderBox){ // add to the parent to allow for selectors like ".ext-strict .ext-ie"
-            var p = bd.parentNode;
-            if(p){
-                p.className += Ext.isStrict ? ' ext-strict' : ' ext-border-box';
-            }
-        }
-        bd.className += cls.join(' ');
-        return true;
-    }
-
-    if(!initExtCss()){
-        Ext.onReady(initExtCss);
-    }
-})();
-
-
-/**
- * @class Ext.EventObject
- * Just as {@link Ext.Element} wraps around a native DOM node, Ext.EventObject 
- * wraps the browser's native event-object normalizing cross-browser differences,
- * such as which mouse button is clicked, keys pressed, mechanisms to stop
- * event-propagation along with a method to prevent default actions from taking place.
- * <p>For example:</p>
- * <pre><code>
-function handleClick(e, t){ // e is not a standard event object, it is a Ext.EventObject
-    e.preventDefault();
-    var target = e.getTarget(); // same as t (the target HTMLElement)
-    ...
-}
-var myDiv = {@link Ext#get Ext.get}("myDiv");  // get reference to an {@link Ext.Element}
-myDiv.on(         // 'on' is shorthand for addListener
-    "click",      // perform an action on click of myDiv
-    handleClick   // reference to the action handler
-);  
-// other methods to do the same:
-Ext.EventManager.on("myDiv", 'click', handleClick);
-Ext.EventManager.addListener("myDiv", 'click', handleClick);
- </code></pre>
- * @singleton
- */
-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 = {
-           /** @private */
-        setEvent : function(e){
-            var me = this;
-            if(e == me || (e && 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' && 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 || false;
-                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;
-        },
-
-        /**
-         * Stop the event (preventDefault and stopPropagation)
-         */
-        stopEvent : function(){
-            var me = this;
-            if(me.browserEvent){
-                if(me.browserEvent.type == 'mousedown'){
-                    Ext.EventManager.stoppedMouseDownEvent.fire(me);
-                }
-                E.stopEvent(me.browserEvent);
-            }
-        },
-
-        /**
-         * Prevents the browsers default handling of the event.
-         */
-        preventDefault : function(){
-            if(this.browserEvent){
-                E.preventDefault(this.browserEvent);
-            }
-        },        
-
-        /**
-         * Cancels bubbling of the event.
-         */
-        stopPropagation : function(){
-            var me = this;
-            if(me.browserEvent){
-                if(me.browserEvent.type == 'mousedown'){
-                    Ext.EventManager.stoppedMouseDownEvent.fire(me);
-                }
-                E.stopPropagation(me.browserEvent);
-            }
-        },
-
-        /**
-         * Gets the character code for the event.
-         * @return {Number}
-         */
-        getCharCode : function(){
-            return this.charCode || this.keyCode;
-        },
-
-        /**
-         * Returns a normalized keyCode for the event.
-         * @return {Number} The key code
-         */
-        getKey : function(){
-            return this.normalizeKey(this.keyCode || this.charCode)
-        },
-        
-        // private
-        normalizeKey: function(k){
-            return Ext.isSafari ? (safariKeys[k] || k) : k; 
-        },
-
-        /**
-         * Gets the x coordinate of the event.
-         * @return {Number}
-         */
-        getPageX : function(){
-            return this.xy[0];
-        },
-
-        /**
-         * Gets the y coordinate of the event.
-         * @return {Number}
-         */
-        getPageY : function(){
-            return this.xy[1];
-        },
-
-        /**
-         * Gets the page coordinates of the event.
-         * @return {Array} The xy values like [x, y]
-         */
-        getXY : function(){
-            return this.xy;
-        },
-
-        /**
-         * Gets the target for the event.
-         * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
-         * @param {Number/Mixed} maxDepth (optional) The max depth to
-                search as a number or element (defaults to 10 || document.body)
-         * @param {Boolean} returnEl (optional) True to return a Ext.Element object instead of DOM node
-         * @return {HTMLelement}
-         */
-        getTarget : function(selector, maxDepth, returnEl){
-            return selector ? Ext.fly(this.target).findParent(selector, maxDepth, returnEl) : (returnEl ? Ext.get(this.target) : this.target);
-        },
-
-        /**
-         * Gets the related target.
-         * @return {HTMLElement}
-         */
-        getRelatedTarget : function(){
-            return this.browserEvent ? E.getRelatedTarget(this.browserEvent) : null;
-        },
-
-        /**
-         * Normalizes mouse wheel delta across browsers
-         * @return {Number} The delta
-         */
-        getWheelDelta : function(){
-            var e = this.browserEvent;
-            var delta = 0;
-            if(e.wheelDelta){ /* IE/Opera. */
-                delta = e.wheelDelta/120;
-            }else if(e.detail){ /* Mozilla case. */
-                delta = -e.detail/3;
-            }
-            return delta;
-        },
-        
-        /**
-        * Returns true if the target of this event is a child of el.  Unless the allowEl parameter is set, it will return false if if the target is el.
-        * Example usage:<pre><code>
-        // Handle click on any child of an element
-        Ext.getBody().on('click', function(e){
-            if(e.within('some-el')){
-                alert('Clicked on a child of some-el!');
-            }
-        });
-        
-        // Handle click directly on an element, ignoring clicks on child nodes
-        Ext.getBody().on('click', function(e,t){
-            if((t.id == 'some-el') && !e.within(t, true)){
-                alert('Clicked directly on some-el!');
-            }
-        });
-        </code></pre>
-         * @param {Mixed} el The id, DOM element or Ext.Element to check
-         * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
-         * @param {Boolean} allowEl {optional} true to also check if the passed element is the target or related target
-         * @return {Boolean}
-         */
-        within : function(el, related, allowEl){
-            if(el){
-                var t = this[related ? "getRelatedTarget" : "getTarget"]();
-                return t && ((allowEl ? (t == Ext.getDom(el)) : false) || Ext.fly(el).contains(t));
-            }
-            return false;
-        }
-     };
-
-    return new Ext.EventObjectImpl();
-}();/**\r
+Ext.util.Observable.observeClass = function(c, listeners){\r
+    if(c){\r
+      if(!c.fireEvent){\r
+          Ext.apply(c, new Ext.util.Observable());\r
+          Ext.util.Observable.capture(c.prototype, c.fireEvent, c);\r
+      }\r
+      if(Ext.isObject(listeners)){\r
+          c.on(listeners);\r
+      }\r
+      return c;\r
+   }\r
+};/**\r
  * @class Ext.EventManager\r
+ * Registers event handlers that want to receive a normalized EventObject instead of the standard browser event and provides\r
+ * several useful events directly.\r
+ * See {@link Ext.EventObject} for more details on normalized event objects.\r
+ * @singleton\r
  */\r
-Ext.apply(Ext.EventManager, function(){\r
-       var resizeEvent, \r
-       resizeTask, \r
-       textEvent, \r
-       textSize,\r
-       D = Ext.lib.Dom,\r
-       E = Ext.lib.Event,\r
-       propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,\r
-        curWidth = 0,\r
-        curHeight = 0,\r
-        // note 1: IE fires ONLY the keydown event on specialkey autorepeat\r
-        // note 2: Safari < 3.1, Gecko (Mac/Linux) & Opera fire only the keypress event on specialkey autorepeat\r
-        // (research done by @Jan Wolter at http://unixpapa.com/js/key.html)\r
-        useKeydown = Ext.isWebKit ? \r
-                    Ext.num(navigator.userAgent.match(/AppleWebKit\/(\d+)/)[1]) >= 525 :\r
-                    !((Ext.isGecko && !Ext.isWindows) || Ext.isOpera);\r
-       \r
-       return { \r
-               // private\r
-           doResizeEvent: function(){\r
-            var h = D.getViewHeight(),\r
-                w = D.getViewWidth();\r
-            \r
-            //whacky problem in IE where the resize event will fire even though the w/h are the same.\r
-            if(curHeight != h || curWidth != w){\r
-                resizeEvent.fire(curWidth = w, curHeight = h);\r
-            }\r
-           },\r
-           \r
-           /**\r
-            * Fires when the window is resized and provides resize event buffering (50 milliseconds), passes new viewport width and height to handlers.\r
-            * @param {Function} fn        The method the event invokes\r
-            * @param {Object}   scope    An object that becomes the scope of the handler\r
-            * @param {boolean}  options\r
-            */\r
-           onWindowResize : function(fn, scope, options){\r
-               if(!resizeEvent){\r
-                   resizeEvent = new Ext.util.Event();\r
-                   resizeTask = new Ext.util.DelayedTask(this.doResizeEvent);\r
-                   E.on(window, "resize", this.fireWindowResize, this);\r
-               }\r
-               resizeEvent.addListener(fn, scope, options);\r
-           },\r
-       \r
-           // exposed only to allow manual firing\r
-           fireWindowResize : function(){\r
-               if(resizeEvent){\r
-                   if((Ext.isIE||Ext.isAir) && resizeTask){\r
-                       resizeTask.delay(50);\r
-                   }else{\r
-                       resizeEvent.fire(D.getViewWidth(), D.getViewHeight());\r
-                   }\r
-               }\r
-           },\r
-       \r
-           /**\r
-            * Fires when the user changes the active text size. Handler gets called with 2 params, the old size and the new size.\r
-            * @param {Function} fn        The method the event invokes\r
-            * @param {Object}   scope    An object that becomes the scope of the handler\r
-            * @param {boolean}  options\r
-            */\r
-           onTextResize : function(fn, scope, options){\r
-               if(!textEvent){\r
-                   textEvent = new Ext.util.Event();\r
-                   var textEl = new Ext.Element(document.createElement('div'));\r
-                   textEl.dom.className = 'x-text-resize';\r
-                   textEl.dom.innerHTML = 'X';\r
-                   textEl.appendTo(document.body);\r
-                   textSize = textEl.dom.offsetHeight;\r
-                   setInterval(function(){\r
-                       if(textEl.dom.offsetHeight != textSize){\r
-                           textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);\r
-                       }\r
-                   }, this.textResizeInterval);\r
-               }\r
-               textEvent.addListener(fn, scope, options);\r
-           },\r
-       \r
-           /**\r
-            * Removes the passed window resize listener.\r
-            * @param {Function} fn        The method the event invokes\r
-            * @param {Object}   scope    The scope of handler\r
-            */\r
-           removeResizeListener : function(fn, scope){\r
-               if(resizeEvent){\r
-                   resizeEvent.removeListener(fn, scope);\r
-               }\r
-           },\r
-       \r
-           // private\r
-           fireResize : function(){\r
-               if(resizeEvent){\r
-                   resizeEvent.fire(D.getViewWidth(), D.getViewHeight());\r
-               }\r
-           },\r
-           \r
-            /**\r
-            * The frequency, in milliseconds, to check for text resize events (defaults to 50)\r
-            */\r
-           textResizeInterval : 50,\r
-           \r
-           /**\r
-         * Url used for onDocumentReady with using SSL (defaults to Ext.SSL_SECURE_URL)\r
+Ext.EventManager = function(){\r
+    var docReadyEvent,\r
+        docReadyProcId,\r
+        docReadyState = false,\r
+        E = Ext.lib.Event,\r
+        D = Ext.lib.Dom,\r
+        DOC = document,\r
+        WINDOW = window,\r
+        IEDEFERED = "ie-deferred-loader",\r
+        DOMCONTENTLOADED = "DOMContentLoaded",\r
+        propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,\r
+        /*\r
+         * This cache is used to hold special js objects, the document and window, that don't have an id. We need to keep\r
+         * a reference to them so we can look them up at a later point.\r
          */\r
-        ieDeferSrc : false,\r
-        \r
-        // protected for use inside the framework\r
-        // detects whether we should use keydown or keypress based on the browser.\r
-        useKeydown: useKeydown\r
-    };\r
-}());\r
+        specialElCache = [];\r
+\r
+     function getId(el){\r
+        var id = false,\r
+            i = 0,\r
+            len = specialElCache.length,\r
+            id = false,\r
+            skip = false,\r
+            o;\r
+        if(el){\r
+            if(el.getElementById || el.navigator){\r
+                // look up the id\r
+                for(; i < len; ++i){\r
+                    o = specialElCache[i];\r
+                    if(o.el === el){\r
+                        id = o.id;\r
+                        break;\r
+                    }\r
+                }\r
+                if(!id){\r
+                    // for browsers that support it, ensure that give the el the same id\r
+                    id = Ext.id(el);\r
+                    specialElCache.push({\r
+                        id: id,\r
+                        el: el\r
+                    });\r
+                    skip = true;\r
+                }\r
+            }else{\r
+                id = Ext.id(el);\r
+            }\r
+            if(!Ext.elCache[id]){\r
+                Ext.Element.addToCache(new Ext.Element(el), id);\r
+                if(skip){\r
+                    Ext.elCache[id].skipGC = true;\r
+                }\r
+            }\r
+        }\r
+        return id;\r
+     };\r
 \r
-Ext.EventManager.on = Ext.EventManager.addListener;\r
-\r
-\r
-Ext.apply(Ext.EventObjectImpl.prototype, {\r
-    /** Key constant @type Number */\r
-    BACKSPACE: 8,\r
-    /** Key constant @type Number */\r
-    TAB: 9,\r
-    /** Key constant @type Number */\r
-    NUM_CENTER: 12,\r
-    /** Key constant @type Number */\r
-    ENTER: 13,\r
-    /** Key constant @type Number */\r
-    RETURN: 13,\r
-    /** Key constant @type Number */\r
-    SHIFT: 16,\r
-    /** Key constant @type Number */\r
-    CTRL: 17,\r
-    CONTROL : 17, // legacy\r
-    /** Key constant @type Number */\r
-    ALT: 18,\r
-    /** Key constant @type Number */\r
-    PAUSE: 19,\r
-    /** Key constant @type Number */\r
-    CAPS_LOCK: 20,\r
-    /** Key constant @type Number */\r
-    ESC: 27,\r
-    /** Key constant @type Number */\r
-    SPACE: 32,\r
-    /** Key constant @type Number */\r
-    PAGE_UP: 33,\r
-    PAGEUP : 33, // legacy\r
-    /** Key constant @type Number */\r
-    PAGE_DOWN: 34,\r
-    PAGEDOWN : 34, // legacy\r
-    /** Key constant @type Number */\r
-    END: 35,\r
-    /** Key constant @type Number */\r
-    HOME: 36,\r
-    /** Key constant @type Number */\r
-    LEFT: 37,\r
-    /** Key constant @type Number */\r
-    UP: 38,\r
-    /** Key constant @type Number */\r
-    RIGHT: 39,\r
-    /** Key constant @type Number */\r
-    DOWN: 40,\r
-    /** Key constant @type Number */\r
-    PRINT_SCREEN: 44,\r
-    /** Key constant @type Number */\r
-    INSERT: 45,\r
-    /** Key constant @type Number */\r
-    DELETE: 46,\r
-    /** Key constant @type Number */\r
-    ZERO: 48,\r
-    /** Key constant @type Number */\r
-    ONE: 49,\r
-    /** Key constant @type Number */\r
-    TWO: 50,\r
-    /** Key constant @type Number */\r
-    THREE: 51,\r
-    /** Key constant @type Number */\r
-    FOUR: 52,\r
-    /** Key constant @type Number */\r
-    FIVE: 53,\r
-    /** Key constant @type Number */\r
-    SIX: 54,\r
-    /** Key constant @type Number */\r
-    SEVEN: 55,\r
-    /** Key constant @type Number */\r
-    EIGHT: 56,\r
-    /** Key constant @type Number */\r
-    NINE: 57,\r
-    /** Key constant @type Number */\r
-    A: 65,\r
-    /** Key constant @type Number */\r
-    B: 66,\r
-    /** Key constant @type Number */\r
-    C: 67,\r
-    /** Key constant @type Number */\r
-    D: 68,\r
-    /** Key constant @type Number */\r
-    E: 69,\r
-    /** Key constant @type Number */\r
-    F: 70,\r
-    /** Key constant @type Number */\r
-    G: 71,\r
-    /** Key constant @type Number */\r
-    H: 72,\r
-    /** Key constant @type Number */\r
-    I: 73,\r
-    /** Key constant @type Number */\r
-    J: 74,\r
-    /** Key constant @type Number */\r
-    K: 75,\r
-    /** Key constant @type Number */\r
-    L: 76,\r
-    /** Key constant @type Number */\r
-    M: 77,\r
-    /** Key constant @type Number */\r
-    N: 78,\r
-    /** Key constant @type Number */\r
-    O: 79,\r
-    /** Key constant @type Number */\r
-    P: 80,\r
-    /** Key constant @type Number */\r
-    Q: 81,\r
-    /** Key constant @type Number */\r
-    R: 82,\r
-    /** Key constant @type Number */\r
-    S: 83,\r
-    /** Key constant @type Number */\r
-    T: 84,\r
-    /** Key constant @type Number */\r
-    U: 85,\r
-    /** Key constant @type Number */\r
-    V: 86,\r
-    /** Key constant @type Number */\r
-    W: 87,\r
-    /** Key constant @type Number */\r
-    X: 88,\r
-    /** Key constant @type Number */\r
-    Y: 89,\r
-    /** Key constant @type Number */\r
-    Z: 90,\r
-    /** Key constant @type Number */\r
-    CONTEXT_MENU: 93,\r
-    /** Key constant @type Number */\r
-    NUM_ZERO: 96,\r
-    /** Key constant @type Number */\r
-    NUM_ONE: 97,\r
-    /** Key constant @type Number */\r
-    NUM_TWO: 98,\r
-    /** Key constant @type Number */\r
-    NUM_THREE: 99,\r
-    /** Key constant @type Number */\r
-    NUM_FOUR: 100,\r
-    /** Key constant @type Number */\r
-    NUM_FIVE: 101,\r
-    /** Key constant @type Number */\r
-    NUM_SIX: 102,\r
-    /** Key constant @type Number */\r
-    NUM_SEVEN: 103,\r
-    /** Key constant @type Number */\r
-    NUM_EIGHT: 104,\r
-    /** Key constant @type Number */\r
-    NUM_NINE: 105,\r
-    /** Key constant @type Number */\r
-    NUM_MULTIPLY: 106,\r
-    /** Key constant @type Number */\r
-    NUM_PLUS: 107,\r
-    /** Key constant @type Number */\r
-    NUM_MINUS: 109,\r
-    /** Key constant @type Number */\r
-    NUM_PERIOD: 110,\r
-    /** Key constant @type Number */\r
-    NUM_DIVISION: 111,\r
-    /** Key constant @type Number */\r
-    F1: 112,\r
-    /** Key constant @type Number */\r
-    F2: 113,\r
-    /** Key constant @type Number */\r
-    F3: 114,\r
-    /** Key constant @type Number */\r
-    F4: 115,\r
-    /** Key constant @type Number */\r
-    F5: 116,\r
-    /** Key constant @type Number */\r
-    F6: 117,\r
-    /** Key constant @type Number */\r
-    F7: 118,\r
-    /** Key constant @type Number */\r
-    F8: 119,\r
-    /** Key constant @type Number */\r
-    F9: 120,\r
-    /** Key constant @type Number */\r
-    F10: 121,\r
-    /** Key constant @type Number */\r
-    F11: 122,\r
-    /** Key constant @type Number */\r
-    F12: 123,  \r
-    \r
-    /** @private */\r
-    isNavKeyPress : function(){\r
-        var me = this,\r
-               k = this.normalizeKey(me.keyCode);              \r
-        return (k >= 33 && k <= 40) ||  // Page Up/Down, End, Home, Left, Up, Right, Down\r
-               k == me.RETURN ||\r
-               k == me.TAB ||\r
-               k == me.ESC;\r
-    },\r
+    /// There is some jquery work around stuff here that isn't needed in Ext Core.\r
+    function addListener(el, ename, fn, task, wrap, scope){\r
+        el = Ext.getDom(el);\r
+        var id = getId(el),\r
+            es = Ext.elCache[id].events,\r
+            wfn;\r
+\r
+        wfn = E.on(el, ename, wrap);\r
+        es[ename] = es[ename] || [];\r
+\r
+        /* 0 = Original Function,\r
+           1 = Event Manager Wrapped Function,\r
+           2 = Scope,\r
+           3 = Adapter Wrapped Function,\r
+           4 = Buffered Task\r
+        */\r
+        es[ename].push([fn, wrap, scope, wfn, task]);\r
 \r
-    isSpecialKey : function(){\r
-        var k = this.normalizeKey(this.keyCode);\r
-        return (this.type == 'keypress' && this.ctrlKey) ||\r
-               this.isNavKeyPress() ||\r
-        (k == this.BACKSPACE) || // Backspace\r
-               (k >= 16 && k <= 20) || // Shift, Ctrl, Alt, Pause, Caps Lock\r
-               (k >= 44 && k <= 45);   // Print Screen, Insert\r
-    },\r
-       \r
-       getPoint : function(){\r
-           return new Ext.lib.Point(this.xy[0], this.xy[1]);\r
-       },\r
+        // this is a workaround for jQuery and should somehow be removed from Ext Core in the future\r
+        // without breaking ExtJS.\r
 \r
-    /**\r
-     * Returns true if the control, meta, shift or alt key was pressed during this event.\r
-     * @return {Boolean}\r
-     */\r
-    hasModifier : function(){\r
-        return ((this.ctrlKey || this.altKey) || this.shiftKey);\r
-    }\r
-});/**\r
- * @class Ext.Element\r
- * <p>Encapsulates a DOM element, adding simple DOM manipulation facilities, normalizing for browser differences.</p>\r
- * <p>All instances of this class inherit the methods of {@link Ext.Fx} making visual effects easily available to all DOM elements.</p>\r
- * <p>Note that the events documented in this class are not Ext events, they encapsulate browser events. To\r
- * access the underlying browser event, see {@link Ext.EventObject#browserEvent}. Some older\r
- * browsers may not support the full range of events. Which events are supported is beyond the control of ExtJs.</p>\r
- * Usage:<br>\r
-<pre><code>\r
-// by id\r
-var el = Ext.get("my-div");\r
+        // workaround for jQuery\r
+        if(el.addEventListener && ename == "mousewheel"){\r
+            var args = ["DOMMouseScroll", wrap, false];\r
+            el.addEventListener.apply(el, args);\r
+            Ext.EventManager.addListener(WINDOW, 'unload', function(){\r
+                el.removeEventListener.apply(el, args);\r
+            });\r
+        }\r
 \r
-// by DOM element reference\r
-var el = Ext.get(myDivElement);\r
-</code></pre>\r
- * <b>Animations</b><br />\r
- * <p>When an element is manipulated, by default there is no animation.</p>\r
- * <pre><code>\r
-var el = Ext.get("my-div");\r
+        // fix stopped mousedowns on the document\r
+        if(el == DOC && ename == "mousedown"){\r
+            Ext.EventManager.stoppedMouseDownEvent.addListener(wrap);\r
+        }\r
+    };\r
 \r
-// no animation\r
-el.setWidth(100);\r
- * </code></pre>\r
- * <p>Many of the functions for manipulating an element have an optional "animate" parameter.  This\r
- * parameter can be specified as boolean (<tt>true</tt>) for default animation effects.</p>\r
- * <pre><code>\r
-// default animation\r
-el.setWidth(100, true);\r
- * </code></pre>\r
- * \r
- * <p>To configure the effects, an object literal with animation options to use as the Element animation\r
- * configuration object can also be specified. Note that the supported Element animation configuration\r
- * options are a subset of the {@link Ext.Fx} animation options specific to Fx effects.  The supported\r
- * Element animation configuration options are:</p>\r
-<pre>\r
-Option    Default   Description\r
---------- --------  ---------------------------------------------\r
-{@link Ext.Fx#duration duration}  .35       The duration of the animation in seconds\r
-{@link Ext.Fx#easing easing}    easeOut   The easing method\r
-{@link Ext.Fx#callback callback}  none      A function to execute when the anim completes\r
-{@link Ext.Fx#scope scope}     this      The scope (this) of the callback function\r
-</pre>\r
- * \r
- * <pre><code>\r
-// Element animation options object\r
-var opt = {\r
-    {@link Ext.Fx#duration duration}: 1,\r
-    {@link Ext.Fx#easing easing}: 'elasticIn',\r
-    {@link Ext.Fx#callback callback}: this.foo,\r
-    {@link Ext.Fx#scope scope}: this\r
-};\r
-// animation with some options set\r
-el.setWidth(100, opt);\r
- * </code></pre>\r
- * <p>The Element animation object being used for the animation will be set on the options\r
- * object as "anim", which allows you to stop or manipulate the animation. Here is an example:</p>\r
- * <pre><code>\r
-// using the "anim" property to get the Anim object\r
-if(opt.anim.isAnimated()){\r
-    opt.anim.stop();\r
-}\r
- * </code></pre>\r
- * <p>Also see the <tt>{@link #animate}</tt> method for another animation technique.</p>\r
- * <p><b> Composite (Collections of) Elements</b></p>\r
- * <p>For working with collections of Elements, see {@link Ext.CompositeElement}</p>\r
- * @constructor Create a new Element directly.\r
- * @param {String/HTMLElement} element\r
- * @param {Boolean} forceNew (optional) By default the constructor checks to see if there is already an instance of this element in the cache and if there is it returns the same instance. This will skip that check (useful for extending this class).\r
- */\r
-(function(){\r
-var DOC = document;\r
+    function fireDocReady(){\r
+        if(!docReadyState){\r
+            Ext.isReady = docReadyState = true;\r
+            if(docReadyProcId){\r
+                clearInterval(docReadyProcId);\r
+            }\r
+            if(Ext.isGecko || Ext.isOpera) {\r
+                DOC.removeEventListener(DOMCONTENTLOADED, fireDocReady, false);\r
+            }\r
+            if(Ext.isIE){\r
+                var defer = DOC.getElementById(IEDEFERED);\r
+                if(defer){\r
+                    defer.onreadystatechange = null;\r
+                    defer.parentNode.removeChild(defer);\r
+                }\r
+            }\r
+            if(docReadyEvent){\r
+                docReadyEvent.fire();\r
+                docReadyEvent.listeners = []; // clearListeners no longer compatible.  Force single: true?\r
+            }\r
+        }\r
+    };\r
 \r
-Ext.Element = function(element, forceNew){\r
-    var dom = typeof element == "string" ?\r
-              DOC.getElementById(element) : element,\r
-        id;\r
+    function initDocReady(){\r
+        var COMPLETE = "complete";\r
+\r
+        docReadyEvent = new Ext.util.Event();\r
+        if (Ext.isGecko || Ext.isOpera) {\r
+            DOC.addEventListener(DOMCONTENTLOADED, fireDocReady, false);\r
+        } else if (Ext.isIE){\r
+            DOC.write("<s"+'cript id=' + IEDEFERED + ' defer="defer" src="/'+'/:"></s'+"cript>");\r
+            DOC.getElementById(IEDEFERED).onreadystatechange = function(){\r
+                if(this.readyState == COMPLETE){\r
+                    fireDocReady();\r
+                }\r
+            };\r
+        } else if (Ext.isWebKit){\r
+            docReadyProcId = setInterval(function(){\r
+                if(DOC.readyState == COMPLETE) {\r
+                    fireDocReady();\r
+                 }\r
+            }, 10);\r
+        }\r
+        // no matter what, make sure it fires on load\r
+        E.on(WINDOW, "load", fireDocReady);\r
+    };\r
 \r
-    if(!dom) return null;\r
+    function createTargeted(h, o){\r
+        return function(){\r
+            var args = Ext.toArray(arguments);\r
+            if(o.target == Ext.EventObject.setEvent(args[0]).target){\r
+                h.apply(this, args);\r
+            }\r
+        };\r
+    };\r
 \r
-    id = dom.id;\r
+    function createBuffered(h, o, task){\r
+        return function(e){\r
+            // create new event object impl so new events don't wipe out properties\r
+            task.delay(o.buffer, h, null, [new Ext.EventObjectImpl(e)]);\r
+        };\r
+    };\r
 \r
-    if(!forceNew && id && Ext.Element.cache[id]){ // element object already exists\r
-        return Ext.Element.cache[id];\r
-    }\r
+    function createSingle(h, el, ename, fn, scope){\r
+        return function(e){\r
+            Ext.EventManager.removeListener(el, ename, fn, scope);\r
+            h(e);\r
+        };\r
+    };\r
 \r
-    /**\r
-     * The DOM element\r
-     * @type HTMLElement\r
-     */\r
-    this.dom = dom;\r
+    function createDelayed(h, o, fn){\r
+        return function(e){\r
+            var task = new Ext.util.DelayedTask(h);\r
+            if(!fn.tasks) {\r
+                fn.tasks = [];\r
+            }\r
+            fn.tasks.push(task);\r
+            task.delay(o.delay || 10, h, null, [new Ext.EventObjectImpl(e)]);\r
+        };\r
+    };\r
 \r
-    /**\r
-     * The DOM element ID\r
-     * @type String\r
-     */\r
-    this.id = id || Ext.id(dom);\r
-};\r
+    function listen(element, ename, opt, fn, scope){\r
+        var o = !Ext.isObject(opt) ? {} : opt,\r
+            el = Ext.getDom(element), task;\r
 \r
-var D = Ext.lib.Dom,\r
-    DH = Ext.DomHelper,\r
-    E = Ext.lib.Event,\r
-    A = Ext.lib.Anim,\r
-    El = Ext.Element;\r
+        fn = fn || o.fn;\r
+        scope = scope || o.scope;\r
 \r
-El.prototype = {\r
-    /**\r
-     * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)\r
-     * @param {Object} o The object with the attributes\r
-     * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.\r
-     * @return {Ext.Element} this\r
-     */\r
-    set : function(o, useSet){\r
-        var el = this.dom,\r
-            attr,\r
-            val;        \r
-       \r
-        for(attr in o){\r
-            val = o[attr];\r
-            if (attr != "style" && !Ext.isFunction(val)) {\r
-                if (attr == "cls" ) {\r
-                    el.className = val;\r
-                } else if (o.hasOwnProperty(attr)) {\r
-                    if (useSet || !!el.setAttribute) el.setAttribute(attr, val);\r
-                    else el[attr] = val;\r
+        if(!el){\r
+            throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';\r
+        }\r
+        function h(e){\r
+            // prevent errors while unload occurring\r
+            if(!Ext){// !window[xname]){  ==> can't we do this?\r
+                return;\r
+            }\r
+            e = Ext.EventObject.setEvent(e);\r
+            var t;\r
+            if (o.delegate) {\r
+                if(!(t = e.getTarget(o.delegate, el))){\r
+                    return;\r
                 }\r
+            } else {\r
+                t = e.target;\r
+            }\r
+            if (o.stopEvent) {\r
+                e.stopEvent();\r
             }\r
+            if (o.preventDefault) {\r
+               e.preventDefault();\r
+            }\r
+            if (o.stopPropagation) {\r
+                e.stopPropagation();\r
+            }\r
+            if (o.normalized) {\r
+                e = e.browserEvent;\r
+            }\r
+\r
+            fn.call(scope || el, e, t, o);\r
+        };\r
+        if(o.target){\r
+            h = createTargeted(h, o);\r
         }\r
-        if(o.style){\r
-            DH.applyStyles(el, o.style);\r
+        if(o.delay){\r
+            h = createDelayed(h, o, fn);\r
+        }\r
+        if(o.single){\r
+            h = createSingle(h, el, ename, fn, scope);\r
+        }\r
+        if(o.buffer){\r
+            task = new Ext.util.DelayedTask(h);\r
+            h = createBuffered(h, o, task);\r
         }\r
-        return this;\r
-    },\r
-    \r
-//  Mouse events\r
-    /**\r
-     * @event click\r
-     * Fires when a mouse click is detected within the element.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-    /**\r
-     * @event contextmenu\r
-     * Fires when a right click is detected within the element.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-    /**\r
-     * @event dblclick\r
-     * Fires when a mouse double click is detected within the element.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-    /**\r
-     * @event mousedown\r
-     * Fires when a mousedown is detected within the element.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-    /**\r
-     * @event mouseup\r
-     * Fires when a mouseup is detected within the element.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-    /**\r
-     * @event mouseover\r
-     * Fires when a mouseover is detected within the element.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-    /**\r
-     * @event mousemove\r
-     * Fires when a mousemove is detected with the element.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-    /**\r
-     * @event mouseout\r
-     * Fires when a mouseout is detected with the element.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-    /**\r
-     * @event mouseenter\r
-     * Fires when the mouse enters the element.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-    /**\r
-     * @event mouseleave\r
-     * Fires when the mouse leaves the element.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-    \r
-//  Keyboard events\r
-    /**\r
-     * @event keypress\r
-     * Fires when a keypress is detected within the element.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-    /**\r
-     * @event keydown\r
-     * Fires when a keydown is detected within the element.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-    /**\r
-     * @event keyup\r
-     * Fires when a keyup is detected within the element.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-\r
-\r
-//  HTML frame/object events\r
-    /**\r
-     * @event load\r
-     * Fires when the user agent finishes loading all content within the element. Only supported by window, frames, objects and images.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-    /**\r
-     * @event unload\r
-     * Fires when the user agent removes all content from a window or frame. For elements, it fires when the target element or any of its content has been removed.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-    /**\r
-     * @event abort\r
-     * Fires when an object/image is stopped from loading before completely loaded.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-    /**\r
-     * @event error\r
-     * Fires when an object/image/frame cannot be loaded properly.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-    /**\r
-     * @event resize\r
-     * Fires when a document view is resized.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-    /**\r
-     * @event scroll\r
-     * Fires when a document view is scrolled.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-\r
-//  Form events\r
-    /**\r
-     * @event select\r
-     * Fires when a user selects some text in a text field, including input and textarea.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-    /**\r
-     * @event change\r
-     * Fires when a control loses the input focus and its value has been modified since gaining focus.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-    /**\r
-     * @event submit\r
-     * Fires when a form is submitted.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-    /**\r
-     * @event reset\r
-     * Fires when a form is reset.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-    /**\r
-     * @event focus\r
-     * Fires when an element receives focus either via the pointing device or by tab navigation.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-    /**\r
-     * @event blur\r
-     * Fires when an element loses focus either via the pointing device or by tabbing navigation.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-\r
-//  User Interface events\r
-    /**\r
-     * @event DOMFocusIn\r
-     * Where supported. Similar to HTML focus event, but can be applied to any focusable element.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-    /**\r
-     * @event DOMFocusOut\r
-     * Where supported. Similar to HTML blur event, but can be applied to any focusable element.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-    /**\r
-     * @event DOMActivate\r
-     * Where supported. Fires when an element is activated, for instance, through a mouse click or a keypress.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-\r
-//  DOM Mutation events\r
-    /**\r
-     * @event DOMSubtreeModified\r
-     * Where supported. Fires when the subtree is modified.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-    /**\r
-     * @event DOMNodeInserted\r
-     * Where supported. Fires when a node has been added as a child of another node.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-    /**\r
-     * @event DOMNodeRemoved\r
-     * Where supported. Fires when a descendant node of the element is removed.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-    /**\r
-     * @event DOMNodeRemovedFromDocument\r
-     * Where supported. Fires when a node is being removed from a document.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-    /**\r
-     * @event DOMNodeInsertedIntoDocument\r
-     * Where supported. Fires when a node is being inserted into a document.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-    /**\r
-     * @event DOMAttrModified\r
-     * Where supported. Fires when an attribute has been modified.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-    /**\r
-     * @event DOMCharacterDataModified\r
-     * Where supported. Fires when the character data has been modified.\r
-     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
-     * @param {HtmlElement} t The target of the event.\r
-     * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
-     */\r
-\r
-    /**\r
-     * The default unit to append to CSS values where a unit isn't provided (defaults to px).\r
-     * @type String\r
-     */\r
-    defaultUnit : "px",\r
 \r
-    /**\r
-     * Returns true if this element matches the passed simple selector (e.g. div.some-class or span:first-child)\r
-     * @param {String} selector The simple selector to test\r
-     * @return {Boolean} True if this element matches the selector, else false\r
-     */\r
-    is : function(simpleSelector){\r
-        return Ext.DomQuery.is(this.dom, simpleSelector);\r
-    },\r
+        addListener(el, ename, fn, task, h, scope);\r
+        return h;\r
+    };\r
 \r
-    /**\r
-     * Tries to focus the element. Any exceptions are caught and ignored.\r
-     * @param {Number} defer (optional) Milliseconds to defer the focus\r
-     * @return {Ext.Element} this\r
-     */\r
-    focus : function(defer, /* private */ dom) {\r
-        var me = this,\r
-            dom = dom || me.dom;\r
-        try{\r
-            if(Number(defer)){\r
-                me.focus.defer(defer, null, [null, dom]);\r
-            }else{\r
-                dom.focus();\r
+    var pub = {\r
+        /**\r
+         * Appends an event handler to an element.  The shorthand version {@link #on} is equivalent.  Typically you will\r
+         * use {@link Ext.Element#addListener} directly on an Element in favor of calling this version.\r
+         * @param {String/HTMLElement} el The html element or id to assign the event handler to.\r
+         * @param {String} eventName The name of the event to listen for.\r
+         * @param {Function} handler The handler function the event invokes. This function is passed\r
+         * the following parameters:<ul>\r
+         * <li>evt : EventObject<div class="sub-desc">The {@link Ext.EventObject EventObject} describing the event.</div></li>\r
+         * <li>t : Element<div class="sub-desc">The {@link Ext.Element Element} which was the target of the event.\r
+         * Note that this may be filtered by using the <tt>delegate</tt> option.</div></li>\r
+         * <li>o : Object<div class="sub-desc">The options object from the addListener call.</div></li>\r
+         * </ul>\r
+         * @param {Object} scope (optional) The scope (<b><code>this</code></b> reference) in which the handler function is executed. <b>Defaults to the Element</b>.\r
+         * @param {Object} options (optional) An object containing handler configuration properties.\r
+         * This may contain any of the following properties:<ul>\r
+         * <li>scope : Object<div class="sub-desc">The scope (<b><code>this</code></b> reference) in which the handler function is executed. <b>Defaults to the Element</b>.</div></li>\r
+         * <li>delegate : String<div class="sub-desc">A simple selector to filter the target or look for a descendant of the target</div></li>\r
+         * <li>stopEvent : Boolean<div class="sub-desc">True to stop the event. That is stop propagation, and prevent the default action.</div></li>\r
+         * <li>preventDefault : Boolean<div class="sub-desc">True to prevent the default action</div></li>\r
+         * <li>stopPropagation : Boolean<div class="sub-desc">True to prevent event propagation</div></li>\r
+         * <li>normalized : Boolean<div class="sub-desc">False to pass a browser event to the handler function instead of an Ext.EventObject</div></li>\r
+         * <li>delay : Number<div class="sub-desc">The number of milliseconds to delay the invocation of the handler after te event fires.</div></li>\r
+         * <li>single : Boolean<div class="sub-desc">True to add a handler to handle just the next firing of the event, and then remove itself.</div></li>\r
+         * <li>buffer : Number<div class="sub-desc">Causes the handler to be scheduled to run in an {@link Ext.util.DelayedTask} delayed\r
+         * by the specified number of milliseconds. If the event fires again within that time, the original\r
+         * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</div></li>\r
+         * <li>target : Element<div class="sub-desc">Only call the handler if the event was fired on the target Element, <i>not</i> if the event was bubbled up from a child node.</div></li>\r
+         * </ul><br>\r
+         * <p>See {@link Ext.Element#addListener} for examples of how to use these options.</p>\r
+         */\r
+        addListener : function(element, eventName, fn, scope, options){\r
+            if(Ext.isObject(eventName)){\r
+                var o = eventName, e, val;\r
+                for(e in o){\r
+                    val = o[e];\r
+                    if(!propRe.test(e)){\r
+                        if(Ext.isFunction(val)){\r
+                            // shared options\r
+                            listen(element, e, o, val, o.scope);\r
+                        }else{\r
+                            // individual options\r
+                            listen(element, e, val);\r
+                        }\r
+                    }\r
+                }\r
+            } else {\r
+                listen(element, eventName, options, fn, scope);\r
             }\r
-        }catch(e){}\r
-        return me;\r
-    },\r
-\r
-    /**\r
-     * Tries to blur the element. Any exceptions are caught and ignored.\r
-     * @return {Ext.Element} this\r
-     */\r
-    blur : function() {\r
-        try{\r
-            this.dom.blur();\r
-        }catch(e){}\r
-        return this;\r
-    },\r
+        },\r
 \r
-    /**\r
-     * Returns the value of the "value" attribute\r
-     * @param {Boolean} asNumber true to parse the value as a number\r
-     * @return {String/Number}\r
-     */\r
-    getValue : function(asNumber){\r
-        var val = this.dom.value;\r
-        return asNumber ? parseInt(val, 10) : val;\r
-    },\r
+        /**\r
+         * Removes an event handler from an element.  The shorthand version {@link #un} is equivalent.  Typically\r
+         * you will use {@link Ext.Element#removeListener} directly on an Element in favor of calling this version.\r
+         * @param {String/HTMLElement} el The id or html element from which to remove the listener.\r
+         * @param {String} eventName The name of the event.\r
+         * @param {Function} fn The handler function to remove. <b>This must be a reference to the function passed into the {@link #addListener} call.</b>\r
+         * @param {Object} scope If a scope (<b><code>this</code></b> reference) was specified when the listener was added,\r
+         * then this must refer to the same object.\r
+         */\r
+        removeListener : function(el, eventName, fn, scope){\r
+            el = Ext.getDom(el);\r
+            var id = getId(el),\r
+                f = el && (Ext.elCache[id].events)[eventName] || [],\r
+                wrap, i, l, k, len, fnc;\r
 \r
-    /**\r
-     * Appends an event handler to this element.  The shorthand version {@link #on} is equivalent.\r
-     * @param {String} eventName The name of event to handle.\r
-     * @param {Function} fn The handler function the event invokes. This function is passed\r
-     * the following parameters:<ul>\r
-     * <li><b>evt</b> : EventObject<div class="sub-desc">The {@link Ext.EventObject EventObject} describing the event.</div></li>\r
-     * <li><b>el</b> : HtmlElement<div class="sub-desc">The DOM element which was the target of the event.\r
-     * Note that this may be filtered by using the <tt>delegate</tt> option.</div></li>\r
-     * <li><b>o</b> : Object<div class="sub-desc">The options object from the addListener call.</div></li>\r
-     * </ul>\r
-     * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the handler function is executed.\r
-     * <b>If omitted, defaults to this Element.</b>.\r
-     * @param {Object} options (optional) An object containing handler configuration properties.\r
-     * This may contain any of the following properties:<ul>\r
-     * <li><b>scope</b> Object : <div class="sub-desc">The scope (<code><b>this</b></code> reference) in which the handler function is executed.\r
-     * <b>If omitted, defaults to this Element.</b></div></li>\r
-     * <li><b>delegate</b> String: <div class="sub-desc">A simple selector to filter the target or look for a descendant of the target. See below for additional details.</div></li>\r
-     * <li><b>stopEvent</b> Boolean: <div class="sub-desc">True to stop the event. That is stop propagation, and prevent the default action.</div></li>\r
-     * <li><b>preventDefault</b> Boolean: <div class="sub-desc">True to prevent the default action</div></li>\r
-     * <li><b>stopPropagation</b> Boolean: <div class="sub-desc">True to prevent event propagation</div></li>\r
-     * <li><b>normalized</b> Boolean: <div class="sub-desc">False to pass a browser event to the handler function instead of an Ext.EventObject</div></li>\r
-     * <li><b>target</b> Ext.Element: <div class="sub-desc">Only call the handler if the event was fired on the target Element, <i>not</i> if the event was bubbled up from a child node.</div></li>\r
-     * <li><b>delay</b> Number: <div class="sub-desc">The number of milliseconds to delay the invocation of the handler after the event fires.</div></li>\r
-     * <li><b>single</b> Boolean: <div class="sub-desc">True to add a handler to handle just the next firing of the event, and then remove itself.</div></li>\r
-     * <li><b>buffer</b> Number: <div class="sub-desc">Causes the handler to be scheduled to run in an {@link Ext.util.DelayedTask} delayed\r
-     * by the specified number of milliseconds. If the event fires again within that time, the original\r
-     * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</div></li>\r
-     * </ul><br>\r
-     * <p>\r
-     * <b>Combining Options</b><br>\r
-     * In the following examples, the shorthand form {@link #on} is used rather than the more verbose\r
-     * addListener.  The two are equivalent.  Using the options argument, it is possible to combine different\r
-     * types of listeners:<br>\r
-     * <br>\r
-     * A delayed, one-time listener that auto stops the event and adds a custom argument (forumId) to the\r
-     * options object. The options object is available as the third parameter in the handler function.<div style="margin: 5px 20px 20px;">\r
-     * Code:<pre><code>\r
-el.on('click', this.onClick, this, {\r
-    single: true,\r
-    delay: 100,\r
-    stopEvent : true,\r
-    forumId: 4\r
-});</code></pre></p>\r
-     * <p>\r
-     * <b>Attaching multiple handlers in 1 call</b><br>\r
-     * The method also allows for a single argument to be passed which is a config object containing properties\r
-     * which specify multiple handlers.</p>\r
-     * <p>\r
-     * Code:<pre><code>\r
-el.on({\r
-    'click' : {\r
-        fn: this.onClick,\r
-        scope: this,\r
-        delay: 100\r
-    },\r
-    'mouseover' : {\r
-        fn: this.onMouseOver,\r
-        scope: this\r
-    },\r
-    'mouseout' : {\r
-        fn: this.onMouseOut,\r
-        scope: this\r
-    }\r
-});</code></pre>\r
-     * <p>\r
-     * Or a shorthand syntax:<br>\r
-     * Code:<pre><code></p>\r
-el.on({\r
-    'click' : this.onClick,\r
-    'mouseover' : this.onMouseOver,\r
-    'mouseout' : this.onMouseOut,\r
-    scope: this\r
-});\r
-     * </code></pre></p>\r
-     * <p><b>delegate</b></p>\r
-     * <p>This is a configuration option that you can pass along when registering a handler for\r
-     * an event to assist with event delegation. Event delegation is a technique that is used to\r
-     * reduce memory consumption and prevent exposure to memory-leaks. By registering an event\r
-     * for a container element as opposed to each element within a container. By setting this\r
-     * configuration option to a simple selector, the target element will be filtered to look for\r
-     * a descendant of the target.\r
-     * For example:<pre><code>\r
-// using this markup:\r
-&lt;div id='elId'>\r
-    &lt;p id='p1'>paragraph one&lt;/p>\r
-    &lt;p id='p2' class='clickable'>paragraph two&lt;/p>\r
-    &lt;p id='p3'>paragraph three&lt;/p>\r
-&lt;/div>\r
-// utilize event delegation to registering just one handler on the container element: \r
-el = Ext.get('elId');\r
-el.on(\r
-    'click',\r
-    function(e,t) {\r
-        // handle click\r
-        console.info(t.id); // 'p2'\r
-    },\r
-    this,\r
-    {\r
-        // filter the target element to be a descendant with the class 'clickable'\r
-        delegate: '.clickable' \r
-    }\r
-);\r
-     * </code></pre></p>\r
-     * @return {Ext.Element} this\r
-     */\r
-    addListener : function(eventName, fn, scope, options){\r
-        Ext.EventManager.on(this.dom,  eventName, fn, scope || this, options);\r
-        return this;\r
-    },\r
+            for (i = 0, len = f.length; i < len; i++) {\r
 \r
-    /**\r
-     * Removes an event handler from this element.  The shorthand version {@link #un} is equivalent.\r
-     * <b>Note</b>: if a <i>scope</i> was explicitly specified when {@link #addListener adding} the\r
-     * listener, the same scope must be specified here.\r
-     * Example:\r
-     * <pre><code>\r
-el.removeListener('click', this.handlerFn);\r
-// or\r
-el.un('click', this.handlerFn);\r
-</code></pre>\r
-     * @param {String} eventName The name of the event from which to remove the handler.\r
-     * @param {Function} fn The handler function to remove. <b>This must be a reference to the function passed into the {@link #addListener} call.</b>\r
-     * @param {Object} scope If a scope (<b><code>this</code></b> reference) was specified when the listener was added,\r
-     * then this must refer to the same object.\r
-     * @return {Ext.Element} this\r
-     */\r
-    removeListener : function(eventName, fn, scope){\r
-        Ext.EventManager.removeListener(this.dom,  eventName, fn, scope || this);\r
-        return this;\r
-    },\r
+                /* 0 = Original Function,\r
+                   1 = Event Manager Wrapped Function,\r
+                   2 = Scope,\r
+                   3 = Adapter Wrapped Function,\r
+                   4 = Buffered Task\r
+                */\r
+                if (Ext.isArray(fnc = f[i]) && fnc[0] == fn && (!scope || fnc[2] == scope)) {\r
+                    if(fnc[4]) {\r
+                        fnc[4].cancel();\r
+                    }\r
+                    k = fn.tasks && fn.tasks.length;\r
+                    if(k) {\r
+                        while(k--) {\r
+                            fn.tasks[k].cancel();\r
+                        }\r
+                        delete fn.tasks;\r
+                    }\r
+                    wrap = fnc[1];\r
+                    E.un(el, eventName, E.extAdapter ? fnc[3] : wrap);\r
 \r
-    /**\r
-     * Removes all previous added listeners from this element\r
-     * @return {Ext.Element} this\r
-     */\r
-    removeAllListeners : function(){\r
-        Ext.EventManager.removeAll(this.dom);\r
-        return this;\r
-    },\r
+                    // jQuery workaround that should be removed from Ext Core\r
+                    if(wrap && el.addEventListener && eventName == "mousewheel"){\r
+                        el.removeEventListener("DOMMouseScroll", wrap, false);\r
+                    }\r
 \r
-    /**\r
-     * @private Test if size has a unit, otherwise appends the default\r
-     */\r
-    addUnits : function(size){\r
-        if(size === "" || size == "auto" || size === undefined){\r
-            size = size || '';\r
-        } else if(!isNaN(size) || !unitPattern.test(size)){\r
-            size = size + (this.defaultUnit || 'px');\r
-        }\r
-        return size;\r
-    },\r
+                    // fix stopped mousedowns on the document\r
+                    if(wrap && el == DOC && eventName == "mousedown"){\r
+                        Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);\r
+                    }\r
 \r
-    /**\r
-     * <p>Updates the <a href="http://developer.mozilla.org/en/DOM/element.innerHTML">innerHTML</a> of this Element\r
-     * from a specified URL. Note that this is subject to the <a href="http://en.wikipedia.org/wiki/Same_origin_policy">Same Origin Policy</a></p>\r
-     * <p>Updating innerHTML of an element will <b>not</b> execute embedded <tt>&lt;script></tt> elements. This is a browser restriction.</p>\r
-     * @param {Mixed} options. Either a sring containing the URL from which to load the HTML, or an {@link Ext.Ajax#request} options object specifying\r
-     * exactly how to request the HTML.\r
-     * @return {Ext.Element} this\r
-     */\r
-    load : function(url, params, cb){\r
-        Ext.Ajax.request(Ext.apply({\r
-            params: params,\r
-            url: url.url || url,\r
-            callback: cb,\r
-            el: this.dom,\r
-            indicatorText: url.indicatorText || ''\r
-        }, Ext.isObject(url) ? url : {}));\r
-        return this;\r
-    },\r
+                    f.splice(i, 1);\r
+                    if (f.length === 0) {\r
+                        delete Ext.elCache[id].events[eventName];\r
+                    }\r
+                    for (k in Ext.elCache[id].events) {\r
+                        return false;\r
+                    }\r
+                    Ext.elCache[id].events = {};\r
+                    return false;\r
+                }\r
+            }\r
+        },\r
 \r
-    /**\r
-     * Tests various css rules/browsers to determine if this element uses a border box\r
-     * @return {Boolean}\r
-     */\r
-    isBorderBox : function(){\r
-        return noBoxAdjust[(this.dom.tagName || "").toLowerCase()] || Ext.isBorderBox;\r
-    },\r
+        /**\r
+         * Removes all event handers from an element.  Typically you will use {@link Ext.Element#removeAllListeners}\r
+         * directly on an Element in favor of calling this version.\r
+         * @param {String/HTMLElement} el The id or html element from which to remove all event handlers.\r
+         */\r
+        removeAll : function(el){\r
+            el = Ext.getDom(el);\r
+            var id = getId(el),\r
+                ec = Ext.elCache[id] || {},\r
+                es = ec.events || {},\r
+                f, i, len, ename, fn, k, wrap;\r
+\r
+            for(ename in es){\r
+                if(es.hasOwnProperty(ename)){\r
+                    f = es[ename];\r
+                    /* 0 = Original Function,\r
+                       1 = Event Manager Wrapped Function,\r
+                       2 = Scope,\r
+                       3 = Adapter Wrapped Function,\r
+                       4 = Buffered Task\r
+                    */\r
+                    for (i = 0, len = f.length; i < len; i++) {\r
+                        fn = f[i];\r
+                        if(fn[4]) {\r
+                            fn[4].cancel();\r
+                        }\r
+                        if(fn[0].tasks && (k = fn[0].tasks.length)) {\r
+                            while(k--) {\r
+                                fn[0].tasks[k].cancel();\r
+                            }\r
+                            delete fn.tasks;\r
+                        }\r
+                        wrap =  fn[1];\r
+                        E.un(el, ename, E.extAdapter ? fn[3] : wrap);\r
 \r
-    /**\r
-     * Removes this element from the DOM and deletes it from the cache\r
-     */\r
-    remove : function(){\r
-        var me = this,\r
-            dom = me.dom;\r
-        \r
-        me.removeAllListeners();\r
-        if (dom) {\r
-            delete me.dom;\r
-            delete El.cache[dom.id];\r
-            delete El.dataCache[dom.id];\r
-            Ext.removeNode(dom);\r
-        }\r
-    },\r
+                        // jQuery workaround that should be removed from Ext Core\r
+                        if(el.addEventListener && wrap && ename == "mousewheel"){\r
+                            el.removeEventListener("DOMMouseScroll", wrap, false);\r
+                        }\r
 \r
-    /**\r
-     * Sets up event handlers to call the passed functions when the mouse is moved into and out of the Element.\r
-     * @param {Function} overFn The function to call when the mouse enters the Element.\r
-     * @param {Function} outFn The function to call when the mouse leaves the Element.\r
-     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the functions are executed. Defaults to the Element's DOM element.\r
-     * @param {Object} options (optional) Options for the listener. See {@link Ext.util.Observable#addListener the <tt>options</tt> parameter}.\r
-     * @return {Ext.Element} this\r
-     */\r
-    hover : function(overFn, outFn, scope, options){\r
-        var me = this;\r
-        me.on('mouseenter', overFn, scope || me.dom, options);\r
-        me.on('mouseleave', outFn, scope || me.dom, options);\r
-        return me;\r
-    },\r
+                        // fix stopped mousedowns on the document\r
+                        if(wrap && el == DOC &&  ename == "mousedown"){\r
+                            Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+            if (Ext.elCache[id]) {\r
+                Ext.elCache[id].events = {};\r
+            }\r
+        },\r
 \r
-    /**\r
-     * Returns true if this element is an ancestor of the passed element\r
-     * @param {HTMLElement/String} el The element to check\r
-     * @return {Boolean} True if this element is an ancestor of el, else false\r
-     */\r
-    contains : function(el){\r
-        return !el ? false : Ext.lib.Dom.isAncestor(this.dom, el.dom ? el.dom : el);\r
-    },\r
+        getListeners : function(el, eventName) {\r
+            el = Ext.getDom(el);\r
+            var id = getId(el),\r
+                ec = Ext.elCache[id] || {},\r
+                es = ec.events || {},\r
+                results = [];\r
+            if (es && es[eventName]) {\r
+                return es[eventName];\r
+            } else {\r
+                return null;\r
+            }\r
+        },\r
 \r
-    /**\r
-     * Returns the value of a namespaced attribute from the element's underlying DOM node.\r
-     * @param {String} namespace The namespace in which to look for the attribute\r
-     * @param {String} name The attribute name\r
-     * @return {String} The attribute value\r
-     * @deprecated\r
-     */\r
-    getAttributeNS : function(ns, name){\r
-        return this.getAttribute(name, ns); \r
-    },\r
-    \r
-    /**\r
-     * Returns the value of an attribute from the element's underlying DOM node.\r
-     * @param {String} name The attribute name\r
-     * @param {String} namespace (optional) The namespace in which to look for the attribute\r
-     * @return {String} The attribute value\r
-     */\r
-    getAttribute : Ext.isIE ? function(name, ns){\r
-        var d = this.dom,\r
-            type = typeof d[ns + ":" + name];\r
+        purgeElement : function(el, recurse, eventName) {\r
+            el = Ext.getDom(el);\r
+            var id = getId(el),\r
+                ec = Ext.elCache[id] || {},\r
+                es = ec.events || {},\r
+                i, f, len;\r
+            if (eventName) {\r
+                if (es && es.hasOwnProperty(eventName)) {\r
+                    f = es[eventName];\r
+                    for (i = 0, len = f.length; i < len; i++) {\r
+                        Ext.EventManager.removeListener(el, eventName, f[i][0]);\r
+                    }\r
+                }\r
+            } else {\r
+                Ext.EventManager.removeAll(el);\r
+            }\r
+            if (recurse && el && el.childNodes) {\r
+                for (i = 0, len = el.childNodes.length; i < len; i++) {\r
+                    Ext.EventManager.purgeElement(el.childNodes[i], recurse, eventName);\r
+                }\r
+            }\r
+        },\r
 \r
-        if(['undefined', 'unknown'].indexOf(type) == -1){\r
-            return d[ns + ":" + name];\r
+        _unload : function() {\r
+            var el;\r
+            for (el in Ext.elCache) {\r
+                Ext.EventManager.removeAll(el);\r
+            }\r
+            delete Ext.elCache;\r
+            delete Ext.Element._flyweights;\r
+        },\r
+        /**\r
+         * Adds a listener to be notified when the document is ready (before onload and before images are loaded). Can be\r
+         * accessed shorthanded as Ext.onReady().\r
+         * @param {Function} fn The method the event invokes.\r
+         * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the handler function executes. Defaults to the browser window.\r
+         * @param {boolean} options (optional) Options object as passed to {@link Ext.Element#addListener}. It is recommended that the options\r
+         * <code>{single: true}</code> be used so that the handler is removed on first invocation.\r
+         */\r
+        onDocumentReady : function(fn, scope, options){\r
+            if(docReadyState){ // if it already fired\r
+                docReadyEvent.addListener(fn, scope, options);\r
+                docReadyEvent.fire();\r
+                docReadyEvent.listeners = []; // clearListeners no longer compatible.  Force single: true?\r
+            } else {\r
+                if(!docReadyEvent) initDocReady();\r
+                options = options || {};\r
+                options.delay = options.delay || 1;\r
+                docReadyEvent.addListener(fn, scope, options);\r
+            }\r
         }\r
-        return d[name];\r
-    } : function(name, ns){\r
-        var d = this.dom;\r
-        return d.getAttributeNS(ns, name) || d.getAttribute(ns + ":" + name) || d.getAttribute(name) || d[name];\r
-    },\r
-    \r
-    /**\r
-    * Update the innerHTML of this element\r
-    * @param {String} html The new HTML\r
-    * @return {Ext.Element} this\r
+    };\r
+     /**\r
+     * Appends an event handler to an element.  Shorthand for {@link #addListener}.\r
+     * @param {String/HTMLElement} el The html element or id to assign the event handler to\r
+     * @param {String} eventName The name of the event to listen for.\r
+     * @param {Function} handler The handler function the event invokes.\r
+     * @param {Object} scope (optional) (<code>this</code> reference) in which the handler function executes. <b>Defaults to the Element</b>.\r
+     * @param {Object} options (optional) An object containing standard {@link #addListener} options\r
+     * @member Ext.EventManager\r
+     * @method on\r
+     */\r
+    pub.on = pub.addListener;\r
+    /**\r
+     * Removes an event handler from an element.  Shorthand for {@link #removeListener}.\r
+     * @param {String/HTMLElement} el The id or html element from which to remove the listener.\r
+     * @param {String} eventName The name of the event.\r
+     * @param {Function} fn The handler function to remove. <b>This must be a reference to the function passed into the {@link #on} call.</b>\r
+     * @param {Object} scope If a scope (<b><code>this</code></b> reference) was specified when the listener was added,\r
+     * then this must refer to the same object.\r
+     * @member Ext.EventManager\r
+     * @method un\r
      */\r
-    update : function(html) {\r
-        if (this.dom) {\r
-            this.dom.innerHTML = html;\r
-        }\r
-        return this;\r
-    }\r
-};\r
-\r
-var ep = El.prototype;\r
-\r
-El.addMethods = function(o){\r
-   Ext.apply(ep, o);\r
-};\r
-\r
-/**\r
- * Appends an event handler (shorthand for {@link #addListener}).\r
- * @param {String} eventName The name of event to handle.\r
- * @param {Function} fn The handler function the event invokes.\r
- * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the handler function is executed.\r
- * @param {Object} options (optional) An object containing standard {@link #addListener} options\r
- * @member Ext.Element\r
- * @method on\r
- */\r
-ep.on = ep.addListener;\r
+    pub.un = pub.removeListener;\r
 \r
+    pub.stoppedMouseDownEvent = new Ext.util.Event();\r
+    return pub;\r
+}();\r
 /**\r
- * Removes an event handler from this element (see {@link #removeListener} for additional notes).\r
- * @param {String} eventName The name of the event from which to remove the handler.\r
- * @param {Function} fn The handler function to remove. <b>This must be a reference to the function passed into the {@link #addListener} call.</b>\r
- * @param {Object} scope If a scope (<b><code>this</code></b> reference) was specified when the listener was added,\r
- * then this must refer to the same object.\r
- * @return {Ext.Element} this\r
- * @member Ext.Element\r
- * @method un\r
+  * Adds a listener to be notified when the document is ready (before onload and before images are loaded). Shorthand of {@link Ext.EventManager#onDocumentReady}.\r
+  * @param {Function} fn The method the event invokes.\r
+  * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the handler function executes. Defaults to the browser window.\r
+  * @param {boolean} options (optional) Options object as passed to {@link Ext.Element#addListener}. It is recommended that the options\r
+  * <code>{single: true}</code> be used so that the handler is removed on first invocation.\r
+  * @member Ext\r
+  * @method onReady\r
  */\r
-ep.un = ep.removeListener;\r
+Ext.onReady = Ext.EventManager.onDocumentReady;\r
 \r
-/**\r
- * true to automatically adjust width and height settings for box-model issues (default to true)\r
- */\r
-ep.autoBoxAdjust = true;\r
 \r
-// private\r
-var unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i,\r
-    docEl;\r
+//Initialize doc classes\r
+(function(){\r
 \r
-/**\r
- * @private\r
- */\r
-El.cache = {};\r
-El.dataCache = {};\r
+    var initExtCss = function(){\r
+        // find the body element\r
+        var bd = document.body || document.getElementsByTagName('body')[0];\r
+        if(!bd){ return false; }\r
+        var cls = [' ',\r
+                Ext.isIE ? "ext-ie " + (Ext.isIE6 ? 'ext-ie6' : (Ext.isIE7 ? 'ext-ie7' : 'ext-ie8'))\r
+                : Ext.isGecko ? "ext-gecko " + (Ext.isGecko2 ? 'ext-gecko2' : 'ext-gecko3')\r
+                : Ext.isOpera ? "ext-opera"\r
+                : Ext.isWebKit ? "ext-webkit" : ""];\r
 \r
-/**\r
- * Retrieves Ext.Element objects.\r
- * <p><b>This method does not retrieve {@link Ext.Component Component}s.</b> This method\r
- * retrieves Ext.Element objects which encapsulate DOM elements. To retrieve a Component by\r
- * its ID, use {@link Ext.ComponentMgr#get}.</p>\r
- * <p>Uses simple caching to consistently return the same object. Automatically fixes if an\r
- * object was recreated with the same id via AJAX or DOM.</p>\r
- * @param {Mixed} el The id of the node, a DOM Node or an existing Element.\r
- * @return {Element} The Element object (or null if no matching element was found)\r
- * @static\r
- * @member Ext.Element\r
- * @method get\r
- */\r
-El.get = function(el){\r
-    var ex,\r
-        elm,\r
-        id;\r
-    if(!el){ return null; }\r
-    if (typeof el == "string") { // element id\r
-        if (!(elm = DOC.getElementById(el))) {\r
-            return null;\r
-        }\r
-        if (ex = El.cache[el]) {\r
-            ex.dom = elm;\r
-        } else {\r
-            ex = El.cache[el] = new El(elm);\r
-        }\r
-        return ex;\r
-    } else if (el.tagName) { // dom element\r
-        if(!(id = el.id)){\r
-            id = Ext.id(el);\r
+        if(Ext.isSafari){\r
+            cls.push("ext-safari " + (Ext.isSafari2 ? 'ext-safari2' : (Ext.isSafari3 ? 'ext-safari3' : 'ext-safari4')));\r
+        }else if(Ext.isChrome){\r
+            cls.push("ext-chrome");\r
         }\r
-        if(ex = El.cache[id]){\r
-            ex.dom = el;\r
-        }else{\r
-            ex = El.cache[id] = new El(el);\r
+\r
+        if(Ext.isMac){\r
+            cls.push("ext-mac");\r
         }\r
-        return ex;\r
-    } else if (el instanceof El) {\r
-        if(el != docEl){\r
-            el.dom = DOC.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,\r
-                                                          // catch case where it hasn't been appended\r
-            El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it\r
+        if(Ext.isLinux){\r
+            cls.push("ext-linux");\r
         }\r
-        return el;\r
-    } else if(el.isComposite) {\r
-        return el;\r
-    } else if(Ext.isArray(el)) {\r
-        return El.select(el);\r
-    } else if(el == DOC) {\r
-        // create a bogus element object representing the document object\r
-        if(!docEl){\r
-            var f = function(){};\r
-            f.prototype = El.prototype;\r
-            docEl = new f();\r
-            docEl.dom = DOC;\r
-        }\r
-        return docEl;\r
-    }\r
-    return null;\r
-};\r
 \r
-// private method for getting and setting element data\r
-El.data = function(el, key, value){\r
-    var c = El.dataCache[el.id];\r
-    if(!c){\r
-        c = El.dataCache[el.id] = {};\r
-    }\r
-    if(arguments.length == 2){\r
-        return c[key];    \r
-    }else{\r
-        return (c[key] = value);\r
-    }\r
-};\r
-\r
-// private\r
-// Garbage collection - uncache elements/purge listeners on orphaned elements\r
-// so we don't hold a reference and cause the browser to retain them\r
-function garbageCollect(){\r
-    if(!Ext.enableGarbageCollector){\r
-        clearInterval(El.collectorThread);\r
-    } else {\r
-        var eid,\r
-            el,\r
-            d;\r
-\r
-        for(eid in El.cache){\r
-            el = El.cache[eid];\r
-            d = el.dom;\r
-            // -------------------------------------------------------\r
-            // Determining what is garbage:\r
-            // -------------------------------------------------------\r
-            // !d\r
-            // dom node is null, definitely garbage\r
-            // -------------------------------------------------------\r
-            // !d.parentNode\r
-            // no parentNode == direct orphan, definitely garbage\r
-            // -------------------------------------------------------\r
-            // !d.offsetParent && !document.getElementById(eid)\r
-            // display none elements have no offsetParent so we will\r
-            // also try to look it up by it's id. However, check\r
-            // offsetParent first so we don't do unneeded lookups.\r
-            // This enables collection of elements that are not orphans\r
-            // directly, but somewhere up the line they have an orphan\r
-            // parent.\r
-            // -------------------------------------------------------\r
-            if(!d || !d.parentNode || (!d.offsetParent && !DOC.getElementById(eid))){\r
-                delete El.cache[eid];\r
-                if(d && Ext.enableListenerCollection){\r
-                    Ext.EventManager.removeAll(d);\r
-                }\r
+        if(Ext.isStrict || Ext.isBorderBox){ // add to the parent to allow for selectors like ".ext-strict .ext-ie"\r
+            var p = bd.parentNode;\r
+            if(p){\r
+                p.className += Ext.isStrict ? ' ext-strict' : ' ext-border-box';\r
             }\r
         }\r
+        bd.className += cls.join(' ');\r
+        return true;\r
     }\r
-}\r
-El.collectorThreadId = setInterval(garbageCollect, 30000);\r
-\r
-var flyFn = function(){};\r
-flyFn.prototype = El.prototype;\r
-\r
-// dom is optional\r
-El.Flyweight = function(dom){\r
-    this.dom = dom;\r
-};\r
-\r
-El.Flyweight.prototype = new flyFn();\r
-El.Flyweight.prototype.isFlyweight = true;\r
-El._flyweights = {};\r
 \r
-/**\r
- * <p>Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -\r
- * the dom node can be overwritten by other code. Shorthand of {@link Ext.Element#fly}</p>\r
- * <p>Use this to make one-time references to DOM elements which are not going to be accessed again either by\r
- * application code, or by Ext's classes. If accessing an element which will be processed regularly, then {@link Ext#get}\r
- * will be more appropriate to take advantage of the caching provided by the Ext.Element class.</p>\r
- * @param {String/HTMLElement} el The dom node or id\r
- * @param {String} named (optional) Allows for creation of named reusable flyweights to prevent conflicts\r
- * (e.g. internally Ext uses "_global")\r
- * @return {Element} The shared Element object (or null if no matching element was found)\r
- * @member Ext.Element\r
- * @method fly\r
- */\r
-El.fly = function(el, named){\r
-    var ret = null;\r
-    named = named || '_global';\r
-\r
-    if (el = Ext.getDom(el)) {\r
-        (El._flyweights[named] = El._flyweights[named] || new El.Flyweight()).dom = el;\r
-        ret = El._flyweights[named];\r
+    if(!initExtCss()){\r
+        Ext.onReady(initExtCss);\r
     }\r
-    return ret;\r
-};\r
+})();\r
 \r
-/**\r
- * Retrieves Ext.Element objects.\r
- * <p><b>This method does not retrieve {@link Ext.Component Component}s.</b> This method\r
- * retrieves Ext.Element objects which encapsulate DOM elements. To retrieve a Component by\r
- * its ID, use {@link Ext.ComponentMgr#get}.</p>\r
- * <p>Uses simple caching to consistently return the same object. Automatically fixes if an\r
- * object was recreated with the same id via AJAX or DOM.</p>\r
- * Shorthand of {@link Ext.Element#get}\r
- * @param {Mixed} el The id of the node, a DOM Node or an existing Element.\r
- * @return {Element} The Element object (or null if no matching element was found)\r
- * @member Ext\r
- * @method get\r
- */\r
-Ext.get = El.get;\r
 \r
 /**\r
- * <p>Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -\r
- * the dom node can be overwritten by other code. Shorthand of {@link Ext.Element#fly}</p>\r
- * <p>Use this to make one-time references to DOM elements which are not going to be accessed again either by\r
- * application code, or by Ext's classes. If accessing an element which will be processed regularly, then {@link Ext#get}\r
- * will be more appropriate to take advantage of the caching provided by the Ext.Element class.</p>\r
- * @param {String/HTMLElement} el The dom node or id\r
- * @param {String} named (optional) Allows for creation of named reusable flyweights to prevent conflicts\r
- * (e.g. internally Ext uses "_global")\r
- * @return {Element} The shared Element object (or null if no matching element was found)\r
- * @member Ext\r
- * @method fly\r
- */\r
-Ext.fly = El.fly;\r
-\r
-// speedy lookup for elements never to box adjust\r
-var noBoxAdjust = Ext.isStrict ? {\r
-    select:1\r
-} : {\r
-    input:1, select:1, textarea:1\r
-};\r
-if(Ext.isIE || Ext.isGecko){\r
-    noBoxAdjust['button'] = 1;\r
+ * @class Ext.EventObject\r
+ * Just as {@link Ext.Element} wraps around a native DOM node, Ext.EventObject\r
+ * wraps the browser's native event-object normalizing cross-browser differences,\r
+ * such as which mouse button is clicked, keys pressed, mechanisms to stop\r
+ * event-propagation along with a method to prevent default actions from taking place.\r
+ * <p>For example:</p>\r
+ * <pre><code>\r
+function handleClick(e, t){ // e is not a standard event object, it is a Ext.EventObject\r
+    e.preventDefault();\r
+    var target = e.getTarget(); // same as t (the target HTMLElement)\r
+    ...\r
 }\r
-\r
-\r
-Ext.EventManager.on(window, 'unload', function(){\r
-    delete El.cache;\r
-    delete El.dataCache;\r
-    delete El._flyweights;\r
-});\r
-})();\r
-/**\r
- * @class Ext.Element\r
+var myDiv = {@link Ext#get Ext.get}("myDiv");  // get reference to an {@link Ext.Element}\r
+myDiv.on(         // 'on' is shorthand for addListener\r
+    "click",      // perform an action on click of myDiv\r
+    handleClick   // reference to the action handler\r
+);\r
+// other methods to do the same:\r
+Ext.EventManager.on("myDiv", 'click', handleClick);\r
+Ext.EventManager.addListener("myDiv", 'click', handleClick);\r
+ </code></pre>\r
+ * @singleton\r
  */\r
-Ext.Element.addMethods({    \r
-    /**\r
-     * Stops the specified event(s) from bubbling and optionally prevents the default action\r
-     * @param {String/Array} eventName an event / array of events to stop from bubbling\r
-     * @param {Boolean} preventDefault (optional) true to prevent the default action too\r
-     * @return {Ext.Element} this\r
-     */\r
-    swallowEvent : function(eventName, preventDefault){\r
-           var me = this;\r
-        function fn(e){\r
-            e.stopPropagation();\r
-            if(preventDefault){\r
-                e.preventDefault();\r
-            }\r
-        }\r
-        if(Ext.isArray(eventName)){            \r
-               Ext.each(eventName, function(e) {\r
-                 me.on(e, fn);\r
-            });\r
-            return me;\r
+Ext.EventObject = function(){\r
+    var E = Ext.lib.Event,\r
+        // safari keypress events for special keys return bad keycodes\r
+        safariKeys = {\r
+            3 : 13, // enter\r
+            63234 : 37, // left\r
+            63235 : 39, // right\r
+            63232 : 38, // up\r
+            63233 : 40, // down\r
+            63276 : 33, // page up\r
+            63277 : 34, // page down\r
+            63272 : 46, // delete\r
+            63273 : 36, // home\r
+            63275 : 35  // end\r
+        },\r
+        // normalize button clicks\r
+        btnMap = Ext.isIE ? {1:0,4:1,2:2} :\r
+                (Ext.isWebKit ? {1:0,2:1,3:2} : {0:0,1:1,2:2});\r
+\r
+    Ext.EventObjectImpl = function(e){\r
+        if(e){\r
+            this.setEvent(e.browserEvent || e);\r
         }\r
-        me.on(eventName, fn);\r
-        return me;\r
-    },\r
-    \r
-    /**\r
-     * Create an event handler on this element such that when the event fires and is handled by this element,\r
-     * it will be relayed to another object (i.e., fired again as if it originated from that object instead).\r
-     * @param {String} eventName The type of event to relay\r
-     * @param {Object} object Any object that extends {@link Ext.util.Observable} that will provide the context\r
-     * for firing the relayed event\r
-     */\r
-    relayEvent : function(eventName, observable){\r
-        this.on(eventName, function(e){\r
-            observable.fireEvent(eventName, e);\r
-        });\r
-    },\r
-    \r
-       /**\r
-     * Removes worthless text nodes\r
-     * @param {Boolean} forceReclean (optional) By default the element\r
-     * keeps track if it has been cleaned already so\r
-     * you can call this over and over. However, if you update the element and\r
-     * need to force a reclean, you can pass true.\r
-     */\r
-    clean : function(forceReclean){\r
-        var me = this, \r
-            dom = me.dom,\r
-               n = dom.firstChild, \r
-               ni = -1;\r
-               \r
-           if(Ext.Element.data(dom, 'isCleaned') && forceReclean !== true){\r
-            return me;\r
-        }      \r
-               \r
-           while(n){\r
-               var nx = n.nextSibling;\r
-            if(n.nodeType == 3 && !/\S/.test(n.nodeValue)){\r
-                dom.removeChild(n);\r
+    };\r
+\r
+    Ext.EventObjectImpl.prototype = {\r
+           /** @private */\r
+        setEvent : function(e){\r
+            var me = this;\r
+            if(e == me || (e && e.browserEvent)){ // already wrapped\r
+                return e;\r
+            }\r
+            me.browserEvent = e;\r
+            if(e){\r
+                // normalize buttons\r
+                me.button = e.button ? btnMap[e.button] : (e.which ? e.which - 1 : -1);\r
+                if(e.type == 'click' && me.button == -1){\r
+                    me.button = 0;\r
+                }\r
+                me.type = e.type;\r
+                me.shiftKey = e.shiftKey;\r
+                // mac metaKey behaves like ctrlKey\r
+                me.ctrlKey = e.ctrlKey || e.metaKey || false;\r
+                me.altKey = e.altKey;\r
+                // in getKey these will be normalized for the mac\r
+                me.keyCode = e.keyCode;\r
+                me.charCode = e.charCode;\r
+                // cache the target for the delayed and or buffered events\r
+                me.target = E.getTarget(e);\r
+                // same for XY\r
+                me.xy = E.getXY(e);\r
             }else{\r
-                n.nodeIndex = ++ni;\r
+                me.button = -1;\r
+                me.shiftKey = false;\r
+                me.ctrlKey = false;\r
+                me.altKey = false;\r
+                me.keyCode = 0;\r
+                me.charCode = 0;\r
+                me.target = null;\r
+                me.xy = [0, 0];\r
             }\r
-               n = nx;\r
-           }\r
-        Ext.Element.data(dom, 'isCleaned', true);\r
-           return me;\r
-       },\r
-    \r
-    /**\r
-     * Direct access to the Updater {@link Ext.Updater#update} method. The method takes the same object\r
-     * parameter as {@link Ext.Updater#update}\r
-     * @return {Ext.Element} this\r
-     */\r
-    load : function(){\r
-        var um = this.getUpdater();\r
-        um.update.apply(um, arguments);\r
-        return this;\r
-    },\r
+            return me;\r
+        },\r
 \r
-    /**\r
-    * Gets this element's {@link Ext.Updater Updater}\r
-    * @return {Ext.Updater} The Updater\r
-    */\r
-    getUpdater : function(){\r
-        return this.updateManager || (this.updateManager = new Ext.Updater(this));\r
-    },\r
-    \r
-       /**\r
-    * Update the innerHTML of this element, optionally searching for and processing scripts\r
-    * @param {String} html The new HTML\r
-    * @param {Boolean} loadScripts (optional) True to look for and process scripts (defaults to false)\r
-    * @param {Function} callback (optional) For async script loading you can be notified when the update completes\r
-    * @return {Ext.Element} this\r
-     */\r
-    update : function(html, loadScripts, callback){\r
-        html = html || "";\r
-           \r
-        if(loadScripts !== true){\r
-            this.dom.innerHTML = html;\r
-            if(Ext.isFunction(callback)){\r
-                callback();\r
-            }\r
-            return this;\r
-        }\r
-        \r
-        var id = Ext.id(),\r
-               dom = this.dom;\r
-\r
-        html += '<span id="' + id + '"></span>';\r
-\r
-        Ext.lib.Event.onAvailable(id, function(){\r
-            var DOC = document,\r
-                hd = DOC.getElementsByTagName("head")[0],\r
-               re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig,\r
-               srcRe = /\ssrc=([\'\"])(.*?)\1/i,\r
-               typeRe = /\stype=([\'\"])(.*?)\1/i,\r
-               match,\r
-               attrs,\r
-               srcMatch,\r
-               typeMatch,\r
-               el,\r
-               s;\r
-\r
-            while((match = re.exec(html))){\r
-                attrs = match[1];\r
-                srcMatch = attrs ? attrs.match(srcRe) : false;\r
-                if(srcMatch && srcMatch[2]){\r
-                   s = DOC.createElement("script");\r
-                   s.src = srcMatch[2];\r
-                   typeMatch = attrs.match(typeRe);\r
-                   if(typeMatch && typeMatch[2]){\r
-                       s.type = typeMatch[2];\r
-                   }\r
-                   hd.appendChild(s);\r
-                }else if(match[2] && match[2].length > 0){\r
-                    if(window.execScript) {\r
-                       window.execScript(match[2]);\r
-                    } else {\r
-                       window.eval(match[2]);\r
-                    }\r
+        /**\r
+         * Stop the event (preventDefault and stopPropagation)\r
+         */\r
+        stopEvent : function(){\r
+            var me = this;\r
+            if(me.browserEvent){\r
+                if(me.browserEvent.type == 'mousedown'){\r
+                    Ext.EventManager.stoppedMouseDownEvent.fire(me);\r
                 }\r
+                E.stopEvent(me.browserEvent);\r
             }\r
-            el = DOC.getElementById(id);\r
-            if(el){Ext.removeNode(el);}\r
-            if(Ext.isFunction(callback)){\r
-                callback();\r
-            }\r
-        });\r
-        dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");\r
-        return this;\r
-    },\r
-    \r
-    /**\r
-     * Creates a proxy element of this element\r
-     * @param {String/Object} config The class name of the proxy element or a DomHelper config object\r
-     * @param {String/HTMLElement} renderTo (optional) The element or element id to render the proxy to (defaults to document.body)\r
-     * @param {Boolean} matchBox (optional) True to align and size the proxy to this element now (defaults to false)\r
-     * @return {Ext.Element} The new proxy element\r
-     */\r
-    createProxy : function(config, renderTo, matchBox){\r
-        config = Ext.isObject(config) ? config : {tag : "div", cls: config};\r
-\r
-        var me = this,\r
-               proxy = renderTo ? Ext.DomHelper.append(renderTo, config, true) :\r
-                                                  Ext.DomHelper.insertBefore(me.dom, config, true);        \r
-        \r
-        if(matchBox && me.setBox && me.getBox){ // check to make sure Element.position.js is loaded\r
-           proxy.setBox(me.getBox());\r
-        }\r
-        return proxy;\r
-    }\r
-});\r
-\r
-Ext.Element.prototype.getUpdateManager = Ext.Element.prototype.getUpdater;\r
-\r
-// private\r
-Ext.Element.uncache = function(el){\r
-    for(var i = 0, a = arguments, len = a.length; i < len; i++) {\r
-        if(a[i]){\r
-            delete Ext.Element.cache[a[i].id || a[i]];\r
-        }\r
-    }\r
-};/**\r
- * @class Ext.Element\r
- */\r
-Ext.Element.addMethods({\r
-    /**\r
-     * Gets the x,y coordinates specified by the anchor position on the element.\r
-     * @param {String} anchor (optional) The specified anchor position (defaults to "c").  See {@link #alignTo}\r
-     * for details on supported anchor positions.\r
-     * @param {Boolean} local (optional) True to get the local (element top/left-relative) anchor position instead\r
-     * of page coordinates\r
-     * @param {Object} size (optional) An object containing the size to use for calculating anchor position\r
-     * {width: (target width), height: (target height)} (defaults to the element's current size)\r
-     * @return {Array} [x, y] An array containing the element's x and y coordinates\r
-     */\r
-    getAnchorXY : function(anchor, local, s){\r
-        //Passing a different size is useful for pre-calculating anchors,\r
-        //especially for anchored animations that change the el size.\r
-               anchor = (anchor || "tl").toLowerCase();\r
-        s = s || {};\r
-        \r
-        var me = this,        \r
-               vp = me.dom == document.body || me.dom == document,\r
-               w = s.width || vp ? Ext.lib.Dom.getViewWidth() : me.getWidth(),\r
-               h = s.height || vp ? Ext.lib.Dom.getViewHeight() : me.getHeight(),                              \r
-               xy,             \r
-               r = Math.round,\r
-               o = me.getXY(),\r
-               scroll = me.getScroll(),\r
-               extraX = vp ? scroll.left : !local ? o[0] : 0,\r
-               extraY = vp ? scroll.top : !local ? o[1] : 0,\r
-               hash = {\r
-                       c  : [r(w * 0.5), r(h * 0.5)],\r
-                       t  : [r(w * 0.5), 0],\r
-                       l  : [0, r(h * 0.5)],\r
-                       r  : [w, r(h * 0.5)],\r
-                       b  : [r(w * 0.5), h],\r
-                       tl : [0, 0],    \r
-                       bl : [0, h],\r
-                       br : [w, h],\r
-                       tr : [w, 0]\r
-               };\r
-        \r
-        xy = hash[anchor];     \r
-        return [xy[0] + extraX, xy[1] + extraY]; \r
-    },\r
-\r
-    /**\r
-     * Anchors an element to another element and realigns it when the window is resized.\r
-     * @param {Mixed} element The element to align to.\r
-     * @param {String} position The position to align to.\r
-     * @param {Array} offsets (optional) Offset the positioning by [x, y]\r
-     * @param {Boolean/Object} animate (optional) True for the default animation or a standard Element animation config object\r
-     * @param {Boolean/Number} monitorScroll (optional) True to monitor body scroll and reposition. If this parameter\r
-     * is a number, it is used as the buffer delay (defaults to 50ms).\r
-     * @param {Function} callback The function to call after the animation finishes\r
-     * @return {Ext.Element} this\r
-     */\r
-    anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){        \r
-           var me = this,\r
-            dom = me.dom;\r
-           \r
-           function action(){\r
-            Ext.fly(dom).alignTo(el, alignment, offsets, animate);\r
-            Ext.callback(callback, Ext.fly(dom));\r
-        }\r
-        \r
-        Ext.EventManager.onWindowResize(action, me);\r
-        \r
-        if(!Ext.isEmpty(monitorScroll)){\r
-            Ext.EventManager.on(window, 'scroll', action, me,\r
-                {buffer: !isNaN(monitorScroll) ? monitorScroll : 50});\r
-        }\r
-        action.call(me); // align immediately\r
-        return me;\r
-    },\r
+        },\r
 \r
-    /**\r
-     * Gets the x,y coordinates to align this element with another element. See {@link #alignTo} for more info on the\r
-     * supported position values.\r
-     * @param {Mixed} element The element to align to.\r
-     * @param {String} position The position to align to.\r
-     * @param {Array} offsets (optional) Offset the positioning by [x, y]\r
-     * @return {Array} [x, y]\r
-     */\r
-    getAlignToXY : function(el, p, o){     \r
-        el = Ext.get(el);\r
-        \r
-        if(!el || !el.dom){\r
-            throw "Element.alignToXY with an element that doesn't exist";\r
-        }\r
-        \r
-        o = o || [0,0];\r
-        p = (p == "?" ? "tl-bl?" : (!/-/.test(p) && p !== "" ? "tl-" + p : p || "tl-bl")).toLowerCase();       \r
-                \r
-        var me = this,\r
-               d = me.dom,\r
-               a1,\r
-               a2,\r
-               x,\r
-               y,\r
-               //constrain the aligned el to viewport if necessary\r
-               w,\r
-               h,\r
-               r,\r
-               dw = Ext.lib.Dom.getViewWidth() -10, // 10px of margin for ie\r
-               dh = Ext.lib.Dom.getViewHeight()-10, // 10px of margin for ie\r
-               p1y,\r
-               p1x,            \r
-               p2y,\r
-               p2x,\r
-               swapY,\r
-               swapX,\r
-               doc = document,\r
-               docElement = doc.documentElement,\r
-               docBody = doc.body,\r
-               scrollX = (docElement.scrollLeft || docBody.scrollLeft || 0)+5,\r
-               scrollY = (docElement.scrollTop || docBody.scrollTop || 0)+5,\r
-               c = false, //constrain to viewport\r
-               p1 = "", \r
-               p2 = "",\r
-               m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);\r
-        \r
-        if(!m){\r
-           throw "Element.alignTo with an invalid alignment " + p;\r
-        }\r
-        \r
-        p1 = m[1]; \r
-        p2 = m[2]; \r
-        c = !!m[3];\r
-\r
-        //Subtract the aligned el's internal xy from the target's offset xy\r
-        //plus custom offset to get the aligned el's new offset xy\r
-        a1 = me.getAnchorXY(p1, true);\r
-        a2 = el.getAnchorXY(p2, false);\r
-\r
-        x = a2[0] - a1[0] + o[0];\r
-        y = a2[1] - a1[1] + o[1];\r
-\r
-        if(c){    \r
-              w = me.getWidth();\r
-           h = me.getHeight();\r
-           r = el.getRegion();       \r
-           //If we are at a viewport boundary and the aligned el is anchored on a target border that is\r
-           //perpendicular to the vp border, allow the aligned el to slide on that border,\r
-           //otherwise swap the aligned el to the opposite border of the target.\r
-           p1y = p1.charAt(0);\r
-           p1x = p1.charAt(p1.length-1);\r
-           p2y = p2.charAt(0);\r
-           p2x = p2.charAt(p2.length-1);\r
-           swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));\r
-           swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));          \r
-           \r
-\r
-           if (x + w > dw + scrollX) {\r
-                x = swapX ? r.left-w : dw+scrollX-w;\r
-           }\r
-           if (x < scrollX) {\r
-               x = swapX ? r.right : scrollX;\r
-           }\r
-           if (y + h > dh + scrollY) {\r
-                y = swapY ? r.top-h : dh+scrollY-h;\r
+        /**\r
+         * Prevents the browsers default handling of the event.\r
+         */\r
+        preventDefault : function(){\r
+            if(this.browserEvent){\r
+                E.preventDefault(this.browserEvent);\r
             }\r
-           if (y < scrollY){\r
-               y = swapY ? r.bottom : scrollY;\r
-           }\r
-        }\r
-        return [x,y];\r
-    },\r
-\r
-    /**\r
-     * Aligns this element with another element relative to the specified anchor points. If the other element is the\r
-     * document it aligns it to the viewport.\r
-     * The position parameter is optional, and can be specified in any one of the following formats:\r
-     * <ul>\r
-     *   <li><b>Blank</b>: Defaults to aligning the element's top-left corner to the target's bottom-left corner ("tl-bl").</li>\r
-     *   <li><b>One anchor (deprecated)</b>: The passed anchor position is used as the target element's anchor point.\r
-     *       The element being aligned will position its top-left corner (tl) to that point.  <i>This method has been\r
-     *       deprecated in favor of the newer two anchor syntax below</i>.</li>\r
-     *   <li><b>Two anchors</b>: If two values from the table below are passed separated by a dash, the first value is used as the\r
-     *       element's anchor point, and the second value is used as the target's anchor point.</li>\r
-     * </ul>\r
-     * In addition to the anchor points, the position parameter also supports the "?" character.  If "?" is passed at the end of\r
-     * the position string, the element will attempt to align as specified, but the position will be adjusted to constrain to\r
-     * the viewport if necessary.  Note that the element being aligned might be swapped to align to a different position than\r
-     * that specified in order to enforce the viewport constraints.\r
-     * Following are all of the supported anchor positions:\r
-<pre>\r
-Value  Description\r
------  -----------------------------\r
-tl     The top left corner (default)\r
-t      The center of the top edge\r
-tr     The top right corner\r
-l      The center of the left edge\r
-c      In the center of the element\r
-r      The center of the right edge\r
-bl     The bottom left corner\r
-b      The center of the bottom edge\r
-br     The bottom right corner\r
-</pre>\r
-Example Usage:\r
-<pre><code>\r
-// align el to other-el using the default positioning ("tl-bl", non-constrained)\r
-el.alignTo("other-el");\r
-\r
-// align the top left corner of el with the top right corner of other-el (constrained to viewport)\r
-el.alignTo("other-el", "tr?");\r
-\r
-// align the bottom right corner of el with the center left edge of other-el\r
-el.alignTo("other-el", "br-l?");\r
+        },\r
 \r
-// align the center of el with the bottom left corner of other-el and\r
-// adjust the x position by -6 pixels (and the y position by 0)\r
-el.alignTo("other-el", "c-bl", [-6, 0]);\r
-</code></pre>\r
-     * @param {Mixed} element The element to align to.\r
-     * @param {String} position The position to align to.\r
-     * @param {Array} offsets (optional) Offset the positioning by [x, y]\r
-     * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object\r
-     * @return {Ext.Element} this\r
-     */\r
-    alignTo : function(element, position, offsets, animate){\r
-           var me = this;\r
-        return me.setXY(me.getAlignToXY(element, position, offsets),\r
-                               me.preanim && !!animate ? me.preanim(arguments, 3) : false);\r
-    },\r
-    \r
-    // private ==>  used outside of core\r
-    adjustForConstraints : function(xy, parent, offsets){\r
-        return this.getConstrainToXY(parent || document, false, offsets, xy) ||  xy;\r
-    },\r
+        /**\r
+         * Cancels bubbling of the event.\r
+         */\r
+        stopPropagation : function(){\r
+            var me = this;\r
+            if(me.browserEvent){\r
+                if(me.browserEvent.type == 'mousedown'){\r
+                    Ext.EventManager.stoppedMouseDownEvent.fire(me);\r
+                }\r
+                E.stopPropagation(me.browserEvent);\r
+            }\r
+        },\r
 \r
-    // private ==>  used outside of core\r
-    getConstrainToXY : function(el, local, offsets, proposedXY){   \r
-           var os = {top:0, left:0, bottom:0, right: 0};\r
+        /**\r
+         * Gets the character code for the event.\r
+         * @return {Number}\r
+         */\r
+        getCharCode : function(){\r
+            return this.charCode || this.keyCode;\r
+        },\r
 \r
-        return function(el, local, offsets, proposedXY){\r
-            el = Ext.get(el);\r
-            offsets = offsets ? Ext.applyIf(offsets, os) : os;\r
+        /**\r
+         * Returns a normalized keyCode for the event.\r
+         * @return {Number} The key code\r
+         */\r
+        getKey : function(){\r
+            return this.normalizeKey(this.keyCode || this.charCode)\r
+        },\r
 \r
-            var vw, vh, vx = 0, vy = 0;\r
-            if(el.dom == document.body || el.dom == document){\r
-                vw =Ext.lib.Dom.getViewWidth();\r
-                vh = Ext.lib.Dom.getViewHeight();\r
-            }else{\r
-                vw = el.dom.clientWidth;\r
-                vh = el.dom.clientHeight;\r
-                if(!local){\r
-                    var vxy = el.getXY();\r
-                    vx = vxy[0];\r
-                    vy = vxy[1];\r
-                }\r
-            }\r
+        // private\r
+        normalizeKey: function(k){\r
+            return Ext.isSafari ? (safariKeys[k] || k) : k;\r
+        },\r
 \r
-            var s = el.getScroll();\r
+        /**\r
+         * Gets the x coordinate of the event.\r
+         * @return {Number}\r
+         */\r
+        getPageX : function(){\r
+            return this.xy[0];\r
+        },\r
 \r
-            vx += offsets.left + s.left;\r
-            vy += offsets.top + s.top;\r
+        /**\r
+         * Gets the y coordinate of the event.\r
+         * @return {Number}\r
+         */\r
+        getPageY : function(){\r
+            return this.xy[1];\r
+        },\r
 \r
-            vw -= offsets.right;\r
-            vh -= offsets.bottom;\r
+        /**\r
+         * Gets the page coordinates of the event.\r
+         * @return {Array} The xy values like [x, y]\r
+         */\r
+        getXY : function(){\r
+            return this.xy;\r
+        },\r
 \r
-            var vr = vx+vw;\r
-            var vb = vy+vh;\r
+        /**\r
+         * Gets the target for the event.\r
+         * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target\r
+         * @param {Number/Mixed} maxDepth (optional) The max depth to\r
+                search as a number or element (defaults to 10 || document.body)\r
+         * @param {Boolean} returnEl (optional) True to return a Ext.Element object instead of DOM node\r
+         * @return {HTMLelement}\r
+         */\r
+        getTarget : function(selector, maxDepth, returnEl){\r
+            return selector ? Ext.fly(this.target).findParent(selector, maxDepth, returnEl) : (returnEl ? Ext.get(this.target) : this.target);\r
+        },\r
 \r
-            var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);\r
-            var x = xy[0], y = xy[1];\r
-            var w = this.dom.offsetWidth, h = this.dom.offsetHeight;\r
+        /**\r
+         * Gets the related target.\r
+         * @return {HTMLElement}\r
+         */\r
+        getRelatedTarget : function(){\r
+            return this.browserEvent ? E.getRelatedTarget(this.browserEvent) : null;\r
+        },\r
 \r
-            // only move it if it needs it\r
-            var moved = false;\r
+        /**\r
+         * Normalizes mouse wheel delta across browsers\r
+         * @return {Number} The delta\r
+         */\r
+        getWheelDelta : function(){\r
+            var e = this.browserEvent;\r
+            var delta = 0;\r
+            if(e.wheelDelta){ /* IE/Opera. */\r
+                delta = e.wheelDelta/120;\r
+            }else if(e.detail){ /* Mozilla case. */\r
+                delta = -e.detail/3;\r
+            }\r
+            return delta;\r
+        },\r
 \r
-            // first validate right/bottom\r
-            if((x + w) > vr){\r
-                x = vr - w;\r
-                moved = true;\r
+        /**\r
+        * Returns true if the target of this event is a child of el.  Unless the allowEl parameter is set, it will return false if if the target is el.\r
+        * Example usage:<pre><code>\r
+        // Handle click on any child of an element\r
+        Ext.getBody().on('click', function(e){\r
+            if(e.within('some-el')){\r
+                alert('Clicked on a child of some-el!');\r
             }\r
-            if((y + h) > vb){\r
-                y = vb - h;\r
-                moved = true;\r
+        });\r
+\r
+        // Handle click directly on an element, ignoring clicks on child nodes\r
+        Ext.getBody().on('click', function(e,t){\r
+            if((t.id == 'some-el') && !e.within(t, true)){\r
+                alert('Clicked directly on some-el!');\r
             }\r
-            // then make sure top/left isn't negative\r
-            if(x < vx){\r
-                x = vx;\r
-                moved = true;\r
+        });\r
+        </code></pre>\r
+         * @param {Mixed} el The id, DOM element or Ext.Element to check\r
+         * @param {Boolean} related (optional) true to test if the related target is within el instead of the target\r
+         * @param {Boolean} allowEl {optional} true to also check if the passed element is the target or related target\r
+         * @return {Boolean}\r
+         */\r
+        within : function(el, related, allowEl){\r
+            if(el){\r
+                var t = this[related ? "getRelatedTarget" : "getTarget"]();\r
+                return t && ((allowEl ? (t == Ext.getDom(el)) : false) || Ext.fly(el).contains(t));\r
             }\r
-            if(y < vy){\r
-                y = vy;\r
-                moved = true;\r
-            }\r
-            return moved ? [x, y] : false;\r
-        };\r
-    }(),\r
-           \r
-           \r
-               \r
-//         el = Ext.get(el);\r
-//         offsets = Ext.applyIf(offsets || {}, {top : 0, left : 0, bottom : 0, right : 0});\r
-\r
-//         var me = this,\r
-//             doc = document,\r
-//             s = el.getScroll(),\r
-//             vxy = el.getXY(),\r
-//             vx = offsets.left + s.left, \r
-//             vy = offsets.top + s.top,               \r
-//             vw = -offsets.right, \r
-//             vh = -offsets.bottom, \r
-//             vr,\r
-//             vb,\r
-//             xy = proposedXY || (!local ? me.getXY() : [me.getLeft(true), me.getTop(true)]),\r
-//             x = xy[0],\r
-//             y = xy[1],\r
-//             w = me.dom.offsetWidth, h = me.dom.offsetHeight,\r
-//             moved = false; // only move it if it needs it\r
-//       \r
-//             \r
-//         if(el.dom == doc.body || el.dom == doc){\r
-//             vw += Ext.lib.Dom.getViewWidth();\r
-//             vh += Ext.lib.Dom.getViewHeight();\r
-//         }else{\r
-//             vw += el.dom.clientWidth;\r
-//             vh += el.dom.clientHeight;\r
-//             if(!local){                    \r
-//                 vx += vxy[0];\r
-//                 vy += vxy[1];\r
-//             }\r
-//         }\r
-\r
-//         // first validate right/bottom\r
-//         if(x + w > vx + vw){\r
-//             x = vx + vw - w;\r
-//             moved = true;\r
-//         }\r
-//         if(y + h > vy + vh){\r
-//             y = vy + vh - h;\r
-//             moved = true;\r
-//         }\r
-//         // then make sure top/left isn't negative\r
-//         if(x < vx){\r
-//             x = vx;\r
-//             moved = true;\r
-//         }\r
-//         if(y < vy){\r
-//             y = vy;\r
-//             moved = true;\r
-//         }\r
-//         return moved ? [x, y] : false;\r
-//    },\r
-    \r
-    /**\r
-    * Calculates the x, y to center this element on the screen\r
-    * @return {Array} The x, y values [x, y]\r
-    */\r
-    getCenterXY : function(){\r
-        return this.getAlignToXY(document, 'c-c');\r
-    },\r
+            return false;\r
+        }\r
+     };\r
 \r
-    /**\r
-    * Centers the Element in either the viewport, or another Element.\r
-    * @param {Mixed} centerIn (optional) The element in which to center the element.\r
-    */\r
-    center : function(centerIn){\r
-        return this.alignTo(centerIn || document, 'c-c');        \r
-    }    \r
-});\r
-/**\r
- * @class Ext.Element\r
- */\r
-Ext.Element.addMethods(function(){\r
-       var PARENTNODE = 'parentNode',\r
-               NEXTSIBLING = 'nextSibling',\r
-               PREVIOUSSIBLING = 'previousSibling',\r
-               DQ = Ext.DomQuery,\r
-               GET = Ext.get;\r
-       \r
-       return {\r
-               /**\r
-            * Looks at this node and then at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)\r
-            * @param {String} selector The simple selector to test\r
-            * @param {Number/Mixed} maxDepth (optional) The max depth to search as a number or element (defaults to 50 || document.body)\r
-            * @param {Boolean} returnEl (optional) True to return a Ext.Element object instead of DOM node\r
-            * @return {HTMLElement} The matching DOM node (or null if no match was found)\r
-            */\r
-           findParent : function(simpleSelector, maxDepth, returnEl){\r
-               var p = this.dom,\r
-                       b = document.body, \r
-                       depth = 0,                      \r
-                       stopEl;         \r
-            if(Ext.isGecko && Object.prototype.toString.call(p) == '[object XULElement]') {\r
-                return null;\r
-            }\r
-               maxDepth = maxDepth || 50;\r
-               if (isNaN(maxDepth)) {\r
-                   stopEl = Ext.getDom(maxDepth);\r
-                   maxDepth = Number.MAX_VALUE;\r
-               }\r
-               while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){\r
-                   if(DQ.is(p, simpleSelector)){\r
-                       return returnEl ? GET(p) : p;\r
-                   }\r
-                   depth++;\r
-                   p = p.parentNode;\r
-               }\r
-               return null;\r
-           },\r
-       \r
-           /**\r
-            * Looks at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)\r
-            * @param {String} selector The simple selector to test\r
-            * @param {Number/Mixed} maxDepth (optional) The max depth to\r
-                   search as a number or element (defaults to 10 || document.body)\r
-            * @param {Boolean} returnEl (optional) True to return a Ext.Element object instead of DOM node\r
-            * @return {HTMLElement} The matching DOM node (or null if no match was found)\r
-            */\r
-           findParentNode : function(simpleSelector, maxDepth, returnEl){\r
-               var p = Ext.fly(this.dom.parentNode, '_internal');\r
-               return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;\r
-           },\r
-       \r
-           /**\r
-            * Walks up the dom looking for a parent node that matches the passed simple selector (e.g. div.some-class or span:first-child).\r
-            * This is a shortcut for findParentNode() that always returns an Ext.Element.\r
-            * @param {String} selector The simple selector to test\r
-            * @param {Number/Mixed} maxDepth (optional) The max depth to\r
-                   search as a number or element (defaults to 10 || document.body)\r
-            * @return {Ext.Element} The matching DOM node (or null if no match was found)\r
-            */\r
-           up : function(simpleSelector, maxDepth){\r
-               return this.findParentNode(simpleSelector, maxDepth, true);\r
-           },\r
-       \r
-           /**\r
-            * Creates a {@link Ext.CompositeElement} for child nodes based on the passed CSS selector (the selector should not contain an id).\r
-            * @param {String} selector The CSS selector\r
-            * @param {Boolean} unique (optional) True to create a unique Ext.Element for each child (defaults to false, which creates a single shared flyweight object)\r
-            * @return {CompositeElement/CompositeElementLite} The composite element\r
-            */\r
-           select : function(selector, unique){\r
-               return Ext.Element.select(selector, unique, this.dom);\r
-           },\r
-       \r
-           /**\r
-            * Selects child nodes based on the passed CSS selector (the selector should not contain an id).\r
-            * @param {String} selector The CSS selector\r
-            * @return {Array} An array of the matched nodes\r
-            */\r
-           query : function(selector, unique){\r
-               return DQ.select(selector, this.dom);\r
-           },\r
-       \r
-           /**\r
-            * Selects a single child at any depth below this element based on the passed CSS selector (the selector should not contain an id).\r
-            * @param {String} selector The CSS selector\r
-            * @param {Boolean} returnDom (optional) True to return the DOM node instead of Ext.Element (defaults to false)\r
-            * @return {HTMLElement/Ext.Element} The child Ext.Element (or DOM node if returnDom = true)\r
-            */\r
-           child : function(selector, returnDom){\r
-               var n = DQ.selectNode(selector, this.dom);\r
-               return returnDom ? n : GET(n);\r
-           },\r
-       \r
-           /**\r
-            * Selects a single *direct* child based on the passed CSS selector (the selector should not contain an id).\r
-            * @param {String} selector The CSS selector\r
-            * @param {Boolean} returnDom (optional) True to return the DOM node instead of Ext.Element (defaults to false)\r
-            * @return {HTMLElement/Ext.Element} The child Ext.Element (or DOM node if returnDom = true)\r
-            */\r
-           down : function(selector, returnDom){\r
-               var n = DQ.selectNode(" > " + selector, this.dom);\r
-               return returnDom ? n : GET(n);\r
-           },\r
-       \r
-                /**\r
-            * Gets the parent node for this element, optionally chaining up trying to match a selector\r
-            * @param {String} selector (optional) Find a parent node that matches the passed simple selector\r
-            * @param {Boolean} returnDom (optional) True to return a raw dom node instead of an Ext.Element\r
-            * @return {Ext.Element/HTMLElement} The parent node or null\r
-                */\r
-           parent : function(selector, returnDom){\r
-               return this.matchNode(PARENTNODE, PARENTNODE, selector, returnDom);\r
-           },\r
-       \r
-            /**\r
-            * Gets the next sibling, skipping text nodes\r
-            * @param {String} selector (optional) Find the next sibling that matches the passed simple selector\r
-            * @param {Boolean} returnDom (optional) True to return a raw dom node instead of an Ext.Element\r
-            * @return {Ext.Element/HTMLElement} The next sibling or null\r
-                */\r
-           next : function(selector, returnDom){\r
-               return this.matchNode(NEXTSIBLING, NEXTSIBLING, selector, returnDom);\r
-           },\r
-       \r
-           /**\r
-            * Gets the previous sibling, skipping text nodes\r
-            * @param {String} selector (optional) Find the previous sibling that matches the passed simple selector\r
-            * @param {Boolean} returnDom (optional) True to return a raw dom node instead of an Ext.Element\r
-            * @return {Ext.Element/HTMLElement} The previous sibling or null\r
-                */\r
-           prev : function(selector, returnDom){\r
-               return this.matchNode(PREVIOUSSIBLING, PREVIOUSSIBLING, selector, returnDom);\r
-           },\r
-       \r
-       \r
-           /**\r
-            * Gets the first child, skipping text nodes\r
-            * @param {String} selector (optional) Find the next sibling that matches the passed simple selector\r
-            * @param {Boolean} returnDom (optional) True to return a raw dom node instead of an Ext.Element\r
-            * @return {Ext.Element/HTMLElement} The first child or null\r
-                */\r
-           first : function(selector, returnDom){\r
-               return this.matchNode(NEXTSIBLING, 'firstChild', selector, returnDom);\r
-           },\r
-       \r
-           /**\r
-            * Gets the last child, skipping text nodes\r
-            * @param {String} selector (optional) Find the previous sibling that matches the passed simple selector\r
-            * @param {Boolean} returnDom (optional) True to return a raw dom node instead of an Ext.Element\r
-            * @return {Ext.Element/HTMLElement} The last child or null\r
-                */\r
-           last : function(selector, returnDom){\r
-               return this.matchNode(PREVIOUSSIBLING, 'lastChild', selector, returnDom);\r
-           },\r
-           \r
-           matchNode : function(dir, start, selector, returnDom){\r
-               var n = this.dom[start];\r
-               while(n){\r
-                   if(n.nodeType == 1 && (!selector || DQ.is(n, selector))){\r
-                       return !returnDom ? GET(n) : n;\r
-                   }\r
-                   n = n[dir];\r
-               }\r
-               return null;\r
-           }   \r
-    }\r
-}());/**\r
- * @class Ext.Element\r
- */\r
-Ext.Element.addMethods(\r
-function() {\r
-       var GETDOM = Ext.getDom,\r
-               GET = Ext.get,\r
-               DH = Ext.DomHelper;\r
-       \r
-       return {\r
-           /**\r
-            * Appends the passed element(s) to this element\r
-            * @param {String/HTMLElement/Array/Element/CompositeElement} el\r
-            * @return {Ext.Element} this\r
-            */\r
-           appendChild: function(el){        \r
-               return GET(el).appendTo(this);        \r
-           },\r
-       \r
-           /**\r
-            * Appends this element to the passed element\r
-            * @param {Mixed} el The new parent element\r
-            * @return {Ext.Element} this\r
-            */\r
-           appendTo: function(el){        \r
-               GETDOM(el).appendChild(this.dom);        \r
-               return this;\r
-           },\r
-       \r
-           /**\r
-            * Inserts this element before the passed element in the DOM\r
-            * @param {Mixed} el The element before which this element will be inserted\r
-            * @return {Ext.Element} this\r
-            */\r
-           insertBefore: function(el){                   \r
-               (el = GETDOM(el)).parentNode.insertBefore(this.dom, el);\r
-               return this;\r
-           },\r
-       \r
-           /**\r
-            * Inserts this element after the passed element in the DOM\r
-            * @param {Mixed} el The element to insert after\r
-            * @return {Ext.Element} this\r
-            */\r
-           insertAfter: function(el){\r
-               (el = GETDOM(el)).parentNode.insertBefore(this.dom, el.nextSibling);\r
-               return this;\r
-           },\r
-       \r
-           /**\r
-            * Inserts (or creates) an element (or DomHelper config) as the first child of this element\r
-            * @param {Mixed/Object} el The id or element to insert or a DomHelper config to create and insert\r
-            * @return {Ext.Element} The new child\r
-            */\r
-           insertFirst: function(el, returnDom){\r
-            el = el || {};\r
-            if(el.nodeType || el.dom || typeof el == 'string'){ // element\r
-                el = GETDOM(el);\r
-                this.dom.insertBefore(el, this.dom.firstChild);\r
-                return !returnDom ? GET(el) : el;\r
-            }else{ // dh config\r
-                return this.createChild(el, this.dom.firstChild, returnDom);\r
-            }\r
-        },\r
-       \r
-           /**\r
-            * Replaces the passed element with this element\r
-            * @param {Mixed} el The element to replace\r
-            * @return {Ext.Element} this\r
-            */\r
-           replace: function(el){\r
-               el = GET(el);\r
-               this.insertBefore(el);\r
-               el.remove();\r
-               return this;\r
-           },\r
-       \r
-           /**\r
-            * Replaces this element with the passed element\r
-            * @param {Mixed/Object} el The new element or a DomHelper config of an element to create\r
-            * @return {Ext.Element} this\r
-            */\r
-           replaceWith: function(el){\r
-                   var me = this,\r
-                       Element = Ext.Element;\r
-            if(el.nodeType || el.dom || typeof el == 'string'){\r
-                el = GETDOM(el);\r
-                me.dom.parentNode.insertBefore(el, me.dom);\r
-            }else{\r
-                el = DH.insertBefore(me.dom, el);\r
-            }\r
-               \r
-               delete Element.cache[me.id];\r
-               Ext.removeNode(me.dom);      \r
-               me.id = Ext.id(me.dom = el);\r
-               return Element.cache[me.id] = me;        \r
-           },\r
-           \r
-               /**\r
-                * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.\r
-                * @param {Object} config DomHelper element config object.  If no tag is specified (e.g., {tag:'input'}) then a div will be\r
-                * automatically generated with the specified attributes.\r
-                * @param {HTMLElement} insertBefore (optional) a child element of this element\r
-                * @param {Boolean} returnDom (optional) true to return the dom node instead of creating an Element\r
-                * @return {Ext.Element} The new child element\r
-                */\r
-               createChild: function(config, insertBefore, returnDom){\r
-                   config = config || {tag:'div'};\r
-                   return insertBefore ? \r
-                          DH.insertBefore(insertBefore, config, returnDom !== true) :  \r
-                          DH[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config,  returnDom !== true);\r
-               },\r
-               \r
-               /**\r
-                * Creates and wraps this element with another element\r
-                * @param {Object} config (optional) DomHelper element config object for the wrapper element or null for an empty div\r
-                * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Ext.Element\r
-                * @return {HTMLElement/Element} The newly created wrapper element\r
-                */\r
-               wrap: function(config, returnDom){        \r
-                   var newEl = DH.insertBefore(this.dom, config || {tag: "div"}, !returnDom);\r
-                   newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);\r
-                   return newEl;\r
-               },\r
-               \r
-               /**\r
-                * Inserts an html fragment into this element\r
-                * @param {String} where Where to insert the html in relation to this element - beforeBegin, afterBegin, beforeEnd, afterEnd.\r
-                * @param {String} html The HTML fragment\r
-                * @param {Boolean} returnEl (optional) True to return an Ext.Element (defaults to false)\r
-                * @return {HTMLElement/Ext.Element} The inserted node (or nearest related if more than 1 inserted)\r
-                */\r
-               insertHtml : function(where, html, returnEl){\r
-                   var el = DH.insertHtml(where, this.dom, html);\r
-                   return returnEl ? Ext.get(el) : el;\r
-               }\r
-       }\r
-}());/**\r
- * @class Ext.Element\r
- */\r
-Ext.apply(Ext.Element.prototype, function() {\r
-       var GETDOM = Ext.getDom,\r
-               GET = Ext.get,\r
-               DH = Ext.DomHelper;\r
-       \r
-       return {        \r
-               /**\r
-            * Inserts (or creates) the passed element (or DomHelper config) as a sibling of this element\r
-            * @param {Mixed/Object/Array} el The id, element to insert or a DomHelper config to create and insert *or* an array of any of those.\r
-            * @param {String} where (optional) 'before' or 'after' defaults to before\r
-            * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Ext.Element\r
-            * @return {Ext.Element} the inserted Element\r
-            */\r
-           insertSibling: function(el, where, returnDom){\r
-               var me = this,\r
-                       rt;\r
-                       \r
-               if(Ext.isArray(el)){            \r
-                   Ext.each(el, function(e) {\r
-                           rt = me.insertSibling(e, where, returnDom);\r
-                   });\r
-                   return rt;\r
-               }\r
-                       \r
-               where = (where || 'before').toLowerCase();\r
-               el = el || {};\r
-               \r
-            if(el.nodeType || el.dom){\r
-                rt = me.dom.parentNode.insertBefore(GETDOM(el), where == 'before' ? me.dom : me.dom.nextSibling);\r
-                if (!returnDom) {\r
-                    rt = GET(rt);\r
-                }\r
-            }else{\r
-                if (where == 'after' && !me.dom.nextSibling) {\r
-                    rt = DH.append(me.dom.parentNode, el, !returnDom);\r
-                } else {                    \r
-                    rt = DH[where == 'after' ? 'insertAfter' : 'insertBefore'](me.dom, el, !returnDom);\r
-                }\r
-            }\r
-               return rt;\r
-           }\r
-    };\r
-}());/**
+    return new Ext.EventObjectImpl();\r
+}();\r
+/**
+* @class Ext.EventManager
+*/
+Ext.apply(Ext.EventManager, function(){
+   var resizeEvent,
+       resizeTask,
+       textEvent,
+       textSize,
+       D = Ext.lib.Dom,
+       propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,
+       curWidth = 0,
+       curHeight = 0,
+       // note 1: IE fires ONLY the keydown event on specialkey autorepeat
+       // note 2: Safari < 3.1, Gecko (Mac/Linux) & Opera fire only the keypress event on specialkey autorepeat
+       // (research done by @Jan Wolter at http://unixpapa.com/js/key.html)
+       useKeydown = Ext.isWebKit ?
+                   Ext.num(navigator.userAgent.match(/AppleWebKit\/(\d+)/)[1]) >= 525 :
+                   !((Ext.isGecko && !Ext.isWindows) || Ext.isOpera);
+
+   return {
+       // private
+       doResizeEvent: function(){
+           var h = D.getViewHeight(),
+               w = D.getViewWidth();
+
+            //whacky problem in IE where the resize event will fire even though the w/h are the same.
+            if(curHeight != h || curWidth != w){
+               resizeEvent.fire(curWidth = w, curHeight = h);
+            }
+       },
+
+       /**
+        * Adds a listener to be notified when the browser window is resized and provides resize event buffering (100 milliseconds),
+        * passes new viewport width and height to handlers.
+        * @param {Function} fn      The handler function the window resize event invokes.
+        * @param {Object}   scope   The scope (<code>this</code> reference) in which the handler function executes. Defaults to the browser window.
+        * @param {boolean}  options Options object as passed to {@link Ext.Element#addListener}
+        */
+       onWindowResize : function(fn, scope, options){
+           if(!resizeEvent){
+               resizeEvent = new Ext.util.Event();
+               resizeTask = new Ext.util.DelayedTask(this.doResizeEvent);
+               Ext.EventManager.on(window, "resize", this.fireWindowResize, this);
+           }
+           resizeEvent.addListener(fn, scope, options);
+       },
+
+       // exposed only to allow manual firing
+       fireWindowResize : function(){
+           if(resizeEvent){
+               resizeTask.delay(100);
+           }
+       },
+
+       /**
+        * Adds a listener to be notified when the user changes the active text size. Handler gets called with 2 params, the old size and the new size.
+        * @param {Function} fn      The function the event invokes.
+        * @param {Object}   scope   The scope (<code>this</code> reference) in which the handler function executes. Defaults to the browser window.
+        * @param {boolean}  options Options object as passed to {@link Ext.Element#addListener}
+        */
+       onTextResize : function(fn, scope, options){
+           if(!textEvent){
+               textEvent = new Ext.util.Event();
+               var textEl = new Ext.Element(document.createElement('div'));
+               textEl.dom.className = 'x-text-resize';
+               textEl.dom.innerHTML = 'X';
+               textEl.appendTo(document.body);
+               textSize = textEl.dom.offsetHeight;
+               setInterval(function(){
+                   if(textEl.dom.offsetHeight != textSize){
+                       textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
+                   }
+               }, this.textResizeInterval);
+           }
+           textEvent.addListener(fn, scope, options);
+       },
+
+       /**
+        * Removes the passed window resize listener.
+        * @param {Function} fn        The method the event invokes
+        * @param {Object}   scope    The scope of handler
+        */
+       removeResizeListener : function(fn, scope){
+           if(resizeEvent){
+               resizeEvent.removeListener(fn, scope);
+           }
+       },
+
+       // private
+       fireResize : function(){
+           if(resizeEvent){
+               resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
+           }
+       },
+
+        /**
+        * The frequency, in milliseconds, to check for text resize events (defaults to 50)
+        */
+       textResizeInterval : 50,
+
+       /**
+        * Url used for onDocumentReady with using SSL (defaults to Ext.SSL_SECURE_URL)
+        */
+       ieDeferSrc : false,
+
+       // protected for use inside the framework
+       // detects whether we should use keydown or keypress based on the browser.
+       useKeydown: useKeydown
+   };
+}());
+
+Ext.EventManager.on = Ext.EventManager.addListener;
+
+
+Ext.apply(Ext.EventObjectImpl.prototype, {
+   /** Key constant @type Number */
+   BACKSPACE: 8,
+   /** Key constant @type Number */
+   TAB: 9,
+   /** Key constant @type Number */
+   NUM_CENTER: 12,
+   /** Key constant @type Number */
+   ENTER: 13,
+   /** Key constant @type Number */
+   RETURN: 13,
+   /** Key constant @type Number */
+   SHIFT: 16,
+   /** Key constant @type Number */
+   CTRL: 17,
+   CONTROL : 17, // legacy
+   /** Key constant @type Number */
+   ALT: 18,
+   /** Key constant @type Number */
+   PAUSE: 19,
+   /** Key constant @type Number */
+   CAPS_LOCK: 20,
+   /** Key constant @type Number */
+   ESC: 27,
+   /** Key constant @type Number */
+   SPACE: 32,
+   /** Key constant @type Number */
+   PAGE_UP: 33,
+   PAGEUP : 33, // legacy
+   /** Key constant @type Number */
+   PAGE_DOWN: 34,
+   PAGEDOWN : 34, // legacy
+   /** Key constant @type Number */
+   END: 35,
+   /** Key constant @type Number */
+   HOME: 36,
+   /** Key constant @type Number */
+   LEFT: 37,
+   /** Key constant @type Number */
+   UP: 38,
+   /** Key constant @type Number */
+   RIGHT: 39,
+   /** Key constant @type Number */
+   DOWN: 40,
+   /** Key constant @type Number */
+   PRINT_SCREEN: 44,
+   /** Key constant @type Number */
+   INSERT: 45,
+   /** Key constant @type Number */
+   DELETE: 46,
+   /** Key constant @type Number */
+   ZERO: 48,
+   /** Key constant @type Number */
+   ONE: 49,
+   /** Key constant @type Number */
+   TWO: 50,
+   /** Key constant @type Number */
+   THREE: 51,
+   /** Key constant @type Number */
+   FOUR: 52,
+   /** Key constant @type Number */
+   FIVE: 53,
+   /** Key constant @type Number */
+   SIX: 54,
+   /** Key constant @type Number */
+   SEVEN: 55,
+   /** Key constant @type Number */
+   EIGHT: 56,
+   /** Key constant @type Number */
+   NINE: 57,
+   /** Key constant @type Number */
+   A: 65,
+   /** Key constant @type Number */
+   B: 66,
+   /** Key constant @type Number */
+   C: 67,
+   /** Key constant @type Number */
+   D: 68,
+   /** Key constant @type Number */
+   E: 69,
+   /** Key constant @type Number */
+   F: 70,
+   /** Key constant @type Number */
+   G: 71,
+   /** Key constant @type Number */
+   H: 72,
+   /** Key constant @type Number */
+   I: 73,
+   /** Key constant @type Number */
+   J: 74,
+   /** Key constant @type Number */
+   K: 75,
+   /** Key constant @type Number */
+   L: 76,
+   /** Key constant @type Number */
+   M: 77,
+   /** Key constant @type Number */
+   N: 78,
+   /** Key constant @type Number */
+   O: 79,
+   /** Key constant @type Number */
+   P: 80,
+   /** Key constant @type Number */
+   Q: 81,
+   /** Key constant @type Number */
+   R: 82,
+   /** Key constant @type Number */
+   S: 83,
+   /** Key constant @type Number */
+   T: 84,
+   /** Key constant @type Number */
+   U: 85,
+   /** Key constant @type Number */
+   V: 86,
+   /** Key constant @type Number */
+   W: 87,
+   /** Key constant @type Number */
+   X: 88,
+   /** Key constant @type Number */
+   Y: 89,
+   /** Key constant @type Number */
+   Z: 90,
+   /** Key constant @type Number */
+   CONTEXT_MENU: 93,
+   /** Key constant @type Number */
+   NUM_ZERO: 96,
+   /** Key constant @type Number */
+   NUM_ONE: 97,
+   /** Key constant @type Number */
+   NUM_TWO: 98,
+   /** Key constant @type Number */
+   NUM_THREE: 99,
+   /** Key constant @type Number */
+   NUM_FOUR: 100,
+   /** Key constant @type Number */
+   NUM_FIVE: 101,
+   /** Key constant @type Number */
+   NUM_SIX: 102,
+   /** Key constant @type Number */
+   NUM_SEVEN: 103,
+   /** Key constant @type Number */
+   NUM_EIGHT: 104,
+   /** Key constant @type Number */
+   NUM_NINE: 105,
+   /** Key constant @type Number */
+   NUM_MULTIPLY: 106,
+   /** Key constant @type Number */
+   NUM_PLUS: 107,
+   /** Key constant @type Number */
+   NUM_MINUS: 109,
+   /** Key constant @type Number */
+   NUM_PERIOD: 110,
+   /** Key constant @type Number */
+   NUM_DIVISION: 111,
+   /** Key constant @type Number */
+   F1: 112,
+   /** Key constant @type Number */
+   F2: 113,
+   /** Key constant @type Number */
+   F3: 114,
+   /** Key constant @type Number */
+   F4: 115,
+   /** Key constant @type Number */
+   F5: 116,
+   /** Key constant @type Number */
+   F6: 117,
+   /** Key constant @type Number */
+   F7: 118,
+   /** Key constant @type Number */
+   F8: 119,
+   /** Key constant @type Number */
+   F9: 120,
+   /** Key constant @type Number */
+   F10: 121,
+   /** Key constant @type Number */
+   F11: 122,
+   /** Key constant @type Number */
+   F12: 123,
+
+   /** @private */
+   isNavKeyPress : function(){
+       var me = this,
+           k = this.normalizeKey(me.keyCode);
+       return (k >= 33 && k <= 40) ||  // Page Up/Down, End, Home, Left, Up, Right, Down
+       k == me.RETURN ||
+       k == me.TAB ||
+       k == me.ESC;
+   },
+
+   isSpecialKey : function(){
+       var k = this.normalizeKey(this.keyCode);
+       return (this.type == 'keypress' && this.ctrlKey) ||
+       this.isNavKeyPress() ||
+       (k == this.BACKSPACE) || // Backspace
+       (k >= 16 && k <= 20) || // Shift, Ctrl, Alt, Pause, Caps Lock
+       (k >= 44 && k <= 45);   // Print Screen, Insert
+   },
+
+   getPoint : function(){
+       return new Ext.lib.Point(this.xy[0], this.xy[1]);
+   },
+
+   /**
+    * Returns true if the control, meta, shift or alt key was pressed during this event.
+    * @return {Boolean}
+    */
+   hasModifier : function(){
+       return ((this.ctrlKey || this.altKey) || this.shiftKey);
+   }
+});/**
  * @class Ext.Element
+ * <p>Encapsulates a DOM element, adding simple DOM manipulation facilities, normalizing for browser differences.</p>
+ * <p>All instances of this class inherit the methods of {@link Ext.Fx} making visual effects easily available to all DOM elements.</p>
+ * <p>Note that the events documented in this class are not Ext events, they encapsulate browser events. To
+ * access the underlying browser event, see {@link Ext.EventObject#browserEvent}. Some older
+ * browsers may not support the full range of events. Which events are supported is beyond the control of ExtJs.</p>
+ * Usage:<br>
+<pre><code>
+// by id
+var el = Ext.get("my-div");
+
+// by DOM element reference
+var el = Ext.get(myDivElement);
+</code></pre>
+ * <b>Animations</b><br />
+ * <p>When an element is manipulated, by default there is no animation.</p>
+ * <pre><code>
+var el = Ext.get("my-div");
+
+// no animation
+el.setWidth(100);
+ * </code></pre>
+ * <p>Many of the functions for manipulating an element have an optional "animate" parameter.  This
+ * parameter can be specified as boolean (<tt>true</tt>) for default animation effects.</p>
+ * <pre><code>
+// default animation
+el.setWidth(100, true);
+ * </code></pre>
+ *
+ * <p>To configure the effects, an object literal with animation options to use as the Element animation
+ * configuration object can also be specified. Note that the supported Element animation configuration
+ * options are a subset of the {@link Ext.Fx} animation options specific to Fx effects.  The supported
+ * Element animation configuration options are:</p>
+<pre>
+Option    Default   Description
+--------- --------  ---------------------------------------------
+{@link Ext.Fx#duration duration}  .35       The duration of the animation in seconds
+{@link Ext.Fx#easing easing}    easeOut   The easing method
+{@link Ext.Fx#callback callback}  none      A function to execute when the anim completes
+{@link Ext.Fx#scope scope}     this      The scope (this) of the callback function
+</pre>
+ *
+ * <pre><code>
+// Element animation options object
+var opt = {
+    {@link Ext.Fx#duration duration}: 1,
+    {@link Ext.Fx#easing easing}: 'elasticIn',
+    {@link Ext.Fx#callback callback}: this.foo,
+    {@link Ext.Fx#scope scope}: this
+};
+// animation with some options set
+el.setWidth(100, opt);
+ * </code></pre>
+ * <p>The Element animation object being used for the animation will be set on the options
+ * object as "anim", which allows you to stop or manipulate the animation. Here is an example:</p>
+ * <pre><code>
+// using the "anim" property to get the Anim object
+if(opt.anim.isAnimated()){
+    opt.anim.stop();
+}
+ * </code></pre>
+ * <p>Also see the <tt>{@link #animate}</tt> method for another animation technique.</p>
+ * <p><b> Composite (Collections of) Elements</b></p>
+ * <p>For working with collections of Elements, see {@link Ext.CompositeElement}</p>
+ * @constructor Create a new Element directly.
+ * @param {String/HTMLElement} element
+ * @param {Boolean} forceNew (optional) By default the constructor checks to see if there is already an instance of this element in the cache and if there is it returns the same instance. This will skip that check (useful for extending this class).
  */
-Ext.Element.addMethods(function(){  
-    // local style camelizing for speed
-    var propCache = {},
-        camelRe = /(-[a-z])/gi,
-        classReCache = {},
-        view = document.defaultView,
-        propFloat = Ext.isIE ? 'styleFloat' : 'cssFloat',
-        opacityRe = /alpha\(opacity=(.*)\)/i,
-        trimRe = /^\s+|\s+$/g,
-        EL = Ext.Element,   
-        PADDING = "padding",
-        MARGIN = "margin",
-        BORDER = "border",
-        LEFT = "-left",
-        RIGHT = "-right",
-        TOP = "-top",
-        BOTTOM = "-bottom",
-        WIDTH = "-width",    
-        MATH = Math,
-        HIDDEN = 'hidden',
-        ISCLIPPED = 'isClipped',
-        OVERFLOW = 'overflow',
-        OVERFLOWX = 'overflow-x',
-        OVERFLOWY = 'overflow-y',
-        ORIGINALCLIP = 'originalClip',
-        // special markup used throughout Ext when box wrapping elements    
-        borders = {l: BORDER + LEFT + WIDTH, r: BORDER + RIGHT + WIDTH, t: BORDER + TOP + WIDTH, b: BORDER + BOTTOM + WIDTH},
-        paddings = {l: PADDING + LEFT, r: PADDING + RIGHT, t: PADDING + TOP, b: PADDING + BOTTOM},
-        margins = {l: MARGIN + LEFT, r: MARGIN + RIGHT, t: MARGIN + TOP, b: MARGIN + BOTTOM},
-        data = Ext.Element.data;
-        
-    
-    // private  
-    function camelFn(m, a) {
-        return a.charAt(1).toUpperCase();
-    }
-    
-    function chkCache(prop) {
-        return propCache[prop] || (propCache[prop] = prop == 'float' ? propFloat : prop.replace(camelRe, camelFn));
+(function(){
+var DOC = document;
+
+Ext.Element = function(element, forceNew){
+    var dom = typeof element == "string" ?
+              DOC.getElementById(element) : element,
+        id;
+
+    if(!dom) return null;
+
+    id = dom.id;
+
+    if(!forceNew && id && Ext.elCache[id]){ // element object already exists
+        return Ext.elCache[id].el;
     }
-            
-    return {
-        // private  ==> used by Fx  
-        adjustWidth : function(width) {
-            var me = this;
-            var isNum = Ext.isNumber(width);
-            if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
-               width -= (me.getBorderWidth("lr") + me.getPadding("lr"));
-            }
-            return (isNum && width < 0) ? 0 : width;
-        },
-        
-        // private   ==> used by Fx 
-        adjustHeight : function(height) {
-            var me = this;
-            var isNum = Ext.isNumber(height);
-            if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
-               height -= (me.getBorderWidth("tb") + me.getPadding("tb"));               
-            }
-            return (isNum && height < 0) ? 0 : height;
-        },
-    
-    
-        /**
-         * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
-         * @param {String/Array} className The CSS class to add, or an array of classes
-         * @return {Ext.Element} this
-         */
-        addClass : function(className){
-            var me = this;
-            Ext.each(className, function(v) {
-                me.dom.className += (!me.hasClass(v) && v ? " " + v : "");  
-            });
-            return me;
-        },
-    
-        /**
-         * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
-         * @param {String/Array} className The CSS class to add, or an array of classes
-         * @return {Ext.Element} this
-         */
-        radioClass : function(className){
-            Ext.each(this.dom.parentNode.childNodes, function(v) {
-                if(v.nodeType == 1) {
-                    Ext.fly(v, '_internal').removeClass(className);          
+
+    /**
+     * The DOM element
+     * @type HTMLElement
+     */
+    this.dom = dom;
+
+    /**
+     * The DOM element ID
+     * @type String
+     */
+    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,
+    EC = Ext.elCache;
+
+El.prototype = {
+    /**
+     * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)
+     * @param {Object} o The object with the attributes
+     * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.
+     * @return {Ext.Element} this
+     */
+    set : function(o, useSet){
+        var el = this.dom,
+            attr,
+            val,
+            useSet = (useSet !== false) && !!el.setAttribute;
+
+        for(attr in o){
+            if (o.hasOwnProperty(attr)) {
+                val = o[attr];
+                if (attr == 'style') {
+                    DH.applyStyles(el, val);
+                } else if (attr == 'cls') {
+                    el.className = val;
+                } else if (useSet) {
+                    el.setAttribute(attr, val);
+                } else {
+                    el[attr] = val;
                 }
-            });
-            return this.addClass(className);
-        },
-    
-        /**
-         * Removes one or more CSS classes from the element.
-         * @param {String/Array} className The CSS class to remove, or an array of classes
-         * @return {Ext.Element} this
-         */
-        removeClass : function(className){
-            var me = this;
-            if (me.dom && me.dom.className) {
-                Ext.each(className, function(v) {               
-                    me.dom.className = me.dom.className.replace(
-                        classReCache[v] = classReCache[v] || new RegExp('(?:^|\\s+)' + v + '(?:\\s+|$)', "g"), 
-                        " ");               
-                });    
             }
-            return me;
-        },
-    
-        /**
-         * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
-         * @param {String} className The CSS class to toggle
-         * @return {Ext.Element} this
-         */
-        toggleClass : function(className){
-            return this.hasClass(className) ? this.removeClass(className) : this.addClass(className);
-        },
-    
-        /**
-         * Checks if the specified CSS class exists on this element's DOM node.
-         * @param {String} className The CSS class to check for
-         * @return {Boolean} True if the class exists, else false
-         */
-        hasClass : function(className){
-            return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
-        },
-    
-        /**
-         * Replaces a CSS class on the element with another.  If the old name does not exist, the new name will simply be added.
-         * @param {String} oldClassName The CSS class to replace
-         * @param {String} newClassName The replacement CSS class
-         * @return {Ext.Element} this
-         */
-        replaceClass : function(oldClassName, newClassName){
-            return this.removeClass(oldClassName).addClass(newClassName);
-        },
-        
-        isStyle : function(style, val) {
-            return this.getStyle(style) == val;  
-        },
-    
-        /**
-         * Normalizes currentStyle and computedStyle.
-         * @param {String} property The style property whose value is returned.
-         * @return {String} The current value of the style property for this element.
-         */
-        getStyle : function(){         
-            return view && view.getComputedStyle ?
-                function(prop){
-                    var el = this.dom,
-                        v,                  
-                        cs,
-                        out;
-                    if(el == document) return null;
-                    prop = chkCache(prop);
-                    out = (v = el.style[prop]) ? v : 
-                           (cs = view.getComputedStyle(el, "")) ? cs[prop] : null;
-                    
-                    // Webkit returns rgb values for transparent.
-                    if(Ext.isWebKit && out == 'rgba(0, 0, 0, 0)'){
-                        out = 'transparent';
-                    }
-                    return out;
-                } :
-                function(prop){      
-                    var el = this.dom, 
-                        m, 
-                        cs;     
-                        
-                    if(el == document) return null;      
-                    if (prop == 'opacity') {
-                        if (el.style.filter.match) {                       
-                            if(m = el.style.filter.match(opacityRe)){
-                                var fv = parseFloat(m[1]);
-                                if(!isNaN(fv)){
-                                    return fv ? fv / 100 : 0;
-                                }
-                            }
-                        }
-                        return 1;
-                    }
-                    prop = chkCache(prop);  
-                    return el.style[prop] || ((cs = el.currentStyle) ? cs[prop] : null);
-                };
-        }(),
+        }
+        return this;
+    },
 
-        /**
-         * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
-         * are convert to standard 6 digit hex color.
-         * @param {String} attr The css attribute
-         * @param {String} defaultValue The default value to use when a valid color isn't found
-         * @param {String} prefix (optional) defaults to #. Use an empty string when working with
-         * color anims.
-         */
-        getColor : function(attr, defaultValue, prefix){
-            var v = this.getStyle(attr),
-                color = Ext.isDefined(prefix) ? prefix : '#',
-                h;
-                
-            if(!v || /transparent|inherit/.test(v)){
-                return defaultValue;
-            }
-            if(/^r/.test(v)){
-                Ext.each(v.slice(4, v.length -1).split(','), function(s){
-                    h = parseInt(s, 10);
-                    color += (h < 16 ? '0' : '') + h.toString(16); 
-                });
+//  Mouse events
+    /**
+     * @event click
+     * Fires when a mouse click is detected within the element.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event contextmenu
+     * Fires when a right click is detected within the element.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event dblclick
+     * Fires when a mouse double click is detected within the element.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event mousedown
+     * Fires when a mousedown is detected within the element.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event mouseup
+     * Fires when a mouseup is detected within the element.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event mouseover
+     * Fires when a mouseover is detected within the element.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event mousemove
+     * Fires when a mousemove is detected with the element.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event mouseout
+     * Fires when a mouseout is detected with the element.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event mouseenter
+     * Fires when the mouse enters the element.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event mouseleave
+     * Fires when the mouse leaves the element.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+
+//  Keyboard events
+    /**
+     * @event keypress
+     * Fires when a keypress is detected within the element.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event keydown
+     * Fires when a keydown is detected within the element.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event keyup
+     * Fires when a keyup is detected within the element.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+
+
+//  HTML frame/object events
+    /**
+     * @event load
+     * Fires when the user agent finishes loading all content within the element. Only supported by window, frames, objects and images.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event unload
+     * Fires when the user agent removes all content from a window or frame. For elements, it fires when the target element or any of its content has been removed.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event abort
+     * Fires when an object/image is stopped from loading before completely loaded.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event error
+     * Fires when an object/image/frame cannot be loaded properly.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event resize
+     * Fires when a document view is resized.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event scroll
+     * Fires when a document view is scrolled.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+
+//  Form events
+    /**
+     * @event select
+     * Fires when a user selects some text in a text field, including input and textarea.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event change
+     * Fires when a control loses the input focus and its value has been modified since gaining focus.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event submit
+     * Fires when a form is submitted.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event reset
+     * Fires when a form is reset.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event focus
+     * Fires when an element receives focus either via the pointing device or by tab navigation.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event blur
+     * Fires when an element loses focus either via the pointing device or by tabbing navigation.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+
+//  User Interface events
+    /**
+     * @event DOMFocusIn
+     * Where supported. Similar to HTML focus event, but can be applied to any focusable element.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event DOMFocusOut
+     * Where supported. Similar to HTML blur event, but can be applied to any focusable element.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event DOMActivate
+     * Where supported. Fires when an element is activated, for instance, through a mouse click or a keypress.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+
+//  DOM Mutation events
+    /**
+     * @event DOMSubtreeModified
+     * Where supported. Fires when the subtree is modified.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event DOMNodeInserted
+     * Where supported. Fires when a node has been added as a child of another node.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event DOMNodeRemoved
+     * Where supported. Fires when a descendant node of the element is removed.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event DOMNodeRemovedFromDocument
+     * Where supported. Fires when a node is being removed from a document.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event DOMNodeInsertedIntoDocument
+     * Where supported. Fires when a node is being inserted into a document.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event DOMAttrModified
+     * Where supported. Fires when an attribute has been modified.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+    /**
+     * @event DOMCharacterDataModified
+     * Where supported. Fires when the character data has been modified.
+     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
+     * @param {HtmlElement} t The target of the event.
+     * @param {Object} o The options configuration passed to the {@link #addListener} call.
+     */
+
+    /**
+     * The default unit to append to CSS values where a unit isn't provided (defaults to px).
+     * @type String
+     */
+    defaultUnit : "px",
+
+    /**
+     * Returns true if this element matches the passed simple selector (e.g. div.some-class or span:first-child)
+     * @param {String} selector The simple selector to test
+     * @return {Boolean} True if this element matches the selector, else false
+     */
+    is : function(simpleSelector){
+        return Ext.DomQuery.is(this.dom, simpleSelector);
+    },
+
+    /**
+     * Tries to focus the element. Any exceptions are caught and ignored.
+     * @param {Number} defer (optional) Milliseconds to defer the focus
+     * @return {Ext.Element} this
+     */
+    focus : function(defer, /* private */ dom) {
+        var me = this,
+            dom = dom || me.dom;
+        try{
+            if(Number(defer)){
+                me.focus.defer(defer, null, [null, dom]);
             }else{
-                v = v.replace('#', '');
-                color += v.length == 3 ? v.replace(/^(\w)(\w)(\w)$/, '$1$1$2$2$3$3') : v;
+                dom.focus();
             }
-            return(color.length > 5 ? color.toLowerCase() : defaultValue);
-        },
-    
-        /**
-         * Wrapper for setting style properties, also takes single object parameter of multiple styles.
-         * @param {String/Object} property The style property to be set, or an object of multiple styles.
-         * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
-         * @return {Ext.Element} this
-         */
-        setStyle : function(prop, value){
-            var tmp, 
-                style,
-                camel;
-            if (!Ext.isObject(prop)) {
-                tmp = {};
-                tmp[prop] = value;          
-                prop = tmp;
+        }catch(e){}
+        return me;
+    },
+
+    /**
+     * Tries to blur the element. Any exceptions are caught and ignored.
+     * @return {Ext.Element} this
+     */
+    blur : function() {
+        try{
+            this.dom.blur();
+        }catch(e){}
+        return this;
+    },
+
+    /**
+     * Returns the value of the "value" attribute
+     * @param {Boolean} asNumber true to parse the value as a number
+     * @return {String/Number}
+     */
+    getValue : function(asNumber){
+        var val = this.dom.value;
+        return asNumber ? parseInt(val, 10) : val;
+    },
+
+    /**
+     * Appends an event handler to this element.  The shorthand version {@link #on} is equivalent.
+     * @param {String} eventName The name of event to handle.
+     * @param {Function} fn The handler function the event invokes. This function is passed
+     * the following parameters:<ul>
+     * <li><b>evt</b> : EventObject<div class="sub-desc">The {@link Ext.EventObject EventObject} describing the event.</div></li>
+     * <li><b>el</b> : HtmlElement<div class="sub-desc">The DOM element which was the target of the event.
+     * Note that this may be filtered by using the <tt>delegate</tt> option.</div></li>
+     * <li><b>o</b> : Object<div class="sub-desc">The options object from the addListener call.</div></li>
+     * </ul>
+     * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the handler function is executed.
+     * <b>If omitted, defaults to this Element.</b>.
+     * @param {Object} options (optional) An object containing handler configuration properties.
+     * This may contain any of the following properties:<ul>
+     * <li><b>scope</b> Object : <div class="sub-desc">The scope (<code><b>this</b></code> reference) in which the handler function is executed.
+     * <b>If omitted, defaults to this Element.</b></div></li>
+     * <li><b>delegate</b> String: <div class="sub-desc">A simple selector to filter the target or look for a descendant of the target. See below for additional details.</div></li>
+     * <li><b>stopEvent</b> Boolean: <div class="sub-desc">True to stop the event. That is stop propagation, and prevent the default action.</div></li>
+     * <li><b>preventDefault</b> Boolean: <div class="sub-desc">True to prevent the default action</div></li>
+     * <li><b>stopPropagation</b> Boolean: <div class="sub-desc">True to prevent event propagation</div></li>
+     * <li><b>normalized</b> Boolean: <div class="sub-desc">False to pass a browser event to the handler function instead of an Ext.EventObject</div></li>
+     * <li><b>target</b> Ext.Element: <div class="sub-desc">Only call the handler if the event was fired on the target Element, <i>not</i> if the event was bubbled up from a child node.</div></li>
+     * <li><b>delay</b> Number: <div class="sub-desc">The number of milliseconds to delay the invocation of the handler after the event fires.</div></li>
+     * <li><b>single</b> Boolean: <div class="sub-desc">True to add a handler to handle just the next firing of the event, and then remove itself.</div></li>
+     * <li><b>buffer</b> Number: <div class="sub-desc">Causes the handler to be scheduled to run in an {@link Ext.util.DelayedTask} delayed
+     * by the specified number of milliseconds. If the event fires again within that time, the original
+     * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</div></li>
+     * </ul><br>
+     * <p>
+     * <b>Combining Options</b><br>
+     * In the following examples, the shorthand form {@link #on} is used rather than the more verbose
+     * addListener.  The two are equivalent.  Using the options argument, it is possible to combine different
+     * types of listeners:<br>
+     * <br>
+     * A delayed, one-time listener that auto stops the event and adds a custom argument (forumId) to the
+     * options object. The options object is available as the third parameter in the handler function.<div style="margin: 5px 20px 20px;">
+     * Code:<pre><code>
+el.on('click', this.onClick, this, {
+    single: true,
+    delay: 100,
+    stopEvent : true,
+    forumId: 4
+});</code></pre></p>
+     * <p>
+     * <b>Attaching multiple handlers in 1 call</b><br>
+     * The method also allows for a single argument to be passed which is a config object containing properties
+     * which specify multiple handlers.</p>
+     * <p>
+     * Code:<pre><code>
+el.on({
+    'click' : {
+        fn: this.onClick,
+        scope: this,
+        delay: 100
+    },
+    'mouseover' : {
+        fn: this.onMouseOver,
+        scope: this
+    },
+    'mouseout' : {
+        fn: this.onMouseOut,
+        scope: this
+    }
+});</code></pre>
+     * <p>
+     * Or a shorthand syntax:<br>
+     * Code:<pre><code></p>
+el.on({
+    'click' : this.onClick,
+    'mouseover' : this.onMouseOver,
+    'mouseout' : this.onMouseOut,
+    scope: this
+});
+     * </code></pre></p>
+     * <p><b>delegate</b></p>
+     * <p>This is a configuration option that you can pass along when registering a handler for
+     * an event to assist with event delegation. Event delegation is a technique that is used to
+     * reduce memory consumption and prevent exposure to memory-leaks. By registering an event
+     * for a container element as opposed to each element within a container. By setting this
+     * configuration option to a simple selector, the target element will be filtered to look for
+     * a descendant of the target.
+     * For example:<pre><code>
+// using this markup:
+&lt;div id='elId'>
+    &lt;p id='p1'>paragraph one&lt;/p>
+    &lt;p id='p2' class='clickable'>paragraph two&lt;/p>
+    &lt;p id='p3'>paragraph three&lt;/p>
+&lt;/div>
+// utilize event delegation to registering just one handler on the container element:
+el = Ext.get('elId');
+el.on(
+    'click',
+    function(e,t) {
+        // handle click
+        console.info(t.id); // 'p2'
+    },
+    this,
+    {
+        // filter the target element to be a descendant with the class 'clickable'
+        delegate: '.clickable'
+    }
+);
+     * </code></pre></p>
+     * @return {Ext.Element} this
+     */
+    addListener : function(eventName, fn, scope, options){
+        Ext.EventManager.on(this.dom,  eventName, fn, scope || this, options);
+        return this;
+    },
+
+    /**
+     * Removes an event handler from this element.  The shorthand version {@link #un} is equivalent.
+     * <b>Note</b>: if a <i>scope</i> was explicitly specified when {@link #addListener adding} the
+     * listener, the same scope must be specified here.
+     * Example:
+     * <pre><code>
+el.removeListener('click', this.handlerFn);
+// or
+el.un('click', this.handlerFn);
+</code></pre>
+     * @param {String} eventName The name of the event from which to remove the handler.
+     * @param {Function} fn The handler function to remove. <b>This must be a reference to the function passed into the {@link #addListener} call.</b>
+     * @param {Object} scope If a scope (<b><code>this</code></b> reference) was specified when the listener was added,
+     * then this must refer to the same object.
+     * @return {Ext.Element} this
+     */
+    removeListener : function(eventName, fn, scope){
+        Ext.EventManager.removeListener(this.dom,  eventName, fn, scope || this);
+        return this;
+    },
+
+    /**
+     * Removes all previous added listeners from this element
+     * @return {Ext.Element} this
+     */
+    removeAllListeners : function(){
+        Ext.EventManager.removeAll(this.dom);
+        return this;
+    },
+
+    /**
+     * Recursively removes all previous added listeners from this element and its children
+     * @return {Ext.Element} this
+     */
+    purgeAllListeners : function() {
+        Ext.EventManager.purgeElement(this, true);
+        return this;
+    },
+    /**
+     * @private Test if size has a unit, otherwise appends the default
+     */
+    addUnits : function(size){
+        if(size === "" || size == "auto" || size === undefined){
+            size = size || '';
+        } else if(!isNaN(size) || !unitPattern.test(size)){
+            size = size + (this.defaultUnit || 'px');
+        }
+        return size;
+    },
+
+    /**
+     * <p>Updates the <a href="http://developer.mozilla.org/en/DOM/element.innerHTML">innerHTML</a> of this Element
+     * from a specified URL. Note that this is subject to the <a href="http://en.wikipedia.org/wiki/Same_origin_policy">Same Origin Policy</a></p>
+     * <p>Updating innerHTML of an element will <b>not</b> execute embedded <tt>&lt;script></tt> elements. This is a browser restriction.</p>
+     * @param {Mixed} options. Either a sring containing the URL from which to load the HTML, or an {@link Ext.Ajax#request} options object specifying
+     * exactly how to request the HTML.
+     * @return {Ext.Element} this
+     */
+    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;
+    },
+
+    /**
+     * Tests various css rules/browsers to determine if this element uses a border box
+     * @return {Boolean}
+     */
+    isBorderBox : function(){
+        return noBoxAdjust[(this.dom.tagName || "").toLowerCase()] || Ext.isBorderBox;
+    },
+
+    /**
+     * <p>Removes this element's dom reference.  Note that event and cache removal is handled at {@link Ext#removeNode}</p>
+     */
+    remove : function(){
+        var me = this,
+            dom = me.dom;
+
+        if (dom) {
+            delete me.dom;
+            Ext.removeNode(dom);
+        }
+    },
+
+    /**
+     * Sets up event handlers to call the passed functions when the mouse is moved into and out of the Element.
+     * @param {Function} overFn The function to call when the mouse enters the Element.
+     * @param {Function} outFn The function to call when the mouse leaves the Element.
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the functions are executed. Defaults to the Element's DOM element.
+     * @param {Object} options (optional) Options for the listener. See {@link Ext.util.Observable#addListener the <tt>options</tt> parameter}.
+     * @return {Ext.Element} this
+     */
+    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;
+    },
+
+    /**
+     * Returns true if this element is an ancestor of the passed element
+     * @param {HTMLElement/String} el The element to check
+     * @return {Boolean} True if this element is an ancestor of el, else false
+     */
+    contains : function(el){
+        return !el ? false : Ext.lib.Dom.isAncestor(this.dom, el.dom ? el.dom : el);
+    },
+
+    /**
+     * Returns the value of a namespaced attribute from the element's underlying DOM node.
+     * @param {String} namespace The namespace in which to look for the attribute
+     * @param {String} name The attribute name
+     * @return {String} The attribute value
+     * @deprecated
+     */
+    getAttributeNS : function(ns, name){
+        return this.getAttribute(name, ns);
+    },
+
+    /**
+     * Returns the value of an attribute from the element's underlying DOM node.
+     * @param {String} name The attribute name
+     * @param {String} namespace (optional) The namespace in which to look for the attribute
+     * @return {String} The attribute value
+     */
+    getAttribute : Ext.isIE ? function(name, ns){
+        var d = this.dom,
+            type = typeof d[ns + ":" + name];
+
+        if(['undefined', 'unknown'].indexOf(type) == -1){
+            return d[ns + ":" + name];
+        }
+        return d[name];
+    } : function(name, ns){
+        var d = this.dom;
+        return d.getAttributeNS(ns, name) || d.getAttribute(ns + ":" + name) || d.getAttribute(name) || d[name];
+    },
+
+    /**
+    * Update the innerHTML of this element
+    * @param {String} html The new HTML
+    * @return {Ext.Element} this
+     */
+    update : function(html) {
+        if (this.dom) {
+            this.dom.innerHTML = html;
+        }
+        return this;
+    }
+};
+
+var ep = El.prototype;
+
+El.addMethods = function(o){
+   Ext.apply(ep, o);
+};
+
+/**
+ * Appends an event handler (shorthand for {@link #addListener}).
+ * @param {String} eventName The name of event to handle.
+ * @param {Function} fn The handler function the event invokes.
+ * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the handler function is executed.
+ * @param {Object} options (optional) An object containing standard {@link #addListener} options
+ * @member Ext.Element
+ * @method on
+ */
+ep.on = ep.addListener;
+
+/**
+ * Removes an event handler from this element (see {@link #removeListener} for additional notes).
+ * @param {String} eventName The name of the event from which to remove the handler.
+ * @param {Function} fn The handler function to remove. <b>This must be a reference to the function passed into the {@link #addListener} call.</b>
+ * @param {Object} scope If a scope (<b><code>this</code></b> reference) was specified when the listener was added,
+ * then this must refer to the same object.
+ * @return {Ext.Element} this
+ * @member Ext.Element
+ * @method un
+ */
+ep.un = ep.removeListener;
+
+/**
+ * true to automatically adjust width and height settings for box-model issues (default to true)
+ */
+ep.autoBoxAdjust = true;
+
+// private
+var unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i,
+    docEl;
+
+/**
+ * @private
+ */
+
+/**
+ * Retrieves Ext.Element objects.
+ * <p><b>This method does not retrieve {@link Ext.Component Component}s.</b> This method
+ * retrieves Ext.Element objects which encapsulate DOM elements. To retrieve a Component by
+ * its ID, use {@link Ext.ComponentMgr#get}.</p>
+ * <p>Uses simple caching to consistently return the same object. Automatically fixes if an
+ * object was recreated with the same id via AJAX or DOM.</p>
+ * @param {Mixed} el The id of the node, a DOM Node or an existing Element.
+ * @return {Element} The Element object (or null if no matching element was found)
+ * @static
+ * @member Ext.Element
+ * @method get
+ */
+El.get = function(el){
+    var ex,
+        elm,
+        id;
+    if(!el){ return null; }
+    if (typeof el == "string") { // element id
+        if (!(elm = DOC.getElementById(el))) {
+            return null;
+        }
+        if (EC[el] && EC[el].el) {
+            ex = EC[el].el;
+            ex.dom = elm;
+        } else {
+            ex = El.addToCache(new El(elm));
+        }
+        return ex;
+    } else if (el.tagName) { // dom element
+        if(!(id = el.id)){
+            id = Ext.id(el);
+        }
+        if (EC[id] && EC[id].el) {
+            ex = EC[id].el;
+            ex.dom = el;
+        } else {
+            ex = El.addToCache(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
+        }
+        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;
+};
+
+El.addToCache = function(el, id){
+    id = id || el.id;
+    EC[id] = {
+        el:  el,
+        data: {},
+        events: {}
+    };
+    return el;
+};
+
+// private method for getting and setting element data
+El.data = function(el, key, value){
+    el = El.get(el);
+    if (!el) {
+        return null;
+    }
+    var c = EC[el.id].data;
+    if(arguments.length == 2){
+        return c[key];
+    }else{
+        return (c[key] = value);
+    }
+};
+
+// 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.collectorThreadId);
+    } else {
+        var eid,
+            el,
+            d,
+            o;
+
+        for(eid in EC){
+            o = EC[eid];
+            if(o.skipGC){
+                continue;
             }
-            for (style in prop) {
-                value = prop[style];            
-                style == 'opacity' ? 
-                    this.setOpacity(value) : 
-                    this.dom.style[chkCache(style)] = value;
+            el = o.el;
+            d = el.dom;
+            // -------------------------------------------------------
+            // Determining what is garbage:
+            // -------------------------------------------------------
+            // !d
+            // dom node is null, definitely garbage
+            // -------------------------------------------------------
+            // !d.parentNode
+            // no parentNode == direct orphan, definitely garbage
+            // -------------------------------------------------------
+            // !d.offsetParent && !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 && !DOC.getElementById(eid))){
+                if(Ext.enableListenerCollection){
+                    Ext.EventManager.removeAll(d);
+                }
+                delete EC[eid];
             }
-            return this;
-        },
-        
-        /**
-         * Set the opacity of the element
-         * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
-         * @param {Boolean/Object} animate (optional) a standard Element animation config object or <tt>true</tt> for
-         * the default animation (<tt>{duration: .35, easing: 'easeIn'}</tt>)
-         * @return {Ext.Element} this
-         */
-         setOpacity : function(opacity, animate){
-            var me = this,
-                s = me.dom.style;
-                
-            if(!animate || !me.anim){            
-                if(Ext.isIE){
-                    var opac = opacity < 1 ? 'alpha(opacity=' + opacity * 100 + ')' : '', 
-                    val = s.filter.replace(opacityRe, '').replace(trimRe, '');
+        }
+        // Cleanup IE Object leaks
+        if (Ext.isIE) {
+            var t = {};
+            for (eid in EC) {
+                t[eid] = EC[eid];
+            }
+            EC = Ext.elCache = t;
+        }
+    }
+}
+El.collectorThreadId = setInterval(garbageCollect, 30000);
 
-                    s.zoom = 1;
-                    s.filter = val + (val.length > 0 ? ' ' : '') + opac;
-                }else{
-                    s.opacity = opacity;
-                }
-            }else{
-                me.anim({opacity: {to: opacity}}, me.preanim(arguments, 1), null, .35, 'easeIn');
+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 = {};
+
+/**
+ * <p>Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
+ * the dom node can be overwritten by other code. Shorthand of {@link Ext.Element#fly}</p>
+ * <p>Use this to make one-time references to DOM elements which are not going to be accessed again either by
+ * application code, or by Ext's classes. If accessing an element which will be processed regularly, then {@link Ext#get}
+ * will be more appropriate to take advantage of the caching provided by the Ext.Element class.</p>
+ * @param {String/HTMLElement} el The dom node or id
+ * @param {String} named (optional) Allows for creation of named reusable flyweights to prevent conflicts
+ * (e.g. internally Ext uses "_global")
+ * @return {Element} The shared Element object (or null if no matching element was found)
+ * @member Ext.Element
+ * @method fly
+ */
+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;
+};
+
+/**
+ * Retrieves Ext.Element objects.
+ * <p><b>This method does not retrieve {@link Ext.Component Component}s.</b> This method
+ * retrieves Ext.Element objects which encapsulate DOM elements. To retrieve a Component by
+ * its ID, use {@link Ext.ComponentMgr#get}.</p>
+ * <p>Uses simple caching to consistently return the same object. Automatically fixes if an
+ * object was recreated with the same id via AJAX or DOM.</p>
+ * Shorthand of {@link Ext.Element#get}
+ * @param {Mixed} el The id of the node, a DOM Node or an existing Element.
+ * @return {Element} The Element object (or null if no matching element was found)
+ * @member Ext
+ * @method get
+ */
+Ext.get = El.get;
+
+/**
+ * <p>Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
+ * the dom node can be overwritten by other code. Shorthand of {@link Ext.Element#fly}</p>
+ * <p>Use this to make one-time references to DOM elements which are not going to be accessed again either by
+ * application code, or by Ext's classes. If accessing an element which will be processed regularly, then {@link Ext#get}
+ * will be more appropriate to take advantage of the caching provided by the Ext.Element class.</p>
+ * @param {String/HTMLElement} el The dom node or id
+ * @param {String} named (optional) Allows for creation of named reusable flyweights to prevent conflicts
+ * (e.g. internally Ext uses "_global")
+ * @return {Element} The shared Element object (or null if no matching element was found)
+ * @member Ext
+ * @method fly
+ */
+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;
+}
+
+})();
+/**
+ * @class Ext.Element
+ */
+Ext.Element.addMethods({
+    /**
+     * Stops the specified event(s) from bubbling and optionally prevents the default action
+     * @param {String/Array} eventName an event / array of events to stop from bubbling
+     * @param {Boolean} preventDefault (optional) true to prevent the default action too
+     * @return {Ext.Element} this
+     */
+    swallowEvent : function(eventName, preventDefault){
+        var me = this;
+        function fn(e){
+            e.stopPropagation();
+            if(preventDefault){
+                e.preventDefault();
             }
+        }
+        if(Ext.isArray(eventName)){
+            Ext.each(eventName, function(e) {
+                 me.on(e, fn);
+            });
             return me;
-        },
-        
-        /**
-         * Clears any opacity settings from this element. Required in some cases for IE.
-         * @return {Ext.Element} this
-         */
-        clearOpacity : function(){
-            var style = this.dom.style;
-            if(Ext.isIE){
-                if(!Ext.isEmpty(style.filter)){
-                    style.filter = style.filter.replace(opacityRe, '').replace(trimRe, '');
-                }
+        }
+        me.on(eventName, fn);
+        return me;
+    },
+
+    /**
+     * Create an event handler on this element such that when the event fires and is handled by this element,
+     * it will be relayed to another object (i.e., fired again as if it originated from that object instead).
+     * @param {String} eventName The type of event to relay
+     * @param {Object} object Any object that extends {@link Ext.util.Observable} that will provide the context
+     * for firing the relayed event
+     */
+    relayEvent : function(eventName, observable){
+        this.on(eventName, function(e){
+            observable.fireEvent(eventName, e);
+        });
+    },
+
+    /**
+     * Removes worthless text nodes
+     * @param {Boolean} forceReclean (optional) By default the element
+     * keeps track if it has been cleaned already so
+     * you can call this over and over. However, if you update the element and
+     * need to force a reclean, you can pass true.
+     */
+    clean : function(forceReclean){
+        var me = this,
+            dom = me.dom,
+            n = dom.firstChild,
+            ni = -1;
+
+        if(Ext.Element.data(dom, 'isCleaned') && forceReclean !== true){
+            return me;
+        }
+
+        while(n){
+            var nx = n.nextSibling;
+            if(n.nodeType == 3 && !/\S/.test(n.nodeValue)){
+                dom.removeChild(n);
             }else{
-                style.opacity = style['-moz-opacity'] = style['-khtml-opacity'] = '';
+                n.nodeIndex = ++ni;
+            }
+            n = nx;
+        }
+        Ext.Element.data(dom, 'isCleaned', true);
+        return me;
+    },
+
+    /**
+     * Direct access to the Updater {@link Ext.Updater#update} method. The method takes the same object
+     * parameter as {@link Ext.Updater#update}
+     * @return {Ext.Element} this
+     */
+    load : function(){
+        var um = this.getUpdater();
+        um.update.apply(um, arguments);
+        return this;
+    },
+
+    /**
+    * Gets this element's {@link Ext.Updater Updater}
+    * @return {Ext.Updater} The Updater
+    */
+    getUpdater : function(){
+        return this.updateManager || (this.updateManager = new Ext.Updater(this));
+    },
+
+    /**
+    * Update the innerHTML of this element, optionally searching for and processing scripts
+    * @param {String} html The new HTML
+    * @param {Boolean} loadScripts (optional) True to look for and process scripts (defaults to false)
+    * @param {Function} callback (optional) For async script loading you can be notified when the update completes
+    * @return {Ext.Element} this
+     */
+    update : function(html, loadScripts, callback){
+        if (!this.dom) {
+            return this;
+        }
+        html = html || "";
+
+        if(loadScripts !== true){
+            this.dom.innerHTML = html;
+            if(Ext.isFunction(callback)){
+                callback();
             }
             return this;
-        },
+        }
+
+        var id = Ext.id(),
+            dom = this.dom;
+
+        html += '<span id="' + id + '"></span>';
+
+        Ext.lib.Event.onAvailable(id, function(){
+            var DOC = document,
+                hd = DOC.getElementsByTagName("head")[0],
+                re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig,
+                srcRe = /\ssrc=([\'\"])(.*?)\1/i,
+                typeRe = /\stype=([\'\"])(.*?)\1/i,
+                match,
+                attrs,
+                srcMatch,
+                typeMatch,
+                el,
+                s;
+
+            while((match = re.exec(html))){
+                attrs = match[1];
+                srcMatch = attrs ? attrs.match(srcRe) : false;
+                if(srcMatch && srcMatch[2]){
+                   s = DOC.createElement("script");
+                   s.src = srcMatch[2];
+                   typeMatch = attrs.match(typeRe);
+                   if(typeMatch && typeMatch[2]){
+                       s.type = typeMatch[2];
+                   }
+                   hd.appendChild(s);
+                }else if(match[2] && match[2].length > 0){
+                    if(window.execScript) {
+                       window.execScript(match[2]);
+                    } else {
+                       window.eval(match[2]);
+                    }
+                }
+            }
+            el = DOC.getElementById(id);
+            if(el){Ext.removeNode(el);}
+            if(Ext.isFunction(callback)){
+                callback();
+            }
+        });
+        dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
+        return this;
+    },
+
+    // inherit docs, overridden so we can add removeAnchor
+    removeAllListeners : function(){
+        this.removeAnchor();
+        Ext.EventManager.removeAll(this.dom);
+        return this;
+    },
+
+    /**
+     * Creates a proxy element of this element
+     * @param {String/Object} config The class name of the proxy element or a DomHelper config object
+     * @param {String/HTMLElement} renderTo (optional) The element or element id to render the proxy to (defaults to document.body)
+     * @param {Boolean} matchBox (optional) True to align and size the proxy to this element now (defaults to false)
+     * @return {Ext.Element} The new proxy element
+     */
+    createProxy : function(config, renderTo, matchBox){
+        config = Ext.isObject(config) ? config : {tag : "div", cls: config};
+
+        var me = this,
+            proxy = renderTo ? Ext.DomHelper.append(renderTo, config, true) :
+                               Ext.DomHelper.insertBefore(me.dom, config, true);
+
+        if(matchBox && me.setBox && me.getBox){ // check to make sure Element.position.js is loaded
+           proxy.setBox(me.getBox());
+        }
+        return proxy;
+    }
+});
+
+Ext.Element.prototype.getUpdateManager = Ext.Element.prototype.getUpdater;
+/**
+ * @class Ext.Element
+ */
+Ext.Element.addMethods({
+    /**
+     * Gets the x,y coordinates specified by the anchor position on the element.
+     * @param {String} anchor (optional) The specified anchor position (defaults to "c").  See {@link #alignTo}
+     * for details on supported anchor positions.
+     * @param {Boolean} local (optional) True to get the local (element top/left-relative) anchor position instead
+     * of page coordinates
+     * @param {Object} size (optional) An object containing the size to use for calculating anchor position
+     * {width: (target width), height: (target height)} (defaults to the element's current size)
+     * @return {Array} [x, y] An array containing the element's x and y coordinates
+     */
+    getAnchorXY : function(anchor, local, s){
+        //Passing a different size is useful for pre-calculating anchors,
+        //especially for anchored animations that change the el size.
+               anchor = (anchor || "tl").toLowerCase();
+        s = s || {};
+        
+        var me = this,        
+               vp = me.dom == document.body || me.dom == document,
+               w = s.width || vp ? Ext.lib.Dom.getViewWidth() : me.getWidth(),
+               h = s.height || vp ? Ext.lib.Dom.getViewHeight() : me.getHeight(),                              
+               xy,             
+               r = Math.round,
+               o = me.getXY(),
+               scroll = me.getScroll(),
+               extraX = vp ? scroll.left : !local ? o[0] : 0,
+               extraY = vp ? scroll.top : !local ? o[1] : 0,
+               hash = {
+                       c  : [r(w * 0.5), r(h * 0.5)],
+                       t  : [r(w * 0.5), 0],
+                       l  : [0, r(h * 0.5)],
+                       r  : [w, r(h * 0.5)],
+                       b  : [r(w * 0.5), h],
+                       tl : [0, 0],    
+                       bl : [0, h],
+                       br : [w, h],
+                       tr : [w, 0]
+               };
+        
+        xy = hash[anchor];     
+        return [xy[0] + extraX, xy[1] + extraY]; 
+    },
+
+    /**
+     * Anchors an element to another element and realigns it when the window is resized.
+     * @param {Mixed} element The element to align to.
+     * @param {String} position The position to align to.
+     * @param {Array} offsets (optional) Offset the positioning by [x, y]
+     * @param {Boolean/Object} animate (optional) True for the default animation or a standard Element animation config object
+     * @param {Boolean/Number} monitorScroll (optional) True to monitor body scroll and reposition. If this parameter
+     * is a number, it is used as the buffer delay (defaults to 50ms).
+     * @param {Function} callback The function to call after the animation finishes
+     * @return {Ext.Element} this
+     */
+    anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){        
+           var me = this,
+            dom = me.dom,
+            scroll = !Ext.isEmpty(monitorScroll),
+            action = function(){
+                Ext.fly(dom).alignTo(el, alignment, offsets, animate);
+                Ext.callback(callback, Ext.fly(dom));
+            },
+            anchor = this.getAnchor();
+            
+        // previous listener anchor, remove it
+        this.removeAnchor();
+        Ext.apply(anchor, {
+            fn: action,
+            scroll: scroll
+        });
+
+        Ext.EventManager.onWindowResize(action, null);
+        
+        if(scroll){
+            Ext.EventManager.on(window, 'scroll', action, null,
+                {buffer: !isNaN(monitorScroll) ? monitorScroll : 50});
+        }
+        action.call(me); // align immediately
+        return me;
+    },
     
-        /**
-         * Returns the offset height of the element
-         * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
-         * @return {Number} The element's height
-         */
-        getHeight : function(contentHeight){
-            var me = this,
-                dom = me.dom,
-                hidden = Ext.isIE && me.isStyle('display', 'none'),
-                h = MATH.max(dom.offsetHeight, hidden ? 0 : dom.clientHeight) || 0;
-                
-            h = !contentHeight ? h : h - me.getBorderWidth("tb") - me.getPadding("tb");
-            return h < 0 ? 0 : h;
-        },
-    
-        /**
-         * Returns the offset width of the element
-         * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
-         * @return {Number} The element's width
-         */
-        getWidth : function(contentWidth){
-            var me = this,
-                dom = me.dom,
-                hidden = Ext.isIE && me.isStyle('display', 'none'),
-                w = MATH.max(dom.offsetWidth, hidden ? 0 : dom.clientWidth) || 0;
-            w = !contentWidth ? w : w - me.getBorderWidth("lr") - me.getPadding("lr");
-            return w < 0 ? 0 : w;
-        },
-    
-        /**
-         * Set the width of this Element.
-         * @param {Mixed} width The new width. This may be one of:<div class="mdetail-params"><ul>
-         * <li>A Number specifying the new width in this Element's {@link #defaultUnit}s (by default, pixels).</li>
-         * <li>A String used to set the CSS width style. Animation may <b>not</b> be used.
-         * </ul></div>
-         * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
-         * @return {Ext.Element} this
-         */
-        setWidth : function(width, animate){
-            var me = this;
-            width = me.adjustWidth(width);
-            !animate || !me.anim ? 
-                me.dom.style.width = me.addUnits(width) :
-                me.anim({width : {to : width}}, me.preanim(arguments, 1));
-            return me;
-        },
+    /**
+     * Remove any anchor to this element. See {@link #anchorTo}.
+     * @return {Ext.Element} this
+     */
+    removeAnchor : function(){
+        var me = this,
+            anchor = this.getAnchor();
+            
+        if(anchor && anchor.fn){
+            Ext.EventManager.removeResizeListener(anchor.fn);
+            if(anchor.scroll){
+                Ext.EventManager.un(window, 'scroll', anchor.fn);
+            }
+            delete anchor.fn;
+        }
+        return me;
+    },
     
-        /**
-         * Set the height of this Element.
-         * <pre><code>
-// change the height to 200px and animate with default configuration
-Ext.fly('elementId').setHeight(200, true);
+    // private
+    getAnchor : function(){
+        var data = Ext.Element.data,
+            dom = this.dom;
+            if (!dom) {
+                return;
+            }
+            var anchor = data(dom, '_anchor');
+            
+        if(!anchor){
+            anchor = data(dom, '_anchor', {});
+        }
+        return anchor;
+    },
 
-// change the height to 150px and animate with a custom configuration
-Ext.fly('elId').setHeight(150, {
-    duration : .5, // animation will have a duration of .5 seconds
-    // will change the content to "finished"
-    callback: function(){ this.{@link #update}("finished"); } 
-});
-         * </code></pre>
-         * @param {Mixed} height The new height. This may be one of:<div class="mdetail-params"><ul>
-         * <li>A Number specifying the new height in this Element's {@link #defaultUnit}s (by default, pixels.)</li>
-         * <li>A String used to set the CSS height style. Animation may <b>not</b> be used.</li>
-         * </ul></div>
-         * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
-         * @return {Ext.Element} this
-         */
-         setHeight : function(height, animate){
-            var me = this;
-            height = me.adjustHeight(height);
-            !animate || !me.anim ? 
-                me.dom.style.height = me.addUnits(height) :
-                me.anim({height : {to : height}}, me.preanim(arguments, 1));
-            return me;
-        },
+    /**
+     * Gets the x,y coordinates to align this element with another element. See {@link #alignTo} for more info on the
+     * supported position values.
+     * @param {Mixed} element The element to align to.
+     * @param {String} position (optional, defaults to "tl-bl?") The position to align to.
+     * @param {Array} offsets (optional) Offset the positioning by [x, y]
+     * @return {Array} [x, y]
+     */
+    getAlignToXY : function(el, p, o){     
+        el = Ext.get(el);
         
-        /**
-         * Gets the width of the border(s) for the specified side(s)
-         * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
-         * passing <tt>'lr'</tt> would get the border <b><u>l</u></b>eft width + the border <b><u>r</u></b>ight width.
-         * @return {Number} The width of the sides passed added together
-         */
-        getBorderWidth : function(side){
-            return this.addStyles(side, borders);
-        },
-    
-        /**
-         * Gets the width of the padding(s) for the specified side(s)
-         * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
-         * passing <tt>'lr'</tt> would get the padding <b><u>l</u></b>eft + the padding <b><u>r</u></b>ight.
-         * @return {Number} The padding of the sides passed added together
-         */
-        getPadding : function(side){
-            return this.addStyles(side, paddings);
-        },
-    
-        /**
-         *  Store the current overflow setting and clip overflow on the element - use <tt>{@link #unclip}</tt> to remove
-         * @return {Ext.Element} this
-         */
-        clip : function(){
-            var me = this,
-                dom = me.dom;
+        if(!el || !el.dom){
+            throw "Element.alignToXY with an element that doesn't exist";
+        }
+        
+        o = o || [0,0];
+        p = (!p || p == "?" ? "tl-bl?" : (!/-/.test(p) && p !== "" ? "tl-" + p : p || "tl-bl")).toLowerCase();       
                 
-            if(!data(dom, ISCLIPPED)){
-                data(dom, ISCLIPPED, true);
-                data(dom, ORIGINALCLIP, {
-                    o: me.getStyle(OVERFLOW),
-                    x: me.getStyle(OVERFLOWX),
-                    y: me.getStyle(OVERFLOWY)
-                });
-                me.setStyle(OVERFLOW, HIDDEN);
-                me.setStyle(OVERFLOWX, HIDDEN);
-                me.setStyle(OVERFLOWY, HIDDEN);
+        var me = this,
+               d = me.dom,
+               a1,
+               a2,
+               x,
+               y,
+               //constrain the aligned el to viewport if necessary
+               w,
+               h,
+               r,
+               dw = Ext.lib.Dom.getViewWidth() -10, // 10px of margin for ie
+               dh = Ext.lib.Dom.getViewHeight()-10, // 10px of margin for ie
+               p1y,
+               p1x,            
+               p2y,
+               p2x,
+               swapY,
+               swapX,
+               doc = document,
+               docElement = doc.documentElement,
+               docBody = doc.body,
+               scrollX = (docElement.scrollLeft || docBody.scrollLeft || 0)+5,
+               scrollY = (docElement.scrollTop || docBody.scrollTop || 0)+5,
+               c = false, //constrain to viewport
+               p1 = "", 
+               p2 = "",
+               m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
+        
+        if(!m){
+           throw "Element.alignTo with an invalid alignment " + p;
+        }
+        
+        p1 = m[1]; 
+        p2 = m[2]; 
+        c = !!m[3];
+
+        //Subtract the aligned el's internal xy from the target's offset xy
+        //plus custom offset to get the aligned el's new offset xy
+        a1 = me.getAnchorXY(p1, true);
+        a2 = el.getAnchorXY(p2, false);
+
+        x = a2[0] - a1[0] + o[0];
+        y = a2[1] - a1[1] + o[1];
+
+        if(c){    
+              w = me.getWidth();
+           h = me.getHeight();
+           r = el.getRegion();       
+           //If we are at a viewport boundary and the aligned el is anchored on a target border that is
+           //perpendicular to the vp border, allow the aligned el to slide on that border,
+           //otherwise swap the aligned el to the opposite border of the target.
+           p1y = p1.charAt(0);
+           p1x = p1.charAt(p1.length-1);
+           p2y = p2.charAt(0);
+           p2x = p2.charAt(p2.length-1);
+           swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
+           swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));          
+           
+
+           if (x + w > dw + scrollX) {
+                x = swapX ? r.left-w : dw+scrollX-w;
+           }
+           if (x < scrollX) {
+               x = swapX ? r.right : scrollX;
+           }
+           if (y + h > dh + scrollY) {
+                y = swapY ? r.top-h : dh+scrollY-h;
             }
-            return me;
-        },
+           if (y < scrollY){
+               y = swapY ? r.bottom : scrollY;
+           }
+        }
+        return [x,y];
+    },
+
+    /**
+     * Aligns this element with another element relative to the specified anchor points. If the other element is the
+     * document it aligns it to the viewport.
+     * The position parameter is optional, and can be specified in any one of the following formats:
+     * <ul>
+     *   <li><b>Blank</b>: Defaults to aligning the element's top-left corner to the target's bottom-left corner ("tl-bl").</li>
+     *   <li><b>One anchor (deprecated)</b>: The passed anchor position is used as the target element's anchor point.
+     *       The element being aligned will position its top-left corner (tl) to that point.  <i>This method has been
+     *       deprecated in favor of the newer two anchor syntax below</i>.</li>
+     *   <li><b>Two anchors</b>: If two values from the table below are passed separated by a dash, the first value is used as the
+     *       element's anchor point, and the second value is used as the target's anchor point.</li>
+     * </ul>
+     * In addition to the anchor points, the position parameter also supports the "?" character.  If "?" is passed at the end of
+     * the position string, the element will attempt to align as specified, but the position will be adjusted to constrain to
+     * the viewport if necessary.  Note that the element being aligned might be swapped to align to a different position than
+     * that specified in order to enforce the viewport constraints.
+     * Following are all of the supported anchor positions:
+<pre>
+Value  Description
+-----  -----------------------------
+tl     The top left corner (default)
+t      The center of the top edge
+tr     The top right corner
+l      The center of the left edge
+c      In the center of the element
+r      The center of the right edge
+bl     The bottom left corner
+b      The center of the bottom edge
+br     The bottom right corner
+</pre>
+Example Usage:
+<pre><code>
+// align el to other-el using the default positioning ("tl-bl", non-constrained)
+el.alignTo("other-el");
+
+// align the top left corner of el with the top right corner of other-el (constrained to viewport)
+el.alignTo("other-el", "tr?");
+
+// align the bottom right corner of el with the center left edge of other-el
+el.alignTo("other-el", "br-l?");
+
+// align the center of el with the bottom left corner of other-el and
+// adjust the x position by -6 pixels (and the y position by 0)
+el.alignTo("other-el", "c-bl", [-6, 0]);
+</code></pre>
+     * @param {Mixed} element The element to align to.
+     * @param {String} position (optional, defaults to "tl-bl?") The position to align to.
+     * @param {Array} offsets (optional) Offset the positioning by [x, y]
+     * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
+     * @return {Ext.Element} this
+     */
+    alignTo : function(element, position, offsets, animate){
+           var me = this;
+        return me.setXY(me.getAlignToXY(element, position, offsets),
+                               me.preanim && !!animate ? me.preanim(arguments, 3) : false);
+    },
     
-        /**
-         *  Return clipping (overflow) to original clipping before <tt>{@link #clip}</tt> was called
-         * @return {Ext.Element} this
-         */
-        unclip : function(){
-            var me = this,
-                dom = me.dom;
-                
-            if(data(dom, ISCLIPPED)){
-                data(dom, ISCLIPPED, false);
-                var o = data(dom, ORIGINALCLIP);
-                if(o.o){
-                    me.setStyle(OVERFLOW, o.o);
-                }
-                if(o.x){
-                    me.setStyle(OVERFLOWX, o.x);
-                }
-                if(o.y){
-                    me.setStyle(OVERFLOWY, o.y);
+    // private ==>  used outside of core
+    adjustForConstraints : function(xy, parent, offsets){
+        return this.getConstrainToXY(parent || document, false, offsets, xy) ||  xy;
+    },
+
+    // private ==>  used outside of core
+    getConstrainToXY : function(el, local, offsets, proposedXY){   
+           var os = {top:0, left:0, bottom:0, right: 0};
+
+        return function(el, local, offsets, proposedXY){
+            el = Ext.get(el);
+            offsets = offsets ? Ext.applyIf(offsets, os) : os;
+
+            var vw, vh, vx = 0, vy = 0;
+            if(el.dom == document.body || el.dom == document){
+                vw =Ext.lib.Dom.getViewWidth();
+                vh = Ext.lib.Dom.getViewHeight();
+            }else{
+                vw = el.dom.clientWidth;
+                vh = el.dom.clientHeight;
+                if(!local){
+                    var vxy = el.getXY();
+                    vx = vxy[0];
+                    vy = vxy[1];
                 }
             }
-            return me;
-        },
 
-        // private
-        addStyles : function(sides, styles){
-            var val = 0;
+            var s = el.getScroll();
 
-            Ext.each(sides.match(/\w/g), function(s) {
-                if (s = parseInt(this.getStyle(styles[s]), 10)) {
-                    val += MATH.abs(s);
-                }
-            },
-            this);
-            return val;
-        },
+            vx += offsets.left + s.left;
+            vy += offsets.top + s.top;
 
-        margins : margins
-    }
-}()         
-);
+            vw -= offsets.right;
+            vh -= offsets.bottom;
+
+            var vr = vx+vw;
+            var vb = vy+vh;
+
+            var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
+            var x = xy[0], y = xy[1];
+            var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
+
+            // only move it if it needs it
+            var moved = false;
+
+            // first validate right/bottom
+            if((x + w) > vr){
+                x = vr - w;
+                moved = true;
+            }
+            if((y + h) > vb){
+                y = vb - h;
+                moved = true;
+            }
+            // then make sure top/left isn't negative
+            if(x < vx){
+                x = vx;
+                moved = true;
+            }
+            if(y < vy){
+                y = vy;
+                moved = true;
+            }
+            return moved ? [x, y] : false;
+        };
+    }(),
+           
+           
+               
+//         el = Ext.get(el);
+//         offsets = Ext.applyIf(offsets || {}, {top : 0, left : 0, bottom : 0, right : 0});
+
+//         var me = this,
+//             doc = document,
+//             s = el.getScroll(),
+//             vxy = el.getXY(),
+//             vx = offsets.left + s.left, 
+//             vy = offsets.top + s.top,               
+//             vw = -offsets.right, 
+//             vh = -offsets.bottom, 
+//             vr,
+//             vb,
+//             xy = proposedXY || (!local ? me.getXY() : [me.getLeft(true), me.getTop(true)]),
+//             x = xy[0],
+//             y = xy[1],
+//             w = me.dom.offsetWidth, h = me.dom.offsetHeight,
+//             moved = false; // only move it if it needs it
+//       
+//             
+//         if(el.dom == doc.body || el.dom == doc){
+//             vw += Ext.lib.Dom.getViewWidth();
+//             vh += Ext.lib.Dom.getViewHeight();
+//         }else{
+//             vw += el.dom.clientWidth;
+//             vh += el.dom.clientHeight;
+//             if(!local){                    
+//                 vx += vxy[0];
+//                 vy += vxy[1];
+//             }
+//         }
+
+//         // first validate right/bottom
+//         if(x + w > vx + vw){
+//             x = vx + vw - w;
+//             moved = true;
+//         }
+//         if(y + h > vy + vh){
+//             y = vy + vh - h;
+//             moved = true;
+//         }
+//         // then make sure top/left isn't negative
+//         if(x < vx){
+//             x = vx;
+//             moved = true;
+//         }
+//         if(y < vy){
+//             y = vy;
+//             moved = true;
+//         }
+//         return moved ? [x, y] : false;
+//    },
+    
+    /**
+    * Calculates the x, y to center this element on the screen
+    * @return {Array} The x, y values [x, y]
+    */
+    getCenterXY : function(){
+        return this.getAlignToXY(document, 'c-c');
+    },
+
+    /**
+    * Centers the Element in either the viewport, or another Element.
+    * @param {Mixed} centerIn (optional) The element in which to center the element.
+    */
+    center : function(centerIn){
+        return this.alignTo(centerIn || document, 'c-c');        
+    }    
+});
 /**\r
  * @class Ext.Element\r
  */\r
-\r
-// special markup used throughout Ext when box wrapping elements\r
-Ext.Element.boxMarkup = '<div class="{0}-tl"><div class="{0}-tr"><div class="{0}-tc"></div></div></div><div class="{0}-ml"><div class="{0}-mr"><div class="{0}-mc"></div></div></div><div class="{0}-bl"><div class="{0}-br"><div class="{0}-bc"></div></div></div>';\r
-\r
 Ext.Element.addMethods(function(){\r
-       var INTERNAL = "_internal";\r
+       var PARENTNODE = 'parentNode',\r
+               NEXTSIBLING = 'nextSibling',\r
+               PREVIOUSSIBLING = 'previousSibling',\r
+               DQ = Ext.DomQuery,\r
+               GET = Ext.get;\r
+       \r
        return {\r
-           /**\r
-            * More flexible version of {@link #setStyle} for setting style properties.\r
-            * @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form {width:"100px"}, or\r
-            * a function which returns such a specification.\r
-            * @return {Ext.Element} this\r
-            */\r
-           applyStyles : function(style){\r
-               Ext.DomHelper.applyStyles(this.dom, style);\r
-               return this;\r
-           },\r
-\r
                /**\r
-            * Returns an object with properties matching the styles requested.\r
-            * For example, el.getStyles('color', 'font-size', 'width') might return\r
-            * {'color': '#FFFFFF', 'font-size': '13px', 'width': '100px'}.\r
-            * @param {String} style1 A style name\r
-            * @param {String} style2 A style name\r
-            * @param {String} etc.\r
-            * @return {Object} The style object\r
+            * Looks at this node and then at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)\r
+            * @param {String} selector The simple selector to test\r
+            * @param {Number/Mixed} maxDepth (optional) The max depth to search as a number or element (defaults to 50 || document.body)\r
+            * @param {Boolean} returnEl (optional) True to return a Ext.Element object instead of DOM node\r
+            * @return {HTMLElement} The matching DOM node (or null if no match was found)\r
             */\r
-           getStyles : function(){\r
-                   var ret = {};\r
-                   Ext.each(arguments, function(v) {\r
-                          ret[v] = this.getStyle(v);\r
-                   },\r
-                   this);\r
-                   return ret;\r
-           },\r
-\r
-               getStyleSize : function(){\r
-               var me = this,\r
-                       w,\r
-                       h,\r
-                       d = this.dom,\r
-                       s = d.style;\r
-               if(s.width && s.width != 'auto'){\r
-                   w = parseInt(s.width, 10);\r
-                   if(me.isBorderBox()){\r
-                      w -= me.getFrameWidth('lr');\r
-                   }\r
+           findParent : function(simpleSelector, maxDepth, returnEl){\r
+               var p = this.dom,\r
+                       b = document.body, \r
+                       depth = 0,                      \r
+                       stopEl;         \r
+            if(Ext.isGecko && Object.prototype.toString.call(p) == '[object XULElement]') {\r
+                return null;\r
+            }\r
+               maxDepth = maxDepth || 50;\r
+               if (isNaN(maxDepth)) {\r
+                   stopEl = Ext.getDom(maxDepth);\r
+                   maxDepth = Number.MAX_VALUE;\r
                }\r
-               if(s.height && s.height != 'auto'){\r
-                   h = parseInt(s.height, 10);\r
-                   if(me.isBorderBox()){\r
-                      h -= me.getFrameWidth('tb');\r
+               while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){\r
+                   if(DQ.is(p, simpleSelector)){\r
+                       return returnEl ? GET(p) : p;\r
                    }\r
+                   depth++;\r
+                   p = p.parentNode;\r
                }\r
-               return {width: w || me.getWidth(true), height: h || me.getHeight(true)};\r
+               return null;\r
            },\r
-\r
-           // private  ==> used by ext full\r
-               setOverflow : function(v){\r
-                       var dom = this.dom;\r
-               if(v=='auto' && Ext.isMac && Ext.isGecko2){ // work around stupid FF 2.0/Mac scroll bar bug\r
-                       dom.style.overflow = 'hidden';\r
-                       (function(){dom.style.overflow = 'auto';}).defer(1);\r
-               }else{\r
-                       dom.style.overflow = v;\r
-               }\r
-               },\r
-\r
-          /**\r
-               * <p>Wraps the specified element with a special 9 element markup/CSS block that renders by default as\r
-               * a gray container with a gradient background, rounded corners and a 4-way shadow.</p>\r
-               * <p>This special markup is used throughout Ext when box wrapping elements ({@link Ext.Button},\r
-               * {@link Ext.Panel} when <tt>{@link Ext.Panel#frame frame=true}</tt>, {@link Ext.Window}).  The markup\r
-               * is of this form:</p>\r
-               * <pre><code>\r
-Ext.Element.boxMarkup =\r
-    &#39;&lt;div class="{0}-tl">&lt;div class="{0}-tr">&lt;div class="{0}-tc">&lt;/div>&lt;/div>&lt;/div>\r
-     &lt;div class="{0}-ml">&lt;div class="{0}-mr">&lt;div class="{0}-mc">&lt;/div>&lt;/div>&lt;/div>\r
-     &lt;div class="{0}-bl">&lt;div class="{0}-br">&lt;div class="{0}-bc">&lt;/div>&lt;/div>&lt;/div>&#39;;\r
-               * </code></pre>\r
-               * <p>Example usage:</p>\r
-               * <pre><code>\r
-// Basic box wrap\r
-Ext.get("foo").boxWrap();\r
-\r
-// You can also add a custom class and use CSS inheritance rules to customize the box look.\r
-// 'x-box-blue' is a built-in alternative -- look at the related CSS definitions as an example\r
-// for how to create a custom box wrap style.\r
-Ext.get("foo").boxWrap().addClass("x-box-blue");\r
-               * </code></pre>\r
-               * @param {String} class (optional) A base CSS class to apply to the containing wrapper element\r
-               * (defaults to <tt>'x-box'</tt>). Note that there are a number of CSS rules that are dependent on\r
-               * this name to make the overall effect work, so if you supply an alternate base class, make sure you\r
-               * also supply all of the necessary rules.\r
-               * @return {Ext.Element} this\r
-               */\r
-           boxWrap : function(cls){\r
-               cls = cls || 'x-box';\r
-               var el = Ext.get(this.insertHtml("beforeBegin", "<div class='" + cls + "'>" + String.format(Ext.Element.boxMarkup, cls) + "</div>"));        //String.format('<div class="{0}">'+Ext.Element.boxMarkup+'</div>', cls)));\r
-               Ext.DomQuery.selectNode('.' + cls + '-mc', el.dom).appendChild(this.dom);\r
-               return el;\r
+       \r
+           /**\r
+            * Looks at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)\r
+            * @param {String} selector The simple selector to test\r
+            * @param {Number/Mixed} maxDepth (optional) The max depth to\r
+                   search as a number or element (defaults to 10 || document.body)\r
+            * @param {Boolean} returnEl (optional) True to return a Ext.Element object instead of DOM node\r
+            * @return {HTMLElement} The matching DOM node (or null if no match was found)\r
+            */\r
+           findParentNode : function(simpleSelector, maxDepth, returnEl){\r
+               var p = Ext.fly(this.dom.parentNode, '_internal');\r
+               return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;\r
            },\r
-\r
-        /**\r
-         * Set the size of this Element. If animation is true, both width and height will be animated concurrently.\r
-         * @param {Mixed} width The new width. This may be one of:<div class="mdetail-params"><ul>\r
-         * <li>A Number specifying the new width in this Element's {@link #defaultUnit}s (by default, pixels).</li>\r
-         * <li>A String used to set the CSS width style. Animation may <b>not</b> be used.\r
-         * <li>A size object in the format <code>{width: widthValue, height: heightValue}</code>.</li>\r
-         * </ul></div>\r
-         * @param {Mixed} height The new height. This may be one of:<div class="mdetail-params"><ul>\r
-         * <li>A Number specifying the new height in this Element's {@link #defaultUnit}s (by default, pixels).</li>\r
-         * <li>A String used to set the CSS height style. Animation may <b>not</b> be used.</li>\r
-         * </ul></div>\r
-         * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object\r
-         * @return {Ext.Element} this\r
-         */\r
-           setSize : function(width, height, animate){\r
-                       var me = this;\r
-                       if(Ext.isObject(width)){ // in case of object from getSize()\r
-                           height = width.height;\r
-                           width = width.width;\r
-                       }\r
-                       width = me.adjustWidth(width);\r
-                       height = me.adjustHeight(height);\r
-                       if(!animate || !me.anim){\r
-                           me.dom.style.width = me.addUnits(width);\r
-                           me.dom.style.height = me.addUnits(height);\r
-                       }else{\r
-                           me.anim({width: {to: width}, height: {to: height}}, me.preanim(arguments, 2));\r
-                       }\r
-                       return me;\r
+       \r
+           /**\r
+            * Walks up the dom looking for a parent node that matches the passed simple selector (e.g. div.some-class or span:first-child).\r
+            * This is a shortcut for findParentNode() that always returns an Ext.Element.\r
+            * @param {String} selector The simple selector to test\r
+            * @param {Number/Mixed} maxDepth (optional) The max depth to\r
+                   search as a number or element (defaults to 10 || document.body)\r
+            * @return {Ext.Element} The matching DOM node (or null if no match was found)\r
+            */\r
+           up : function(simpleSelector, maxDepth){\r
+               return this.findParentNode(simpleSelector, maxDepth, true);\r
            },\r
-\r
+       \r
            /**\r
-            * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders\r
-            * when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements\r
-            * if a height has not been set using CSS.\r
-            * @return {Number}\r
+            * Creates a {@link Ext.CompositeElement} for child nodes based on the passed CSS selector (the selector should not contain an id).\r
+            * @param {String} selector The CSS selector\r
+            * @return {CompositeElement/CompositeElementLite} The composite element\r
             */\r
-           getComputedHeight : function(){\r
-                   var me = this,\r
-                       h = Math.max(me.dom.offsetHeight, me.dom.clientHeight);\r
-               if(!h){\r
-                   h = parseInt(me.getStyle('height'), 10) || 0;\r
-                   if(!me.isBorderBox()){\r
-                       h += me.getFrameWidth('tb');\r
-                   }\r
-               }\r
-               return h;\r
+           select : function(selector){\r
+               return Ext.Element.select(selector, this.dom);\r
            },\r
-\r
+       \r
            /**\r
-            * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders\r
-            * when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements\r
-            * if a width has not been set using CSS.\r
-            * @return {Number}\r
+            * Selects child nodes based on the passed CSS selector (the selector should not contain an id).\r
+            * @param {String} selector The CSS selector\r
+            * @return {Array} An array of the matched nodes\r
             */\r
-           getComputedWidth : function(){\r
-               var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);\r
-               if(!w){\r
-                   w = parseInt(this.getStyle('width'), 10) || 0;\r
-                   if(!this.isBorderBox()){\r
-                       w += this.getFrameWidth('lr');\r
-                   }\r
-               }\r
-               return w;\r
+           query : function(selector){\r
+               return DQ.select(selector, this.dom);\r
            },\r
-\r
+       \r
            /**\r
-            * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()\r
-            for more information about the sides.\r
-            * @param {String} sides\r
-            * @return {Number}\r
+            * Selects a single child at any depth below this element based on the passed CSS selector (the selector should not contain an id).\r
+            * @param {String} selector The CSS selector\r
+            * @param {Boolean} returnDom (optional) True to return the DOM node instead of Ext.Element (defaults to false)\r
+            * @return {HTMLElement/Ext.Element} The child Ext.Element (or DOM node if returnDom = true)\r
             */\r
-           getFrameWidth : function(sides, onlyContentBox){\r
-               return onlyContentBox && this.isBorderBox() ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));\r
+           child : function(selector, returnDom){\r
+               var n = DQ.selectNode(selector, this.dom);\r
+               return returnDom ? n : GET(n);\r
            },\r
-\r
+       \r
            /**\r
-            * Sets up event handlers to add and remove a css class when the mouse is over this element\r
-            * @param {String} className\r
-            * @return {Ext.Element} this\r
+            * Selects a single *direct* child based on the passed CSS selector (the selector should not contain an id).\r
+            * @param {String} selector The CSS selector\r
+            * @param {Boolean} returnDom (optional) True to return the DOM node instead of Ext.Element (defaults to false)\r
+            * @return {HTMLElement/Ext.Element} The child Ext.Element (or DOM node if returnDom = true)\r
             */\r
-           addClassOnOver : function(className){\r
-               this.hover(\r
-                   function(){\r
-                       Ext.fly(this, INTERNAL).addClass(className);\r
-                   },\r
-                   function(){\r
-                       Ext.fly(this, INTERNAL).removeClass(className);\r
-                   }\r
-               );\r
-               return this;\r
+           down : function(selector, returnDom){\r
+               var n = DQ.selectNode(" > " + selector, this.dom);\r
+               return returnDom ? n : GET(n);\r
            },\r
-\r
+       \r
+                /**\r
+            * Gets the parent node for this element, optionally chaining up trying to match a selector\r
+            * @param {String} selector (optional) Find a parent node that matches the passed simple selector\r
+            * @param {Boolean} returnDom (optional) True to return a raw dom node instead of an Ext.Element\r
+            * @return {Ext.Element/HTMLElement} The parent node or null\r
+                */\r
+           parent : function(selector, returnDom){\r
+               return this.matchNode(PARENTNODE, PARENTNODE, selector, returnDom);\r
+           },\r
+       \r
+            /**\r
+            * Gets the next sibling, skipping text nodes\r
+            * @param {String} selector (optional) Find the next sibling that matches the passed simple selector\r
+            * @param {Boolean} returnDom (optional) True to return a raw dom node instead of an Ext.Element\r
+            * @return {Ext.Element/HTMLElement} The next sibling or null\r
+                */\r
+           next : function(selector, returnDom){\r
+               return this.matchNode(NEXTSIBLING, NEXTSIBLING, selector, returnDom);\r
+           },\r
+       \r
+           /**\r
+            * Gets the previous sibling, skipping text nodes\r
+            * @param {String} selector (optional) Find the previous sibling that matches the passed simple selector\r
+            * @param {Boolean} returnDom (optional) True to return a raw dom node instead of an Ext.Element\r
+            * @return {Ext.Element/HTMLElement} The previous sibling or null\r
+                */\r
+           prev : function(selector, returnDom){\r
+               return this.matchNode(PREVIOUSSIBLING, PREVIOUSSIBLING, selector, returnDom);\r
+           },\r
+       \r
+       \r
+           /**\r
+            * Gets the first child, skipping text nodes\r
+            * @param {String} selector (optional) Find the next sibling that matches the passed simple selector\r
+            * @param {Boolean} returnDom (optional) True to return a raw dom node instead of an Ext.Element\r
+            * @return {Ext.Element/HTMLElement} The first child or null\r
+                */\r
+           first : function(selector, returnDom){\r
+               return this.matchNode(NEXTSIBLING, 'firstChild', selector, returnDom);\r
+           },\r
+       \r
+           /**\r
+            * Gets the last child, skipping text nodes\r
+            * @param {String} selector (optional) Find the previous sibling that matches the passed simple selector\r
+            * @param {Boolean} returnDom (optional) True to return a raw dom node instead of an Ext.Element\r
+            * @return {Ext.Element/HTMLElement} The last child or null\r
+                */\r
+           last : function(selector, returnDom){\r
+               return this.matchNode(PREVIOUSSIBLING, 'lastChild', selector, returnDom);\r
+           },\r
+           \r
+           matchNode : function(dir, start, selector, returnDom){\r
+               var n = this.dom[start];\r
+               while(n){\r
+                   if(n.nodeType == 1 && (!selector || DQ.is(n, selector))){\r
+                       return !returnDom ? GET(n) : n;\r
+                   }\r
+                   n = n[dir];\r
+               }\r
+               return null;\r
+           }   \r
+    }\r
+}());/**\r
+ * @class Ext.Element\r
+ */\r
+Ext.Element.addMethods({\r
+    /**\r
+     * Creates a {@link Ext.CompositeElement} for child nodes based on the passed CSS selector (the selector should not contain an id).\r
+     * @param {String} selector The CSS selector\r
+     * @param {Boolean} unique (optional) True to create a unique Ext.Element for each child (defaults to false, which creates a single shared flyweight object)\r
+     * @return {CompositeElement/CompositeElementLite} The composite element\r
+     */\r
+    select : function(selector, unique){\r
+        return Ext.Element.select(selector, unique, this.dom);\r
+    }\r
+});/**\r
+ * @class Ext.Element\r
+ */\r
+Ext.Element.addMethods(\r
+function() {\r
+       var GETDOM = Ext.getDom,\r
+               GET = Ext.get,\r
+               DH = Ext.DomHelper;\r
+       \r
+       return {\r
            /**\r
-            * Sets up event handlers to add and remove a css class when this element has the focus\r
-            * @param {String} className\r
+            * Appends the passed element(s) to this element\r
+            * @param {String/HTMLElement/Array/Element/CompositeElement} el\r
             * @return {Ext.Element} this\r
             */\r
-           addClassOnFocus : function(className){\r
-                   this.on("focus", function(){\r
-                       Ext.fly(this, INTERNAL).addClass(className);\r
-                   }, this.dom);\r
-                   this.on("blur", function(){\r
-                       Ext.fly(this, INTERNAL).removeClass(className);\r
-                   }, this.dom);\r
-                   return this;\r
+           appendChild: function(el){        \r
+               return GET(el).appendTo(this);        \r
            },\r
-\r
+       \r
            /**\r
-            * Sets up event handlers to add and remove a css class when the mouse is down and then up on this element (a click effect)\r
-            * @param {String} className\r
+            * Appends this element to the passed element\r
+            * @param {Mixed} el The new parent element\r
             * @return {Ext.Element} this\r
             */\r
-           addClassOnClick : function(className){\r
-               var dom = this.dom;\r
-               this.on("mousedown", function(){\r
-                   Ext.fly(dom, INTERNAL).addClass(className);\r
-                   var d = Ext.getDoc(),\r
-                       fn = function(){\r
-                               Ext.fly(dom, INTERNAL).removeClass(className);\r
-                               d.removeListener("mouseup", fn);\r
-                           };\r
-                   d.on("mouseup", fn);\r
-               });\r
+           appendTo: function(el){        \r
+               GETDOM(el).appendChild(this.dom);        \r
                return this;\r
            },\r
-\r
+       \r
            /**\r
-            * Returns the width and height of the viewport.\r
-        * <pre><code>\r
-        var vpSize = Ext.getBody().getViewSize();\r
-\r
-        // all Windows created afterwards will have a default value of 90% height and 95% width\r
-        Ext.Window.override({\r
-            width: vpSize.width * 0.9,\r
-            height: vpSize.height * 0.95\r
-        });\r
-        // To handle window resizing you would have to hook onto onWindowResize.\r
-        </code></pre>\r
-            * @return {Object} An object containing the viewport's size {width: (viewport width), height: (viewport height)}\r
+            * Inserts this element before the passed element in the DOM\r
+            * @param {Mixed} el The element before which this element will be inserted\r
+            * @return {Ext.Element} this\r
             */\r
-           getViewSize : function(){\r
-               var doc = document,\r
-                       d = this.dom,\r
-                       extdom = Ext.lib.Dom,\r
-                       isDoc = (d == doc || d == doc.body);\r
-               return { width : (isDoc ? extdom.getViewWidth() : d.clientWidth),\r
-                                height : (isDoc ? extdom.getViewHeight() : d.clientHeight) };\r
+           insertBefore: function(el){                   \r
+               (el = GETDOM(el)).parentNode.insertBefore(this.dom, el);\r
+               return this;\r
            },\r
-\r
+       \r
            /**\r
-            * Returns the size of the element.\r
-            * @param {Boolean} contentSize (optional) true to get the width/size minus borders and padding\r
-            * @return {Object} An object containing the element's size {width: (element width), height: (element height)}\r
+            * Inserts this element after the passed element in the DOM\r
+            * @param {Mixed} el The element to insert after\r
+            * @return {Ext.Element} this\r
             */\r
-           getSize : function(contentSize){\r
-               return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};\r
+           insertAfter: function(el){\r
+               (el = GETDOM(el)).parentNode.insertBefore(this.dom, el.nextSibling);\r
+               return this;\r
            },\r
-\r
+       \r
+           /**\r
+            * Inserts (or creates) an element (or DomHelper config) as the first child of this element\r
+            * @param {Mixed/Object} el The id or element to insert or a DomHelper config to create and insert\r
+            * @return {Ext.Element} The new child\r
+            */\r
+           insertFirst: function(el, returnDom){\r
+            el = el || {};\r
+            if(el.nodeType || el.dom || typeof el == 'string'){ // element\r
+                el = GETDOM(el);\r
+                this.dom.insertBefore(el, this.dom.firstChild);\r
+                return !returnDom ? GET(el) : el;\r
+            }else{ // dh config\r
+                return this.createChild(el, this.dom.firstChild, returnDom);\r
+            }\r
+        },\r
+       \r
            /**\r
-            * Forces the browser to repaint this element\r
+            * Replaces the passed element with this element\r
+            * @param {Mixed} el The element to replace\r
             * @return {Ext.Element} this\r
             */\r
-           repaint : function(){\r
-               var dom = this.dom;\r
-               this.addClass("x-repaint");\r
-               setTimeout(function(){\r
-                   Ext.fly(dom).removeClass("x-repaint");\r
-               }, 1);\r
+           replace: function(el){\r
+               el = GET(el);\r
+               this.insertBefore(el);\r
+               el.remove();\r
                return this;\r
            },\r
-\r
+       \r
            /**\r
-            * Disables text selection for this element (normalized across browsers)\r
+            * Replaces this element with the passed element\r
+            * @param {Mixed/Object} el The new element or a DomHelper config of an element to create\r
             * @return {Ext.Element} this\r
             */\r
-           unselectable : function(){\r
-               this.dom.unselectable = "on";\r
-               return this.swallowEvent("selectstart", true).\r
-                                   applyStyles("-moz-user-select:none;-khtml-user-select:none;").\r
-                                   addClass("x-unselectable");\r
+           replaceWith: function(el){\r
+                   var me = this;\r
+                \r
+            if(el.nodeType || el.dom || typeof el == 'string'){\r
+                el = GETDOM(el);\r
+                me.dom.parentNode.insertBefore(el, me.dom);\r
+            }else{\r
+                el = DH.insertBefore(me.dom, el);\r
+            }\r
+               \r
+               delete Ext.elCache[me.id];\r
+               Ext.removeNode(me.dom);      \r
+               me.id = Ext.id(me.dom = el);\r
+               Ext.Element.addToCache(me.isFlyweight ? new Ext.Element(me.dom) : me);     \r
+            return me;\r
            },\r
-\r
-           /**\r
-            * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,\r
-            * then it returns the calculated width of the sides (see getPadding)\r
-            * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides\r
-            * @return {Object/Number}\r
-            */\r
-           getMargins : function(side){\r
-                   var me = this,\r
-                       key,\r
-                       hash = {t:"top", l:"left", r:"right", b: "bottom"},\r
-                       o = {};\r
-\r
-                   if (!side) {\r
-                       for (key in me.margins){\r
-                               o[hash[key]] = parseInt(me.getStyle(me.margins[key]), 10) || 0;\r
-                }\r
-                       return o;\r
-               } else {\r
-                   return me.addStyles.call(me, side, me.margins);\r
+           \r
+               /**\r
+                * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.\r
+                * @param {Object} config DomHelper element config object.  If no tag is specified (e.g., {tag:'input'}) then a div will be\r
+                * automatically generated with the specified attributes.\r
+                * @param {HTMLElement} insertBefore (optional) a child element of this element\r
+                * @param {Boolean} returnDom (optional) true to return the dom node instead of creating an Element\r
+                * @return {Ext.Element} The new child element\r
+                */\r
+               createChild: function(config, insertBefore, returnDom){\r
+                   config = config || {tag:'div'};\r
+                   return insertBefore ? \r
+                          DH.insertBefore(insertBefore, config, returnDom !== true) :  \r
+                          DH[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config,  returnDom !== true);\r
+               },\r
+               \r
+               /**\r
+                * Creates and wraps this element with another element\r
+                * @param {Object} config (optional) DomHelper element config object for the wrapper element or null for an empty div\r
+                * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Ext.Element\r
+                * @return {HTMLElement/Element} The newly created wrapper element\r
+                */\r
+               wrap: function(config, returnDom){        \r
+                   var newEl = DH.insertBefore(this.dom, config || {tag: "div"}, !returnDom);\r
+                   newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);\r
+                   return newEl;\r
+               },\r
+               \r
+               /**\r
+                * Inserts an html fragment into this element\r
+                * @param {String} where Where to insert the html in relation to this element - beforeBegin, afterBegin, beforeEnd, afterEnd.\r
+                * @param {String} html The HTML fragment\r
+                * @param {Boolean} returnEl (optional) True to return an Ext.Element (defaults to false)\r
+                * @return {HTMLElement/Ext.Element} The inserted node (or nearest related if more than 1 inserted)\r
+                */\r
+               insertHtml : function(where, html, returnEl){\r
+                   var el = DH.insertHtml(where, this.dom, html);\r
+                   return returnEl ? Ext.get(el) : el;\r
+               }\r
+       }\r
+}());/**\r
+ * @class Ext.Element\r
+ */\r
+Ext.apply(Ext.Element.prototype, function() {\r
+       var GETDOM = Ext.getDom,\r
+               GET = Ext.get,\r
+               DH = Ext.DomHelper;\r
+       \r
+       return {        \r
+               /**\r
+            * Inserts (or creates) the passed element (or DomHelper config) as a sibling of this element\r
+            * @param {Mixed/Object/Array} el The id, element to insert or a DomHelper config to create and insert *or* an array of any of those.\r
+            * @param {String} where (optional) 'before' or 'after' defaults to before\r
+            * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Ext.Element\r
+            * @return {Ext.Element} The inserted Element. If an array is passed, the last inserted element is returned.\r
+            */\r
+           insertSibling: function(el, where, returnDom){\r
+               var me = this,\r
+                       rt,\r
+                isAfter = (where || 'before').toLowerCase() == 'after',\r
+                insertEl;\r
+                       \r
+               if(Ext.isArray(el)){\r
+                insertEl = me;\r
+                   Ext.each(el, function(e) {\r
+                           rt = Ext.fly(insertEl, '_internal').insertSibling(e, where, returnDom);\r
+                    if(isAfter){\r
+                        insertEl = rt;\r
+                    }\r
+                   });\r
+                   return rt;\r
                }\r
+                       \r
+               el = el || {};\r
+               \r
+            if(el.nodeType || el.dom){\r
+                rt = me.dom.parentNode.insertBefore(GETDOM(el), isAfter ? me.dom.nextSibling : me.dom);\r
+                if (!returnDom) {\r
+                    rt = GET(rt);\r
+                }\r
+            }else{\r
+                if (isAfter && !me.dom.nextSibling) {\r
+                    rt = DH.append(me.dom.parentNode, el, !returnDom);\r
+                } else {                    \r
+                    rt = DH[isAfter ? 'insertAfter' : 'insertBefore'](me.dom, el, !returnDom);\r
+                }\r
+            }\r
+               return rt;\r
            }\r
     };\r
-}());/**\r
+}());/**
+ * @class Ext.Element
+ */
+Ext.Element.addMethods(function(){
+    // local style camelizing for speed
+    var propCache = {},
+        camelRe = /(-[a-z])/gi,
+        classReCache = {},
+        view = document.defaultView,
+        propFloat = Ext.isIE ? 'styleFloat' : 'cssFloat',
+        opacityRe = /alpha\(opacity=(.*)\)/i,
+        trimRe = /^\s+|\s+$/g,
+        EL = Ext.Element,
+        PADDING = "padding",
+        MARGIN = "margin",
+        BORDER = "border",
+        LEFT = "-left",
+        RIGHT = "-right",
+        TOP = "-top",
+        BOTTOM = "-bottom",
+        WIDTH = "-width",
+        MATH = Math,
+        HIDDEN = 'hidden',
+        ISCLIPPED = 'isClipped',
+        OVERFLOW = 'overflow',
+        OVERFLOWX = 'overflow-x',
+        OVERFLOWY = 'overflow-y',
+        ORIGINALCLIP = 'originalClip',
+        // special markup used throughout Ext when box wrapping elements
+        borders = {l: BORDER + LEFT + WIDTH, r: BORDER + RIGHT + WIDTH, t: BORDER + TOP + WIDTH, b: BORDER + BOTTOM + WIDTH},
+        paddings = {l: PADDING + LEFT, r: PADDING + RIGHT, t: PADDING + TOP, b: PADDING + BOTTOM},
+        margins = {l: MARGIN + LEFT, r: MARGIN + RIGHT, t: MARGIN + TOP, b: MARGIN + BOTTOM},
+        data = Ext.Element.data;
+
+
+    // private
+    function camelFn(m, a) {
+        return a.charAt(1).toUpperCase();
+    }
+
+    function chkCache(prop) {
+        return propCache[prop] || (propCache[prop] = prop == 'float' ? propFloat : prop.replace(camelRe, camelFn));
+    }
+
+    return {
+        // private  ==> used by Fx
+        adjustWidth : function(width) {
+            var me = this;
+            var isNum = Ext.isNumber(width);
+            if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
+               width -= (me.getBorderWidth("lr") + me.getPadding("lr"));
+            }
+            return (isNum && width < 0) ? 0 : width;
+        },
+
+        // private   ==> used by Fx
+        adjustHeight : function(height) {
+            var me = this;
+            var isNum = Ext.isNumber(height);
+            if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
+               height -= (me.getBorderWidth("tb") + me.getPadding("tb"));
+            }
+            return (isNum && height < 0) ? 0 : height;
+        },
+
+
+        /**
+         * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
+         * @param {String/Array} className The CSS class to add, or an array of classes
+         * @return {Ext.Element} this
+         */
+        addClass : function(className){
+            var me = this, i, len, v;
+            className = Ext.isArray(className) ? className : [className];
+            for (i=0, len = className.length; i < len; i++) {
+                v = className[i];
+                if (v) {
+                    me.dom.className += (!me.hasClass(v) && v ? " " + v : "");
+                };
+            };
+            return me;
+        },
+
+        /**
+         * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
+         * @param {String/Array} className The CSS class to add, or an array of classes
+         * @return {Ext.Element} this
+         */
+        radioClass : function(className){
+            var cn = this.dom.parentNode.childNodes, v;
+            className = Ext.isArray(className) ? className : [className];
+            for (var i=0, len = cn.length; i < len; i++) {
+                v = cn[i];
+                if(v && v.nodeType == 1) {
+                    Ext.fly(v, '_internal').removeClass(className);
+                }
+            };
+            return this.addClass(className);
+        },
+
+        /**
+         * Removes one or more CSS classes from the element.
+         * @param {String/Array} className The CSS class to remove, or an array of classes
+         * @return {Ext.Element} this
+         */
+        removeClass : function(className){
+            var me = this, v;
+            className = Ext.isArray(className) ? className : [className];
+            if (me.dom && me.dom.className) {
+                for (var i=0, len=className.length; i < len; i++) {
+                    v = className[i];
+                    if(v) {
+                        me.dom.className = me.dom.className.replace(
+                            classReCache[v] = classReCache[v] || new RegExp('(?:^|\\s+)' + v + '(?:\\s+|$)', "g"), " "
+                        );
+                    }
+                };
+            }
+            return me;
+        },
+
+        /**
+         * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
+         * @param {String} className The CSS class to toggle
+         * @return {Ext.Element} this
+         */
+        toggleClass : function(className){
+            return this.hasClass(className) ? this.removeClass(className) : this.addClass(className);
+        },
+
+        /**
+         * Checks if the specified CSS class exists on this element's DOM node.
+         * @param {String} className The CSS class to check for
+         * @return {Boolean} True if the class exists, else false
+         */
+        hasClass : function(className){
+            return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
+        },
+
+        /**
+         * Replaces a CSS class on the element with another.  If the old name does not exist, the new name will simply be added.
+         * @param {String} oldClassName The CSS class to replace
+         * @param {String} newClassName The replacement CSS class
+         * @return {Ext.Element} this
+         */
+        replaceClass : function(oldClassName, newClassName){
+            return this.removeClass(oldClassName).addClass(newClassName);
+        },
+
+        isStyle : function(style, val) {
+            return this.getStyle(style) == val;
+        },
+
+        /**
+         * Normalizes currentStyle and computedStyle.
+         * @param {String} property The style property whose value is returned.
+         * @return {String} The current value of the style property for this element.
+         */
+        getStyle : function(){
+            return view && view.getComputedStyle ?
+                function(prop){
+                    var el = this.dom,
+                        v,
+                        cs,
+                        out,
+                        display,
+                        wk = Ext.isWebKit,
+                        display;
+                        
+                    if(el == document){
+                        return null;
+                    }
+                    prop = chkCache(prop);
+                    // Fix bug caused by this: https://bugs.webkit.org/show_bug.cgi?id=13343
+                    if(wk && /marginRight/.test(prop)){
+                        display = this.getStyle('display');
+                        el.style.display = 'inline-block';
+                    }
+                    out = (v = el.style[prop]) ? v :
+                           (cs = view.getComputedStyle(el, "")) ? cs[prop] : null;
+
+                    // Webkit returns rgb values for transparent.
+                    if(wk){
+                        if(out == 'rgba(0, 0, 0, 0)'){
+                            out = 'transparent';
+                        }else if(display){
+                            el.style.display = display;
+                        }
+                    }
+                    return out;
+                } :
+                function(prop){
+                    var el = this.dom,
+                        m,
+                        cs;
+
+                    if(el == document) return null;
+                    if (prop == 'opacity') {
+                        if (el.style.filter.match) {
+                            if(m = el.style.filter.match(opacityRe)){
+                                var fv = parseFloat(m[1]);
+                                if(!isNaN(fv)){
+                                    return fv ? fv / 100 : 0;
+                                }
+                            }
+                        }
+                        return 1;
+                    }
+                    prop = chkCache(prop);
+                    return el.style[prop] || ((cs = el.currentStyle) ? cs[prop] : null);
+                };
+        }(),
+
+        /**
+         * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
+         * are convert to standard 6 digit hex color.
+         * @param {String} attr The css attribute
+         * @param {String} defaultValue The default value to use when a valid color isn't found
+         * @param {String} prefix (optional) defaults to #. Use an empty string when working with
+         * color anims.
+         */
+        getColor : function(attr, defaultValue, prefix){
+            var v = this.getStyle(attr),
+                color = Ext.isDefined(prefix) ? prefix : '#',
+                h;
+
+            if(!v || /transparent|inherit/.test(v)){
+                return defaultValue;
+            }
+            if(/^r/.test(v)){
+                Ext.each(v.slice(4, v.length -1).split(','), function(s){
+                    h = parseInt(s, 10);
+                    color += (h < 16 ? '0' : '') + h.toString(16);
+                });
+            }else{
+                v = v.replace('#', '');
+                color += v.length == 3 ? v.replace(/^(\w)(\w)(\w)$/, '$1$1$2$2$3$3') : v;
+            }
+            return(color.length > 5 ? color.toLowerCase() : defaultValue);
+        },
+
+        /**
+         * Wrapper for setting style properties, also takes single object parameter of multiple styles.
+         * @param {String/Object} property The style property to be set, or an object of multiple styles.
+         * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
+         * @return {Ext.Element} this
+         */
+        setStyle : function(prop, value){
+            var tmp,
+                style,
+                camel;
+            if (!Ext.isObject(prop)) {
+                tmp = {};
+                tmp[prop] = value;
+                prop = tmp;
+            }
+            for (style in prop) {
+                value = prop[style];
+                style == 'opacity' ?
+                    this.setOpacity(value) :
+                    this.dom.style[chkCache(style)] = value;
+            }
+            return this;
+        },
+
+        /**
+         * Set the opacity of the element
+         * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
+         * @param {Boolean/Object} animate (optional) a standard Element animation config object or <tt>true</tt> for
+         * the default animation (<tt>{duration: .35, easing: 'easeIn'}</tt>)
+         * @return {Ext.Element} this
+         */
+         setOpacity : function(opacity, animate){
+            var me = this,
+                s = me.dom.style;
+
+            if(!animate || !me.anim){
+                if(Ext.isIE){
+                    var opac = opacity < 1 ? 'alpha(opacity=' + opacity * 100 + ')' : '',
+                    val = s.filter.replace(opacityRe, '').replace(trimRe, '');
+
+                    s.zoom = 1;
+                    s.filter = val + (val.length > 0 ? ' ' : '') + opac;
+                }else{
+                    s.opacity = opacity;
+                }
+            }else{
+                me.anim({opacity: {to: opacity}}, me.preanim(arguments, 1), null, .35, 'easeIn');
+            }
+            return me;
+        },
+
+        /**
+         * Clears any opacity settings from this element. Required in some cases for IE.
+         * @return {Ext.Element} this
+         */
+        clearOpacity : function(){
+            var style = this.dom.style;
+            if(Ext.isIE){
+                if(!Ext.isEmpty(style.filter)){
+                    style.filter = style.filter.replace(opacityRe, '').replace(trimRe, '');
+                }
+            }else{
+                style.opacity = style['-moz-opacity'] = style['-khtml-opacity'] = '';
+            }
+            return this;
+        },
+
+        /**
+         * Returns the offset height of the element
+         * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
+         * @return {Number} The element's height
+         */
+        getHeight : function(contentHeight){
+            var me = this,
+                dom = me.dom,
+                hidden = Ext.isIE && me.isStyle('display', 'none'),
+                h = MATH.max(dom.offsetHeight, hidden ? 0 : dom.clientHeight) || 0;
+
+            h = !contentHeight ? h : h - me.getBorderWidth("tb") - me.getPadding("tb");
+            return h < 0 ? 0 : h;
+        },
+
+        /**
+         * Returns the offset width of the element
+         * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
+         * @return {Number} The element's width
+         */
+        getWidth : function(contentWidth){
+            var me = this,
+                dom = me.dom,
+                hidden = Ext.isIE && me.isStyle('display', 'none'),
+                w = MATH.max(dom.offsetWidth, hidden ? 0 : dom.clientWidth) || 0;
+            w = !contentWidth ? w : w - me.getBorderWidth("lr") - me.getPadding("lr");
+            return w < 0 ? 0 : w;
+        },
+
+        /**
+         * Set the width of this Element.
+         * @param {Mixed} width The new width. This may be one of:<div class="mdetail-params"><ul>
+         * <li>A Number specifying the new width in this Element's {@link #defaultUnit}s (by default, pixels).</li>
+         * <li>A String used to set the CSS width style. Animation may <b>not</b> be used.
+         * </ul></div>
+         * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
+         * @return {Ext.Element} this
+         */
+        setWidth : function(width, animate){
+            var me = this;
+            width = me.adjustWidth(width);
+            !animate || !me.anim ?
+                me.dom.style.width = me.addUnits(width) :
+                me.anim({width : {to : width}}, me.preanim(arguments, 1));
+            return me;
+        },
+
+        /**
+         * Set the height of this Element.
+         * <pre><code>
+// change the height to 200px and animate with default configuration
+Ext.fly('elementId').setHeight(200, true);
+
+// change the height to 150px and animate with a custom configuration
+Ext.fly('elId').setHeight(150, {
+    duration : .5, // animation will have a duration of .5 seconds
+    // will change the content to "finished"
+    callback: function(){ this.{@link #update}("finished"); }
+});
+         * </code></pre>
+         * @param {Mixed} height The new height. This may be one of:<div class="mdetail-params"><ul>
+         * <li>A Number specifying the new height in this Element's {@link #defaultUnit}s (by default, pixels.)</li>
+         * <li>A String used to set the CSS height style. Animation may <b>not</b> be used.</li>
+         * </ul></div>
+         * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
+         * @return {Ext.Element} this
+         */
+         setHeight : function(height, animate){
+            var me = this;
+            height = me.adjustHeight(height);
+            !animate || !me.anim ?
+                me.dom.style.height = me.addUnits(height) :
+                me.anim({height : {to : height}}, me.preanim(arguments, 1));
+            return me;
+        },
+
+        /**
+         * Gets the width of the border(s) for the specified side(s)
+         * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
+         * passing <tt>'lr'</tt> would get the border <b><u>l</u></b>eft width + the border <b><u>r</u></b>ight width.
+         * @return {Number} The width of the sides passed added together
+         */
+        getBorderWidth : function(side){
+            return this.addStyles(side, borders);
+        },
+
+        /**
+         * Gets the width of the padding(s) for the specified side(s)
+         * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
+         * passing <tt>'lr'</tt> would get the padding <b><u>l</u></b>eft + the padding <b><u>r</u></b>ight.
+         * @return {Number} The padding of the sides passed added together
+         */
+        getPadding : function(side){
+            return this.addStyles(side, paddings);
+        },
+
+        /**
+         *  Store the current overflow setting and clip overflow on the element - use <tt>{@link #unclip}</tt> to remove
+         * @return {Ext.Element} this
+         */
+        clip : function(){
+            var me = this,
+                dom = me.dom;
+
+            if(!data(dom, ISCLIPPED)){
+                data(dom, ISCLIPPED, true);
+                data(dom, ORIGINALCLIP, {
+                    o: me.getStyle(OVERFLOW),
+                    x: me.getStyle(OVERFLOWX),
+                    y: me.getStyle(OVERFLOWY)
+                });
+                me.setStyle(OVERFLOW, HIDDEN);
+                me.setStyle(OVERFLOWX, HIDDEN);
+                me.setStyle(OVERFLOWY, HIDDEN);
+            }
+            return me;
+        },
+
+        /**
+         *  Return clipping (overflow) to original clipping before <tt>{@link #clip}</tt> was called
+         * @return {Ext.Element} this
+         */
+        unclip : function(){
+            var me = this,
+                dom = me.dom;
+
+            if(data(dom, ISCLIPPED)){
+                data(dom, ISCLIPPED, false);
+                var o = data(dom, ORIGINALCLIP);
+                if(o.o){
+                    me.setStyle(OVERFLOW, o.o);
+                }
+                if(o.x){
+                    me.setStyle(OVERFLOWX, o.x);
+                }
+                if(o.y){
+                    me.setStyle(OVERFLOWY, o.y);
+                }
+            }
+            return me;
+        },
+
+        // private
+        addStyles : function(sides, styles){
+            var val = 0,
+                m = sides.match(/\w/g),
+                s;
+            for (var i=0, len=m.length; i<len; i++) {
+                s = m[i] && parseInt(this.getStyle(styles[m[i]]), 10);
+                if (s) {
+                    val += MATH.abs(s);
+                }
+            }
+            return val;
+        },
+
+        margins : margins
+    }
+}()
+);
+/**\r
  * @class Ext.Element\r
  */\r
-(function(){\r
-var D = Ext.lib.Dom,\r
-        LEFT = "left",\r
-        RIGHT = "right",\r
-        TOP = "top",\r
-        BOTTOM = "bottom",\r
-        POSITION = "position",\r
-        STATIC = "static",\r
-        RELATIVE = "relative",\r
-        AUTO = "auto",\r
-        ZINDEX = "z-index";\r
-\r
-Ext.Element.addMethods({\r
-       /**\r
-      * Gets the current X position of the element based on page coordinates.  Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).\r
-      * @return {Number} The X position of the element\r
-      */\r
-    getX : function(){\r
-        return D.getX(this.dom);\r
-    },\r
 \r
-    /**\r
-      * Gets the current Y position of the element based on page coordinates.  Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).\r
-      * @return {Number} The Y position of the element\r
-      */\r
-    getY : function(){\r
-        return D.getY(this.dom);\r
-    },\r
+// special markup used throughout Ext when box wrapping elements\r
+Ext.Element.boxMarkup = '<div class="{0}-tl"><div class="{0}-tr"><div class="{0}-tc"></div></div></div><div class="{0}-ml"><div class="{0}-mr"><div class="{0}-mc"></div></div></div><div class="{0}-bl"><div class="{0}-br"><div class="{0}-bc"></div></div></div>';\r
 \r
-    /**\r
-      * Gets the current position of the element based on page coordinates.  Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).\r
-      * @return {Array} The XY position of the element\r
-      */\r
+Ext.Element.addMethods(function(){\r
+    var INTERNAL = "_internal",\r
+        pxMatch = /(\d+\.?\d+)px/;\r
+    return {\r
+        /**\r
+         * More flexible version of {@link #setStyle} for setting style properties.\r
+         * @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form {width:"100px"}, or\r
+         * a function which returns such a specification.\r
+         * @return {Ext.Element} this\r
+         */\r
+        applyStyles : function(style){\r
+            Ext.DomHelper.applyStyles(this.dom, style);\r
+            return this;\r
+        },\r
+\r
+        /**\r
+         * Returns an object with properties matching the styles requested.\r
+         * For example, el.getStyles('color', 'font-size', 'width') might return\r
+         * {'color': '#FFFFFF', 'font-size': '13px', 'width': '100px'}.\r
+         * @param {String} style1 A style name\r
+         * @param {String} style2 A style name\r
+         * @param {String} etc.\r
+         * @return {Object} The style object\r
+         */\r
+        getStyles : function(){\r
+            var ret = {};\r
+            Ext.each(arguments, function(v) {\r
+               ret[v] = this.getStyle(v);\r
+            },\r
+            this);\r
+            return ret;\r
+        },\r
+\r
+        // private  ==> used by ext full\r
+        setOverflow : function(v){\r
+            var dom = this.dom;\r
+            if(v=='auto' && Ext.isMac && Ext.isGecko2){ // work around stupid FF 2.0/Mac scroll bar bug\r
+                dom.style.overflow = 'hidden';\r
+                (function(){dom.style.overflow = 'auto';}).defer(1);\r
+            }else{\r
+                dom.style.overflow = v;\r
+            }\r
+        },\r
+\r
+       /**\r
+        * <p>Wraps the specified element with a special 9 element markup/CSS block that renders by default as\r
+        * a gray container with a gradient background, rounded corners and a 4-way shadow.</p>\r
+        * <p>This special markup is used throughout Ext when box wrapping elements ({@link Ext.Button},\r
+        * {@link Ext.Panel} when <tt>{@link Ext.Panel#frame frame=true}</tt>, {@link Ext.Window}).  The markup\r
+        * is of this form:</p>\r
+        * <pre><code>\r
+    Ext.Element.boxMarkup =\r
+    &#39;&lt;div class="{0}-tl">&lt;div class="{0}-tr">&lt;div class="{0}-tc">&lt;/div>&lt;/div>&lt;/div>\r
+     &lt;div class="{0}-ml">&lt;div class="{0}-mr">&lt;div class="{0}-mc">&lt;/div>&lt;/div>&lt;/div>\r
+     &lt;div class="{0}-bl">&lt;div class="{0}-br">&lt;div class="{0}-bc">&lt;/div>&lt;/div>&lt;/div>&#39;;\r
+        * </code></pre>\r
+        * <p>Example usage:</p>\r
+        * <pre><code>\r
+    // Basic box wrap\r
+    Ext.get("foo").boxWrap();\r
+\r
+    // You can also add a custom class and use CSS inheritance rules to customize the box look.\r
+    // 'x-box-blue' is a built-in alternative -- look at the related CSS definitions as an example\r
+    // for how to create a custom box wrap style.\r
+    Ext.get("foo").boxWrap().addClass("x-box-blue");\r
+        * </code></pre>\r
+        * @param {String} class (optional) A base CSS class to apply to the containing wrapper element\r
+        * (defaults to <tt>'x-box'</tt>). Note that there are a number of CSS rules that are dependent on\r
+        * this name to make the overall effect work, so if you supply an alternate base class, make sure you\r
+        * also supply all of the necessary rules.\r
+        * @return {Ext.Element} The outermost wrapping element of the created box structure.\r
+        */\r
+        boxWrap : function(cls){\r
+            cls = cls || 'x-box';\r
+            var el = Ext.get(this.insertHtml("beforeBegin", "<div class='" + cls + "'>" + String.format(Ext.Element.boxMarkup, cls) + "</div>"));        //String.format('<div class="{0}">'+Ext.Element.boxMarkup+'</div>', cls)));\r
+            Ext.DomQuery.selectNode('.' + cls + '-mc', el.dom).appendChild(this.dom);\r
+            return el;\r
+        },\r
+\r
+        /**\r
+         * Set the size of this Element. If animation is true, both width and height will be animated concurrently.\r
+         * @param {Mixed} width The new width. This may be one of:<div class="mdetail-params"><ul>\r
+         * <li>A Number specifying the new width in this Element's {@link #defaultUnit}s (by default, pixels).</li>\r
+         * <li>A String used to set the CSS width style. Animation may <b>not</b> be used.\r
+         * <li>A size object in the format <code>{width: widthValue, height: heightValue}</code>.</li>\r
+         * </ul></div>\r
+         * @param {Mixed} height The new height. This may be one of:<div class="mdetail-params"><ul>\r
+         * <li>A Number specifying the new height in this Element's {@link #defaultUnit}s (by default, pixels).</li>\r
+         * <li>A String used to set the CSS height style. Animation may <b>not</b> be used.</li>\r
+         * </ul></div>\r
+         * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object\r
+         * @return {Ext.Element} this\r
+         */\r
+        setSize : function(width, height, animate){\r
+            var me = this;\r
+            if(Ext.isObject(width)){ // in case of object from getSize()\r
+                height = width.height;\r
+                width = width.width;\r
+            }\r
+            width = me.adjustWidth(width);\r
+            height = me.adjustHeight(height);\r
+            if(!animate || !me.anim){\r
+                me.dom.style.width = me.addUnits(width);\r
+                me.dom.style.height = me.addUnits(height);\r
+            }else{\r
+                me.anim({width: {to: width}, height: {to: height}}, me.preanim(arguments, 2));\r
+            }\r
+            return me;\r
+        },\r
+\r
+        /**\r
+         * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders\r
+         * when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements\r
+         * if a height has not been set using CSS.\r
+         * @return {Number}\r
+         */\r
+        getComputedHeight : function(){\r
+            var me = this,\r
+                h = Math.max(me.dom.offsetHeight, me.dom.clientHeight);\r
+            if(!h){\r
+                h = parseFloat(me.getStyle('height')) || 0;\r
+                if(!me.isBorderBox()){\r
+                    h += me.getFrameWidth('tb');\r
+                }\r
+            }\r
+            return h;\r
+        },\r
+\r
+        /**\r
+         * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders\r
+         * when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements\r
+         * if a width has not been set using CSS.\r
+         * @return {Number}\r
+         */\r
+        getComputedWidth : function(){\r
+            var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);\r
+            if(!w){\r
+                w = parseFloat(this.getStyle('width')) || 0;\r
+                if(!this.isBorderBox()){\r
+                    w += this.getFrameWidth('lr');\r
+                }\r
+            }\r
+            return w;\r
+        },\r
+\r
+        /**\r
+         * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()\r
+         for more information about the sides.\r
+         * @param {String} sides\r
+         * @return {Number}\r
+         */\r
+        getFrameWidth : function(sides, onlyContentBox){\r
+            return onlyContentBox && this.isBorderBox() ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));\r
+        },\r
+\r
+        /**\r
+         * Sets up event handlers to add and remove a css class when the mouse is over this element\r
+         * @param {String} className\r
+         * @return {Ext.Element} this\r
+         */\r
+        addClassOnOver : function(className){\r
+            this.hover(\r
+                function(){\r
+                    Ext.fly(this, INTERNAL).addClass(className);\r
+                },\r
+                function(){\r
+                    Ext.fly(this, INTERNAL).removeClass(className);\r
+                }\r
+            );\r
+            return this;\r
+        },\r
+\r
+        /**\r
+         * Sets up event handlers to add and remove a css class when this element has the focus\r
+         * @param {String} className\r
+         * @return {Ext.Element} this\r
+         */\r
+        addClassOnFocus : function(className){\r
+            this.on("focus", function(){\r
+                Ext.fly(this, INTERNAL).addClass(className);\r
+            }, this.dom);\r
+            this.on("blur", function(){\r
+                Ext.fly(this, INTERNAL).removeClass(className);\r
+            }, this.dom);\r
+            return this;\r
+        },\r
+\r
+        /**\r
+         * Sets up event handlers to add and remove a css class when the mouse is down and then up on this element (a click effect)\r
+         * @param {String} className\r
+         * @return {Ext.Element} this\r
+         */\r
+        addClassOnClick : function(className){\r
+            var dom = this.dom;\r
+            this.on("mousedown", function(){\r
+                Ext.fly(dom, INTERNAL).addClass(className);\r
+                var d = Ext.getDoc(),\r
+                    fn = function(){\r
+                        Ext.fly(dom, INTERNAL).removeClass(className);\r
+                        d.removeListener("mouseup", fn);\r
+                    };\r
+                d.on("mouseup", fn);\r
+            });\r
+            return this;\r
+        },\r
+\r
+        /**\r
+         * <p>Returns the dimensions of the element available to lay content out in.<p>\r
+         * <p>If the element (or any ancestor element) has CSS style <code>display : none</code>, the dimensions will be zero.</p>\r
+         * example:<pre><code>\r
+        var vpSize = Ext.getBody().getViewSize();\r
+\r
+        // all Windows created afterwards will have a default value of 90% height and 95% width\r
+        Ext.Window.override({\r
+            width: vpSize.width * 0.9,\r
+            height: vpSize.height * 0.95\r
+        });\r
+        // To handle window resizing you would have to hook onto onWindowResize.\r
+        * </code></pre>\r
+        *\r
+        * getViewSize utilizes clientHeight/clientWidth which excludes sizing of scrollbars.\r
+        * To obtain the size including scrollbars, use getStyleSize\r
+        *\r
+        * Sizing of the document body is handled at the adapter level which handles special cases for IE and strict modes, etc.\r
+        */\r
+\r
+        getViewSize : function(){\r
+            var doc = document,\r
+                d = this.dom,\r
+                isDoc = (d == doc || d == doc.body);\r
+\r
+            // If the body, use Ext.lib.Dom\r
+            if (isDoc) {\r
+                var extdom = Ext.lib.Dom;\r
+                return {\r
+                    width : extdom.getViewWidth(),\r
+                    height : extdom.getViewHeight()\r
+                }\r
+\r
+            // Else use clientHeight/clientWidth\r
+            } else {\r
+                return {\r
+                    width : d.clientWidth,\r
+                    height : d.clientHeight\r
+                }\r
+            }\r
+        },\r
+\r
+        /**\r
+        * <p>Returns the dimensions of the element available to lay content out in.<p>\r
+        *\r
+        * getStyleSize utilizes prefers style sizing if present, otherwise it chooses the larger of offsetHeight/clientHeight and offsetWidth/clientWidth.\r
+        * To obtain the size excluding scrollbars, use getViewSize\r
+        *\r
+        * Sizing of the document body is handled at the adapter level which handles special cases for IE and strict modes, etc.\r
+        */\r
+\r
+        getStyleSize : function(){\r
+            var me = this,\r
+                w, h,\r
+                doc = document,\r
+                d = this.dom,\r
+                isDoc = (d == doc || d == doc.body),\r
+                s = d.style;\r
+\r
+            // If the body, use Ext.lib.Dom\r
+            if (isDoc) {\r
+                var extdom = Ext.lib.Dom;\r
+                return {\r
+                    width : extdom.getViewWidth(),\r
+                    height : extdom.getViewHeight()\r
+                }\r
+            }\r
+            // Use Styles if they are set\r
+            if(s.width && s.width != 'auto'){\r
+                w = parseFloat(s.width);\r
+                if(me.isBorderBox()){\r
+                   w -= me.getFrameWidth('lr');\r
+                }\r
+            }\r
+            // Use Styles if they are set\r
+            if(s.height && s.height != 'auto'){\r
+                h = parseFloat(s.height);\r
+                if(me.isBorderBox()){\r
+                   h -= me.getFrameWidth('tb');\r
+                }\r
+            }\r
+            // Use getWidth/getHeight if style not set.\r
+            return {width: w || me.getWidth(true), height: h || me.getHeight(true)};\r
+        },\r
+\r
+        /**\r
+         * Returns the size of the element.\r
+         * @param {Boolean} contentSize (optional) true to get the width/size minus borders and padding\r
+         * @return {Object} An object containing the element's size {width: (element width), height: (element height)}\r
+         */\r
+        getSize : function(contentSize){\r
+            return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};\r
+        },\r
+\r
+        /**\r
+         * Forces the browser to repaint this element\r
+         * @return {Ext.Element} this\r
+         */\r
+        repaint : function(){\r
+            var dom = this.dom;\r
+            this.addClass("x-repaint");\r
+            setTimeout(function(){\r
+                Ext.fly(dom).removeClass("x-repaint");\r
+            }, 1);\r
+            return this;\r
+        },\r
+\r
+        /**\r
+         * Disables text selection for this element (normalized across browsers)\r
+         * @return {Ext.Element} this\r
+         */\r
+        unselectable : function(){\r
+            this.dom.unselectable = "on";\r
+            return this.swallowEvent("selectstart", true).\r
+                        applyStyles("-moz-user-select:none;-khtml-user-select:none;").\r
+                        addClass("x-unselectable");\r
+        },\r
+\r
+        /**\r
+         * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,\r
+         * then it returns the calculated width of the sides (see getPadding)\r
+         * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides\r
+         * @return {Object/Number}\r
+         */\r
+        getMargins : function(side){\r
+            var me = this,\r
+                key,\r
+                hash = {t:"top", l:"left", r:"right", b: "bottom"},\r
+                o = {};\r
+\r
+            if (!side) {\r
+                for (key in me.margins){\r
+                    o[hash[key]] = parseFloat(me.getStyle(me.margins[key])) || 0;\r
+                }\r
+                return o;\r
+            } else {\r
+                return me.addStyles.call(me, side, me.margins);\r
+            }\r
+        }\r
+    };\r
+}());\r
+/**\r
+ * @class Ext.Element\r
+ */\r
+(function(){\r
+var D = Ext.lib.Dom,\r
+        LEFT = "left",\r
+        RIGHT = "right",\r
+        TOP = "top",\r
+        BOTTOM = "bottom",\r
+        POSITION = "position",\r
+        STATIC = "static",\r
+        RELATIVE = "relative",\r
+        AUTO = "auto",\r
+        ZINDEX = "z-index";\r
+\r
+Ext.Element.addMethods({\r
+       /**\r
+      * Gets the current X position of the element based on page coordinates.  Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).\r
+      * @return {Number} The X position of the element\r
+      */\r
+    getX : function(){\r
+        return D.getX(this.dom);\r
+    },\r
+\r
+    /**\r
+      * Gets the current Y position of the element based on page coordinates.  Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).\r
+      * @return {Number} The Y position of the element\r
+      */\r
+    getY : function(){\r
+        return D.getY(this.dom);\r
+    },\r
+\r
+    /**\r
+      * Gets the current position of the element based on page coordinates.  Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).\r
+      * @return {Array} The XY position of the element\r
+      */\r
     getXY : function(){\r
         return D.getXY(this.dom);\r
     },\r
@@ -6315,13 +6811,24 @@ Ext.Element.addMethods({
         me.setBounds(box.x, box.y, w, h, me.animTest.call(me, arguments, animate, 2));\r
         return me;\r
     },\r
-    \r
+\r
     /**\r
-     * Return a box {x, y, width, height} that can be used to set another elements\r
-     * size/location to match this element.\r
+     * Return an object defining the area of this Element which can be passed to {@link #setBox} to\r
+     * set another Element's size/location to match this element.\r
      * @param {Boolean} contentBox (optional) If true a box for the content of the element is returned.\r
      * @param {Boolean} local (optional) If true the element's left and top are returned instead of page x/y.\r
-     * @return {Object} box An object in the format {x, y, width, height}\r
+     * @return {Object} box An object in the format<pre><code>\r
+{\r
+    x: &lt;Element's X position>,\r
+    y: &lt;Element's Y position>,\r
+    width: &lt;Element's width>,\r
+    height: &lt;Element's height>,\r
+    bottom: &lt;Element's lower bound>,\r
+    right: &lt;Element's rightmost bound>\r
+}\r
+</code></pre>\r
+     * The returned object may also be addressed as an Array where index 0 contains the X position\r
+     * and index 1 contains the Y position. So the result may also be used for {@link #setXY}\r
      */\r
        getBox : function(contentBox, local) {      \r
            var me = this,\r
@@ -6515,14 +7022,16 @@ Ext.Element.addMethods({
      */\r
     scrollTo : function(side, value, animate){\r
         var top = /top/i.test(side), //check if we're scrolling top or left\r
-            prop = 'scroll' + (top ? 'Left' : 'Top'), // if scrolling top, we need to grab scrollLeft, if left, scrollTop\r
-            me = this,\r
-            dom = me.dom;\r
+               me = this,\r
+               dom = me.dom,\r
+            prop;\r
         if (!animate || !me.anim) {\r
+            prop = 'scroll' + (top ? 'Top' : 'Left'), // just setting the value, so grab the direction\r
             dom[prop] = value;\r
-        } else {\r
+        }else{\r
+            prop = 'scroll' + (top ? 'Left' : 'Top'), // if scrolling top, we need to grab scrollLeft, if left, scrollTop\r
             me.anim({scroll: {to: top ? [dom[prop], value] : [value, dom[prop]]}},\r
-                     me.preanim(arguments, 2), 'scroll');\r
+                        me.preanim(arguments, 2), 'scroll');\r
         }\r
         return me;\r
     },\r
@@ -6934,7 +7443,7 @@ function(){
            XMASKED = "x-masked",\r
                XMASKEDRELATIVE = "x-masked-relative",\r
         data = Ext.Element.data;\r
-               \r
+\r
        return {\r
                /**\r
             * Checks whether the element is currently visible using both visibility and display properties.\r
@@ -6946,8 +7455,8 @@ function(){
                        p = this.dom.parentNode;\r
                if(deep !== true || !vis){\r
                    return vis;\r
-               }               \r
-               while(p && !/body/i.test(p.tagName)){\r
+               }\r
+               while(p && !/^body/i.test(p.tagName)){\r
                    if(!Ext.fly(p, '_isVisible').isVisible()){\r
                        return false;\r
                    }\r
@@ -6955,7 +7464,7 @@ function(){
                }\r
                return true;\r
            },\r
-           \r
+\r
            /**\r
             * Returns true if display is not "none"\r
             * @return {Boolean}\r
@@ -6963,20 +7472,20 @@ function(){
            isDisplayed : function() {\r
                return !this.isStyle(DISPLAY, NONE);\r
            },\r
-           \r
+\r
                /**\r
             * Convenience method for setVisibilityMode(Element.DISPLAY)\r
             * @param {String} display (optional) What to set display to when visible\r
             * @return {Ext.Element} this\r
             */\r
-           enableDisplayMode : function(display){          \r
+           enableDisplayMode : function(display){\r
                this.setVisibilityMode(Ext.Element.DISPLAY);\r
                if(!Ext.isEmpty(display)){\r
                 data(this.dom, 'originalDisplay', display);\r
             }\r
                return this;\r
            },\r
-           \r
+\r
                /**\r
             * Puts a mask over this element to disable user interaction. Requires core.css.\r
             * This method can only be applied to elements which accept child nodes.\r
@@ -6989,9 +7498,9 @@ function(){
                        dom = me.dom,\r
                        dh = Ext.DomHelper,\r
                        EXTELMASKMSG = "ext-el-mask-msg",\r
-                el, \r
+                el,\r
                 mask;\r
-                       \r
+\r
                if(me.getStyle("position") == "static"){\r
                    me.addClass(XMASKEDRELATIVE);\r
                }\r
@@ -7001,10 +7510,10 @@ function(){
                if((el = data(dom, 'mask'))){\r
                    el.remove();\r
                }\r
-       \r
+\r
             mask = dh.append(dom, {cls : "ext-el-mask"}, true);\r
                data(dom, 'mask', mask);\r
-       \r
+\r
                me.addClass(XMASKED);\r
                mask.setDisplayed(true);\r
                if(typeof msg == 'string'){\r
@@ -7020,7 +7529,7 @@ function(){
                }\r
                return mask;\r
            },\r
-       \r
+\r
            /**\r
             * Removes a previously applied mask.\r
             */\r
@@ -7039,7 +7548,7 @@ function(){
                }\r
                me.removeClass([XMASKED, XMASKEDRELATIVE]);\r
            },\r
-       \r
+\r
            /**\r
             * Returns true if this element is masked\r
             * @return {Boolean}\r
@@ -7048,14 +7557,14 @@ function(){
             var m = data(this.dom, 'mask');\r
                return m && m.isVisible();\r
            },\r
-           \r
+\r
            /**\r
             * Creates an iframe shim for this element to keep selects and other windowed objects from\r
             * showing through.\r
             * @return {Ext.Element} The new shim element\r
             */\r
            createShim : function(){\r
-               var el = document.createElement('iframe'),              \r
+               var el = document.createElement('iframe'),\r
                        shim;\r
                el.frameBorder = '0';\r
                el.className = 'ext-shim';\r
@@ -7072,9 +7581,9 @@ Ext.Element.addMethods({
     /**\r
      * Convenience method for constructing a KeyMap\r
      * @param {Number/Array/Object/String} key Either a string with the keys to listen for, the numeric key code, array of key codes or an object with the following options:\r
-     *                                  {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}\r
+     * <code>{key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}</code>\r
      * @param {Function} fn The function to call\r
-     * @param {Object} scope (optional) The scope of the function\r
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the specified function is executed. Defaults to this Element.\r
      * @return {Ext.KeyMap} The KeyMap created\r
      */\r
     addKeyListener : function(key, fn, scope){\r
@@ -7672,7 +8181,7 @@ el.frame("C3DAF9", 1, {
             active;\r
 \r
         me.queueFx(o, function(){\r
-            color = color || '#C3DAF9'\r
+            color = color || '#C3DAF9';\r
             if(color.length == 6){\r
                 color = '#' + color;\r
             }            \r
@@ -8264,6 +8773,21 @@ Ext.override(Ext.CompositeElementLite, {
 \r
 Ext.CompositeElementLite.prototype = {\r
     isComposite: true,    \r
+    \r
+    // private\r
+    getElement : function(el){\r
+        // Set the shared flyweight dom property to the current element\r
+        var e = this.el;\r
+        e.dom = el;\r
+        e.id = el.id;\r
+        return e;\r
+    },\r
+    \r
+    // private\r
+    transformElement : function(el){\r
+        return Ext.getDom(el);\r
+    },\r
+    \r
     /**\r
      * Returns the number of elements in this Composite.\r
      * @return Number\r
@@ -8276,27 +8800,40 @@ Ext.CompositeElementLite.prototype = {
      * @param {Mixed} els Either an Array of DOM elements to add, or another Composite object who's elements should be added.\r
      * @return {CompositeElement} This Composite object.\r
      */\r
-    add : function(els){\r
-        if(els){\r
-            if (Ext.isArray(els)) {\r
-                this.elements = this.elements.concat(els);\r
-            } else {\r
-                var yels = this.elements;                                    \r
-                Ext.each(els, function(e) {\r
-                    yels.push(e);\r
-                });\r
-            }\r
+    add : function(els, root){\r
+        var me = this,\r
+            elements = me.elements;\r
+        if(!els){\r
+            return this;\r
         }\r
-        return this;\r
+        if(Ext.isString(els)){\r
+            els = Ext.Element.selectorFunction(els, root);\r
+        }else if(els.isComposite){\r
+            els = els.elements;\r
+        }else if(!Ext.isIterable(els)){\r
+            els = [els];\r
+        }\r
+        \r
+        for(var i = 0, len = els.length; i < len; ++i){\r
+            elements.push(me.transformElement(els[i]));\r
+        }\r
+        return me;\r
     },\r
+    \r
     invoke : function(fn, args){\r
-        var els = this.elements,\r
-            el = this.el;        \r
-        Ext.each(els, function(e) {    \r
-            el.dom = e;\r
-            Ext.Element.prototype[fn].apply(el, args);\r
-        });\r
-        return this;\r
+        var me = this,\r
+            els = me.elements,\r
+            len = els.length, \r
+            e, \r
+            i;\r
+            \r
+        for(i = 0; i < len; i++) {\r
+            e = els[i];\r
+            if(e){\r
+                Ext.Element.prototype[fn].apply(me.getElement(e), args);\r
+            }\r
+        }\r
+        return me;\r
     },\r
     /**\r
      * Returns a flyweight Element of the dom element object at the specified index\r
@@ -8304,19 +8841,28 @@ Ext.CompositeElementLite.prototype = {
      * @return {Ext.Element}\r
      */\r
     item : function(index){\r
-        var me = this;\r
-        if(!me.elements[index]){\r
-            return null;\r
+        var me = this,\r
+            el = me.elements[index],\r
+            out = null;\r
+\r
+        if(el){\r
+            out = me.getElement(el);\r
         }\r
-        me.el.dom = me.elements[index];\r
-        return me.el;\r
+        return out;\r
     },\r
 \r
     // fixes scope with flyweight\r
     addListener : function(eventName, handler, scope, opt){\r
-        Ext.each(this.elements, function(e) {\r
-            Ext.EventManager.on(e, eventName, handler, scope || e, opt);\r
-        });\r
+        var els = this.elements,\r
+            len = els.length,\r
+            i, e;\r
+        \r
+        for(i = 0; i<len; i++) {\r
+            e = els[i];\r
+            if(e) {\r
+                Ext.EventManager.on(e, eventName, handler, scope || e, opt);\r
+            }\r
+        }\r
         return this;\r
     },\r
     /**\r
@@ -8333,12 +8879,19 @@ Ext.CompositeElementLite.prototype = {
      */\r
     each : function(fn, scope){       \r
         var me = this,\r
-            el = me.el;\r
-       \r
-        Ext.each(me.elements, function(e,i) {    \r
-            el.dom = e;\r
-            return fn.call(scope || el, el, me, i);\r
-        });\r
+            els = me.elements,\r
+            len = els.length,\r
+            i, e;\r
+        \r
+        for(i = 0; i<len; i++) {\r
+            e = els[i];\r
+            if(e){\r
+                e = this.getElement(e);\r
+                if(fn.call(scope || e, e, me, i) === false){\r
+                    break;\r
+                }\r
+            }\r
+        }\r
         return me;\r
     },\r
     \r
@@ -8366,16 +8919,19 @@ Ext.CompositeElementLite.prototype = {
     filter : function(selector){\r
         var els = [],\r
             me = this,\r
+            elements = me.elements,\r
             fn = Ext.isFunction(selector) ? selector\r
                 : function(el){\r
                     return el.is(selector);\r
-                }\r
+                };\r
+                \r
+        \r
         me.each(function(el, self, i){\r
             if(fn(el, i) !== false){\r
-                els[els.length] = el.dom;\r
+                els[els.length] = me.transformElement(el);\r
             }\r
         });\r
-        me.fill(els);\r
+        me.elements = els;\r
         return me;\r
     },\r
     \r
@@ -8385,7 +8941,7 @@ Ext.CompositeElementLite.prototype = {
      * @return Number The index of the passed Ext.Element in the composite collection, or -1 if not found.\r
      */\r
     indexOf : function(el){\r
-        return this.elements.indexOf(Ext.getDom(el));\r
+        return this.elements.indexOf(this.transformElement(el));\r
     },\r
     \r
     /**\r
@@ -8447,13 +9003,12 @@ if(Ext.DomQuery){
  * to be applied to many related elements in one statement through the returned {@link Ext.CompositeElement CompositeElement} or\r
  * {@link Ext.CompositeElementLite CompositeElementLite} object.\r
  * @param {String/Array} selector The CSS selector or an array of elements\r
- * @param {Boolean} unique (optional) true to create a unique Ext.Element for each element (defaults to a shared flyweight object) <b>Not supported in core</b>\r
  * @param {HTMLElement/String} root (optional) The root element of the query or id of the root\r
  * @return {CompositeElementLite/CompositeElement}\r
  * @member Ext.Element\r
  * @method select\r
  */\r
-Ext.Element.select = function(selector, unique, root){\r
+Ext.Element.select = function(selector, root){\r
     var els;\r
     if(typeof selector == "string"){\r
         els = Ext.Element.selectorFunction(selector, root);\r
@@ -8469,7 +9024,6 @@ Ext.Element.select = function(selector, unique, root){
  * to be applied to many related elements in one statement through the returned {@link Ext.CompositeElement CompositeElement} or\r
  * {@link Ext.CompositeElementLite CompositeElementLite} object.\r
  * @param {String/Array} selector The CSS selector or an array of elements\r
- * @param {Boolean} unique (optional) true to create a unique Ext.Element for each element (defaults to a shared flyweight object)\r
  * @param {HTMLElement/String} root (optional) The root element of the query or id of the root\r
  * @return {CompositeElementLite/CompositeElement}\r
  * @member Ext\r
@@ -8547,23 +9101,23 @@ Ext.apply(Ext.CompositeElementLite.prototype, {
 /**\r
  * @class Ext.CompositeElement\r
  * @extends Ext.CompositeElementLite\r
- * Standard composite class. Creates a Ext.Element for every element in the collection.\r
- * <br><br>\r
- * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Ext.Element. All Ext.Element\r
- * actions will be performed on all the elements in this collection.</b>\r
- * <br><br>\r
- * All methods return <i>this</i> and can be chained.\r
- <pre><code>\r
- var els = Ext.select("#some-el div.some-class", true);\r
- // or select directly from an existing element\r
- var el = Ext.get('some-el');\r
- el.select('div.some-class', true);\r
-\r
- els.setWidth(100); // all elements become 100 width\r
- els.hide(true); // all elements fade out and hide\r
- // or\r
- els.setWidth(100).hide(true);\r
- </code></pre>\r
+ * <p>This class encapsulates a <i>collection</i> of DOM elements, providing methods to filter\r
+ * members, or to perform collective actions upon the whole set.</p>\r
+ * <p>Although they are not listed, this class supports all of the methods of {@link Ext.Element} and\r
+ * {@link Ext.Fx}. The methods from these classes will be performed on all the elements in this collection.</p>\r
+ * <p>All methods return <i>this</i> and can be chained.</p>\r
+ * Usage:\r
+<pre><code>\r
+var els = Ext.select("#some-el div.some-class", true);\r
+// or select directly from an existing element\r
+var el = Ext.get('some-el');\r
+el.select('div.some-class', true);\r
+\r
+els.setWidth(100); // all elements become 100 width\r
+els.hide(true); // all elements fade out and hide\r
+// or\r
+els.setWidth(100).hide(true);\r
+</code></pre>\r
  */\r
 Ext.CompositeElement = function(els, root){\r
     this.elements = [];\r
@@ -8571,58 +9125,29 @@ Ext.CompositeElement = function(els, root){
 };\r
 \r
 Ext.extend(Ext.CompositeElement, Ext.CompositeElementLite, {\r
-    invoke : function(fn, args){\r
-           Ext.each(this.elements, function(e) {\r
-               Ext.Element.prototype[fn].apply(e, args);\r
-        });\r
-        return this;\r
+    \r
+    // private\r
+    getElement : function(el){\r
+        // In this case just return it, since we already have a reference to it\r
+        return el;\r
     },\r
+    \r
+    // private\r
+    transformElement : function(el){\r
+        return Ext.get(el);\r
+    }\r
 \r
     /**\r
     * Adds elements to this composite.\r
     * @param {String/Array} els A string CSS selector, an array of elements or an element\r
     * @return {CompositeElement} this\r
     */\r
-    add : function(els, root){\r
-           if(!els){\r
-            return this;\r
-        }\r
-        if(typeof els == "string"){\r
-            els = Ext.Element.selectorFunction(els, root);\r
-        }\r
-        var yels = this.elements;\r
-           Ext.each(els, function(e) {\r
-               yels.push(Ext.get(e));\r
-        });\r
-        return this;\r
-    },\r
 \r
     /**\r
      * Returns the Element object at the specified index\r
      * @param {Number} index\r
      * @return {Ext.Element}\r
      */\r
-    item : function(index){\r
-        return this.elements[index] || null;\r
-    },\r
-\r
-\r
-    indexOf : function(el){\r
-        return this.elements.indexOf(Ext.get(el));\r
-    },\r
-\r
-    filter : function(selector){\r
-               var me = this,\r
-                       out = [];\r
-\r
-               Ext.each(me.elements, function(el) {\r
-                       if(el.is(selector)){\r
-                               out.push(Ext.get(el));\r
-                       }\r
-               });\r
-               me.elements = out;\r
-               return me;\r
-       },\r
 \r
     /**\r
      * Iterates each <code>element</code> in this <code>composite</code>\r
@@ -8631,26 +9156,16 @@ Ext.extend(Ext.CompositeElement, Ext.CompositeElementLite, {
      * <code>element</code>. If the supplied function returns <tt>false</tt>,\r
      * iteration stops. This function is called with the following arguments:\r
      * <div class="mdetail-params"><ul>\r
-     * <li><code>element</code> : <i>Object</i>\r
-     * <div class="sub-desc">The element at the current <code>index</code>\r
+     * <li><code>element</code> : <i>Ext.Element</i><div class="sub-desc">The element at the current <code>index</code>\r
      * in the <code>composite</code></div></li>\r
-     * <li><code>composite</code> : <i>Object</i>\r
-     * <div class="sub-desc">This composite.</div></li>\r
-     * <li><code>index</code> : <i>Number</i>\r
-     * <div class="sub-desc">The current index within the <code>composite</code>\r
-     * </div></li>\r
+     * <li><code>composite</code> : <i>Object</i> <div class="sub-desc">This composite.</div></li>\r
+     * <li><code>index</code> : <i>Number</i> <div class="sub-desc">The current index within the <code>composite</code> </div></li>\r
      * </ul></div>\r
-     * @param {Object} scope (optional) The scope to call the specified function.\r
+     * @param {Object} scope (optional) The scope (<code><this</code> reference) in which the specified function is executed.\r
      * Defaults to the <code>element</code> at the current <code>index</code>\r
      * within the composite.\r
      * @return {CompositeElement} this\r
      */\r
-    each : function(fn, scope){\r
-        Ext.each(this.elements, function(e, i){\r
-            return fn.call(scope || e, e, this, i);\r
-        }, this);\r
-        return this;\r
-    }\r
 });\r
 \r
 /**\r
@@ -8697,7 +9212,7 @@ Ext.select = Ext.Element.select;(function(){
         POST = 'POST',\r
         GET = 'GET',\r
         WINDOW = window;\r
-    \r
+\r
     /**\r
      * @class Ext.data.Connection\r
      * @extends Ext.util.Observable\r
@@ -8730,7 +9245,7 @@ Ext.select = Ext.Element.select;(function(){
      * @constructor\r
      * @param {Object} config a configuration object.\r
      */\r
-    Ext.data.Connection = function(config){    \r
+    Ext.data.Connection = function(config){\r
         Ext.apply(this, config);\r
         this.addEvents(\r
             /**\r
@@ -8794,20 +9309,20 @@ Ext.select = Ext.Element.select;(function(){
          * @type Boolean\r
          */\r
         autoAbort:false,\r
-    \r
+\r
         /**\r
          * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)\r
          * @type Boolean\r
          */\r
         disableCaching: true,\r
-        \r
+\r
         /**\r
          * @cfg {String} disableCachingParam (Optional) Change the parameter which is sent went disabling caching\r
          * through a cache buster. Defaults to '_dc'\r
          * @type String\r
          */\r
         disableCachingParam: '_dc',\r
-        \r
+\r
         /**\r
          * <p>Sends an HTTP request to a remote server.</p>\r
          * <p><b>Important:</b> Ajax server requests are asynchronous, and this call will\r
@@ -8845,8 +9360,8 @@ Ext.Ajax.request({
          * parameters:<ul>\r
          * <li><b>options</b> : Object<div class="sub-desc">The parameter to the request call.</div></li>\r
          * <li><b>success</b> : Boolean<div class="sub-desc">True if the request succeeded.</div></li>\r
-         * <li><b>response</b> : Object<div class="sub-desc">The XMLHttpRequest object containing the response data. \r
-         * See <a href="http://www.w3.org/TR/XMLHttpRequest/">http://www.w3.org/TR/XMLHttpRequest/</a> for details about \r
+         * <li><b>response</b> : Object<div class="sub-desc">The XMLHttpRequest object containing the response data.\r
+         * See <a href="http://www.w3.org/TR/XMLHttpRequest/">http://www.w3.org/TR/XMLHttpRequest/</a> for details about\r
          * accessing elements of the response.</div></li>\r
          * </ul></div></li>\r
          * <li><a id="request-option-success"></a><b>success</b> : Function (Optional)<div class="sub-desc">The function\r
@@ -8868,7 +9383,7 @@ Ext.Ajax.request({
          * <li><b>timeout</b> : Number (Optional)<div class="sub-desc">The timeout in milliseconds to be used for this request. Defaults to 30 seconds.</div></li>\r
          * <li><b>form</b> : Element/HTMLElement/String (Optional)<div class="sub-desc">The <tt>&lt;form&gt;</tt>\r
          * Element or the id of the <tt>&lt;form&gt;</tt> to pull parameters from.</div></li>\r
-         * <li><a id="request-option-isUpload"></a><b>isUpload</b> : Boolean (Optional)<div class="sub-desc"><b>Only meaningful when used \r
+         * <li><a id="request-option-isUpload"></a><b>isUpload</b> : Boolean (Optional)<div class="sub-desc"><b>Only meaningful when used\r
          * with the <tt>form</tt> option</b>.\r
          * <p>True if the form object is a file upload (will be set automatically if the form was\r
          * configured with <b><tt>enctype</tt></b> "multipart/form-data").</p>\r
@@ -8913,15 +9428,15 @@ Ext.Ajax.request({
                         me.indicatorText = '<div class="loading-indicator">'+o.indicatorText+"</div>";\r
                     }\r
                     if(me.indicatorText) {\r
-                        Ext.getDom(o.el).innerHTML = me.indicatorText;                        \r
+                        Ext.getDom(o.el).innerHTML = me.indicatorText;\r
                     }\r
                     o.success = (Ext.isFunction(o.success) ? o.success : function(){}).createInterceptor(function(response) {\r
                         Ext.getDom(o.el).innerHTML = response.responseText;\r
                     });\r
                 }\r
-                \r
+\r
                 var p = o.params,\r
-                    url = o.url || me.url,                \r
+                    url = o.url || me.url,\r
                     method,\r
                     cb = {success: me.handleResponse,\r
                           failure: me.handleFailure,\r
@@ -8929,61 +9444,61 @@ Ext.Ajax.request({
                           argument: {options: o},\r
                           timeout : o.timeout || me.timeout\r
                     },\r
-                    form,                    \r
-                    serForm;                    \r
-                  \r
-                     \r
+                    form,\r
+                    serForm;\r
+\r
+\r
                 if (Ext.isFunction(p)) {\r
                     p = p.call(o.scope||WINDOW, o);\r
                 }\r
-                                                           \r
-                p = Ext.urlEncode(me.extraParams, Ext.isObject(p) ? Ext.urlEncode(p) : p);    \r
-                \r
+\r
+                p = Ext.urlEncode(me.extraParams, Ext.isObject(p) ? Ext.urlEncode(p) : p);\r
+\r
                 if (Ext.isFunction(url)) {\r
                     url = url.call(o.scope || WINDOW, o);\r
                 }\r
-    \r
+\r
                 if((form = Ext.getDom(o.form))){\r
                     url = url || form.action;\r
-                     if(o.isUpload || /multipart\/form-data/i.test(form.getAttribute("enctype"))) { \r
+                     if(o.isUpload || /multipart\/form-data/i.test(form.getAttribute("enctype"))) {\r
                          return me.doFormUpload.call(me, o, p, url);\r
                      }\r
-                    serForm = Ext.lib.Ajax.serializeForm(form);                    \r
+                    serForm = Ext.lib.Ajax.serializeForm(form);\r
                     p = p ? (p + '&' + serForm) : serForm;\r
                 }\r
-                \r
+\r
                 method = o.method || me.method || ((p || o.xmlData || o.jsonData) ? POST : GET);\r
-                \r
+\r
                 if(method === GET && (me.disableCaching && o.disableCaching !== false) || o.disableCaching === true){\r
                     var dcp = o.disableCachingParam || me.disableCachingParam;\r
                     url = Ext.urlAppend(url, dcp + '=' + (new Date().getTime()));\r
                 }\r
-                \r
+\r
                 o.headers = Ext.apply(o.headers || {}, me.defaultHeaders || {});\r
-                \r
+\r
                 if(o.autoAbort === true || me.autoAbort) {\r
                     me.abort();\r
                 }\r
-                 \r
+\r
                 if((method == GET || o.xmlData || o.jsonData) && p){\r
-                    url = Ext.urlAppend(url, p);  \r
+                    url = Ext.urlAppend(url, p);\r
                     p = '';\r
                 }\r
                 return (me.transId = Ext.lib.Ajax.request(method, url, cb, p, o));\r
-            }else{                \r
+            }else{\r
                 return o.callback ? o.callback.apply(o.scope, [o,UNDEFINED,UNDEFINED]) : null;\r
             }\r
         },\r
-    \r
+\r
         /**\r
          * Determine whether this object has a request outstanding.\r
          * @param {Number} transactionId (Optional) defaults to the last transaction\r
          * @return {Boolean} True if there is an outstanding request.\r
          */\r
         isLoading : function(transId){\r
-            return transId ? Ext.lib.Ajax.isCallInProgress(transId) : !! this.transId;            \r
+            return transId ? Ext.lib.Ajax.isCallInProgress(transId) : !! this.transId;\r
         },\r
-    \r
+\r
         /**\r
          * Aborts any outstanding request.\r
          * @param {Number} transactionId (Optional) defaults to the last transaction\r
@@ -9042,16 +9557,23 @@ Ext.Ajax.request({
             Ext.fly(frame).set({\r
                 id: id,\r
                 name: id,\r
-                cls: 'x-hidden',\r
-                src: Ext.SSL_SECURE_URL // for IE\r
+                cls: 'x-hidden'\r
+\r
             });\r
+\r
             doc.body.appendChild(frame);\r
 \r
+            //Reset the Frame to neutral domain\r
+            Ext.fly(frame).set({\r
+               src : Ext.SSL_SECURE_URL\r
+            });\r
+\r
             // This is required so that IE doesn't pop the response up in a new window.\r
             if(Ext.isIE){\r
                document.frames[id].name = id;\r
             }\r
 \r
+\r
             Ext.fly(form).set({\r
                 target: id,\r
                 method: POST,\r
@@ -9143,7 +9665,7 @@ Ext.Ajax.request({
 Ext.Ajax.defaultHeaders = {\r
     'Powered-By': 'Ext'\r
 };\r
- * </code></pre> \r
+ * </code></pre>\r
  * </p>\r
  * <p>Common <b>Events</b> you may want to set are:<div class="mdetail-params"><ul>\r
  * <li><b><tt>{@link Ext.data.Connection#beforerequest beforerequest}</tt></b><p class="sub-desc"></p></li>\r
@@ -9155,7 +9677,7 @@ Ext.Ajax.defaultHeaders = {
 Ext.Ajax.on('beforerequest', this.showSpinner, this);\r
 Ext.Ajax.on('requestcomplete', this.hideSpinner, this);\r
 Ext.Ajax.on('requestexception', this.hideSpinner, this);\r
- * </code></pre> \r
+ * </code></pre>\r
  * </p>\r
  * <p>An example request:</p>\r
  * <pre><code>\r
@@ -9175,7 +9697,7 @@ Ext.Ajax.{@link Ext.data.Connection#request request}({
     form: 'some-form',\r
     params: 'foo=bar'\r
 });\r
- * </code></pre> \r
+ * </code></pre>\r
  * </p>\r
  * @singleton\r
  */\r
@@ -9482,17 +10004,17 @@ function() {
             * If params are specified it uses POST, otherwise it uses GET.<br><br>
             * <b>Note:</b> Due to the asynchronous nature of remote server requests, the Element
             * will not have been fully updated when the function returns. To post-process the returned
-            * data, use the callback option, or an <b><tt>update</tt></b> event handler.
+            * data, use the callback option, or an <b><code>update</code></b> event handler.
             * @param {Object} options A config object containing any of the following options:<ul>
             * <li>url : <b>String/Function</b><p class="sub-desc">The URL to request or a function which
             * <i>returns</i> the URL (defaults to the value of {@link Ext.Ajax#url} if not specified).</p></li>
             * <li>method : <b>String</b><p class="sub-desc">The HTTP method to
-            * use. Defaults to POST if the <tt>params</tt> argument is present, otherwise GET.</p></li>
+            * use. Defaults to POST if the <code>params</code> argument is present, otherwise GET.</p></li>
             * <li>params : <b>String/Object/Function</b><p class="sub-desc">The
             * parameters to pass to the server (defaults to none). These may be specified as a url-encoded
             * string, or as an object containing properties which represent parameters,
             * or as a function, which returns such an object.</p></li>
-            * <li>scripts : <b>Boolean</b><p class="sub-desc">If <tt>true</tt>
+            * <li>scripts : <b>Boolean</b><p class="sub-desc">If <code>true</code>
             * any &lt;script&gt; tags embedded in the response text will be extracted
             * and executed (defaults to {@link Ext.Updater.defaults#loadScripts}). If this option is specified,
             * the callback will be called <i>after</i> the execution of the scripts.</p></li>
@@ -9505,11 +10027,11 @@ function() {
             * <li><b>options</b> : Object<p class="sub-desc">The config object passed to the update call.</p></li></ul>
             * </p></li>
             * <li>scope : <b>Object</b><p class="sub-desc">The scope in which
-            * to execute the callback (The callback's <tt>this</tt> reference.) If the
-            * <tt>params</tt> argument is a function, this scope is used for that function also.</p></li>
+            * to execute the callback (The callback's <code>this</code> reference.) If the
+            * <code>params</code> argument is a function, this scope is used for that function also.</p></li>
             * <li>discardUrl : <b>Boolean</b><p class="sub-desc">By default, the URL of this request becomes
             * the default URL for this Updater object, and will be subsequently used in {@link #refresh}
-            * calls.  To bypass this behavior, pass <tt>discardUrl:true</tt> (defaults to false).</p></li>
+            * calls.  To bypass this behavior, pass <code>discardUrl:true</code> (defaults to false).</p></li>
             * <li>timeout : <b>Number</b><p class="sub-desc">The number of seconds to wait for a response before
             * timing out (defaults to {@link Ext.Updater.defaults#timeout}).</p></li>
             * <li>text : <b>String</b><p class="sub-desc">The text to use as the innerHTML of the
@@ -9585,14 +10107,14 @@ function() {
            },          
 
                /**
-            * <p>Performs an async form post, updating this element with the response. If the form has the attribute
+            * <p>Performs an asynchronous form post, updating this element with the response. If the form has the attribute
             * enctype="<a href="http://www.faqs.org/rfcs/rfc2388.html">multipart/form-data</a>", it assumes it's a file upload.
             * Uses this.sslBlankUrl for SSL file uploads to prevent IE security warning.</p>
             * <p>File uploads are not performed using normal "Ajax" techniques, that is they are <b>not</b>
             * performed using XMLHttpRequests. Instead the form is submitted in the standard manner with the
-            * DOM <tt>&lt;form></tt> element temporarily modified to have its
+            * DOM <code>&lt;form></code> element temporarily modified to have its
             * <a href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-target">target</a> set to refer
-            * to a dynamically generated, hidden <tt>&lt;iframe></tt> which is inserted into the document
+            * to a dynamically generated, hidden <code>&lt;iframe></code> which is inserted into the document
             * but removed after the return data has been gathered.</p>
             * <p>Be aware that file upload packets, sent with the content type <a href="http://www.faqs.org/rfcs/rfc2388.html">multipart/form-data</a>
             * and some server technologies (notably JEE) may require some custom processing in order to
@@ -9769,17 +10291,17 @@ Ext.Updater.updateElement = function(el, url, params, options){
 
 /**
  * @class Ext.Updater.BasicRenderer
- * Default Content renderer. Updates the elements innerHTML with the responseText.
+ * <p>This class is a base class implementing a simple render method which updates an element using results from an Ajax request.</p>
+ * <p>The BasicRenderer updates the element's innerHTML with the responseText. To perform a custom render (i.e. XML or JSON processing),
+ * create an object with a conforming {@link #render} method and pass it to setRenderer on the Updater.</p>
  */
 Ext.Updater.BasicRenderer = function(){};
 
 Ext.Updater.BasicRenderer.prototype = {
     /**
-     * This is called when the transaction is completed and it's time to update the element - The BasicRenderer
-     * updates the elements innerHTML with the responseText - To perform a custom render (i.e. XML or JSON processing),
-     * create an object with a "render(el, response)" method and pass it to setRenderer on the Updater.
+     * This method is called when an Ajax response is received, and an Element needs updating.
      * @param {Ext.Element} el The element being rendered
-     * @param {Object} response The XMLHttpRequest object
+     * @param {Object} xhr The XMLHttpRequest object
      * @param {Updater} updateManager The calling update manager
      * @param {Function} callback A callback that will need to be called if loadScripts is true on the Updater
      */
@@ -10396,15 +10918,15 @@ dt = Date.parseDate("2006-02-29 03:20:01", "Y-m-d H:i:s", true); // returns null
                     "dt = (new Date()).clearTime();",
 
                     // date calculations (note: these calculations create a dependency on Ext.num())
-                    "y = y >= 0? y : Ext.num(def.y, dt.getFullYear());",
-                    "m = m >= 0? m : Ext.num(def.m - 1, dt.getMonth());",
-                    "d = d >= 0? d : Ext.num(def.d, dt.getDate());",
+                    "y = Ext.num(y, Ext.num(def.y, dt.getFullYear()));",
+                    "m = Ext.num(m, Ext.num(def.m - 1, dt.getMonth()));",
+                    "d = Ext.num(d, Ext.num(def.d, dt.getDate()));",
 
                     // time calculations (note: these calculations create a dependency on Ext.num())
-                    "h  = h || Ext.num(def.h, dt.getHours());",
-                    "i  = i || Ext.num(def.i, dt.getMinutes());",
-                    "s  = s || Ext.num(def.s, dt.getSeconds());",
-                    "ms = ms || Ext.num(def.ms, dt.getMilliseconds());",
+                    "h  = Ext.num(h, Ext.num(def.h, dt.getHours()));",
+                    "i  = Ext.num(i, Ext.num(def.i, dt.getMinutes()));",
+                    "s  = Ext.num(s, Ext.num(def.s, dt.getSeconds()));",
+                    "ms = Ext.num(ms, Ext.num(def.ms, dt.getMilliseconds()));",
 
                     "if(z >= 0 && y >= 0){",
                         // both the year and zero-based day of year are defined and >= 0.
@@ -11097,748 +11619,694 @@ console.group('ISO-8601 Granularity Test (see http://www.w3.org/TR/NOTE-datetime
 console.groupEnd();
 
 //*//**
- * @class Ext.util.DelayedTask
- * <p> The DelayedTask class provides a convenient way to "buffer" the execution of a method,
- * performing setTimeout where a new timeout cancels the old timeout. When called, the
- * task will wait the specified time period before executing. If durng that time period,
- * the task is called again, the original call will be cancelled. This continues so that
- * the function is only called a single time for each iteration.</p>
- * <p>This method is especially useful for things like detecting whether a user has finished
- * typing in a text field. An example would be performing validation on a keypress. You can
- * use this class to buffer the keypress events for a certain number of milliseconds, and
- * perform only if they stop for that amount of time.  Usage:</p><pre><code>
-var task = new Ext.util.DelayedTask(function(){
-    alert(Ext.getDom('myInputField').value.length);
-});
-// Wait 500ms before calling our function. If the user presses another key 
-// during that 500ms, it will be cancelled and we'll wait another 500ms.
-Ext.get('myInputField').on('keypress', function(){
-    task.{@link #delay}(500); 
-});
- * </code></pre> 
- * <p>Note that we are using a DelayedTask here to illustrate a point. The configuration
- * option <tt>buffer</tt> for {@link Ext.util.Observable#addListener addListener/on} will
- * also setup a delayed task for you to buffer events.</p> 
- * @constructor The parameters to this constructor serve as defaults and are not required.
- * @param {Function} fn (optional) The default function to call.
- * @param {Object} scope The default scope (The <code><b>this</b></code> reference) in which the
- * function is called. If not specified, <code>this</code> will refer to the browser window.
- * @param {Array} args (optional) The default Array of arguments.
+ * @class Ext.util.MixedCollection
+ * @extends Ext.util.Observable
+ * A Collection class that maintains both numeric indexes and keys and exposes events.
+ * @constructor
+ * @param {Boolean} allowFunctions Specify <tt>true</tt> if the {@link #addAll}
+ * function should add function references to the collection. Defaults to
+ * <tt>false</tt>.
+ * @param {Function} keyFn A function that can accept an item of the type(s) stored in this MixedCollection
+ * and return the key value for that item.  This is used when available to look up the key on items that
+ * were passed without an explicit key parameter to a MixedCollection method.  Passing this parameter is
+ * equivalent to providing an implementation for the {@link #getKey} method.
  */
-Ext.util.DelayedTask = function(fn, scope, args){
-    var me = this,
-       id,     
-       call = function(){
-               clearInterval(id);
-               id = null;
-               fn.apply(scope, args || []);
-           };
-           
+Ext.util.MixedCollection = function(allowFunctions, keyFn){
+    this.items = [];
+    this.map = {};
+    this.keys = [];
+    this.length = 0;
+    this.addEvents(
+        /**
+         * @event clear
+         * Fires when the collection is cleared.
+         */
+        'clear',
+        /**
+         * @event add
+         * Fires when an item is added to the collection.
+         * @param {Number} index The index at which the item was added.
+         * @param {Object} o The item added.
+         * @param {String} key The key associated with the added item.
+         */
+        'add',
+        /**
+         * @event replace
+         * Fires when an item is replaced in the collection.
+         * @param {String} key he key associated with the new added.
+         * @param {Object} old The item being replaced.
+         * @param {Object} new The new item.
+         */
+        'replace',
+        /**
+         * @event remove
+         * Fires when an item is removed from the collection.
+         * @param {Object} o The item being removed.
+         * @param {String} key (optional) The key associated with the removed item.
+         */
+        'remove',
+        'sort'
+    );
+    this.allowFunctions = allowFunctions === true;
+    if(keyFn){
+        this.getKey = keyFn;
+    }
+    Ext.util.MixedCollection.superclass.constructor.call(this);
+};
+
+Ext.extend(Ext.util.MixedCollection, Ext.util.Observable, {
+
     /**
-     * Cancels any pending timeout and queues a new one
-     * @param {Number} delay The milliseconds to delay
-     * @param {Function} newFn (optional) Overrides function passed to constructor
-     * @param {Object} newScope (optional) Overrides scope passed to constructor. Remember that if no scope
-     * is specified, <code>this</code> will refer to the browser window.
-     * @param {Array} newArgs (optional) Overrides args passed to constructor
+     * @cfg {Boolean} allowFunctions Specify <tt>true</tt> if the {@link #addAll}
+     * function should add function references to the collection. Defaults to
+     * <tt>false</tt>.
      */
-    me.delay = function(delay, newFn, newScope, newArgs){
-        me.cancel();
-        fn = newFn || fn;
-        scope = newScope || scope;
-        args = newArgs || args;
-        id = setInterval(call, delay);
-    };
+    allowFunctions : false,
 
     /**
-     * Cancel the last queued timeout
+     * Adds an item to the collection. Fires the {@link #add} event when complete.
+     * @param {String} key <p>The key to associate with the item, or the new item.</p>
+     * <p>If a {@link #getKey} implementation was specified for this MixedCollection,
+     * or if the key of the stored items is in a property called <tt><b>id</b></tt>,
+     * the MixedCollection will be able to <i>derive</i> the key for the new item.
+     * In this case just pass the new item in this parameter.</p>
+     * @param {Object} o The item to add.
+     * @return {Object} The item added.
      */
-    me.cancel = function(){
-        if(id){
-            clearInterval(id);
-            id = null;
+    add : function(key, o){
+        if(arguments.length == 1){
+            o = arguments[0];
+            key = this.getKey(o);
         }
-    };
-};/**\r
- * @class Ext.util.MixedCollection\r
- * @extends Ext.util.Observable\r
- * A Collection class that maintains both numeric indexes and keys and exposes events.\r
- * @constructor\r
- * @param {Boolean} allowFunctions Specify <tt>true</tt> if the {@link #addAll}\r
- * function should add function references to the collection. Defaults to\r
- * <tt>false</tt>.\r
- * @param {Function} keyFn A function that can accept an item of the type(s) stored in this MixedCollection\r
- * and return the key value for that item.  This is used when available to look up the key on items that\r
- * were passed without an explicit key parameter to a MixedCollection method.  Passing this parameter is\r
- * equivalent to providing an implementation for the {@link #getKey} method.\r
- */\r
-Ext.util.MixedCollection = function(allowFunctions, keyFn){\r
-    this.items = [];\r
-    this.map = {};\r
-    this.keys = [];\r
-    this.length = 0;\r
-    this.addEvents(\r
-        /**\r
-         * @event clear\r
-         * Fires when the collection is cleared.\r
-         */\r
-        'clear',\r
-        /**\r
-         * @event add\r
-         * Fires when an item is added to the collection.\r
-         * @param {Number} index The index at which the item was added.\r
-         * @param {Object} o The item added.\r
-         * @param {String} key The key associated with the added item.\r
-         */\r
-        'add',\r
-        /**\r
-         * @event replace\r
-         * Fires when an item is replaced in the collection.\r
-         * @param {String} key he key associated with the new added.\r
-         * @param {Object} old The item being replaced.\r
-         * @param {Object} new The new item.\r
-         */\r
-        'replace',\r
-        /**\r
-         * @event remove\r
-         * Fires when an item is removed from the collection.\r
-         * @param {Object} o The item being removed.\r
-         * @param {String} key (optional) The key associated with the removed item.\r
-         */\r
-        'remove',\r
-        'sort'\r
-    );\r
-    this.allowFunctions = allowFunctions === true;\r
-    if(keyFn){\r
-        this.getKey = keyFn;\r
-    }\r
-    Ext.util.MixedCollection.superclass.constructor.call(this);\r
-};\r
-\r
-Ext.extend(Ext.util.MixedCollection, Ext.util.Observable, {\r
-\r
-    /**\r
-     * @cfg {Boolean} allowFunctions Specify <tt>true</tt> if the {@link #addAll}\r
-     * function should add function references to the collection. Defaults to\r
-     * <tt>false</tt>.\r
-     */\r
-    allowFunctions : false,\r
-\r
-    /**\r
-     * Adds an item to the collection. Fires the {@link #add} event when complete.\r
-     * @param {String} key <p>The key to associate with the item, or the new item.</p>\r
-     * <p>If a {@link #getKey} implementation was specified for this MixedCollection,\r
-     * or if the key of the stored items is in a property called <tt><b>id</b></tt>,\r
-     * the MixedCollection will be able to <i>derive</i> the key for the new item.\r
-     * In this case just pass the new item in this parameter.</p>\r
-     * @param {Object} o The item to add.\r
-     * @return {Object} The item added.\r
-     */\r
-    add : function(key, o){\r
-        if(arguments.length == 1){\r
-            o = arguments[0];\r
-            key = this.getKey(o);\r
-        }\r
-        if(typeof key != 'undefined' && key !== null){\r
-            var old = this.map[key];\r
-            if(typeof old != 'undefined'){\r
-                return this.replace(key, o);\r
-            }\r
-            this.map[key] = o;\r
-        }\r
-        this.length++;\r
-        this.items.push(o);\r
-        this.keys.push(key);\r
-        this.fireEvent('add', this.length-1, o, key);\r
-        return o;\r
-    },\r
-\r
-    /**\r
-      * MixedCollection has a generic way to fetch keys if you implement getKey.  The default implementation\r
-      * simply returns <b><code>item.id</code></b> but you can provide your own implementation\r
-      * to return a different value as in the following examples:<pre><code>\r
-// normal way\r
-var mc = new Ext.util.MixedCollection();\r
-mc.add(someEl.dom.id, someEl);\r
-mc.add(otherEl.dom.id, otherEl);\r
-//and so on\r
-\r
-// using getKey\r
-var mc = new Ext.util.MixedCollection();\r
-mc.getKey = function(el){\r
-   return el.dom.id;\r
-};\r
-mc.add(someEl);\r
-mc.add(otherEl);\r
-\r
-// or via the constructor\r
-var mc = new Ext.util.MixedCollection(false, function(el){\r
-   return el.dom.id;\r
-});\r
-mc.add(someEl);\r
-mc.add(otherEl);\r
-     * </code></pre>\r
-     * @param {Object} item The item for which to find the key.\r
-     * @return {Object} The key for the passed item.\r
-     */\r
-    getKey : function(o){\r
-         return o.id;\r
-    },\r
-\r
-    /**\r
-     * Replaces an item in the collection. Fires the {@link #replace} event when complete.\r
-     * @param {String} key <p>The key associated with the item to replace, or the replacement item.</p>\r
-     * <p>If you supplied a {@link #getKey} implementation for this MixedCollection, or if the key\r
-     * of your stored items is in a property called <tt><b>id</b></tt>, then the MixedCollection\r
-     * will be able to <i>derive</i> the key of the replacement item. If you want to replace an item\r
-     * with one having the same key value, then just pass the replacement item in this parameter.</p>\r
-     * @param o {Object} o (optional) If the first parameter passed was a key, the item to associate\r
-     * with that key.\r
-     * @return {Object}  The new item.\r
-     */\r
-    replace : function(key, o){\r
-        if(arguments.length == 1){\r
-            o = arguments[0];\r
-            key = this.getKey(o);\r
-        }\r
-        var old = this.map[key];\r
-        if(typeof key == 'undefined' || key === null || typeof old == 'undefined'){\r
-             return this.add(key, o);\r
-        }\r
-        var index = this.indexOfKey(key);\r
-        this.items[index] = o;\r
-        this.map[key] = o;\r
-        this.fireEvent('replace', key, old, o);\r
-        return o;\r
-    },\r
-\r
-    /**\r
-     * Adds all elements of an Array or an Object to the collection.\r
-     * @param {Object/Array} objs An Object containing properties which will be added\r
-     * to the collection, or an Array of values, each of which are added to the collection.\r
-     * Functions references will be added to the collection if <code>{@link #allowFunctions}</code>\r
-     * has been set to <tt>true</tt>.\r
-     */\r
-    addAll : function(objs){\r
-        if(arguments.length > 1 || Ext.isArray(objs)){\r
-            var args = arguments.length > 1 ? arguments : objs;\r
-            for(var i = 0, len = args.length; i < len; i++){\r
-                this.add(args[i]);\r
-            }\r
-        }else{\r
-            for(var key in objs){\r
-                if(this.allowFunctions || typeof objs[key] != 'function'){\r
-                    this.add(key, objs[key]);\r
-                }\r
-            }\r
-        }\r
-    },\r
-\r
-    /**\r
-     * Executes the specified function once for every item in the collection, passing the following arguments:\r
-     * <div class="mdetail-params"><ul>\r
-     * <li><b>item</b> : Mixed<p class="sub-desc">The collection item</p></li>\r
-     * <li><b>index</b> : Number<p class="sub-desc">The item's index</p></li>\r
-     * <li><b>length</b> : Number<p class="sub-desc">The total number of items in the collection</p></li>\r
-     * </ul></div>\r
-     * The function should return a boolean value. Returning false from the function will stop the iteration.\r
-     * @param {Function} fn The function to execute for each item.\r
-     * @param {Object} scope (optional) The scope in which to execute the function.\r
-     */\r
-    each : function(fn, scope){\r
-        var items = [].concat(this.items); // each safe for removal\r
-        for(var i = 0, len = items.length; i < len; i++){\r
-            if(fn.call(scope || items[i], items[i], i, len) === false){\r
-                break;\r
-            }\r
-        }\r
-    },\r
-\r
-    /**\r
-     * Executes the specified function once for every key in the collection, passing each\r
-     * key, and its associated item as the first two parameters.\r
-     * @param {Function} fn The function to execute for each item.\r
-     * @param {Object} scope (optional) The scope in which to execute the function.\r
-     */\r
-    eachKey : function(fn, scope){\r
-        for(var i = 0, len = this.keys.length; i < len; i++){\r
-            fn.call(scope || window, this.keys[i], this.items[i], i, len);\r
-        }\r
-    },\r
-\r
-    /**\r
-     * Returns the first item in the collection which elicits a true return value from the\r
-     * passed selection function.\r
-     * @param {Function} fn The selection function to execute for each item.\r
-     * @param {Object} scope (optional) The scope in which to execute the function.\r
-     * @return {Object} The first item in the collection which returned true from the selection function.\r
-     */\r
-    find : function(fn, scope){\r
-        for(var i = 0, len = this.items.length; i < len; i++){\r
-            if(fn.call(scope || window, this.items[i], this.keys[i])){\r
-                return this.items[i];\r
-            }\r
-        }\r
-        return null;\r
-    },\r
-\r
-    /**\r
-     * Inserts an item at the specified index in the collection. Fires the {@link #add} event when complete.\r
-     * @param {Number} index The index to insert the item at.\r
-     * @param {String} key The key to associate with the new item, or the item itself.\r
-     * @param {Object} o (optional) If the second parameter was a key, the new item.\r
-     * @return {Object} The item inserted.\r
-     */\r
-    insert : function(index, key, o){\r
-        if(arguments.length == 2){\r
-            o = arguments[1];\r
-            key = this.getKey(o);\r
-        }\r
-        if(this.containsKey(key)){\r
-            this.suspendEvents();\r
-            this.removeKey(key);\r
-            this.resumeEvents();\r
-        }\r
-        if(index >= this.length){\r
-            return this.add(key, o);\r
-        }\r
-        this.length++;\r
-        this.items.splice(index, 0, o);\r
-        if(typeof key != 'undefined' && key !== null){\r
-            this.map[key] = o;\r
-        }\r
-        this.keys.splice(index, 0, key);\r
-        this.fireEvent('add', index, o, key);\r
-        return o;\r
-    },\r
-\r
-    /**\r
-     * Remove an item from the collection.\r
-     * @param {Object} o The item to remove.\r
-     * @return {Object} The item removed or false if no item was removed.\r
-     */\r
-    remove : function(o){\r
-        return this.removeAt(this.indexOf(o));\r
-    },\r
-\r
-    /**\r
-     * Remove an item from a specified index in the collection. Fires the {@link #remove} event when complete.\r
-     * @param {Number} index The index within the collection of the item to remove.\r
-     * @return {Object} The item removed or false if no item was removed.\r
-     */\r
-    removeAt : function(index){\r
-        if(index < this.length && index >= 0){\r
-            this.length--;\r
-            var o = this.items[index];\r
-            this.items.splice(index, 1);\r
-            var key = this.keys[index];\r
-            if(typeof key != 'undefined'){\r
-                delete this.map[key];\r
-            }\r
-            this.keys.splice(index, 1);\r
-            this.fireEvent('remove', o, key);\r
-            return o;\r
-        }\r
-        return false;\r
-    },\r
-\r
-    /**\r
-     * Removed an item associated with the passed key fom the collection.\r
-     * @param {String} key The key of the item to remove.\r
-     * @return {Object} The item removed or false if no item was removed.\r
-     */\r
-    removeKey : function(key){\r
-        return this.removeAt(this.indexOfKey(key));\r
-    },\r
-\r
-    /**\r
-     * Returns the number of items in the collection.\r
-     * @return {Number} the number of items in the collection.\r
-     */\r
-    getCount : function(){\r
-        return this.length;\r
-    },\r
-    \r
-    /**\r
-     * Returns index within the collection of the passed Object.\r
-     * @param {Object} o The item to find the index of.\r
-     * @return {Number} index of the item. Returns -1 if not found.\r
-     */\r
-    indexOf : function(o){\r
-        return this.items.indexOf(o);\r
-    },\r
-\r
-    /**\r
-     * Returns index within the collection of the passed key.\r
-     * @param {String} key The key to find the index of.\r
-     * @return {Number} index of the key.\r
-     */\r
-    indexOfKey : function(key){\r
-        return this.keys.indexOf(key);\r
-    },\r
-\r
-    /**\r
-     * Returns the item associated with the passed key OR index.\r
-     * Key has priority over index.  This is the equivalent\r
-     * of calling {@link #key} first, then if nothing matched calling {@link #itemAt}.\r
-     * @param {String/Number} key The key or index of the item.\r
-     * @return {Object} If the item is found, returns the item.  If the item was not found, returns <tt>undefined</tt>.\r
-     * If an item was found, but is a Class, returns <tt>null</tt>.\r
-     */\r
-    item : function(key){\r
-        var mk = this.map[key],\r
-            item = mk !== undefined ? mk : (typeof key == 'number') ? this.items[key] : undefined;\r
-        return !Ext.isFunction(item) || this.allowFunctions ? item : null; // for prototype!\r
-    },\r
-\r
-    /**\r
-     * Returns the item at the specified index.\r
-     * @param {Number} index The index of the item.\r
-     * @return {Object} The item at the specified index.\r
-     */\r
-    itemAt : function(index){\r
-        return this.items[index];\r
-    },\r
-\r
-    /**\r
-     * Returns the item associated with the passed key.\r
-     * @param {String/Number} key The key of the item.\r
-     * @return {Object} The item associated with the passed key.\r
-     */\r
-    key : function(key){\r
-        return this.map[key];\r
-    },\r
-\r
-    /**\r
-     * Returns true if the collection contains the passed Object as an item.\r
-     * @param {Object} o  The Object to look for in the collection.\r
-     * @return {Boolean} True if the collection contains the Object as an item.\r
-     */\r
-    contains : function(o){\r
-        return this.indexOf(o) != -1;\r
-    },\r
-\r
-    /**\r
-     * Returns true if the collection contains the passed Object as a key.\r
-     * @param {String} key The key to look for in the collection.\r
-     * @return {Boolean} True if the collection contains the Object as a key.\r
-     */\r
-    containsKey : function(key){\r
-        return typeof this.map[key] != 'undefined';\r
-    },\r
-\r
-    /**\r
-     * Removes all items from the collection.  Fires the {@link #clear} event when complete.\r
-     */\r
-    clear : function(){\r
-        this.length = 0;\r
-        this.items = [];\r
-        this.keys = [];\r
-        this.map = {};\r
-        this.fireEvent('clear');\r
-    },\r
-\r
-    /**\r
-     * Returns the first item in the collection.\r
-     * @return {Object} the first item in the collection..\r
-     */\r
-    first : function(){\r
-        return this.items[0];\r
-    },\r
-\r
-    /**\r
-     * Returns the last item in the collection.\r
-     * @return {Object} the last item in the collection..\r
-     */\r
-    last : function(){\r
-        return this.items[this.length-1];\r
-    },\r
-\r
-    /**\r
-     * @private\r
-     * @param {String} property Property to sort by ('key', 'value', or 'index')\r
-     * @param {String} dir (optional) Direction to sort 'ASC' or 'DESC'. Defaults to 'ASC'.\r
-     * @param {Function} fn (optional) Comparison function that defines the sort order.\r
-     * Defaults to sorting by numeric value.  \r
-     */\r
-    _sort : function(property, dir, fn){\r
-        var i,\r
-            len,\r
-            dsc = String(dir).toUpperCase() == 'DESC' ? -1 : 1,\r
-            c = [], k = this.keys, items = this.items;\r
-            \r
-        fn = fn || function(a, b){\r
-            return a-b;\r
-        };\r
-        for(i = 0, len = items.length; i < len; i++){\r
-            c[c.length] = {key: k[i], value: items[i], index: i};\r
-        }\r
-        c.sort(function(a, b){\r
-            var v = fn(a[property], b[property]) * dsc;\r
-            if(v === 0){\r
-                v = (a.index < b.index ? -1 : 1);\r
-            }\r
-            return v;\r
-        });\r
-        for(i = 0, len = c.length; i < len; i++){\r
-            items[i] = c[i].value;\r
-            k[i] = c[i].key;\r
-        }\r
-        this.fireEvent('sort', this);\r
-    },\r
-\r
-    /**\r
-     * Sorts this collection by <b>item</b> value with the passed comparison function.\r
-     * @param {String} direction (optional) 'ASC' or 'DESC'. Defaults to 'ASC'.\r
-     * @param {Function} fn (optional) Comparison function that defines the sort order.\r
-     * Defaults to sorting by numeric value.  \r
-     */\r
-    sort : function(dir, fn){\r
-        this._sort('value', dir, fn);\r
-    },\r
-\r
-    /**\r
-     * Sorts this collection by <b>key</b>s.\r
-     * @param {String} direction (optional) 'ASC' or 'DESC'. Defaults to 'ASC'.\r
-     * @param {Function} fn (optional) Comparison function that defines the sort order.\r
-     * Defaults to sorting by case insensitive string.  \r
-     */\r
-    keySort : function(dir, fn){\r
-        this._sort('key', dir, fn || function(a, b){\r
-            var v1 = String(a).toUpperCase(), v2 = String(b).toUpperCase();\r
-            return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);\r
-        });\r
-    },\r
-\r
-    /**\r
-     * Returns a range of items in this collection\r
-     * @param {Number} startIndex (optional) The starting index. Defaults to 0.\r
-     * @param {Number} endIndex (optional) The ending index. Defaults to the last item.\r
-     * @return {Array} An array of items\r
-     */\r
-    getRange : function(start, end){\r
-        var items = this.items;\r
-        if(items.length < 1){\r
-            return [];\r
-        }\r
-        start = start || 0;\r
-        end = Math.min(typeof end == 'undefined' ? this.length-1 : end, this.length-1);\r
-        var i, r = [];\r
-        if(start <= end){\r
-            for(i = start; i <= end; i++) {\r
-                r[r.length] = items[i];\r
-            }\r
-        }else{\r
-            for(i = start; i >= end; i--) {\r
-                r[r.length] = items[i];\r
-            }\r
-        }\r
-        return r;\r
-    },\r
-\r
-    /**\r
-     * Filter the <i>objects</i> in this collection by a specific property.\r
-     * Returns a new collection that has been filtered.\r
-     * @param {String} property A property on your objects\r
-     * @param {String/RegExp} value Either string that the property values\r
-     * should start with or a RegExp to test against the property\r
-     * @param {Boolean} anyMatch (optional) True to match any part of the string, not just the beginning\r
-     * @param {Boolean} caseSensitive (optional) True for case sensitive comparison (defaults to False).\r
-     * @return {MixedCollection} The new filtered collection\r
-     */\r
-    filter : function(property, value, anyMatch, caseSensitive){\r
-        if(Ext.isEmpty(value, false)){\r
-            return this.clone();\r
-        }\r
-        value = this.createValueMatcher(value, anyMatch, caseSensitive);\r
-        return this.filterBy(function(o){\r
-            return o && value.test(o[property]);\r
-        });\r
-    },\r
-\r
-    /**\r
-     * Filter by a function. Returns a <i>new</i> collection that has been filtered.\r
-     * The passed function will be called with each object in the collection.\r
-     * If the function returns true, the value is included otherwise it is filtered.\r
-     * @param {Function} fn The function to be called, it will receive the args o (the object), k (the key)\r
-     * @param {Object} scope (optional) The scope of the function (defaults to this)\r
-     * @return {MixedCollection} The new filtered collection\r
-     */\r
-    filterBy : function(fn, scope){\r
-        var r = new Ext.util.MixedCollection();\r
-        r.getKey = this.getKey;\r
-        var k = this.keys, it = this.items;\r
-        for(var i = 0, len = it.length; i < len; i++){\r
-            if(fn.call(scope||this, it[i], k[i])){\r
-                r.add(k[i], it[i]);\r
-            }\r
-        }\r
-        return r;\r
-    },\r
-\r
-    /**\r
-     * Finds the index of the first matching object in this collection by a specific property/value.\r
-     * @param {String} property The name of a property on your objects.\r
-     * @param {String/RegExp} value A string that the property values\r
-     * should start with or a RegExp to test against the property.\r
-     * @param {Number} start (optional) The index to start searching at (defaults to 0).\r
-     * @param {Boolean} anyMatch (optional) True to match any part of the string, not just the beginning.\r
-     * @param {Boolean} caseSensitive (optional) True for case sensitive comparison.\r
-     * @return {Number} The matched index or -1\r
-     */\r
-    findIndex : function(property, value, start, anyMatch, caseSensitive){\r
-        if(Ext.isEmpty(value, false)){\r
-            return -1;\r
-        }\r
-        value = this.createValueMatcher(value, anyMatch, caseSensitive);\r
-        return this.findIndexBy(function(o){\r
-            return o && value.test(o[property]);\r
-        }, null, start);\r
-    },\r
-\r
-    /**\r
-     * Find the index of the first matching object in this collection by a function.\r
-     * If the function returns <i>true</i> it is considered a match.\r
-     * @param {Function} fn The function to be called, it will receive the args o (the object), k (the key).\r
-     * @param {Object} scope (optional) The scope of the function (defaults to this).\r
-     * @param {Number} start (optional) The index to start searching at (defaults to 0).\r
-     * @return {Number} The matched index or -1\r
-     */\r
-    findIndexBy : function(fn, scope, start){\r
-        var k = this.keys, it = this.items;\r
-        for(var i = (start||0), len = it.length; i < len; i++){\r
-            if(fn.call(scope||this, it[i], k[i])){\r
-                return i;\r
-            }\r
-        }\r
-        return -1;\r
-    },\r
-\r
-    // private\r
-    createValueMatcher : function(value, anyMatch, caseSensitive){\r
-        if(!value.exec){ // not a regex\r
-            value = String(value);\r
-            value = new RegExp((anyMatch === true ? '' : '^') + Ext.escapeRe(value), caseSensitive ? '' : 'i');\r
-        }\r
-        return value;\r
-    },\r
-\r
-    /**\r
-     * Creates a shallow copy of this collection\r
-     * @return {MixedCollection}\r
-     */\r
-    clone : function(){\r
-        var r = new Ext.util.MixedCollection();\r
-        var k = this.keys, it = this.items;\r
-        for(var i = 0, len = it.length; i < len; i++){\r
-            r.add(k[i], it[i]);\r
-        }\r
-        r.getKey = this.getKey;\r
-        return r;\r
-    }\r
-});\r
-/**\r
- * This method calls {@link #item item()}.\r
- * Returns the item associated with the passed key OR index. Key has priority\r
- * over index.  This is the equivalent of calling {@link #key} first, then if\r
- * nothing matched calling {@link #itemAt}.\r
- * @param {String/Number} key The key or index of the item.\r
- * @return {Object} If the item is found, returns the item.  If the item was\r
- * not found, returns <tt>undefined</tt>. If an item was found, but is a Class,\r
- * returns <tt>null</tt>.\r
- */\r
-Ext.util.MixedCollection.prototype.get = Ext.util.MixedCollection.prototype.item;/**
- * @class Ext.util.JSON
- * Modified version of Douglas Crockford"s json.js that doesn"t
- * mess with the Object prototype
- * http://www.json.org/js.html
- * @singleton
- */
-Ext.util.JSON = new (function(){
-    var useHasOwn = !!{}.hasOwnProperty,
-        isNative = function() {
-            var useNative = null;
+        if(typeof key != 'undefined' && key !== null){
+            var old = this.map[key];
+            if(typeof old != 'undefined'){
+                return this.replace(key, o);
+            }
+            this.map[key] = o;
+        }
+        this.length++;
+        this.items.push(o);
+        this.keys.push(key);
+        this.fireEvent('add', this.length-1, o, key);
+        return o;
+    },
 
-            return function() {
-                if (useNative === null) {
-                    useNative = Ext.USE_NATIVE_JSON && window.JSON && JSON.toString() == '[object JSON]';
-                }
-        
-                return useNative;
-            };
-        }(),
-        pad = function(n) {
-            return n < 10 ? "0" + n : n;
-        },
-        doDecode = function(json){
-            return eval("(" + json + ')');    
-        },
-        doEncode = function(o){
-            if(!Ext.isDefined(o) || o === null){
-                return "null";
-            }else if(Ext.isArray(o)){
-                return encodeArray(o);
-            }else if(Ext.isDate(o)){
-                return Ext.util.JSON.encodeDate(o);
-            }else if(Ext.isString(o)){
-                return encodeString(o);
-            }else if(typeof o == "number"){
-                //don't use isNumber here, since finite checks happen inside isNumber
-                return isFinite(o) ? String(o) : "null";
-            }else if(Ext.isBoolean(o)){
-                return String(o);
-            }else {
-                var a = ["{"], b, i, v;
-                for (i in o) {
-                    // don't encode DOM objects
-                    if(!o.getElementsByTagName){
-                        if(!useHasOwn || o.hasOwnProperty(i)) {
-                            v = o[i];
-                            switch (typeof v) {
-                            case "undefined":
-                            case "function":
-                            case "unknown":
-                                break;
-                            default:
-                                if(b){
-                                    a.push(',');
-                                }
-                                a.push(doEncode(i), ":",
-                                        v === null ? "null" : doEncode(v));
-                                b = true;
-                            }
-                        }
-                    }
+    /**
+      * MixedCollection has a generic way to fetch keys if you implement getKey.  The default implementation
+      * simply returns <b><code>item.id</code></b> but you can provide your own implementation
+      * to return a different value as in the following examples:<pre><code>
+// normal way
+var mc = new Ext.util.MixedCollection();
+mc.add(someEl.dom.id, someEl);
+mc.add(otherEl.dom.id, otherEl);
+//and so on
+
+// using getKey
+var mc = new Ext.util.MixedCollection();
+mc.getKey = function(el){
+   return el.dom.id;
+};
+mc.add(someEl);
+mc.add(otherEl);
+
+// or via the constructor
+var mc = new Ext.util.MixedCollection(false, function(el){
+   return el.dom.id;
+});
+mc.add(someEl);
+mc.add(otherEl);
+     * </code></pre>
+     * @param {Object} item The item for which to find the key.
+     * @return {Object} The key for the passed item.
+     */
+    getKey : function(o){
+         return o.id;
+    },
+
+    /**
+     * Replaces an item in the collection. Fires the {@link #replace} event when complete.
+     * @param {String} key <p>The key associated with the item to replace, or the replacement item.</p>
+     * <p>If you supplied a {@link #getKey} implementation for this MixedCollection, or if the key
+     * of your stored items is in a property called <tt><b>id</b></tt>, then the MixedCollection
+     * will be able to <i>derive</i> the key of the replacement item. If you want to replace an item
+     * with one having the same key value, then just pass the replacement item in this parameter.</p>
+     * @param o {Object} o (optional) If the first parameter passed was a key, the item to associate
+     * with that key.
+     * @return {Object}  The new item.
+     */
+    replace : function(key, o){
+        if(arguments.length == 1){
+            o = arguments[0];
+            key = this.getKey(o);
+        }
+        var old = this.map[key];
+        if(typeof key == 'undefined' || key === null || typeof old == 'undefined'){
+             return this.add(key, o);
+        }
+        var index = this.indexOfKey(key);
+        this.items[index] = o;
+        this.map[key] = o;
+        this.fireEvent('replace', key, old, o);
+        return o;
+    },
+
+    /**
+     * Adds all elements of an Array or an Object to the collection.
+     * @param {Object/Array} objs An Object containing properties which will be added
+     * to the collection, or an Array of values, each of which are added to the collection.
+     * Functions references will be added to the collection if <code>{@link #allowFunctions}</code>
+     * has been set to <tt>true</tt>.
+     */
+    addAll : function(objs){
+        if(arguments.length > 1 || Ext.isArray(objs)){
+            var args = arguments.length > 1 ? arguments : objs;
+            for(var i = 0, len = args.length; i < len; i++){
+                this.add(args[i]);
+            }
+        }else{
+            for(var key in objs){
+                if(this.allowFunctions || typeof objs[key] != 'function'){
+                    this.add(key, objs[key]);
                 }
-                a.push("}");
-                return a.join("");
-            }    
-        },
-        m = {
-            "\b": '\\b',
-            "\t": '\\t',
-            "\n": '\\n',
-            "\f": '\\f',
-            "\r": '\\r',
-            '"' : '\\"',
-            "\\": '\\\\'
-        },
-        encodeString = function(s){
-            if (/["\\\x00-\x1f]/.test(s)) {
-                return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
-                    var c = m[b];
-                    if(c){
-                        return c;
-                    }
-                    c = b.charCodeAt();
-                    return "\\u00" +
-                        Math.floor(c / 16).toString(16) +
-                        (c % 16).toString(16);
-                }) + '"';
             }
-            return '"' + s + '"';
-        },
-        encodeArray = function(o){
+        }
+    },
+
+    /**
+     * Executes the specified function once for every item in the collection, passing the following arguments:
+     * <div class="mdetail-params"><ul>
+     * <li><b>item</b> : Mixed<p class="sub-desc">The collection item</p></li>
+     * <li><b>index</b> : Number<p class="sub-desc">The item's index</p></li>
+     * <li><b>length</b> : Number<p class="sub-desc">The total number of items in the collection</p></li>
+     * </ul></div>
+     * The function should return a boolean value. Returning false from the function will stop the iteration.
+     * @param {Function} fn The function to execute for each item.
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to the current item in the iteration.
+     */
+    each : function(fn, scope){
+        var items = [].concat(this.items); // each safe for removal
+        for(var i = 0, len = items.length; i < len; i++){
+            if(fn.call(scope || items[i], items[i], i, len) === false){
+                break;
+            }
+        }
+    },
+
+    /**
+     * Executes the specified function once for every key in the collection, passing each
+     * key, and its associated item as the first two parameters.
+     * @param {Function} fn The function to execute for each item.
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to the browser window.
+     */
+    eachKey : function(fn, scope){
+        for(var i = 0, len = this.keys.length; i < len; i++){
+            fn.call(scope || window, this.keys[i], this.items[i], i, len);
+        }
+    },
+
+    /**
+     * Returns the first item in the collection which elicits a true return value from the
+     * passed selection function.
+     * @param {Function} fn The selection function to execute for each item.
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to the browser window.
+     * @return {Object} The first item in the collection which returned true from the selection function.
+     */
+    find : function(fn, scope){
+        for(var i = 0, len = this.items.length; i < len; i++){
+            if(fn.call(scope || window, this.items[i], this.keys[i])){
+                return this.items[i];
+            }
+        }
+        return null;
+    },
+
+    /**
+     * Inserts an item at the specified index in the collection. Fires the {@link #add} event when complete.
+     * @param {Number} index The index to insert the item at.
+     * @param {String} key The key to associate with the new item, or the item itself.
+     * @param {Object} o (optional) If the second parameter was a key, the new item.
+     * @return {Object} The item inserted.
+     */
+    insert : function(index, key, o){
+        if(arguments.length == 2){
+            o = arguments[1];
+            key = this.getKey(o);
+        }
+        if(this.containsKey(key)){
+            this.suspendEvents();
+            this.removeKey(key);
+            this.resumeEvents();
+        }
+        if(index >= this.length){
+            return this.add(key, o);
+        }
+        this.length++;
+        this.items.splice(index, 0, o);
+        if(typeof key != 'undefined' && key !== null){
+            this.map[key] = o;
+        }
+        this.keys.splice(index, 0, key);
+        this.fireEvent('add', index, o, key);
+        return o;
+    },
+
+    /**
+     * Remove an item from the collection.
+     * @param {Object} o The item to remove.
+     * @return {Object} The item removed or false if no item was removed.
+     */
+    remove : function(o){
+        return this.removeAt(this.indexOf(o));
+    },
+
+    /**
+     * Remove an item from a specified index in the collection. Fires the {@link #remove} event when complete.
+     * @param {Number} index The index within the collection of the item to remove.
+     * @return {Object} The item removed or false if no item was removed.
+     */
+    removeAt : function(index){
+        if(index < this.length && index >= 0){
+            this.length--;
+            var o = this.items[index];
+            this.items.splice(index, 1);
+            var key = this.keys[index];
+            if(typeof key != 'undefined'){
+                delete this.map[key];
+            }
+            this.keys.splice(index, 1);
+            this.fireEvent('remove', o, key);
+            return o;
+        }
+        return false;
+    },
+
+    /**
+     * Removed an item associated with the passed key fom the collection.
+     * @param {String} key The key of the item to remove.
+     * @return {Object} The item removed or false if no item was removed.
+     */
+    removeKey : function(key){
+        return this.removeAt(this.indexOfKey(key));
+    },
+
+    /**
+     * Returns the number of items in the collection.
+     * @return {Number} the number of items in the collection.
+     */
+    getCount : function(){
+        return this.length;
+    },
+
+    /**
+     * Returns index within the collection of the passed Object.
+     * @param {Object} o The item to find the index of.
+     * @return {Number} index of the item. Returns -1 if not found.
+     */
+    indexOf : function(o){
+        return this.items.indexOf(o);
+    },
+
+    /**
+     * Returns index within the collection of the passed key.
+     * @param {String} key The key to find the index of.
+     * @return {Number} index of the key.
+     */
+    indexOfKey : function(key){
+        return this.keys.indexOf(key);
+    },
+
+    /**
+     * Returns the item associated with the passed key OR index.
+     * Key has priority over index.  This is the equivalent
+     * of calling {@link #key} first, then if nothing matched calling {@link #itemAt}.
+     * @param {String/Number} key The key or index of the item.
+     * @return {Object} If the item is found, returns the item.  If the item was not found, returns <tt>undefined</tt>.
+     * If an item was found, but is a Class, returns <tt>null</tt>.
+     */
+    item : function(key){
+        var mk = this.map[key],
+            item = mk !== undefined ? mk : (typeof key == 'number') ? this.items[key] : undefined;
+        return !Ext.isFunction(item) || this.allowFunctions ? item : null; // for prototype!
+    },
+
+    /**
+     * Returns the item at the specified index.
+     * @param {Number} index The index of the item.
+     * @return {Object} The item at the specified index.
+     */
+    itemAt : function(index){
+        return this.items[index];
+    },
+
+    /**
+     * Returns the item associated with the passed key.
+     * @param {String/Number} key The key of the item.
+     * @return {Object} The item associated with the passed key.
+     */
+    key : function(key){
+        return this.map[key];
+    },
+
+    /**
+     * Returns true if the collection contains the passed Object as an item.
+     * @param {Object} o  The Object to look for in the collection.
+     * @return {Boolean} True if the collection contains the Object as an item.
+     */
+    contains : function(o){
+        return this.indexOf(o) != -1;
+    },
+
+    /**
+     * Returns true if the collection contains the passed Object as a key.
+     * @param {String} key The key to look for in the collection.
+     * @return {Boolean} True if the collection contains the Object as a key.
+     */
+    containsKey : function(key){
+        return typeof this.map[key] != 'undefined';
+    },
+
+    /**
+     * Removes all items from the collection.  Fires the {@link #clear} event when complete.
+     */
+    clear : function(){
+        this.length = 0;
+        this.items = [];
+        this.keys = [];
+        this.map = {};
+        this.fireEvent('clear');
+    },
+
+    /**
+     * Returns the first item in the collection.
+     * @return {Object} the first item in the collection..
+     */
+    first : function(){
+        return this.items[0];
+    },
+
+    /**
+     * Returns the last item in the collection.
+     * @return {Object} the last item in the collection..
+     */
+    last : function(){
+        return this.items[this.length-1];
+    },
+
+    /**
+     * @private
+     * @param {String} property Property to sort by ('key', 'value', or 'index')
+     * @param {String} dir (optional) Direction to sort 'ASC' or 'DESC'. Defaults to 'ASC'.
+     * @param {Function} fn (optional) Comparison function that defines the sort order.
+     * Defaults to sorting by numeric value.
+     */
+    _sort : function(property, dir, fn){
+        var i,
+            len,
+            dsc = String(dir).toUpperCase() == 'DESC' ? -1 : 1,
+            c = [], k = this.keys, items = this.items;
+
+        fn = fn || function(a, b){
+            return a-b;
+        };
+        for(i = 0, len = items.length; i < len; i++){
+            c[c.length] = {key: k[i], value: items[i], index: i};
+        }
+        c.sort(function(a, b){
+            var v = fn(a[property], b[property]) * dsc;
+            if(v === 0){
+                v = (a.index < b.index ? -1 : 1);
+            }
+            return v;
+        });
+        for(i = 0, len = c.length; i < len; i++){
+            items[i] = c[i].value;
+            k[i] = c[i].key;
+        }
+        this.fireEvent('sort', this);
+    },
+
+    /**
+     * Sorts this collection by <b>item</b> value with the passed comparison function.
+     * @param {String} direction (optional) 'ASC' or 'DESC'. Defaults to 'ASC'.
+     * @param {Function} fn (optional) Comparison function that defines the sort order.
+     * Defaults to sorting by numeric value.
+     */
+    sort : function(dir, fn){
+        this._sort('value', dir, fn);
+    },
+
+    /**
+     * Sorts this collection by <b>key</b>s.
+     * @param {String} direction (optional) 'ASC' or 'DESC'. Defaults to 'ASC'.
+     * @param {Function} fn (optional) Comparison function that defines the sort order.
+     * Defaults to sorting by case insensitive string.
+     */
+    keySort : function(dir, fn){
+        this._sort('key', dir, fn || function(a, b){
+            var v1 = String(a).toUpperCase(), v2 = String(b).toUpperCase();
+            return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
+        });
+    },
+
+    /**
+     * Returns a range of items in this collection
+     * @param {Number} startIndex (optional) The starting index. Defaults to 0.
+     * @param {Number} endIndex (optional) The ending index. Defaults to the last item.
+     * @return {Array} An array of items
+     */
+    getRange : function(start, end){
+        var items = this.items;
+        if(items.length < 1){
+            return [];
+        }
+        start = start || 0;
+        end = Math.min(typeof end == 'undefined' ? this.length-1 : end, this.length-1);
+        var i, r = [];
+        if(start <= end){
+            for(i = start; i <= end; i++) {
+                r[r.length] = items[i];
+            }
+        }else{
+            for(i = start; i >= end; i--) {
+                r[r.length] = items[i];
+            }
+        }
+        return r;
+    },
+
+    /**
+     * Filter the <i>objects</i> in this collection by a specific property.
+     * Returns a new collection that has been filtered.
+     * @param {String} property A property on your objects
+     * @param {String/RegExp} value Either string that the property values
+     * should start with or a RegExp to test against the property
+     * @param {Boolean} anyMatch (optional) True to match any part of the string, not just the beginning
+     * @param {Boolean} caseSensitive (optional) True for case sensitive comparison (defaults to False).
+     * @return {MixedCollection} The new filtered collection
+     */
+    filter : function(property, value, anyMatch, caseSensitive){
+        if(Ext.isEmpty(value, false)){
+            return this.clone();
+        }
+        value = this.createValueMatcher(value, anyMatch, caseSensitive);
+        return this.filterBy(function(o){
+            return o && value.test(o[property]);
+        });
+    },
+
+    /**
+     * Filter by a function. Returns a <i>new</i> collection that has been filtered.
+     * The passed function will be called with each object in the collection.
+     * If the function returns true, the value is included otherwise it is filtered.
+     * @param {Function} fn The function to be called, it will receive the args o (the object), k (the key)
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to this MixedCollection.
+     * @return {MixedCollection} The new filtered collection
+     */
+    filterBy : function(fn, scope){
+        var r = new Ext.util.MixedCollection();
+        r.getKey = this.getKey;
+        var k = this.keys, it = this.items;
+        for(var i = 0, len = it.length; i < len; i++){
+            if(fn.call(scope||this, it[i], k[i])){
+                r.add(k[i], it[i]);
+            }
+        }
+        return r;
+    },
+
+    /**
+     * Finds the index of the first matching object in this collection by a specific property/value.
+     * @param {String} property The name of a property on your objects.
+     * @param {String/RegExp} value A string that the property values
+     * should start with or a RegExp to test against the property.
+     * @param {Number} start (optional) The index to start searching at (defaults to 0).
+     * @param {Boolean} anyMatch (optional) True to match any part of the string, not just the beginning.
+     * @param {Boolean} caseSensitive (optional) True for case sensitive comparison.
+     * @return {Number} The matched index or -1
+     */
+    findIndex : function(property, value, start, anyMatch, caseSensitive){
+        if(Ext.isEmpty(value, false)){
+            return -1;
+        }
+        value = this.createValueMatcher(value, anyMatch, caseSensitive);
+        return this.findIndexBy(function(o){
+            return o && value.test(o[property]);
+        }, null, start);
+    },
+
+    /**
+     * Find the index of the first matching object in this collection by a function.
+     * If the function returns <i>true</i> it is considered a match.
+     * @param {Function} fn The function to be called, it will receive the args o (the object), k (the key).
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to this MixedCollection.
+     * @param {Number} start (optional) The index to start searching at (defaults to 0).
+     * @return {Number} The matched index or -1
+     */
+    findIndexBy : function(fn, scope, start){
+        var k = this.keys, it = this.items;
+        for(var i = (start||0), len = it.length; i < len; i++){
+            if(fn.call(scope||this, it[i], k[i])){
+                return i;
+            }
+        }
+        return -1;
+    },
+
+    // private
+    createValueMatcher : function(value, anyMatch, caseSensitive, exactMatch) {
+        if (!value.exec) { // not a regex
+            var er = Ext.escapeRe;
+            value = String(value);
+            if (anyMatch === true) {
+                value = er(value);
+            } else {
+                value = '^' + er(value);
+                if (exactMatch === true) {
+                    value += '$';
+                }
+            }
+            value = new RegExp(value, caseSensitive ? '' : 'i');
+         }
+         return value;
+    },
+
+    /**
+     * Creates a shallow copy of this collection
+     * @return {MixedCollection}
+     */
+    clone : function(){
+        var r = new Ext.util.MixedCollection();
+        var k = this.keys, it = this.items;
+        for(var i = 0, len = it.length; i < len; i++){
+            r.add(k[i], it[i]);
+        }
+        r.getKey = this.getKey;
+        return r;
+    }
+});
+/**
+ * This method calls {@link #item item()}.
+ * Returns the item associated with the passed key OR index. Key has priority
+ * over index.  This is the equivalent of calling {@link #key} first, then if
+ * nothing matched calling {@link #itemAt}.
+ * @param {String/Number} key The key or index of the item.
+ * @return {Object} If the item is found, returns the item.  If the item was
+ * not found, returns <tt>undefined</tt>. If an item was found, but is a Class,
+ * returns <tt>null</tt>.
+ */
+Ext.util.MixedCollection.prototype.get = Ext.util.MixedCollection.prototype.item;/**
+ * @class Ext.util.JSON
+ * Modified version of Douglas Crockford"s json.js that doesn"t
+ * mess with the Object prototype
+ * http://www.json.org/js.html
+ * @singleton
+ */
+Ext.util.JSON = new (function(){
+    var useHasOwn = !!{}.hasOwnProperty,
+        isNative = function() {
+            var useNative = null;
+
+            return function() {
+                if (useNative === null) {
+                    useNative = Ext.USE_NATIVE_JSON && window.JSON && JSON.toString() == '[object JSON]';
+                }
+        
+                return useNative;
+            };
+        }(),
+        pad = function(n) {
+            return n < 10 ? "0" + n : n;
+        },
+        doDecode = function(json){
+            return eval("(" + json + ')');    
+        },
+        doEncode = function(o){
+            if(!Ext.isDefined(o) || o === null){
+                return "null";
+            }else if(Ext.isArray(o)){
+                return encodeArray(o);
+            }else if(Ext.isDate(o)){
+                return Ext.util.JSON.encodeDate(o);
+            }else if(Ext.isString(o)){
+                return encodeString(o);
+            }else if(typeof o == "number"){
+                //don't use isNumber here, since finite checks happen inside isNumber
+                return isFinite(o) ? String(o) : "null";
+            }else if(Ext.isBoolean(o)){
+                return String(o);
+            }else {
+                var a = ["{"], b, i, v;
+                for (i in o) {
+                    // don't encode DOM objects
+                    if(!o.getElementsByTagName){
+                        if(!useHasOwn || o.hasOwnProperty(i)) {
+                            v = o[i];
+                            switch (typeof v) {
+                            case "undefined":
+                            case "function":
+                            case "unknown":
+                                break;
+                            default:
+                                if(b){
+                                    a.push(',');
+                                }
+                                a.push(doEncode(i), ":",
+                                        v === null ? "null" : doEncode(v));
+                                b = true;
+                            }
+                        }
+                    }
+                }
+                a.push("}");
+                return a.join("");
+            }    
+        },
+        m = {
+            "\b": '\\b',
+            "\t": '\\t',
+            "\n": '\\n',
+            "\f": '\\f',
+            "\r": '\\r',
+            '"' : '\\"',
+            "\\": '\\\\'
+        },
+        encodeString = function(s){
+            if (/["\\\x00-\x1f]/.test(s)) {
+                return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
+                    var c = m[b];
+                    if(c){
+                        return c;
+                    }
+                    c = b.charCodeAt();
+                    return "\\u00" +
+                        Math.floor(c / 16).toString(16) +
+                        (c % 16).toString(16);
+                }) + '"';
+            }
+            return '"' + s + '"';
+        },
+        encodeArray = function(o){
             var a = ["["], b, i, l = o.length, v;
                 for (i = 0; i < l; i += 1) {
                     v = o[i];
@@ -11859,6 +12327,18 @@ Ext.util.JSON = new (function(){
                 return a.join("");
         };
 
+    /**
+     * <p>Encodes a Date. This returns the actual string which is inserted into the JSON string as the literal expression.
+     * <b>The returned value includes enclosing double quotation marks.</b></p>
+     * <p>The default return format is "yyyy-mm-ddThh:mm:ss".</p>
+     * <p>To override this:</p><pre><code>
+Ext.util.JSON.encodeDate = function(d) {
+    return d.format('"Y-m-d"');
+};
+</code></pre>
+     * @param {Date} d The Date to encode
+     * @return {String} The string literal to use in a JSON string.
+     */
     this.encodeDate = function(o){
         return '"' + o.getFullYear() + "-" +
                 pad(o.getMonth() + 1) + "-" +
@@ -11925,7 +12405,11 @@ Ext.decode = Ext.util.JSON.decode;
  * @singleton\r
  */\r
 Ext.util.Format = function(){\r
-    var trimRe = /^\s+|\s+$/g;\r
+    var trimRe = /^\s+|\s+$/g,\r
+        stripTagsRE = /<\/?[^>]+>/gi,\r
+        stripScriptsRe = /(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig,\r
+        nl2brRe = /\r?\n/g;\r
+        \r
     return {\r
         /**\r
          * Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length\r
@@ -11937,8 +12421,8 @@ Ext.util.Format = function(){
         ellipsis : function(value, len, word){\r
             if(value && value.length > len){\r
                 if(word){\r
-                    var vs = value.substr(0, len - 2);\r
-                    var index = Math.max(vs.lastIndexOf(' '), vs.lastIndexOf('.'), vs.lastIndexOf('!'), vs.lastIndexOf('?'));\r
+                    var vs = value.substr(0, len - 2),\r
+                        index = Math.max(vs.lastIndexOf(' '), vs.lastIndexOf('.'), vs.lastIndexOf('!'), vs.lastIndexOf('?'));\r
                     if(index == -1 || index < (len - 15)){\r
                         return value.substr(0, len - 3) + "...";\r
                     }else{\r
@@ -12055,10 +12539,10 @@ Ext.util.Format = function(){
             v = (Math.round((v-0)*100))/100;\r
             v = (v == Math.floor(v)) ? v + ".00" : ((v*10 == Math.floor(v*10)) ? v + "0" : v);\r
             v = String(v);\r
-            var ps = v.split('.');\r
-            var whole = ps[0];\r
-            var sub = ps[1] ? '.'+ ps[1] : '.00';\r
-            var r = /(\d+)(\d{3})/;\r
+            var ps = v.split('.'),\r
+                whole = ps[0],\r
+                sub = ps[1] ? '.'+ ps[1] : '.00',\r
+                r = /(\d+)(\d{3})/;\r
             while (r.test(whole)) {\r
                 whole = whole.replace(r, '$1' + ',' + '$2');\r
             }\r
@@ -12095,9 +12579,6 @@ Ext.util.Format = function(){
                 return Ext.util.Format.date(v, format);\r
             };\r
         },\r
-\r
-        // private\r
-        stripTagsRE : /<\/?[^>]+>/gi,\r
         \r
         /**\r
          * Strips all HTML tags\r
@@ -12105,18 +12586,16 @@ Ext.util.Format = function(){
          * @return {String} The stripped text\r
          */\r
         stripTags : function(v){\r
-            return !v ? v : String(v).replace(this.stripTagsRE, "");\r
+            return !v ? v : String(v).replace(stripTagsRE, "");\r
         },\r
 \r
-        stripScriptsRe : /(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig,\r
-\r
         /**\r
          * Strips all script tags\r
          * @param {Mixed} value The text from which to strip script tags\r
          * @return {String} The stripped text\r
          */\r
         stripScripts : function(v){\r
-            return !v ? v : String(v).replace(this.stripScriptsRe, "");\r
+            return !v ? v : String(v).replace(stripScriptsRe, "");\r
         },\r
 \r
         /**\r
@@ -12265,10 +12744,11 @@ Ext.util.Format = function(){
          * @return {String} The string with embedded &lt;br/> tags in place of newlines.\r
          */\r
         nl2br : function(v){\r
-            return v === undefined || v === null ? '' : v.replace(/\n/g, '<br/>');\r
+            return Ext.isEmpty(v) ? '' : v.replace(nl2brRe, '<br/>');\r
         }\r
     }\r
-}();/**
+}();\r
+/**
  * @class Ext.XTemplate
  * @extends Ext.Template
  * <p>A template class that supports advanced functionality like:<div class="mdetail-params"><ul>
@@ -13196,6 +13676,13 @@ Ext.KeyNav.prototype = {
             e.stopEvent();
         }
     },
+    
+    /**
+     * Destroy this KeyNav (this is the same as calling disable).
+     */
+    destroy: function(){
+        this.disable();    
+    },
 
        /**
         * Enable this KeyNav
@@ -13408,7 +13895,7 @@ map.addBinding({
      * following options:\r
      * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}\r
      * @param {Function} fn The function to call\r
-     * @param {Object} scope (optional) The scope of the function\r
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to the browser window.\r
      */\r
     on : function(key, fn, scope){\r
         var keyCode, shift, ctrl, alt;\r
@@ -13530,6 +14017,7 @@ Ext.util.TextMetrics.Instance = function(bindTo, fixedWidth){
 
     var instance = {
         /**
+         * <p><b>Only available on the instance returned from {@link #createInstance}, <u>not</u> on the singleton.</b></p>
          * Returns the size of the specified text based on the internal element's style and width properties
          * @param {String} text The text to measure
          * @return {Object} An object containing the text's size {width: (width), height: (height)}
@@ -13542,6 +14030,7 @@ Ext.util.TextMetrics.Instance = function(bindTo, fixedWidth){
         },
 
         /**
+         * <p><b>Only available on the instance returned from {@link #createInstance}, <u>not</u> on the singleton.</b></p>
          * Binds this TextMetrics instance to an element from which to copy existing CSS styles
          * that can affect the size of the rendered text
          * @param {String/HTMLElement} el The element, dom node or id
@@ -13553,6 +14042,7 @@ Ext.util.TextMetrics.Instance = function(bindTo, fixedWidth){
         },
 
         /**
+         * <p><b>Only available on the instance returned from {@link #createInstance}, <u>not</u> on the singleton.</b></p>
          * Sets a fixed width on the internal measurement element.  If the text will be multiline, you have
          * to set a fixed width in order to accurately measure the text height.
          * @param {Number} width The width to set on the element
@@ -13562,6 +14052,7 @@ Ext.util.TextMetrics.Instance = function(bindTo, fixedWidth){
         },
 
         /**
+         * <p><b>Only available on the instance returned from {@link #createInstance}, <u>not</u> on the singleton.</b></p>
          * Returns the measured width of the specified text
          * @param {String} text The text to measure
          * @return {Number} width The width in pixels
@@ -13572,6 +14063,7 @@ Ext.util.TextMetrics.Instance = function(bindTo, fixedWidth){
         },
 
         /**
+         * <p><b>Only available on the instance returned from {@link #createInstance}, <u>not</u> on the singleton.</b></p>
          * Returns the measured height of the specified text.  For multiline text, be sure to call
          * {@link #setFixedWidth} if necessary.
          * @param {String} text The text to measure
@@ -13813,10 +14305,10 @@ Ext.ComponentMgr = function(){
         },
 
         /**
-         * Registers a function that will be called when a specified component is added to ComponentMgr
+         * Registers a function that will be called when a Component with the specified id is added to ComponentMgr. This will happen on instantiation.
          * @param {String} id The component {@link Ext.Component#id id}
          * @param {Function} fn The callback function
-         * @param {Object} scope The scope of the callback
+         * @param {Object} scope The scope (<code>this</code> reference) in which the callback is executed. Defaults to the Component.
          */
         onAvailable : function(id, fn, scope){
             all.on("add", function(index, o){
@@ -13834,6 +14326,18 @@ Ext.ComponentMgr = function(){
          */
         all : all,
         
+        /**
+         * The xtypes that have been registered with the component manager.
+         * @type {Object}
+         */
+        types : types,
+        
+        /**
+         * The ptypes that have been registered with the component manager.
+         * @type {Object}
+         */
+        ptypes: ptypes,
+        
         /**
          * Checks if a Component type is registered.
          * @param {Ext.Component} xtype The mnemonic string by which the Component class may be looked up
@@ -13842,6 +14346,15 @@ Ext.ComponentMgr = function(){
         isRegistered : function(xtype){
             return types[xtype] !== undefined;    
         },
+        
+        /**
+         * Checks if a Plugin type is registered.
+         * @param {Ext.Component} ptype The mnemonic string by which the Plugin class may be looked up
+         * @return {Boolean} Whether the type is registered.
+         */
+        isPluginRegistered : function(ptype){
+            return ptypes[ptype] !== undefined;    
+        },        
 
         /**
          * <p>Registers a new Component constructor, keyed by a new
@@ -13893,7 +14406,12 @@ Ext.ComponentMgr = function(){
          * @return {Ext.Component} The newly instantiated Plugin.
          */
         createPlugin : function(config, defaultType){
-            return new ptypes[config.ptype || defaultType](config);
+            var PluginCls = ptypes[config.ptype || defaultType];
+            if (PluginCls.init) {
+                return PluginCls;                
+            } else {
+                return new PluginCls(config);
+            }            
         }
     };
 }();
@@ -13996,7 +14514,7 @@ menutextitem     {@link Ext.menu.TextItem}
 
 Form components
 ---------------------------------------
-form             {@link Ext.FormPanel}
+form             {@link Ext.form.FormPanel}
 checkbox         {@link Ext.form.Checkbox}
 checkboxgroup    {@link Ext.form.CheckboxGroup}
 combo            {@link Ext.form.ComboBox}
@@ -14065,6 +14583,14 @@ Ext.Component = function(config){
 
     Ext.apply(this, config);
     this.addEvents(
+        /**
+         * @event added
+         * Fires when a component is added to an Ext.Container
+         * @param {Ext.Component} this
+         * @param {Ext.Container} ownerCt Container which holds the component
+         * @param {number} index Position at which the component was added
+         */
+        'added',
         /**
          * @event disable
          * Fires after the component is disabled.
@@ -14104,6 +14630,13 @@ Ext.Component = function(config){
          * @param {Ext.Component} this
          */
         'hide',
+        /**
+         * @event removed
+         * Fires when a component is removed from an Ext.Container
+         * @param {Ext.Component} this
+         * @param {Ext.Container} ownerCt Container which holds the component
+         */
+        'removed',
         /**
          * @event beforerender
          * Fires before the component is {@link #rendered}. Return false from an
@@ -14199,7 +14732,7 @@ Ext.Component = function(config){
     }
 
     if(this.stateful !== false){
-        this.initState(config);
+        this.initState();
     }
 
     if(this.applyTo){
@@ -14348,17 +14881,6 @@ new Ext.FormPanel({
 </code></pre>
      */
 
-    // Configs below are used for all Components when rendered by AnchorLayout.
-    /**
-     * @cfg {String} anchor <p><b>Note</b>: this config is only used when this Component is rendered
-     * by a Container which has been configured to use an <b>{@link Ext.layout.AnchorLayout AnchorLayout}</b>
-     * based layout manager, for example:<div class="mdetail-params"><ul>
-     * <li>{@link Ext.form.FormPanel}</li>
-     * <li>specifying <code>layout: 'anchor' // or 'form', or 'absolute'</code></li>
-     * </ul></div></p>
-     * <p>See {@link Ext.layout.AnchorLayout}.{@link Ext.layout.AnchorLayout#anchor anchor} also.</p>
-     */
-
     /**
      * @cfg {String} id
      * <p>The <b>unique</b> id of this component (defaults to an {@link #getId auto-assigned id}).
@@ -14710,6 +15232,53 @@ new Ext.Panel({
      */
     rendered : false,
 
+    /**
+     * @cfg {String} contentEl
+     * <p>Optional. Specify an existing HTML element, or the <code>id</code> of an existing HTML element to use as the content
+     * for this component.</p>
+     * <ul>
+     * <li><b>Description</b> :
+     * <div class="sub-desc">This config option is used to take an existing HTML element and place it in the layout element
+     * of a new component (it simply moves the specified DOM element <i>after the Component is rendered</i> to use as the content.</div></li>
+     * <li><b>Notes</b> :
+     * <div class="sub-desc">The specified HTML element is appended to the layout element of the component <i>after any configured
+     * {@link #html HTML} has been inserted</i>, and so the document will not contain this element at the time the {@link #render} event is fired.</div>
+     * <div class="sub-desc">The specified HTML element used will not participate in any <code><b>{@link Ext.Container#layout layout}</b></code>
+     * scheme that the Component may use. It is just HTML. Layouts operate on child <code><b>{@link Ext.Container#items items}</b></code>.</div>
+     * <div class="sub-desc">Add either the <code>x-hidden</code> or the <code>x-hide-display</code> CSS class to
+     * prevent a brief flicker of the content before it is rendered to the panel.</div></li>
+     * </ul>
+     */
+    /**
+     * @cfg {String/Object} html
+     * An HTML fragment, or a {@link Ext.DomHelper DomHelper} specification to use as the layout element
+     * content (defaults to ''). The HTML content is added after the component is rendered,
+     * so the document will not contain this HTML at the time the {@link #render} event is fired.
+     * This content is inserted into the body <i>before</i> any configured {@link #contentEl} is appended.
+     */
+
+    /**
+     * @cfg {Mixed} tpl
+     * An <bold>{@link Ext.Template}</bold>, <bold>{@link Ext.XTemplate}</bold>
+     * or an array of strings to form an Ext.XTemplate.
+     * Used in conjunction with the <code>{@link #data}</code> and
+     * <code>{@link #tplWriteMode}</code> configurations.
+     */
+
+    /**
+     * @cfg {String} tplWriteMode The Ext.(X)Template method to use when
+     * updating the content area of the Component. Defaults to <tt>'overwrite'</tt>
+     * (see <code>{@link Ext.XTemplate#overwrite}</code>).
+     */
+    tplWriteMode : 'overwrite',
+
+    /**
+     * @cfg {Mixed} data
+     * The initial set of data to apply to the <code>{@link #tpl}</code> to
+     * update the content area of the Component.
+     */
+
+
     // private
     ctype : 'Ext.Component',
 
@@ -14825,7 +15394,32 @@ Ext.Foo = Ext.extend(Ext.Bar, {
                 this.el.addClassOnOver(this.overCls);
             }
             this.fireEvent('render', this);
+
+
+            // Populate content of the component with html, contentEl or
+            // a tpl.
+            var contentTarget = this.getContentTarget();
+            if (this.html){
+                contentTarget.update(Ext.DomHelper.markup(this.html));
+                delete this.html;
+            }
+            if (this.contentEl){
+                var ce = Ext.getDom(this.contentEl);
+                Ext.fly(ce).removeClass(['x-hidden', 'x-hide-display']);
+                contentTarget.appendChild(ce);
+            }
+            if (this.tpl) {
+                if (!this.tpl.compile) {
+                    this.tpl = new Ext.XTemplate(this.tpl);
+                }
+                if (this.data) {
+                    this.tpl[this.tplWriteMode](contentTarget, this.data);
+                    delete this.data;
+                }
+            }
             this.afterRender(this.container);
+
+
             if(this.hidden){
                 // call this so we don't fire initial hide events.
                 this.doHide();
@@ -14838,17 +15432,70 @@ Ext.Foo = Ext.extend(Ext.Bar, {
             if(this.stateful !== false){
                 this.initStateEvents();
             }
-            this.initRef();
             this.fireEvent('afterrender', this);
         }
         return this;
     },
 
-    initRef : function(){
+
+    /**
+     * Update the content area of a component.
+     * @param {Mixed} htmlOrData
+     * If this component has been configured with a template via the tpl config
+     * then it will use this argument as data to populate the template.
+     * If this component was not configured with a template, the components
+     * content area will be updated via Ext.Element update
+     * @param {Boolean} loadScripts
+     * (optional) Only legitimate when using the html configuration. Defaults to false
+     * @param {Function} callback
+     * (optional) Only legitimate when using the html configuration. Callback to execute when scripts have finished loading
+     */
+    update: function(htmlOrData, loadScripts, cb) {
+        var contentTarget = this.getContentTarget();
+        if (this.tpl && typeof htmlOrData !== "string") {
+            this.tpl[this.tplWriteMode](contentTarget, htmlOrData || {});
+        } else {
+            var html = Ext.isObject(htmlOrData) ? Ext.DomHelper.markup(htmlOrData) : htmlOrData;
+            contentTarget.update(html, loadScripts, cb);
+        }
+    },
+
+
+    /**
+     * @private
+     * Method to manage awareness of when components are added to their
+     * respective Container, firing an added event.
+     * References are established at add time rather than at render time.
+     * @param {Ext.Container} container Container which holds the component
+     * @param {number} pos Position at which the component was added
+     */
+    onAdded : function(container, pos) {
+        this.ownerCt = container;
+        this.initRef();
+        this.fireEvent('added', this, container, pos);
+    },
+
+    /**
+     * @private
+     * Method to manage awareness of when components are removed from their
+     * respective Container, firing an removed event. References are properly
+     * cleaned up after removing a component from its owning container.
+     */
+    onRemoved : function() {
+        this.removeRef();
+        this.fireEvent('removed', this, this.ownerCt);
+        delete this.ownerCt;
+    },
+
+    /**
+     * @private
+     * Method to establish a reference to a component.
+     */
+    initRef : function() {
         /**
          * @cfg {String} ref
-         * <p>A path specification, relative to the Component's {@link #ownerCt} specifying into which
-         * ancestor Container to place a named reference to this Component.</p>
+         * <p>A path specification, relative to the Component's <code>{@link #ownerCt}</code>
+         * specifying into which ancestor Container to place a named reference to this Component.</p>
          * <p>The ancestor axis can be traversed by using '/' characters in the path.
          * For example, to put a reference to a Toolbar Button into <i>the Panel which owns the Toolbar</i>:</p><pre><code>
 var myGrid = new Ext.grid.EditorGridPanel({
@@ -14869,33 +15516,50 @@ var myGrid = new Ext.grid.EditorGridPanel({
     }
 });
 </code></pre>
-         * <p>In the code above, if the ref had been <code>'saveButton'</code> the reference would
-         * have been placed into the Toolbar. Each '/' in the ref moves up one level from the
-         * Component's {@link #ownerCt}.</p>
+         * <p>In the code above, if the <code>ref</code> had been <code>'saveButton'</code>
+         * the reference would have been placed into the Toolbar. Each '/' in the <code>ref</code>
+         * moves up one level from the Component's <code>{@link #ownerCt}</code>.</p>
+         * <p>Also see the <code>{@link #added}</code> and <code>{@link #removed}</code> events.</p>
          */
-        if(this.ref){
-            var levels = this.ref.split('/');
-            var last = levels.length, i = 0;
-            var t = this;
-            while(i < last){
-                if(t.ownerCt){
-                    t = t.ownerCt;
-                }
-                i++;
+        if(this.ref && !this.refOwner){
+            var levels = this.ref.split('/'),
+                last = levels.length,
+                i = 0,
+                t = this;
+
+            while(t && i < last){
+                t = t.ownerCt;
+                ++i;
+            }
+            if(t){
+                t[this.refName = levels[--i]] = this;
+                /**
+                 * @type Ext.Container
+                 * @property refOwner
+                 * The ancestor Container into which the {@link #ref} reference was inserted if this Component
+                 * is a child of a Container, and has been configured with a <code>ref</code>.
+                 */
+                this.refOwner = t;
             }
-            t[levels[--i]] = this;
+        }
+    },
+
+    removeRef : function() {
+        if (this.refOwner && this.refName) {
+            delete this.refOwner[this.refName];
+            delete this.refOwner;
         }
     },
 
     // private
-    initState : function(config){
+    initState : function(){
         if(Ext.state.Manager){
             var id = this.getStateId();
             if(id){
                 var state = Ext.state.Manager.get(id);
                 if(state){
                     if(this.fireEvent('beforestaterestore', this, state) !== false){
-                        this.applyState(state);
+                        this.applyState(Ext.apply({}, state));
                         this.fireEvent('staterestore', this, state);
                     }
                 }
@@ -14905,7 +15569,7 @@ var myGrid = new Ext.grid.EditorGridPanel({
 
     // private
     getStateId : function(){
-        return this.stateId || ((this.id.indexOf('ext-comp-') == 0 || this.id.indexOf('ext-gen') == 0) ? null : this.id);
+        return this.stateId || ((/^(ext-comp-|ext-gen)/).test(String(this.id)) ? null : this.id);
     },
 
     // private
@@ -15000,6 +15664,10 @@ var myGrid = new Ext.grid.EditorGridPanel({
             this.el = Ext.get(this.el);
             if(this.allowDomMove !== false){
                 ct.dom.insertBefore(this.el.dom, position);
+                if (div) {
+                    Ext.removeNode(div);
+                    div = null;
+                }
             }
         }
     },
@@ -15027,9 +15695,12 @@ var myGrid = new Ext.grid.EditorGridPanel({
     destroy : function(){
         if(!this.isDestroyed){
             if(this.fireEvent('beforedestroy', this) !== false){
+                this.destroying = true;
                 this.beforeDestroy();
+                if(this.ownerCt && this.ownerCt.remove){
+                    this.ownerCt.remove(this, false);
+                }
                 if(this.rendered){
-                    this.el.removeAllListeners();
                     this.el.remove();
                     if(this.actionMode == 'container' || this.removeMode == 'container'){
                         this.container.remove();
@@ -15039,11 +15710,19 @@ var myGrid = new Ext.grid.EditorGridPanel({
                 Ext.ComponentMgr.unregister(this);
                 this.fireEvent('destroy', this);
                 this.purgeListeners();
+                this.destroying = false;
                 this.isDestroyed = true;
             }
         }
     },
 
+    deleteMembers : function(){
+        var args = arguments;
+        for(var i = 0, len = args.length; i < len; ++i){
+            delete this[args[i]];
+        }
+    },
+
     // private
     beforeDestroy : Ext.emptyFn,
 
@@ -15075,6 +15754,11 @@ new Ext.Panel({
         return this.el;
     },
 
+    // private
+    getContentTarget : function(){
+        return this.el;
+    },
+
     /**
      * Returns the <code>id</code> of this component or automatically generates and
      * returns an <code>id</code> if an <code>id</code> is not defined yet:<pre><code>
@@ -15356,8 +16040,9 @@ alert(t.getXTypes());  // alerts 'component/box/field/textfield'
             });
     },
 
-    getDomPositionEl : function(){
-        return this.getPositionEl ? this.getPositionEl() : this.getEl();
+    // protected
+    getPositionEl : function(){
+        return this.positionEl || this.el;
     },
 
     // private
@@ -15375,7 +16060,7 @@ alert(t.getXTypes());  // alerts 'component/box/field/textfield'
         }, this);
         this.mons = [];
     },
-    
+
     // private
     createMons: function(){
         if(!this.mons){
@@ -15384,7 +16069,26 @@ alert(t.getXTypes());  // alerts 'component/box/field/textfield'
         }
     },
 
-    // internal function for auto removal of assigned event handlers on destruction
+    /**
+     * <p>Adds listeners to any Observable object (or Elements) which are automatically removed when this Component
+     * is destroyed. Usage:</p><code><pre>
+myGridPanel.mon(myGridPanel.getSelectionModel(), 'selectionchange', handleSelectionChange, null, {buffer: 50});
+</pre></code>
+     * <p>or:</p><code><pre>
+myGridPanel.mon(myGridPanel.getSelectionModel(), {
+    selectionchange: handleSelectionChange,
+    buffer: 50
+});
+</pre></code>
+     * @param {Observable|Element} item The item to which to add a listener/listeners.
+     * @param {Object|String} ename The event name, or an object containing event name properties.
+     * @param {Function} fn Optional. If the <code>ename</code> parameter was an event name, this
+     * is the handler function.
+     * @param {Object} scope Optional. If the <code>ename</code> parameter was an event name, this
+     * is the scope (<code>this</code> reference) in which the handler function is executed.
+     * @param {Object} opt Optional. If the <code>ename</code> parameter was an event name, this
+     * is the {@link Ext.util.Observable#addListener addListener} options.
+     */
     mon : function(item, ename, fn, scope, opt){
         this.createMons();
         if(Ext.isObject(ename)){
@@ -15418,7 +16122,15 @@ alert(t.getXTypes());  // alerts 'component/box/field/textfield'
         item.on(ename, fn, scope, opt);
     },
 
-    // protected, opposite of mon
+    /**
+     * Removes listeners that were added by the {@link #mon} method.
+     * @param {Observable|Element} item The item from which to remove a listener/listeners.
+     * @param {Object|String} ename The event name, or an object containing event name properties.
+     * @param {Function} fn Optional. If the <code>ename</code> parameter was an event name, this
+     * is the handler function.
+     * @param {Object} scope Optional. If the <code>ename</code> parameter was an event name, this
+     * is the scope (<code>this</code> reference) in which the handler function is executed.
+     */
     mun : function(item, ename, fn, scope){
         var found, mon;
         this.createMons();
@@ -15471,8 +16183,7 @@ alert(t.getXTypes());  // alerts 'component/box/field/textfield'
     }
 });
 
-Ext.reg('component', Ext.Component);
-/**\r
+Ext.reg('component', Ext.Component);/**\r
  * @class Ext.Action\r
  * <p>An Action is a piece of reusable functionality that can be abstracted out of any particular component so that it\r
  * can be usefully shared among multiple components.  Actions let you share handlers, configuration options and UI\r
@@ -15525,13 +16236,7 @@ aRef.setText('New text');
  * @constructor\r
  * @param {Object} config The configuration options\r
  */\r
-Ext.Action = function(config){\r
-    this.initialConfig = config;\r
-    this.itemId = config.itemId = (config.itemId || config.id || Ext.id());\r
-    this.items = [];\r
-}\r
-\r
-Ext.Action.prototype = {\r
+Ext.Action = Ext.extend(Object, {\r
     /**\r
      * @cfg {String} text The text to set for all components using this action (defaults to '').\r
      */\r
@@ -15564,9 +16269,16 @@ Ext.Action.prototype = {
      * See {@link Ext.Component}.{@link Ext.Component#itemId itemId}.\r
      */\r
     /**\r
-     * @cfg {Object} scope The scope in which the {@link #handler} function will execute.\r
+     * @cfg {Object} scope The scope (<tt><b>this</b></tt> reference) in which the\r
+     * <code>{@link #handler}</code> is executed. Defaults to this Button.\r
      */\r
 \r
+    constructor : function(config){\r
+        this.initialConfig = config;\r
+        this.itemId = config.itemId = (config.itemId || config.id || Ext.id());\r
+        this.items = [];\r
+    },\r
+    \r
     // private\r
     isAction : true,\r
 \r
@@ -15666,10 +16378,10 @@ Ext.Action.prototype = {
     },\r
 \r
     /**\r
-     * Sets the function that will be called by each component using this action when its primary event is triggered.\r
+     * Sets the function that will be called by each Component using this action when its primary event is triggered.\r
      * @param {Function} fn The function that will be invoked by the action's components.  The function\r
      * will be called with no arguments.\r
-     * @param {Object} scope The scope in which the function will execute\r
+     * @param {Object} scope The scope (<code>this</code> reference) in which the function is executed. Defaults to the Component firing the event.\r
      */\r
     setHandler : function(fn, scope){\r
         this.initialConfig.handler = fn;\r
@@ -15678,10 +16390,10 @@ Ext.Action.prototype = {
     },\r
 \r
     /**\r
-     * Executes the specified function once for each component currently tied to this action.  The function passed\r
+     * Executes the specified function once for each Component currently tied to this action.  The function passed\r
      * in should accept a single argument that will be an object that supports the basic Action config/method interface.\r
      * @param {Function} fn The function to execute for each component\r
-     * @param {Object} scope The scope in which the function will execute\r
+     * @param {Object} scope The scope (<code>this</code> reference) in which the function is executed.  Defaults to the Component.\r
      */\r
     each : function(fn, scope){\r
         Ext.each(this.items, fn, scope);\r
@@ -15717,7 +16429,7 @@ Ext.Action.prototype = {
     execute : function(){\r
         this.initialConfig.handler.apply(this.initialConfig.scope || window, arguments);\r
     }\r
-};
+});\r
 /**
  * @class Ext.Layer
  * @extends Ext.Element
@@ -15888,7 +16600,7 @@ Ext.extend(Ext.Layer, Ext.Element, {
         }
         this.removeAllListeners();
         Ext.removeNode(this.dom);
-        Ext.Element.uncache(this.id);
+        delete this.dom;
     },
 
     remove : function(){
@@ -16177,7 +16889,8 @@ Ext.extend(Ext.Layer, Ext.Element, {
         return this;
     }
 });
-})();/**
+})();
+/**
  * @class Ext.Shadow
  * Simple class that can provide a shadow effect for any element.  Note that the element MUST be absolutely positioned,
  * and the shadow does not provide any shimming.  This should be used only in simple cases -- for more advanced
@@ -16392,6 +17105,26 @@ var myImage = new Ext.BoxComponent({
  */
 Ext.BoxComponent = Ext.extend(Ext.Component, {
 
+    // Configs below are used for all Components when rendered by BoxLayout.
+    /**
+     * @cfg {Number} flex
+     * <p><b>Note</b>: this config is only used when this Component is rendered
+     * by a Container which has been configured to use a <b>{@link Ext.layout.BoxLayout BoxLayout}.</b>
+     * Each child Component with a <code>flex</code> property will be flexed either vertically (by a VBoxLayout)
+     * or horizontally (by an HBoxLayout) according to the item's <b>relative</b> <code>flex</code> value
+     * compared to the sum of all Components with <code>flex</flex> value specified. Any child items that have
+     * either a <code>flex = 0</code> or <code>flex = undefined</code> will not be 'flexed' (the initial size will not be changed).
+     */
+    // Configs below are used for all Components when rendered by AnchorLayout.
+    /**
+     * @cfg {String} anchor <p><b>Note</b>: this config is only used when this Component is rendered
+     * by a Container which has been configured to use an <b>{@link Ext.layout.AnchorLayout AnchorLayout} (or subclass thereof).</b>
+     * based layout manager, for example:<div class="mdetail-params"><ul>
+     * <li>{@link Ext.form.FormPanel}</li>
+     * <li>specifying <code>layout: 'anchor' // or 'form', or 'absolute'</code></li>
+     * </ul></div></p>
+     * <p>See {@link Ext.layout.AnchorLayout}.{@link Ext.layout.AnchorLayout#anchor anchor} also.</p>
+     */
     // tabTip config is used when a BoxComponent is a child of a TabPanel
     /**
      * @cfg {String} tabTip
@@ -16460,6 +17193,26 @@ Ext.BoxComponent = Ext.extend(Ext.Component, {
      * The width of this component in pixels (defaults to auto).
      * <b>Note</b> to express this dimension as a percentage or offset see {@link Ext.Component#anchor}.
      */
+    /**
+     * @cfg {Number} boxMinHeight
+     * <p>The minimum value in pixels which this BoxComponent will set its height to.</p>
+     * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
+     */
+    /**
+     * @cfg {Number} boxMinWidth
+     * <p>The minimum value in pixels which this BoxComponent will set its width to.</p>
+     * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
+     */
+    /**
+     * @cfg {Number} boxMaxHeight
+     * <p>The maximum value in pixels which this BoxComponent will set its height to.</p>
+     * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
+     */
+    /**
+     * @cfg {Number} boxMaxWidth
+     * <p>The maximum value in pixels which this BoxComponent will set its width to.</p>
+     * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
+     */
     /**
      * @cfg {Boolean} autoHeight
      * <p>True to use height:'auto', false to use fixed height (or allow it to be managed by its parent
@@ -16534,6 +17287,11 @@ var myPanel = new Ext.Panel({
 });
 </code></pre>
      */
+    /**
+     * @cfg {Boolean} autoScroll
+     * <code>true</code> to use overflow:'auto' on the components layout element and show scroll bars automatically when
+     * necessary, <code>false</code> to clip any overflowing content (defaults to <code>false</code>).
+     */
 
     /* // private internal config
      * {Boolean} deferHeight
@@ -16589,15 +17347,26 @@ var myPanel = new Ext.Panel({
      * @return {Ext.BoxComponent} this
      */
     setSize : function(w, h){
+
         // support for standard size objects
         if(typeof w == 'object'){
-            h = w.height;
-            w = w.width;
+            h = w.height, w = w.width;
+        }
+        if (Ext.isDefined(w) && Ext.isDefined(this.boxMinWidth) && (w < this.boxMinWidth)) {
+            w = this.boxMinWidth;
+        }
+        if (Ext.isDefined(h) && Ext.isDefined(this.boxMinHeight) && (h < this.boxMinHeight)) {
+            h = this.boxMinHeight;
+        }
+        if (Ext.isDefined(w) && Ext.isDefined(this.boxMaxWidth) && (w > this.boxMaxWidth)) {
+            w = this.boxMaxWidth;
+        }
+        if (Ext.isDefined(h) && Ext.isDefined(this.boxMaxHeight) && (h > this.boxMaxHeight)) {
+            h = this.boxMaxHeight;
         }
         // not rendered
         if(!this.boxReady){
-            this.width = w;
-            this.height = h;
+            this.width = w, this.height = h;
             return this;
         }
 
@@ -16606,10 +17375,12 @@ var myPanel = new Ext.Panel({
             return this;
         }
         this.lastSize = {width: w, height: h};
-        var adj = this.adjustSize(w, h);
-        var aw = adj.width, ah = adj.height;
+        var adj = this.adjustSize(w, h),
+            aw = adj.width,
+            ah = adj.height,
+            rz;
         if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters
-            var rz = this.getResizeEl();
+            rz = this.getResizeEl();
             if(!this.deferHeight && aw !== undefined && ah !== undefined){
                 rz.setSize(aw, ah);
             }else if(!this.deferHeight && ah !== undefined){
@@ -16728,14 +17499,23 @@ var myPanel = new Ext.Panel({
      * contains both the <code>&lt;input></code> Element (which is what would be returned
      * by its <code>{@link #getEl}</code> method, <i>and</i> the trigger button Element.
      * This Element is returned as the <code>resizeEl</code>.
+     * @return {Ext.Element} The Element which is to be resized by size managing layouts.
      */
     getResizeEl : function(){
         return this.resizeEl || this.el;
     },
 
-    // protected
-    getPositionEl : function(){
-        return this.positionEl || this.el;
+    /**
+     * Sets the overflow on the content element of the component.
+     * @param {Boolean} scroll True to allow the Component to auto scroll.
+     * @return {Ext.BoxComponent} this
+     */
+    setAutoScroll : function(scroll){
+        if(this.rendered){
+            this.getContentTarget().setOverflow(scroll ? 'auto' : '');
+        }
+        this.autoScroll = scroll;
+        return this;
     },
 
     /**
@@ -16808,6 +17588,7 @@ var myPanel = new Ext.Panel({
             this.positionEl = Ext.get(this.positionEl);
         }
         this.boxReady = true;
+        Ext.isDefined(this.autoScroll) && this.setAutoScroll(this.autoScroll);
         this.setSize(this.width, this.height);
         if(this.x || this.y){
             this.setPosition(this.x, this.y);
@@ -16835,7 +17616,6 @@ var myPanel = new Ext.Panel({
      * @param {Number} rawHeight The height that was originally specified
      */
     onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
-
     },
 
     /* // protected
@@ -16897,12 +17677,12 @@ split.on('moved', splitterMoved);
  * @param {Mixed} dragElement The element to be dragged and act as the SplitBar.\r
  * @param {Mixed} resizingElement The element to be resized based on where the SplitBar element is dragged\r
  * @param {Number} orientation (optional) Either Ext.SplitBar.HORIZONTAL or Ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)\r
- * @param {Number} placement (optional) Either Ext.SplitBar.LEFT or Ext.SplitBar.RIGHT for horizontal or  \r
+ * @param {Number} placement (optional) Either Ext.SplitBar.LEFT or Ext.SplitBar.RIGHT for horizontal or\r
                         Ext.SplitBar.TOP or Ext.SplitBar.BOTTOM for vertical. (By default, this is determined automatically by the initial\r
                         position of the SplitBar).\r
  */\r
 Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){\r
-    \r
+\r
     /** @private */\r
     this.el = Ext.get(dragElement, true);\r
     this.el.dom.unselectable = "on";\r
@@ -16916,7 +17696,7 @@ Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, ex
      * @type Number\r
      */\r
     this.orientation = orientation || Ext.SplitBar.HORIZONTAL;\r
-    \r
+\r
     /**\r
      * The increment, in pixels by which to move this SplitBar. When <i>undefined</i>, the SplitBar moves smoothly.\r
      * @type Number\r
@@ -16927,28 +17707,28 @@ Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, ex
      * @type Number\r
      */\r
     this.minSize = 0;\r
-    \r
+\r
     /**\r
      * The maximum size of the resizing element. (Defaults to 2000)\r
      * @type Number\r
      */\r
     this.maxSize = 2000;\r
-    \r
+\r
     /**\r
      * Whether to animate the transition to the new size\r
      * @type Boolean\r
      */\r
     this.animate = false;\r
-    \r
+\r
     /**\r
      * Whether to create a transparent shim that overlays the page when dragging, enables dragging across iframes.\r
      * @type Boolean\r
      */\r
     this.useShim = false;\r
-    \r
+\r
     /** @private */\r
     this.shim = null;\r
-    \r
+\r
     if(!existingProxy){\r
         /** @private */\r
         this.proxy = Ext.SplitBar.createProxy(this.orientation);\r
@@ -16957,22 +17737,22 @@ Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, ex
     }\r
     /** @private */\r
     this.dd = new Ext.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});\r
-    \r
+\r
     /** @private */\r
     this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);\r
-    \r
+\r
     /** @private */\r
     this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);\r
-    \r
+\r
     /** @private */\r
     this.dragSpecs = {};\r
-    \r
+\r
     /**\r
      * @private The adapter to use to positon and resize elements\r
      */\r
     this.adapter = new Ext.SplitBar.BasicLayoutAdapter();\r
     this.adapter.init(this);\r
-    \r
+\r
     if(this.orientation == Ext.SplitBar.HORIZONTAL){\r
         /** @private */\r
         this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Ext.SplitBar.LEFT : Ext.SplitBar.RIGHT);\r
@@ -16982,7 +17762,7 @@ Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, ex
         this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Ext.SplitBar.TOP : Ext.SplitBar.BOTTOM);\r
         this.el.addClass("x-splitbar-v");\r
     }\r
-    \r
+\r
     this.addEvents(\r
         /**\r
          * @event resize\r
@@ -17027,7 +17807,7 @@ Ext.extend(Ext.SplitBar, Ext.util.Observable, {
         if(this.orientation == Ext.SplitBar.HORIZONTAL){\r
             this.dd.resetConstraints();\r
             this.dd.setXConstraint(\r
-                this.placement == Ext.SplitBar.LEFT ? c1 : c2, \r
+                this.placement == Ext.SplitBar.LEFT ? c1 : c2,\r
                 this.placement == Ext.SplitBar.LEFT ? c2 : c1,\r
                 this.tickSize\r
             );\r
@@ -17036,7 +17816,7 @@ Ext.extend(Ext.SplitBar, Ext.util.Observable, {
             this.dd.resetConstraints();\r
             this.dd.setXConstraint(0, 0);\r
             this.dd.setYConstraint(\r
-                this.placement == Ext.SplitBar.TOP ? c1 : c2, \r
+                this.placement == Ext.SplitBar.TOP ? c1 : c2,\r
                 this.placement == Ext.SplitBar.TOP ? c2 : c1,\r
                 this.tickSize\r
             );\r
@@ -17045,8 +17825,8 @@ Ext.extend(Ext.SplitBar, Ext.util.Observable, {
         this.dragSpecs.startPoint = [x, y];\r
         Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);\r
     },\r
-    \r
-    /** \r
+\r
+    /**\r
      * @private Called after the drag operation by the DDProxy\r
      */\r
     onEndProxyDrag : function(e){\r
@@ -17058,13 +17838,13 @@ Ext.extend(Ext.SplitBar, Ext.util.Observable, {
         }\r
         var newSize;\r
         if(this.orientation == Ext.SplitBar.HORIZONTAL){\r
-            newSize = this.dragSpecs.startSize + \r
+            newSize = this.dragSpecs.startSize +\r
                 (this.placement == Ext.SplitBar.LEFT ?\r
                     endPoint[0] - this.dragSpecs.startPoint[0] :\r
                     this.dragSpecs.startPoint[0] - endPoint[0]\r
                 );\r
         }else{\r
-            newSize = this.dragSpecs.startSize + \r
+            newSize = this.dragSpecs.startSize +\r
                 (this.placement == Ext.SplitBar.TOP ?\r
                     endPoint[1] - this.dragSpecs.startPoint[1] :\r
                     this.dragSpecs.startPoint[1] - endPoint[1]\r
@@ -17079,7 +17859,7 @@ Ext.extend(Ext.SplitBar, Ext.util.Observable, {
             }\r
         }\r
     },\r
-    \r
+\r
     /**\r
      * Get the adapter this SplitBar uses\r
      * @return The adapter object\r
@@ -17087,7 +17867,7 @@ Ext.extend(Ext.SplitBar, Ext.util.Observable, {
     getAdapter : function(){\r
         return this.adapter;\r
     },\r
-    \r
+\r
     /**\r
      * Set the adapter this SplitBar uses\r
      * @param {Object} adapter A SplitBar adapter object\r
@@ -17096,7 +17876,7 @@ Ext.extend(Ext.SplitBar, Ext.util.Observable, {
         this.adapter = adapter;\r
         this.adapter.init(this);\r
     },\r
-    \r
+\r
     /**\r
      * Gets the minimum size for the resizing element\r
      * @return {Number} The minimum size\r
@@ -17104,7 +17884,7 @@ Ext.extend(Ext.SplitBar, Ext.util.Observable, {
     getMinimumSize : function(){\r
         return this.minSize;\r
     },\r
-    \r
+\r
     /**\r
      * Sets the minimum size for the resizing element\r
      * @param {Number} minSize The minimum size\r
@@ -17112,7 +17892,7 @@ Ext.extend(Ext.SplitBar, Ext.util.Observable, {
     setMinimumSize : function(minSize){\r
         this.minSize = minSize;\r
     },\r
-    \r
+\r
     /**\r
      * Gets the maximum size for the resizing element\r
      * @return {Number} The maximum size\r
@@ -17120,7 +17900,7 @@ Ext.extend(Ext.SplitBar, Ext.util.Observable, {
     getMaximumSize : function(){\r
         return this.maxSize;\r
     },\r
-    \r
+\r
     /**\r
      * Sets the maximum size for the resizing element\r
      * @param {Number} maxSize The maximum size\r
@@ -17128,7 +17908,7 @@ Ext.extend(Ext.SplitBar, Ext.util.Observable, {
     setMaximumSize : function(maxSize){\r
         this.maxSize = maxSize;\r
     },\r
-    \r
+\r
     /**\r
      * Sets the initialize size for the resizing element\r
      * @param {Number} size The initial size\r
@@ -17139,18 +17919,18 @@ Ext.extend(Ext.SplitBar, Ext.util.Observable, {
         this.adapter.setElementSize(this, size);\r
         this.animate = oldAnimate;\r
     },\r
-    \r
+\r
     /**\r
-     * Destroy this splitbar. \r
+     * Destroy this splitbar.\r
      * @param {Boolean} removeEl True to remove the element\r
      */\r
     destroy : function(removeEl){\r
-               Ext.destroy(this.shim, Ext.get(this.proxy));\r
+        Ext.destroy(this.shim, Ext.get(this.proxy));\r
         this.dd.unreg();\r
         if(removeEl){\r
             this.el.remove();\r
         }\r
-               this.purgeListeners();\r
+        this.purgeListeners();\r
     }\r
 });\r
 \r
@@ -17159,14 +17939,14 @@ Ext.extend(Ext.SplitBar, Ext.util.Observable, {
  */\r
 Ext.SplitBar.createProxy = function(dir){\r
     var proxy = new Ext.Element(document.createElement("div"));\r
+    document.body.appendChild(proxy.dom);\r
     proxy.unselectable();\r
     var cls = 'x-splitbar-proxy';\r
     proxy.addClass(cls + ' ' + (dir == Ext.SplitBar.HORIZONTAL ? cls +'-h' : cls + '-v'));\r
-    document.body.appendChild(proxy.dom);\r
     return proxy.dom;\r
 };\r
 \r
-/** \r
+/**\r
  * @class Ext.SplitBar.BasicLayoutAdapter\r
  * Default Adapter. It assumes the splitter and resizing element are not positioned\r
  * elements and only gets/sets the width of the element. Generally used for table based layouts.\r
@@ -17177,10 +17957,10 @@ Ext.SplitBar.BasicLayoutAdapter = function(){
 Ext.SplitBar.BasicLayoutAdapter.prototype = {\r
     // do nothing for now\r
     init : function(s){\r
-    \r
+\r
     },\r
     /**\r
-     * Called before drag operations to get the current size of the resizing element. \r
+     * Called before drag operations to get the current size of the resizing element.\r
      * @param {Ext.SplitBar} s The SplitBar using this adapter\r
      */\r
      getElementSize : function(s){\r
@@ -17190,7 +17970,7 @@ Ext.SplitBar.BasicLayoutAdapter.prototype = {
             return s.resizingEl.getHeight();\r
         }\r
     },\r
-    \r
+\r
     /**\r
      * Called after drag operations to set the size of the resizing element.\r
      * @param {Ext.SplitBar} s The SplitBar using this adapter\r
@@ -17208,7 +17988,7 @@ Ext.SplitBar.BasicLayoutAdapter.prototype = {
                 s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');\r
             }\r
         }else{\r
-            \r
+\r
             if(!s.animate){\r
                 s.resizingEl.setHeight(newSize);\r
                 if(onComplete){\r
@@ -17221,10 +18001,10 @@ Ext.SplitBar.BasicLayoutAdapter.prototype = {
     }\r
 };\r
 \r
-/** \r
+/**\r
  *@class Ext.SplitBar.AbsoluteLayoutAdapter\r
  * @extends Ext.SplitBar.BasicLayoutAdapter\r
- * Adapter that  moves the splitter element to align with the resized sizing element. \r
+ * Adapter that  moves the splitter element to align with the resized sizing element.\r
  * Used with an absolute positioned SplitBar.\r
  * @param {Mixed} container The container that wraps around the absolute positioned content. If it's\r
  * document.body, make sure you assign an id to the body element.\r
@@ -17238,15 +18018,15 @@ Ext.SplitBar.AbsoluteLayoutAdapter.prototype = {
     init : function(s){\r
         this.basic.init(s);\r
     },\r
-    \r
+\r
     getElementSize : function(s){\r
         return this.basic.getElementSize(s);\r
     },\r
-    \r
+\r
     setElementSize : function(s, newSize, onComplete){\r
         this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));\r
     },\r
-    \r
+\r
     moveSplitter : function(s){\r
         var yes = Ext.SplitBar;\r
         switch(s.placement){\r
@@ -17307,969 +18087,1018 @@ Ext.SplitBar.TOP = 3;
  * @type Number\r
  */\r
 Ext.SplitBar.BOTTOM = 4;\r
-/**\r
- * @class Ext.Container\r
- * @extends Ext.BoxComponent\r
- * <p>Base class for any {@link Ext.BoxComponent} that may contain other Components. Containers handle the\r
- * basic behavior of containing items, namely adding, inserting and removing items.</p>\r
- *\r
- * <p>The most commonly used Container classes are {@link Ext.Panel}, {@link Ext.Window} and {@link Ext.TabPanel}.\r
- * If you do not need the capabilities offered by the aforementioned classes you can create a lightweight\r
- * Container to be encapsulated by an HTML element to your specifications by using the\r
- * <tt><b>{@link Ext.Component#autoEl autoEl}</b></tt> config option. This is a useful technique when creating\r
- * embedded {@link Ext.layout.ColumnLayout column} layouts inside {@link Ext.form.FormPanel FormPanels}\r
- * for example.</p>\r
- *\r
- * <p>The code below illustrates both how to explicitly create a Container, and how to implicitly\r
- * create one using the <b><tt>'container'</tt></b> xtype:<pre><code>\r
-// explicitly create a Container\r
-var embeddedColumns = new Ext.Container({\r
-    autoEl: 'div',  // This is the default\r
-    layout: 'column',\r
-    defaults: {\r
-        // implicitly create Container by specifying xtype\r
-        xtype: 'container',\r
-        autoEl: 'div', // This is the default.\r
-        layout: 'form',\r
-        columnWidth: 0.5,\r
-        style: {\r
-            padding: '10px'\r
-        }\r
-    },\r
-//  The two items below will be Ext.Containers, each encapsulated by a &lt;DIV> element.\r
-    items: [{\r
-        items: {\r
-            xtype: 'datefield',\r
-            name: 'startDate',\r
-            fieldLabel: 'Start date'\r
-        }\r
-    }, {\r
-        items: {\r
-            xtype: 'datefield',\r
-            name: 'endDate',\r
-            fieldLabel: 'End date'\r
-        }\r
-    }]\r
-});</code></pre></p>\r
- *\r
- * <p><u><b>Layout</b></u></p>\r
- * <p>Container classes delegate the rendering of child Components to a layout\r
- * manager class which must be configured into the Container using the\r
- * <code><b>{@link #layout}</b></code> configuration property.</p>\r
- * <p>When either specifying child <code>{@link #items}</code> of a Container,\r
- * or dynamically {@link #add adding} Components to a Container, remember to\r
- * consider how you wish the Container to arrange those child elements, and\r
- * whether those child elements need to be sized using one of Ext's built-in\r
- * <b><code>{@link #layout}</code></b> schemes. By default, Containers use the\r
- * {@link Ext.layout.ContainerLayout ContainerLayout} scheme which only\r
- * renders child components, appending them one after the other inside the\r
- * Container, and <b>does not apply any sizing</b> at all.</p>\r
- * <p>A common mistake is when a developer neglects to specify a\r
- * <b><code>{@link #layout}</code></b> (e.g. widgets like GridPanels or\r
- * TreePanels are added to Containers for which no <tt><b>{@link #layout}</b></tt>\r
- * has been specified). If a Container is left to use the default\r
- * {@link Ext.layout.ContainerLayout ContainerLayout} scheme, none of its\r
- * child components will be resized, or changed in any way when the Container\r
- * is resized.</p>\r
- * <p>Certain layout managers allow dynamic addition of child components.\r
- * Those that do include {@link Ext.layout.CardLayout},\r
- * {@link Ext.layout.AnchorLayout}, {@link Ext.layout.FormLayout}, and\r
- * {@link Ext.layout.TableLayout}. For example:<pre><code>\r
-//  Create the GridPanel.\r
-var myNewGrid = new Ext.grid.GridPanel({\r
-    store: myStore,\r
-    columns: myColumnModel,\r
-    title: 'Results', // the title becomes the title of the tab\r
-});\r
-\r
-myTabPanel.add(myNewGrid); // {@link Ext.TabPanel} implicitly uses {@link Ext.layout.CardLayout CardLayout}\r
-myTabPanel.{@link Ext.TabPanel#setActiveTab setActiveTab}(myNewGrid);\r
- * </code></pre></p>\r
- * <p>The example above adds a newly created GridPanel to a TabPanel. Note that\r
- * a TabPanel uses {@link Ext.layout.CardLayout} as its layout manager which\r
- * means all its child items are sized to {@link Ext.layout.FitLayout fit}\r
- * exactly into its client area.\r
- * <p><b><u>Overnesting is a common problem</u></b>.\r
- * An example of overnesting occurs when a GridPanel is added to a TabPanel\r
- * by wrapping the GridPanel <i>inside</i> a wrapping Panel (that has no\r
- * <tt><b>{@link #layout}</b></tt> specified) and then add that wrapping Panel\r
- * to the TabPanel. The point to realize is that a GridPanel <b>is</b> a\r
- * Component which can be added directly to a Container. If the wrapping Panel\r
- * has no <tt><b>{@link #layout}</b></tt> configuration, then the overnested\r
- * GridPanel will not be sized as expected.<p>\r
- *\r
- * <p><u><b>Adding via remote configuration</b></u></p>\r
- *\r
- * <p>A server side script can be used to add Components which are generated dynamically on the server.\r
- * An example of adding a GridPanel to a TabPanel where the GridPanel is generated by the server\r
- * based on certain parameters:\r
- * </p><pre><code>\r
-// execute an Ajax request to invoke server side script:\r
-Ext.Ajax.request({\r
-    url: 'gen-invoice-grid.php',\r
-    // send additional parameters to instruct server script\r
-    params: {\r
-        startDate: Ext.getCmp('start-date').getValue(),\r
-        endDate: Ext.getCmp('end-date').getValue()\r
-    },\r
-    // process the response object to add it to the TabPanel:\r
-    success: function(xhr) {\r
-        var newComponent = eval(xhr.responseText); // see discussion below\r
-        myTabPanel.add(newComponent); // add the component to the TabPanel\r
-        myTabPanel.setActiveTab(newComponent);\r
-    },\r
-    failure: function() {\r
-        Ext.Msg.alert("Grid create failed", "Server communication failure");\r
-    }\r
-});\r
-</code></pre>\r
- * <p>The server script needs to return an executable Javascript statement which, when processed\r
- * using <tt>eval()</tt>, will return either a config object with an {@link Ext.Component#xtype xtype},\r
- * or an instantiated Component. The server might return this for example:</p><pre><code>\r
-(function() {\r
-    function formatDate(value){\r
-        return value ? value.dateFormat('M d, Y') : '';\r
-    };\r
-\r
-    var store = new Ext.data.Store({\r
-        url: 'get-invoice-data.php',\r
-        baseParams: {\r
-            startDate: '01/01/2008',\r
-            endDate: '01/31/2008'\r
-        },\r
-        reader: new Ext.data.JsonReader({\r
-            record: 'transaction',\r
-            idProperty: 'id',\r
-            totalRecords: 'total'\r
-        }, [\r
-           'customer',\r
-           'invNo',\r
-           {name: 'date', type: 'date', dateFormat: 'm/d/Y'},\r
-           {name: 'value', type: 'float'}\r
-        ])\r
-    });\r
-\r
-    var grid = new Ext.grid.GridPanel({\r
-        title: 'Invoice Report',\r
-        bbar: new Ext.PagingToolbar(store),\r
-        store: store,\r
-        columns: [\r
-            {header: "Customer", width: 250, dataIndex: 'customer', sortable: true},\r
-            {header: "Invoice Number", width: 120, dataIndex: 'invNo', sortable: true},\r
-            {header: "Invoice Date", width: 100, dataIndex: 'date', renderer: formatDate, sortable: true},\r
-            {header: "Value", width: 120, dataIndex: 'value', renderer: 'usMoney', sortable: true}\r
-        ],\r
-    });\r
-    store.load();\r
-    return grid;  // return instantiated component\r
-})();\r
-</code></pre>\r
- * <p>When the above code fragment is passed through the <tt>eval</tt> function in the success handler\r
- * of the Ajax request, the code is executed by the Javascript processor, and the anonymous function\r
- * runs, and returns the instantiated grid component.</p>\r
- * <p>Note: since the code above is <i>generated</i> by a server script, the <tt>baseParams</tt> for\r
- * the Store, the metadata to allow generation of the Record layout, and the ColumnModel\r
- * can all be generated into the code since these are all known on the server.</p>\r
- *\r
- * @xtype container\r
- */\r
-Ext.Container = Ext.extend(Ext.BoxComponent, {\r
-    /**\r
-     * @cfg {Boolean} monitorResize\r
-     * True to automatically monitor window resize events to handle anything that is sensitive to the current size\r
-     * of the viewport.  This value is typically managed by the chosen <code>{@link #layout}</code> and should not need\r
-     * to be set manually.\r
-     */\r
-    /**\r
-     * @cfg {String/Object} layout\r
-     * <p><b>*Important</b>: In order for child items to be correctly sized and\r
-     * positioned, typically a layout manager <b>must</b> be specified through\r
-     * the <code>layout</code> configuration option.</p>\r
-     * <br><p>The sizing and positioning of child {@link items} is the responsibility of\r
-     * the Container's layout manager which creates and manages the type of layout\r
-     * you have in mind.  For example:</p><pre><code>\r
-new Ext.Window({\r
-    width:300, height: 300,\r
-    layout: 'fit', // explicitly set layout manager: override the default (layout:'auto')\r
-    items: [{\r
-        title: 'Panel inside a Window'\r
-    }]\r
-}).show();\r
-     * </code></pre>\r
-     * <p>If the {@link #layout} configuration is not explicitly specified for\r
-     * a general purpose container (e.g. Container or Panel) the\r
-     * {@link Ext.layout.ContainerLayout default layout manager} will be used\r
-     * which does nothing but render child components sequentially into the\r
-     * Container (no sizing or positioning will be performed in this situation).\r
-     * Some container classes implicitly specify a default layout\r
-     * (e.g. FormPanel specifies <code>layout:'form'</code>). Other specific\r
-     * purpose classes internally specify/manage their internal layout (e.g.\r
-     * GridPanel, TabPanel, TreePanel, Toolbar, Menu, etc.).</p>\r
-     * <br><p><b><code>layout</code></b> may be specified as either as an Object or\r
-     * as a String:</p><div><ul class="mdetail-params">\r
-     *\r
-     * <li><u>Specify as an Object</u></li>\r
-     * <div><ul class="mdetail-params">\r
-     * <li>Example usage:</li>\r
-<pre><code>\r
-layout: {\r
-    type: 'vbox',\r
-    padding: '5',\r
-    align: 'left'\r
-}\r
-</code></pre>\r
-     *\r
-     * <li><tt><b>type</b></tt></li>\r
-     * <br/><p>The layout type to be used for this container.  If not specified,\r
-     * a default {@link Ext.layout.ContainerLayout} will be created and used.</p>\r
-     * <br/><p>Valid layout <tt>type</tt> values are:</p>\r
-     * <div class="sub-desc"><ul class="mdetail-params">\r
-     * <li><tt><b>{@link Ext.layout.AbsoluteLayout absolute}</b></tt></li>\r
-     * <li><tt><b>{@link Ext.layout.AccordionLayout accordion}</b></tt></li>\r
-     * <li><tt><b>{@link Ext.layout.AnchorLayout anchor}</b></tt></li>\r
-     * <li><tt><b>{@link Ext.layout.ContainerLayout auto}</b></tt> &nbsp;&nbsp;&nbsp; <b>Default</b></li>\r
-     * <li><tt><b>{@link Ext.layout.BorderLayout border}</b></tt></li>\r
-     * <li><tt><b>{@link Ext.layout.CardLayout card}</b></tt></li>\r
-     * <li><tt><b>{@link Ext.layout.ColumnLayout column}</b></tt></li>\r
-     * <li><tt><b>{@link Ext.layout.FitLayout fit}</b></tt></li>\r
-     * <li><tt><b>{@link Ext.layout.FormLayout form}</b></tt></li>\r
-     * <li><tt><b>{@link Ext.layout.HBoxLayout hbox}</b></tt></li>\r
-     * <li><tt><b>{@link Ext.layout.MenuLayout menu}</b></tt></li>\r
-     * <li><tt><b>{@link Ext.layout.TableLayout table}</b></tt></li>\r
-     * <li><tt><b>{@link Ext.layout.ToolbarLayout toolbar}</b></tt></li>\r
-     * <li><tt><b>{@link Ext.layout.VBoxLayout vbox}</b></tt></li>\r
-     * </ul></div>\r
-     *\r
-     * <li>Layout specific configuration properties</li>\r
-     * <br/><p>Additional layout specific configuration properties may also be\r
-     * specified. For complete details regarding the valid config options for\r
-     * each layout type, see the layout class corresponding to the <tt>type</tt>\r
-     * specified.</p>\r
-     *\r
-     * </ul></div>\r
-     *\r
-     * <li><u>Specify as a String</u></li>\r
-     * <div><ul class="mdetail-params">\r
-     * <li>Example usage:</li>\r
-<pre><code>\r
-layout: 'vbox',\r
-layoutConfig: {\r
-    padding: '5',\r
-    align: 'left'\r
-}\r
-</code></pre>\r
-     * <li><tt><b>layout</b></tt></li>\r
-     * <br/><p>The layout <tt>type</tt> to be used for this container (see list\r
-     * of valid layout type values above).</p><br/>\r
-     * <li><tt><b>{@link #layoutConfig}</b></tt></li>\r
-     * <br/><p>Additional layout specific configuration properties. For complete\r
-     * details regarding the valid config options for each layout type, see the\r
-     * layout class corresponding to the <tt>layout</tt> specified.</p>\r
-     * </ul></div></ul></div>\r
-     */\r
-    /**\r
-     * @cfg {Object} layoutConfig\r
-     * This is a config object containing properties specific to the chosen\r
-     * <b><code>{@link #layout}</code></b> if <b><code>{@link #layout}</code></b>\r
-     * has been specified as a <i>string</i>.</p>\r
-     */\r
-    /**\r
-     * @cfg {Boolean/Number} bufferResize\r
-     * When set to true (50 milliseconds) or a number of milliseconds, the layout assigned for this container will buffer\r
-     * the frequency it calculates and does a re-layout of components. This is useful for heavy containers or containers\r
-     * with a large quantity of sub-components for which frequent layout calls would be expensive. Defaults to <tt>50</tt>.\r
-     */\r
-    bufferResize: 50,\r
-\r
-    /**\r
-     * @cfg {String/Number} activeItem\r
-     * A string component id or the numeric index of the component that should be initially activated within the\r
-     * container's layout on render.  For example, activeItem: 'item-1' or activeItem: 0 (index 0 = the first\r
-     * item in the container's collection).  activeItem only applies to layout styles that can display\r
-     * items one at a time (like {@link Ext.layout.AccordionLayout}, {@link Ext.layout.CardLayout} and\r
-     * {@link Ext.layout.FitLayout}).  Related to {@link Ext.layout.ContainerLayout#activeItem}.\r
-     */\r
-    /**\r
-     * @cfg {Object/Array} items\r
-     * <pre><b>** IMPORTANT</b>: be sure to <b>{@link #layout specify a <code>layout</code>} if needed ! **</b></pre>\r
-     * <p>A single item, or an array of child Components to be added to this container,\r
-     * for example:</p>\r
-     * <pre><code>\r
-// specifying a single item\r
-items: {...},\r
-layout: 'fit',    // specify a layout!\r
-\r
-// specifying multiple items\r
-items: [{...}, {...}],\r
-layout: 'anchor', // specify a layout!\r
-     * </code></pre>\r
-     * <p>Each item may be:</p>\r
-     * <div><ul class="mdetail-params">\r
-     * <li>any type of object based on {@link Ext.Component}</li>\r
-     * <li>a fully instanciated object or</li>\r
-     * <li>an object literal that:</li>\r
-     * <div><ul class="mdetail-params">\r
-     * <li>has a specified <code>{@link Ext.Component#xtype xtype}</code></li>\r
-     * <li>the {@link Ext.Component#xtype} specified is associated with the Component\r
-     * desired and should be chosen from one of the available xtypes as listed\r
-     * in {@link Ext.Component}.</li>\r
-     * <li>If an <code>{@link Ext.Component#xtype xtype}</code> is not explicitly\r
-     * specified, the {@link #defaultType} for that Container is used.</li>\r
-     * <li>will be "lazily instanciated", avoiding the overhead of constructing a fully\r
-     * instanciated Component object</li>\r
-     * </ul></div></ul></div>\r
-     * <p><b>Notes</b>:</p>\r
-     * <div><ul class="mdetail-params">\r
-     * <li>Ext uses lazy rendering. Child Components will only be rendered\r
-     * should it become necessary. Items are automatically laid out when they are first\r
-     * shown (no sizing is done while hidden), or in response to a {@link #doLayout} call.</li>\r
-     * <li>Do not specify <code>{@link Ext.Panel#contentEl contentEl}</code>/\r
-     * <code>{@link Ext.Panel#html html}</code> with <code>items</code>.</li>\r
-     * </ul></div>\r
-     */\r
-    /**\r
-     * @cfg {Object} defaults\r
-     * <p>A config object that will be applied to all components added to this container either via the {@link #items}\r
-     * config or via the {@link #add} or {@link #insert} methods.  The <tt>defaults</tt> config can contain any\r
-     * number of name/value property pairs to be added to each item, and should be valid for the types of items\r
-     * being added to the container.  For example, to automatically apply padding to the body of each of a set of\r
-     * contained {@link Ext.Panel} items, you could pass: <tt>defaults: {bodyStyle:'padding:15px'}</tt>.</p><br/>\r
-     * <p><b>Note</b>: <tt>defaults</tt> will not be applied to config objects if the option is already specified.\r
-     * For example:</p><pre><code>\r
-defaults: {               // defaults are applied to items, not the container\r
-    autoScroll:true\r
-},\r
-items: [\r
-    {\r
-        xtype: 'panel',   // defaults <b>do not</b> have precedence over\r
-        id: 'panel1',     // options in config objects, so the defaults\r
-        autoScroll: false // will not be applied here, panel1 will be autoScroll:false\r
-    },\r
-    new Ext.Panel({       // defaults <b>do</b> have precedence over options\r
-        id: 'panel2',     // options in components, so the defaults\r
-        autoScroll: false // will be applied here, panel2 will be autoScroll:true.\r
-    })\r
-]\r
-     * </code></pre>\r
-     */\r
-\r
-\r
-    /** @cfg {Boolean} autoDestroy\r
-     * If true the container will automatically destroy any contained component that is removed from it, else\r
-     * destruction must be handled manually (defaults to true).\r
-     */\r
-    autoDestroy : true,\r
-\r
-    /** @cfg {Boolean} forceLayout\r
-     * If true the container will force a layout initially even if hidden or collapsed. This option\r
-     * is useful for forcing forms to render in collapsed or hidden containers. (defaults to false).\r
-     */\r
-    forceLayout: false,\r
-\r
-    /** @cfg {Boolean} hideBorders\r
-     * True to hide the borders of each contained component, false to defer to the component's existing\r
-     * border settings (defaults to false).\r
-     */\r
-    /** @cfg {String} defaultType\r
-     * <p>The default {@link Ext.Component xtype} of child Components to create in this Container when\r
-     * a child item is specified as a raw configuration object, rather than as an instantiated Component.</p>\r
-     * <p>Defaults to <tt>'panel'</tt>, except {@link Ext.menu.Menu} which defaults to <tt>'menuitem'</tt>,\r
-     * and {@link Ext.Toolbar} and {@link Ext.ButtonGroup} which default to <tt>'button'</tt>.</p>\r
-     */\r
-    defaultType : 'panel',\r
-\r
-    /** @cfg {String} resizeEvent\r
-     * The event to listen to for resizing in layouts. Defaults to <tt>'resize'</tt>.\r
-     */\r
-    resizeEvent: 'resize',\r
-    \r
-    /**\r
-     * @cfg {Array} bubbleEvents\r
-     * <p>An array of events that, when fired, should be bubbled to any parent container.\r
-     * Defaults to <tt>['add', 'remove']</tt>.\r
-     */\r
-    bubbleEvents: ['add', 'remove'],\r
-\r
-    // private\r
-    initComponent : function(){\r
-        Ext.Container.superclass.initComponent.call(this);\r
-\r
-        this.addEvents(\r
-            /**\r
-             * @event afterlayout\r
-             * Fires when the components in this container are arranged by the associated layout manager.\r
-             * @param {Ext.Container} this\r
-             * @param {ContainerLayout} layout The ContainerLayout implementation for this container\r
-             */\r
-            'afterlayout',\r
-            /**\r
-             * @event beforeadd\r
-             * Fires before any {@link Ext.Component} is added or inserted into the container.\r
-             * A handler can return false to cancel the add.\r
-             * @param {Ext.Container} this\r
-             * @param {Ext.Component} component The component being added\r
-             * @param {Number} index The index at which the component will be added to the container's items collection\r
-             */\r
-            'beforeadd',\r
-            /**\r
-             * @event beforeremove\r
-             * Fires before any {@link Ext.Component} is removed from the container.  A handler can return\r
-             * false to cancel the remove.\r
-             * @param {Ext.Container} this\r
-             * @param {Ext.Component} component The component being removed\r
-             */\r
-            'beforeremove',\r
-            /**\r
-             * @event add\r
-             * @bubbles\r
-             * Fires after any {@link Ext.Component} is added or inserted into the container.\r
-             * @param {Ext.Container} this\r
-             * @param {Ext.Component} component The component that was added\r
-             * @param {Number} index The index at which the component was added to the container's items collection\r
-             */\r
-            'add',\r
-            /**\r
-             * @event remove\r
-             * @bubbles\r
-             * Fires after any {@link Ext.Component} is removed from the container.\r
-             * @param {Ext.Container} this\r
-             * @param {Ext.Component} component The component that was removed\r
-             */\r
-            'remove'\r
-        );\r
-\r
-        this.enableBubble(this.bubbleEvents);\r
-\r
-        /**\r
-         * The collection of components in this container as a {@link Ext.util.MixedCollection}\r
-         * @type MixedCollection\r
-         * @property items\r
-         */\r
-        var items = this.items;\r
-        if(items){\r
-            delete this.items;\r
-            this.add(items);\r
-        }\r
-    },\r
-\r
-    // private\r
-    initItems : function(){\r
-        if(!this.items){\r
-            this.items = new Ext.util.MixedCollection(false, this.getComponentId);\r
-            this.getLayout(); // initialize the layout\r
-        }\r
-    },\r
-\r
-    // private\r
-    setLayout : function(layout){\r
-        if(this.layout && this.layout != layout){\r
-            this.layout.setContainer(null);\r
-        }\r
-        this.initItems();\r
-        this.layout = layout;\r
-        layout.setContainer(this);\r
-    },\r
-\r
-    afterRender: function(){\r
-        Ext.Container.superclass.afterRender.call(this);\r
-        if(!this.layout){\r
-            this.layout = 'auto';\r
-        }\r
-        if(Ext.isObject(this.layout) && !this.layout.layout){\r
-            this.layoutConfig = this.layout;\r
-            this.layout = this.layoutConfig.type;\r
-        }\r
-        if(Ext.isString(this.layout)){\r
-            this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig);\r
-        }\r
-        this.setLayout(this.layout);\r
-\r
-        if(this.activeItem !== undefined){\r
-            var item = this.activeItem;\r
-            delete this.activeItem;\r
-            this.layout.setActiveItem(item);\r
-        }\r
-        if(!this.ownerCt){\r
-            // force a layout if no ownerCt is set\r
-            this.doLayout(false, true);\r
-        }\r
-        if(this.monitorResize === true){\r
-            Ext.EventManager.onWindowResize(this.doLayout, this, [false]);\r
-        }\r
-    },\r
-\r
-    /**\r
-     * <p>Returns the Element to be used to contain the child Components of this Container.</p>\r
-     * <p>An implementation is provided which returns the Container's {@link #getEl Element}, but\r
-     * if there is a more complex structure to a Container, this may be overridden to return\r
-     * the element into which the {@link #layout layout} renders child Components.</p>\r
-     * @return {Ext.Element} The Element to render child Components into.\r
-     */\r
-    getLayoutTarget : function(){\r
-        return this.el;\r
-    },\r
-\r
-    // private - used as the key lookup function for the items collection\r
-    getComponentId : function(comp){\r
-        return comp.getItemId();\r
-    },\r
-\r
-    /**\r
-     * <p>Adds {@link Ext.Component Component}(s) to this Container.</p>\r
-     * <br><p><b>Description</b></u> :\r
-     * <div><ul class="mdetail-params">\r
-     * <li>Fires the {@link #beforeadd} event before adding</li>\r
-     * <li>The Container's {@link #defaults default config values} will be applied\r
-     * accordingly (see <code>{@link #defaults}</code> for details).</li>\r
-     * <li>Fires the {@link #add} event after the component has been added.</li>\r
-     * </ul></div>\r
-     * <br><p><b>Notes</b></u> :\r
-     * <div><ul class="mdetail-params">\r
-     * <li>If the Container is <i>already rendered</i> when <tt>add</tt>\r
-     * is called, you may need to call {@link #doLayout} to refresh the view which causes\r
-     * any unrendered child Components to be rendered. This is required so that you can\r
-     * <tt>add</tt> multiple child components if needed while only refreshing the layout\r
-     * once. For example:<pre><code>\r
-var tb = new {@link Ext.Toolbar}();\r
-tb.render(document.body);  // toolbar is rendered\r
-tb.add({text:'Button 1'}); // add multiple items ({@link #defaultType} for {@link Ext.Toolbar Toolbar} is 'button')\r
-tb.add({text:'Button 2'});\r
-tb.{@link #doLayout}();             // refresh the layout\r
-     * </code></pre></li>\r
-     * <li><i>Warning:</i> Containers directly managed by the BorderLayout layout manager\r
-     * may not be removed or added.  See the Notes for {@link Ext.layout.BorderLayout BorderLayout}\r
-     * for more details.</li>\r
-     * </ul></div>\r
-     * @param {Object/Array} component\r
-     * <p>Either a single component or an Array of components to add.  See\r
-     * <code>{@link #items}</code> for additional information.</p>\r
-     * @param {Object} (Optional) component_2\r
-     * @param {Object} (Optional) component_n\r
-     * @return {Ext.Component} component The Component (or config object) that was added.\r
-     */\r
-    add : function(comp){\r
-        this.initItems();\r
-        var args = arguments.length > 1;\r
-        if(args || Ext.isArray(comp)){\r
-            Ext.each(args ? arguments : comp, function(c){\r
-                this.add(c);\r
-            }, this);\r
-            return;\r
-        }\r
-        var c = this.lookupComponent(this.applyDefaults(comp));\r
-        var pos = this.items.length;\r
-        if(this.fireEvent('beforeadd', this, c, pos) !== false && this.onBeforeAdd(c) !== false){\r
-            this.items.add(c);\r
-            c.ownerCt = this;\r
-            this.onAdd(c);\r
-            this.fireEvent('add', this, c, pos);\r
-        }\r
-        return c;\r
-    },\r
-\r
-    onAdd : function(c){\r
-        // Empty template method\r
-    },\r
-\r
-    /**\r
-     * Inserts a Component into this Container at a specified index. Fires the\r
-     * {@link #beforeadd} event before inserting, then fires the {@link #add} event after the\r
-     * Component has been inserted.\r
-     * @param {Number} index The index at which the Component will be inserted\r
-     * into the Container's items collection\r
-     * @param {Ext.Component} component The child Component to insert.<br><br>\r
-     * Ext uses lazy rendering, and will only render the inserted Component should\r
-     * it become necessary.<br><br>\r
-     * A Component config object may be passed in order to avoid the overhead of\r
-     * constructing a real Component object if lazy rendering might mean that the\r
-     * inserted Component will not be rendered immediately. To take advantage of\r
-     * this 'lazy instantiation', set the {@link Ext.Component#xtype} config\r
-     * property to the registered type of the Component wanted.<br><br>\r
-     * For a list of all available xtypes, see {@link Ext.Component}.\r
-     * @return {Ext.Component} component The Component (or config object) that was\r
-     * inserted with the Container's default config values applied.\r
-     */\r
-    insert : function(index, comp){\r
-        this.initItems();\r
-        var a = arguments, len = a.length;\r
-        if(len > 2){\r
-            for(var i = len-1; i >= 1; --i) {\r
-                this.insert(index, a[i]);\r
-            }\r
-            return;\r
-        }\r
-        var c = this.lookupComponent(this.applyDefaults(comp));\r
-        index = Math.min(index, this.items.length);\r
-        if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){\r
-            if(c.ownerCt == this){\r
-                this.items.remove(c);\r
-            }\r
-            this.items.insert(index, c);\r
-            c.ownerCt = this;\r
-            this.onAdd(c);\r
-            this.fireEvent('add', this, c, index);\r
-        }\r
-        return c;\r
-    },\r
-\r
-    // private\r
-    applyDefaults : function(c){\r
-        if(this.defaults){\r
-            if(Ext.isString(c)){\r
-                c = Ext.ComponentMgr.get(c);\r
-                Ext.apply(c, this.defaults);\r
-            }else if(!c.events){\r
-                Ext.applyIf(c, this.defaults);\r
-            }else{\r
-                Ext.apply(c, this.defaults);\r
-            }\r
-        }\r
-        return c;\r
-    },\r
-\r
-    // private\r
-    onBeforeAdd : function(item){\r
-        if(item.ownerCt){\r
-            item.ownerCt.remove(item, false);\r
-        }\r
-        if(this.hideBorders === true){\r
-            item.border = (item.border === true);\r
-        }\r
-    },\r
-\r
-    /**\r
-     * Removes a component from this container.  Fires the {@link #beforeremove} event before removing, then fires\r
-     * the {@link #remove} event after the component has been removed.\r
-     * @param {Component/String} component The component reference or id to remove.\r
-     * @param {Boolean} autoDestroy (optional) True to automatically invoke the removed Component's {@link Ext.Component#destroy} function.\r
-     * Defaults to the value of this Container's {@link #autoDestroy} config.\r
-     * @return {Ext.Component} component The Component that was removed.\r
-     */\r
-    remove : function(comp, autoDestroy){\r
-        this.initItems();\r
-        var c = this.getComponent(comp);\r
-        if(c && this.fireEvent('beforeremove', this, c) !== false){\r
-            delete c.ownerCt;\r
-            if(this.layout && this.rendered){\r
-                this.layout.onRemove(c);\r
-            }\r
-            this.onRemove(c);\r
-            this.items.remove(c);\r
-            if(autoDestroy === true || (autoDestroy !== false && this.autoDestroy)){\r
-                c.destroy();\r
-            }\r
-            this.fireEvent('remove', this, c);\r
-        }\r
-        return c;\r
-    },\r
-\r
-    onRemove: function(c){\r
-        // Empty template method\r
-    },\r
-\r
-    /**\r
-     * Removes all components from this container.\r
-     * @param {Boolean} autoDestroy (optional) True to automatically invoke the removed Component's {@link Ext.Component#destroy} function.\r
-     * Defaults to the value of this Container's {@link #autoDestroy} config.\r
-     * @return {Array} Array of the destroyed components\r
-     */\r
-    removeAll: function(autoDestroy){\r
-        this.initItems();\r
-        var item, rem = [], items = [];\r
-        this.items.each(function(i){\r
-            rem.push(i);\r
-        });\r
-        for (var i = 0, len = rem.length; i < len; ++i){\r
-            item = rem[i];\r
-            this.remove(item, autoDestroy);\r
-            if(item.ownerCt !== this){\r
-                items.push(item);\r
-            }\r
-        }\r
-        return items;\r
-    },\r
-\r
-    /**\r
-     * Examines this container's <code>{@link #items}</code> <b>property</b>\r
-     * and gets a direct child component of this container.\r
-     * @param {String/Number} comp This parameter may be any of the following:\r
-     * <div><ul class="mdetail-params">\r
-     * <li>a <b><tt>String</tt></b> : representing the <code>{@link Ext.Component#itemId itemId}</code>\r
-     * or <code>{@link Ext.Component#id id}</code> of the child component </li>\r
-     * <li>a <b><tt>Number</tt></b> : representing the position of the child component\r
-     * within the <code>{@link #items}</code> <b>property</b></li>\r
-     * </ul></div>\r
-     * <p>For additional information see {@link Ext.util.MixedCollection#get}.\r
-     * @return Ext.Component The component (if found).\r
-     */\r
-    getComponent : function(comp){\r
-        if(Ext.isObject(comp)){\r
-            comp = comp.getItemId();\r
-        }\r
-        return this.items.get(comp);\r
-    },\r
-\r
-    // private\r
-    lookupComponent : function(comp){\r
-        if(Ext.isString(comp)){\r
-            return Ext.ComponentMgr.get(comp);\r
-        }else if(!comp.events){\r
-            return this.createComponent(comp);\r
-        }\r
-        return comp;\r
-    },\r
-\r
-    // private\r
-    createComponent : function(config){\r
-        return Ext.create(config, this.defaultType);\r
-    },\r
-\r
-    // private\r
-    canLayout: function() {\r
-        var el = this.getVisibilityEl();\r
-        return el && !el.isStyle("display", "none");\r
-    },\r
-\r
-\r
-    /**\r
-     * Force this container's layout to be recalculated. A call to this function is required after adding a new component\r
-     * to an already rendered container, or possibly after changing sizing/position properties of child components.\r
-     * @param {Boolean} shallow (optional) True to only calc the layout of this component, and let child components auto\r
-     * calc layouts as required (defaults to false, which calls doLayout recursively for each subcontainer)\r
-     * @param {Boolean} force (optional) True to force a layout to occur, even if the item is hidden.\r
-     * @return {Ext.Container} this\r
-     */\r
-    doLayout: function(shallow, force){\r
-        var rendered = this.rendered;\r
-        forceLayout = force || this.forceLayout;\r
-\r
-        if(!this.canLayout() || this.collapsed){\r
-            this.deferLayout = this.deferLayout || !shallow;\r
-            if(!forceLayout){\r
-                return;\r
-            }\r
-            shallow = shallow && !this.deferLayout;\r
-        } else {\r
-            delete this.deferLayout;\r
-        }\r
-        if(rendered && this.layout){\r
-            this.layout.layout();\r
-        }\r
-        if(shallow !== true && this.items){\r
-            var cs = this.items.items;\r
-            for(var i = 0, len = cs.length; i < len; i++){\r
-                var c = cs[i];\r
-                if(c.doLayout){\r
-                    c.doLayout(false, forceLayout);\r
-                }\r
-            }\r
-        }\r
-        if(rendered){\r
-            this.onLayout(shallow, forceLayout);\r
-        }\r
-        // Initial layout completed\r
-        this.hasLayout = true;\r
-        delete this.forceLayout;\r
-    },\r
-\r
-    //private\r
-    onLayout : Ext.emptyFn,\r
-\r
-    // private\r
-    shouldBufferLayout: function(){\r
-        /*\r
-         * Returns true if the container should buffer a layout.\r
-         * This is true only if the container has previously been laid out\r
-         * and has a parent container that is pending a layout.\r
-         */\r
-        var hl = this.hasLayout;\r
-        if(this.ownerCt){\r
-            // Only ever buffer if we've laid out the first time and we have one pending.\r
-            return hl ? !this.hasLayoutPending() : false;\r
-        }\r
-        // Never buffer initial layout\r
-        return hl;\r
-    },\r
-\r
-    // private\r
-    hasLayoutPending: function(){\r
-        // Traverse hierarchy to see if any parent container has a pending layout.\r
-        var pending = false;\r
-        this.ownerCt.bubble(function(c){\r
-            if(c.layoutPending){\r
-                pending = true;\r
-                return false;\r
-            }\r
-        });\r
-        return pending;\r
-    },\r
-\r
-    onShow : function(){\r
-        Ext.Container.superclass.onShow.call(this);\r
-        if(this.deferLayout !== undefined){\r
-            this.doLayout(true);\r
-        }\r
-    },\r
-\r
-    /**\r
-     * Returns the layout currently in use by the container.  If the container does not currently have a layout\r
-     * set, a default {@link Ext.layout.ContainerLayout} will be created and set as the container's layout.\r
-     * @return {ContainerLayout} layout The container's layout\r
-     */\r
-    getLayout : function(){\r
-        if(!this.layout){\r
-            var layout = new Ext.layout.ContainerLayout(this.layoutConfig);\r
-            this.setLayout(layout);\r
-        }\r
-        return this.layout;\r
-    },\r
-\r
-    // private\r
-    beforeDestroy : function(){\r
-        if(this.items){\r
-            Ext.destroy.apply(Ext, this.items.items);\r
-        }\r
-        if(this.monitorResize){\r
-            Ext.EventManager.removeResizeListener(this.doLayout, this);\r
-        }\r
-        Ext.destroy(this.layout);\r
-        Ext.Container.superclass.beforeDestroy.call(this);\r
-    },\r
-\r
-    /**\r
-     * Bubbles up the component/container heirarchy, calling the specified function with each component. The scope (<i>this</i>) of\r
-     * function call will be the scope provided or the current component. The arguments to the function\r
-     * will be the args provided or the current component. If the function returns false at any point,\r
-     * the bubble is stopped.\r
-     * @param {Function} fn The function to call\r
-     * @param {Object} scope (optional) The scope of the function (defaults to current node)\r
-     * @param {Array} args (optional) The args to call the function with (default to passing the current component)\r
-     * @return {Ext.Container} this\r
-     */\r
-    bubble : function(fn, scope, args){\r
-        var p = this;\r
-        while(p){\r
-            if(fn.apply(scope || p, args || [p]) === false){\r
-                break;\r
-            }\r
-            p = p.ownerCt;\r
-        }\r
-        return this;\r
-    },\r
-\r
-    /**\r
-     * Cascades down the component/container heirarchy from this component (called first), calling the specified function with\r
-     * each component. The scope (<i>this</i>) of\r
-     * function call will be the scope provided or the current component. The arguments to the function\r
-     * will be the args provided or the current component. If the function returns false at any point,\r
-     * the cascade is stopped on that branch.\r
-     * @param {Function} fn The function to call\r
-     * @param {Object} scope (optional) The scope of the function (defaults to current component)\r
-     * @param {Array} args (optional) The args to call the function with (defaults to passing the current component)\r
-     * @return {Ext.Container} this\r
-     */\r
-    cascade : function(fn, scope, args){\r
-        if(fn.apply(scope || this, args || [this]) !== false){\r
-            if(this.items){\r
-                var cs = this.items.items;\r
-                for(var i = 0, len = cs.length; i < len; i++){\r
-                    if(cs[i].cascade){\r
-                        cs[i].cascade(fn, scope, args);\r
-                    }else{\r
-                        fn.apply(scope || cs[i], args || [cs[i]]);\r
-                    }\r
-                }\r
-            }\r
-        }\r
-        return this;\r
-    },\r
-\r
-    /**\r
-     * Find a component under this container at any level by id\r
-     * @param {String} id\r
-     * @return Ext.Component\r
-     */\r
-    findById : function(id){\r
-        var m, ct = this;\r
-        this.cascade(function(c){\r
-            if(ct != c && c.id === id){\r
-                m = c;\r
-                return false;\r
-            }\r
-        });\r
-        return m || null;\r
-    },\r
-\r
-    /**\r
-     * Find a component under this container at any level by xtype or class\r
-     * @param {String/Class} xtype The xtype string for a component, or the class of the component directly\r
-     * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is\r
-     * the default), or true to check whether this Component is directly of the specified xtype.\r
-     * @return {Array} Array of Ext.Components\r
-     */\r
-    findByType : function(xtype, shallow){\r
-        return this.findBy(function(c){\r
-            return c.isXType(xtype, shallow);\r
-        });\r
-    },\r
-\r
-    /**\r
-     * Find a component under this container at any level by property\r
-     * @param {String} prop\r
-     * @param {String} value\r
-     * @return {Array} Array of Ext.Components\r
-     */\r
-    find : function(prop, value){\r
-        return this.findBy(function(c){\r
-            return c[prop] === value;\r
-        });\r
-    },\r
-\r
-    /**\r
-     * Find a component under this container at any level by a custom function. If the passed function returns\r
-     * true, the component will be included in the results. The passed function is called with the arguments (component, this container).\r
-     * @param {Function} fn The function to call\r
-     * @param {Object} scope (optional)\r
-     * @return {Array} Array of Ext.Components\r
-     */\r
-    findBy : function(fn, scope){\r
-        var m = [], ct = this;\r
-        this.cascade(function(c){\r
-            if(ct != c && fn.call(scope || c, c, ct) === true){\r
-                m.push(c);\r
-            }\r
-        });\r
-        return m;\r
-    },\r
-\r
-    /**\r
-     * Get a component contained by this container (alias for items.get(key))\r
-     * @param {String/Number} key The index or id of the component\r
-     * @return {Ext.Component} Ext.Component\r
-     */\r
-    get : function(key){\r
-        return this.items.get(key);\r
-    }\r
-});\r
-\r
-Ext.Container.LAYOUTS = {};\r
-Ext.reg('container', Ext.Container);\r
+/**
+ * @class Ext.Container
+ * @extends Ext.BoxComponent
+ * <p>Base class for any {@link Ext.BoxComponent} that may contain other Components. Containers handle the
+ * basic behavior of containing items, namely adding, inserting and removing items.</p>
+ *
+ * <p>The most commonly used Container classes are {@link Ext.Panel}, {@link Ext.Window} and {@link Ext.TabPanel}.
+ * If you do not need the capabilities offered by the aforementioned classes you can create a lightweight
+ * Container to be encapsulated by an HTML element to your specifications by using the
+ * <code><b>{@link Ext.Component#autoEl autoEl}</b></code> config option. This is a useful technique when creating
+ * embedded {@link Ext.layout.ColumnLayout column} layouts inside {@link Ext.form.FormPanel FormPanels}
+ * for example.</p>
+ *
+ * <p>The code below illustrates both how to explicitly create a Container, and how to implicitly
+ * create one using the <b><code>'container'</code></b> xtype:<pre><code>
+// explicitly create a Container
+var embeddedColumns = new Ext.Container({
+    autoEl: 'div',  // This is the default
+    layout: 'column',
+    defaults: {
+        // implicitly create Container by specifying xtype
+        xtype: 'container',
+        autoEl: 'div', // This is the default.
+        layout: 'form',
+        columnWidth: 0.5,
+        style: {
+            padding: '10px'
+        }
+    },
+//  The two items below will be Ext.Containers, each encapsulated by a &lt;DIV> element.
+    items: [{
+        items: {
+            xtype: 'datefield',
+            name: 'startDate',
+            fieldLabel: 'Start date'
+        }
+    }, {
+        items: {
+            xtype: 'datefield',
+            name: 'endDate',
+            fieldLabel: 'End date'
+        }
+    }]
+});</code></pre></p>
+ *
+ * <p><u><b>Layout</b></u></p>
+ * <p>Container classes delegate the rendering of child Components to a layout
+ * manager class which must be configured into the Container using the
+ * <code><b>{@link #layout}</b></code> configuration property.</p>
+ * <p>When either specifying child <code>{@link #items}</code> of a Container,
+ * or dynamically {@link #add adding} Components to a Container, remember to
+ * consider how you wish the Container to arrange those child elements, and
+ * whether those child elements need to be sized using one of Ext's built-in
+ * <b><code>{@link #layout}</code></b> schemes. By default, Containers use the
+ * {@link Ext.layout.ContainerLayout ContainerLayout} scheme which only
+ * renders child components, appending them one after the other inside the
+ * Container, and <b>does not apply any sizing</b> at all.</p>
+ * <p>A common mistake is when a developer neglects to specify a
+ * <b><code>{@link #layout}</code></b> (e.g. widgets like GridPanels or
+ * TreePanels are added to Containers for which no <code><b>{@link #layout}</b></code>
+ * has been specified). If a Container is left to use the default
+ * {@link Ext.layout.ContainerLayout ContainerLayout} scheme, none of its
+ * child components will be resized, or changed in any way when the Container
+ * is resized.</p>
+ * <p>Certain layout managers allow dynamic addition of child components.
+ * Those that do include {@link Ext.layout.CardLayout},
+ * {@link Ext.layout.AnchorLayout}, {@link Ext.layout.FormLayout}, and
+ * {@link Ext.layout.TableLayout}. For example:<pre><code>
+//  Create the GridPanel.
+var myNewGrid = new Ext.grid.GridPanel({
+    store: myStore,
+    columns: myColumnModel,
+    title: 'Results', // the title becomes the title of the tab
+});
+
+myTabPanel.add(myNewGrid); // {@link Ext.TabPanel} implicitly uses {@link Ext.layout.CardLayout CardLayout}
+myTabPanel.{@link Ext.TabPanel#setActiveTab setActiveTab}(myNewGrid);
+ * </code></pre></p>
+ * <p>The example above adds a newly created GridPanel to a TabPanel. Note that
+ * a TabPanel uses {@link Ext.layout.CardLayout} as its layout manager which
+ * means all its child items are sized to {@link Ext.layout.FitLayout fit}
+ * exactly into its client area.
+ * <p><b><u>Overnesting is a common problem</u></b>.
+ * An example of overnesting occurs when a GridPanel is added to a TabPanel
+ * by wrapping the GridPanel <i>inside</i> a wrapping Panel (that has no
+ * <code><b>{@link #layout}</b></code> specified) and then add that wrapping Panel
+ * to the TabPanel. The point to realize is that a GridPanel <b>is</b> a
+ * Component which can be added directly to a Container. If the wrapping Panel
+ * has no <code><b>{@link #layout}</b></code> configuration, then the overnested
+ * GridPanel will not be sized as expected.<p>
+ *
+ * <p><u><b>Adding via remote configuration</b></u></p>
+ *
+ * <p>A server side script can be used to add Components which are generated dynamically on the server.
+ * An example of adding a GridPanel to a TabPanel where the GridPanel is generated by the server
+ * based on certain parameters:
+ * </p><pre><code>
+// execute an Ajax request to invoke server side script:
+Ext.Ajax.request({
+    url: 'gen-invoice-grid.php',
+    // send additional parameters to instruct server script
+    params: {
+        startDate: Ext.getCmp('start-date').getValue(),
+        endDate: Ext.getCmp('end-date').getValue()
+    },
+    // process the response object to add it to the TabPanel:
+    success: function(xhr) {
+        var newComponent = eval(xhr.responseText); // see discussion below
+        myTabPanel.add(newComponent); // add the component to the TabPanel
+        myTabPanel.setActiveTab(newComponent);
+    },
+    failure: function() {
+        Ext.Msg.alert("Grid create failed", "Server communication failure");
+    }
+});
+</code></pre>
+ * <p>The server script needs to return an executable Javascript statement which, when processed
+ * using <code>eval()</code>, will return either a config object with an {@link Ext.Component#xtype xtype},
+ * or an instantiated Component. The server might return this for example:</p><pre><code>
+(function() {
+    function formatDate(value){
+        return value ? value.dateFormat('M d, Y') : '';
+    };
+
+    var store = new Ext.data.Store({
+        url: 'get-invoice-data.php',
+        baseParams: {
+            startDate: '01/01/2008',
+            endDate: '01/31/2008'
+        },
+        reader: new Ext.data.JsonReader({
+            record: 'transaction',
+            idProperty: 'id',
+            totalRecords: 'total'
+        }, [
+           'customer',
+           'invNo',
+           {name: 'date', type: 'date', dateFormat: 'm/d/Y'},
+           {name: 'value', type: 'float'}
+        ])
+    });
+
+    var grid = new Ext.grid.GridPanel({
+        title: 'Invoice Report',
+        bbar: new Ext.PagingToolbar(store),
+        store: store,
+        columns: [
+            {header: "Customer", width: 250, dataIndex: 'customer', sortable: true},
+            {header: "Invoice Number", width: 120, dataIndex: 'invNo', sortable: true},
+            {header: "Invoice Date", width: 100, dataIndex: 'date', renderer: formatDate, sortable: true},
+            {header: "Value", width: 120, dataIndex: 'value', renderer: 'usMoney', sortable: true}
+        ],
+    });
+    store.load();
+    return grid;  // return instantiated component
+})();
+</code></pre>
+ * <p>When the above code fragment is passed through the <code>eval</code> function in the success handler
+ * of the Ajax request, the code is executed by the Javascript processor, and the anonymous function
+ * runs, and returns the instantiated grid component.</p>
+ * <p>Note: since the code above is <i>generated</i> by a server script, the <code>baseParams</code> for
+ * the Store, the metadata to allow generation of the Record layout, and the ColumnModel
+ * can all be generated into the code since these are all known on the server.</p>
+ *
+ * @xtype container
+ */
+Ext.Container = Ext.extend(Ext.BoxComponent, {
+    /**
+     * @cfg {Boolean} monitorResize
+     * True to automatically monitor window resize events to handle anything that is sensitive to the current size
+     * of the viewport.  This value is typically managed by the chosen <code>{@link #layout}</code> and should not need
+     * to be set manually.
+     */
+    /**
+     * @cfg {String/Object} layout
+     * <p><b>*Important</b>: In order for child items to be correctly sized and
+     * positioned, typically a layout manager <b>must</b> be specified through
+     * the <code>layout</code> configuration option.</p>
+     * <br><p>The sizing and positioning of child {@link items} is the responsibility of
+     * the Container's layout manager which creates and manages the type of layout
+     * you have in mind.  For example:</p><pre><code>
+new Ext.Window({
+    width:300, height: 300,
+    layout: 'fit', // explicitly set layout manager: override the default (layout:'auto')
+    items: [{
+        title: 'Panel inside a Window'
+    }]
+}).show();
+     * </code></pre>
+     * <p>If the {@link #layout} configuration is not explicitly specified for
+     * a general purpose container (e.g. Container or Panel) the
+     * {@link Ext.layout.ContainerLayout default layout manager} will be used
+     * which does nothing but render child components sequentially into the
+     * Container (no sizing or positioning will be performed in this situation).
+     * Some container classes implicitly specify a default layout
+     * (e.g. FormPanel specifies <code>layout:'form'</code>). Other specific
+     * purpose classes internally specify/manage their internal layout (e.g.
+     * GridPanel, TabPanel, TreePanel, Toolbar, Menu, etc.).</p>
+     * <br><p><b><code>layout</code></b> may be specified as either as an Object or
+     * as a String:</p><div><ul class="mdetail-params">
+     *
+     * <li><u>Specify as an Object</u></li>
+     * <div><ul class="mdetail-params">
+     * <li>Example usage:</li>
+<pre><code>
+layout: {
+    type: 'vbox',
+    padding: '5',
+    align: 'left'
+}
+</code></pre>
+     *
+     * <li><code><b>type</b></code></li>
+     * <br/><p>The layout type to be used for this container.  If not specified,
+     * a default {@link Ext.layout.ContainerLayout} will be created and used.</p>
+     * <br/><p>Valid layout <code>type</code> values are:</p>
+     * <div class="sub-desc"><ul class="mdetail-params">
+     * <li><code><b>{@link Ext.layout.AbsoluteLayout absolute}</b></code></li>
+     * <li><code><b>{@link Ext.layout.AccordionLayout accordion}</b></code></li>
+     * <li><code><b>{@link Ext.layout.AnchorLayout anchor}</b></code></li>
+     * <li><code><b>{@link Ext.layout.ContainerLayout auto}</b></code> &nbsp;&nbsp;&nbsp; <b>Default</b></li>
+     * <li><code><b>{@link Ext.layout.BorderLayout border}</b></code></li>
+     * <li><code><b>{@link Ext.layout.CardLayout card}</b></code></li>
+     * <li><code><b>{@link Ext.layout.ColumnLayout column}</b></code></li>
+     * <li><code><b>{@link Ext.layout.FitLayout fit}</b></code></li>
+     * <li><code><b>{@link Ext.layout.FormLayout form}</b></code></li>
+     * <li><code><b>{@link Ext.layout.HBoxLayout hbox}</b></code></li>
+     * <li><code><b>{@link Ext.layout.MenuLayout menu}</b></code></li>
+     * <li><code><b>{@link Ext.layout.TableLayout table}</b></code></li>
+     * <li><code><b>{@link Ext.layout.ToolbarLayout toolbar}</b></code></li>
+     * <li><code><b>{@link Ext.layout.VBoxLayout vbox}</b></code></li>
+     * </ul></div>
+     *
+     * <li>Layout specific configuration properties</li>
+     * <br/><p>Additional layout specific configuration properties may also be
+     * specified. For complete details regarding the valid config options for
+     * each layout type, see the layout class corresponding to the <code>type</code>
+     * specified.</p>
+     *
+     * </ul></div>
+     *
+     * <li><u>Specify as a String</u></li>
+     * <div><ul class="mdetail-params">
+     * <li>Example usage:</li>
+<pre><code>
+layout: 'vbox',
+layoutConfig: {
+    padding: '5',
+    align: 'left'
+}
+</code></pre>
+     * <li><code><b>layout</b></code></li>
+     * <br/><p>The layout <code>type</code> to be used for this container (see list
+     * of valid layout type values above).</p><br/>
+     * <li><code><b>{@link #layoutConfig}</b></code></li>
+     * <br/><p>Additional layout specific configuration properties. For complete
+     * details regarding the valid config options for each layout type, see the
+     * layout class corresponding to the <code>layout</code> specified.</p>
+     * </ul></div></ul></div>
+     */
+    /**
+     * @cfg {Object} layoutConfig
+     * This is a config object containing properties specific to the chosen
+     * <b><code>{@link #layout}</code></b> if <b><code>{@link #layout}</code></b>
+     * has been specified as a <i>string</i>.</p>
+     */
+    /**
+     * @cfg {Boolean/Number} bufferResize
+     * When set to true (50 milliseconds) or a number of milliseconds, the layout assigned for this container will buffer
+     * the frequency it calculates and does a re-layout of components. This is useful for heavy containers or containers
+     * with a large quantity of sub-components for which frequent layout calls would be expensive. Defaults to <code>50</code>.
+     */
+    // Deprecated - will be removed in 3.2.x
+    bufferResize: 50,
+
+    /**
+     * @cfg {String/Number} activeItem
+     * A string component id or the numeric index of the component that should be initially activated within the
+     * container's layout on render.  For example, activeItem: 'item-1' or activeItem: 0 (index 0 = the first
+     * item in the container's collection).  activeItem only applies to layout styles that can display
+     * items one at a time (like {@link Ext.layout.AccordionLayout}, {@link Ext.layout.CardLayout} and
+     * {@link Ext.layout.FitLayout}).  Related to {@link Ext.layout.ContainerLayout#activeItem}.
+     */
+    /**
+     * @cfg {Object/Array} items
+     * <pre><b>** IMPORTANT</b>: be sure to <b>{@link #layout specify a <code>layout</code>} if needed ! **</b></pre>
+     * <p>A single item, or an array of child Components to be added to this container,
+     * for example:</p>
+     * <pre><code>
+// specifying a single item
+items: {...},
+layout: 'fit',    // specify a layout!
+
+// specifying multiple items
+items: [{...}, {...}],
+layout: 'anchor', // specify a layout!
+     * </code></pre>
+     * <p>Each item may be:</p>
+     * <div><ul class="mdetail-params">
+     * <li>any type of object based on {@link Ext.Component}</li>
+     * <li>a fully instanciated object or</li>
+     * <li>an object literal that:</li>
+     * <div><ul class="mdetail-params">
+     * <li>has a specified <code>{@link Ext.Component#xtype xtype}</code></li>
+     * <li>the {@link Ext.Component#xtype} specified is associated with the Component
+     * desired and should be chosen from one of the available xtypes as listed
+     * in {@link Ext.Component}.</li>
+     * <li>If an <code>{@link Ext.Component#xtype xtype}</code> is not explicitly
+     * specified, the {@link #defaultType} for that Container is used.</li>
+     * <li>will be "lazily instanciated", avoiding the overhead of constructing a fully
+     * instanciated Component object</li>
+     * </ul></div></ul></div>
+     * <p><b>Notes</b>:</p>
+     * <div><ul class="mdetail-params">
+     * <li>Ext uses lazy rendering. Child Components will only be rendered
+     * should it become necessary. Items are automatically laid out when they are first
+     * shown (no sizing is done while hidden), or in response to a {@link #doLayout} call.</li>
+     * <li>Do not specify <code>{@link Ext.Panel#contentEl contentEl}</code>/
+     * <code>{@link Ext.Panel#html html}</code> with <code>items</code>.</li>
+     * </ul></div>
+     */
+    /**
+     * @cfg {Object|Function} defaults
+     * <p>This option is a means of applying default settings to all added items whether added through the {@link #items}
+     * config or via the {@link #add} or {@link #insert} methods.</p>
+     * <p>If an added item is a config object, and <b>not</b> an instantiated Component, then the default properties are
+     * unconditionally applied. If the added item <b>is</b> an instantiated Component, then the default properties are
+     * applied conditionally so as not to override existing properties in the item.</p>
+     * <p>If the defaults option is specified as a function, then the function will be called using this Container as the
+     * scope (<code>this</code> reference) and passing the added item as the first parameter. Any resulting object
+     * from that call is then applied to the item as default properties.</p>
+     * <p>For example, to automatically apply padding to the body of each of a set of
+     * contained {@link Ext.Panel} items, you could pass: <code>defaults: {bodyStyle:'padding:15px'}</code>.</p>
+     * <p>Usage:</p><pre><code>
+defaults: {               // defaults are applied to items, not the container
+    autoScroll:true
+},
+items: [
+    {
+        xtype: 'panel',   // defaults <b>do not</b> have precedence over
+        id: 'panel1',     // options in config objects, so the defaults
+        autoScroll: false // will not be applied here, panel1 will be autoScroll:false
+    },
+    new Ext.Panel({       // defaults <b>do</b> have precedence over options
+        id: 'panel2',     // options in components, so the defaults
+        autoScroll: false // will be applied here, panel2 will be autoScroll:true.
+    })
+]
+     * </code></pre>
+     */
+
+
+    /** @cfg {Boolean} autoDestroy
+     * If true the container will automatically destroy any contained component that is removed from it, else
+     * destruction must be handled manually (defaults to true).
+     */
+    autoDestroy : true,
+
+    /** @cfg {Boolean} forceLayout
+     * If true the container will force a layout initially even if hidden or collapsed. This option
+     * is useful for forcing forms to render in collapsed or hidden containers. (defaults to false).
+     */
+    forceLayout: false,
+
+    /** @cfg {Boolean} hideBorders
+     * True to hide the borders of each contained component, false to defer to the component's existing
+     * border settings (defaults to false).
+     */
+    /** @cfg {String} defaultType
+     * <p>The default {@link Ext.Component xtype} of child Components to create in this Container when
+     * a child item is specified as a raw configuration object, rather than as an instantiated Component.</p>
+     * <p>Defaults to <code>'panel'</code>, except {@link Ext.menu.Menu} which defaults to <code>'menuitem'</code>,
+     * and {@link Ext.Toolbar} and {@link Ext.ButtonGroup} which default to <code>'button'</code>.</p>
+     */
+    defaultType : 'panel',
+
+    /** @cfg {String} resizeEvent
+     * The event to listen to for resizing in layouts. Defaults to <code>'resize'</code>.
+     */
+    resizeEvent: 'resize',
+
+    /**
+     * @cfg {Array} bubbleEvents
+     * <p>An array of events that, when fired, should be bubbled to any parent container.
+     * See {@link Ext.util.Observable#enableBubble}.
+     * Defaults to <code>['add', 'remove']</code>.
+     */
+    bubbleEvents: ['add', 'remove'],
+
+    // private
+    initComponent : function(){
+        Ext.Container.superclass.initComponent.call(this);
+
+        this.addEvents(
+            /**
+             * @event afterlayout
+             * Fires when the components in this container are arranged by the associated layout manager.
+             * @param {Ext.Container} this
+             * @param {ContainerLayout} layout The ContainerLayout implementation for this container
+             */
+            'afterlayout',
+            /**
+             * @event beforeadd
+             * Fires before any {@link Ext.Component} is added or inserted into the container.
+             * A handler can return false to cancel the add.
+             * @param {Ext.Container} this
+             * @param {Ext.Component} component The component being added
+             * @param {Number} index The index at which the component will be added to the container's items collection
+             */
+            'beforeadd',
+            /**
+             * @event beforeremove
+             * Fires before any {@link Ext.Component} is removed from the container.  A handler can return
+             * false to cancel the remove.
+             * @param {Ext.Container} this
+             * @param {Ext.Component} component The component being removed
+             */
+            'beforeremove',
+            /**
+             * @event add
+             * @bubbles
+             * Fires after any {@link Ext.Component} is added or inserted into the container.
+             * @param {Ext.Container} this
+             * @param {Ext.Component} component The component that was added
+             * @param {Number} index The index at which the component was added to the container's items collection
+             */
+            'add',
+            /**
+             * @event remove
+             * @bubbles
+             * Fires after any {@link Ext.Component} is removed from the container.
+             * @param {Ext.Container} this
+             * @param {Ext.Component} component The component that was removed
+             */
+            'remove'
+        );
+
+        this.enableBubble(this.bubbleEvents);
+
+        /**
+         * The collection of components in this container as a {@link Ext.util.MixedCollection}
+         * @type MixedCollection
+         * @property items
+         */
+        var items = this.items;
+        if(items){
+            delete this.items;
+            this.add(items);
+        }
+    },
+
+    // private
+    initItems : function(){
+        if(!this.items){
+            this.items = new Ext.util.MixedCollection(false, this.getComponentId);
+            this.getLayout(); // initialize the layout
+        }
+    },
+
+    // private
+    setLayout : function(layout){
+        if(this.layout && this.layout != layout){
+            this.layout.setContainer(null);
+        }
+        this.initItems();
+        this.layout = layout;
+        layout.setContainer(this);
+    },
+
+    afterRender: function(){
+        // Render this Container, this should be done before setLayout is called which
+        // will hook onResize
+        Ext.Container.superclass.afterRender.call(this);
+        if(!this.layout){
+            this.layout = 'auto';
+        }
+        if(Ext.isObject(this.layout) && !this.layout.layout){
+            this.layoutConfig = this.layout;
+            this.layout = this.layoutConfig.type;
+        }
+        if(Ext.isString(this.layout)){
+            this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig);
+        }
+        this.setLayout(this.layout);
+
+        // If a CardLayout, the active item set
+        if(this.activeItem !== undefined){
+            var item = this.activeItem;
+            delete this.activeItem;
+            this.layout.setActiveItem(item);
+        }
+
+        // If we have no ownerCt, render and size all children
+        if(!this.ownerCt){
+            this.doLayout(false, true);
+        }
+
+        // This is a manually configured flag set by users in conjunction with renderTo.
+        // Not to be confused with the flag by the same name used in Layouts.
+        if(this.monitorResize === true){
+            Ext.EventManager.onWindowResize(this.doLayout, this, [false]);
+        }
+    },
+
+    /**
+     * <p>Returns the Element to be used to contain the child Components of this Container.</p>
+     * <p>An implementation is provided which returns the Container's {@link #getEl Element}, but
+     * if there is a more complex structure to a Container, this may be overridden to return
+     * the element into which the {@link #layout layout} renders child Components.</p>
+     * @return {Ext.Element} The Element to render child Components into.
+     */
+    getLayoutTarget : function(){
+        return this.el;
+    },
+
+    // private - used as the key lookup function for the items collection
+    getComponentId : function(comp){
+        return comp.getItemId();
+    },
+
+    /**
+     * <p>Adds {@link Ext.Component Component}(s) to this Container.</p>
+     * <br><p><b>Description</b></u> :
+     * <div><ul class="mdetail-params">
+     * <li>Fires the {@link #beforeadd} event before adding</li>
+     * <li>The Container's {@link #defaults default config values} will be applied
+     * accordingly (see <code>{@link #defaults}</code> for details).</li>
+     * <li>Fires the {@link #add} event after the component has been added.</li>
+     * </ul></div>
+     * <br><p><b>Notes</b></u> :
+     * <div><ul class="mdetail-params">
+     * <li>If the Container is <i>already rendered</i> when <code>add</code>
+     * is called, you may need to call {@link #doLayout} to refresh the view which causes
+     * any unrendered child Components to be rendered. This is required so that you can
+     * <code>add</code> multiple child components if needed while only refreshing the layout
+     * once. For example:<pre><code>
+var tb = new {@link Ext.Toolbar}();
+tb.render(document.body);  // toolbar is rendered
+tb.add({text:'Button 1'}); // add multiple items ({@link #defaultType} for {@link Ext.Toolbar Toolbar} is 'button')
+tb.add({text:'Button 2'});
+tb.{@link #doLayout}();             // refresh the layout
+     * </code></pre></li>
+     * <li><i>Warning:</i> Containers directly managed by the BorderLayout layout manager
+     * may not be removed or added.  See the Notes for {@link Ext.layout.BorderLayout BorderLayout}
+     * for more details.</li>
+     * </ul></div>
+     * @param {Object/Array} component
+     * <p>Either a single component or an Array of components to add.  See
+     * <code>{@link #items}</code> for additional information.</p>
+     * @param {Object} (Optional) component_2
+     * @param {Object} (Optional) component_n
+     * @return {Ext.Component} component The Component (or config object) that was added.
+     */
+    add : function(comp){
+        this.initItems();
+        var args = arguments.length > 1;
+        if(args || Ext.isArray(comp)){
+            var result = [];
+            Ext.each(args ? arguments : comp, function(c){
+                result.push(this.add(c));
+            }, this);
+            return result;
+        }
+        var c = this.lookupComponent(this.applyDefaults(comp));
+        var index = this.items.length;
+        if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
+            this.items.add(c);
+            // *onAdded
+            c.onAdded(this, index);
+            this.onAdd(c);
+            this.fireEvent('add', this, c, index);
+        }
+        return c;
+    },
+
+    onAdd : function(c){
+        // Empty template method
+    },
+
+    // private
+    onAdded : function(container, pos) {
+        //overridden here so we can cascade down, not worth creating a template method.
+        this.ownerCt = container;
+        this.initRef();
+        //initialize references for child items
+        this.cascade(function(c){
+            c.initRef();
+        });
+        this.fireEvent('added', this, container, pos);
+    },
+
+    /**
+     * Inserts a Component into this Container at a specified index. Fires the
+     * {@link #beforeadd} event before inserting, then fires the {@link #add} event after the
+     * Component has been inserted.
+     * @param {Number} index The index at which the Component will be inserted
+     * into the Container's items collection
+     * @param {Ext.Component} component The child Component to insert.<br><br>
+     * Ext uses lazy rendering, and will only render the inserted Component should
+     * it become necessary.<br><br>
+     * A Component config object may be passed in order to avoid the overhead of
+     * constructing a real Component object if lazy rendering might mean that the
+     * inserted Component will not be rendered immediately. To take advantage of
+     * this 'lazy instantiation', set the {@link Ext.Component#xtype} config
+     * property to the registered type of the Component wanted.<br><br>
+     * For a list of all available xtypes, see {@link Ext.Component}.
+     * @return {Ext.Component} component The Component (or config object) that was
+     * inserted with the Container's default config values applied.
+     */
+    insert : function(index, comp){
+        this.initItems();
+        var a = arguments, len = a.length;
+        if(len > 2){
+            var result = [];
+            for(var i = len-1; i >= 1; --i) {
+                result.push(this.insert(index, a[i]));
+            }
+            return result;
+        }
+        var c = this.lookupComponent(this.applyDefaults(comp));
+        index = Math.min(index, this.items.length);
+        if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
+            if(c.ownerCt == this){
+                this.items.remove(c);
+            }
+            this.items.insert(index, c);
+            c.onAdded(this, index);
+            this.onAdd(c);
+            this.fireEvent('add', this, c, index);
+        }
+        return c;
+    },
+
+    // private
+    applyDefaults : function(c){
+        var d = this.defaults;
+        if(d){
+            if(Ext.isFunction(d)){
+                d = d.call(this, c);
+            }
+            if(Ext.isString(c)){
+                c = Ext.ComponentMgr.get(c);
+                Ext.apply(c, d);
+            }else if(!c.events){
+                Ext.applyIf(c, d);
+            }else{
+                Ext.apply(c, d);
+            }
+        }
+        return c;
+    },
+
+    // private
+    onBeforeAdd : function(item){
+        if(item.ownerCt){
+            item.ownerCt.remove(item, false);
+        }
+        if(this.hideBorders === true){
+            item.border = (item.border === true);
+        }
+    },
+
+    /**
+     * Removes a component from this container.  Fires the {@link #beforeremove} event before removing, then fires
+     * the {@link #remove} event after the component has been removed.
+     * @param {Component/String} component The component reference or id to remove.
+     * @param {Boolean} autoDestroy (optional) True to automatically invoke the removed Component's {@link Ext.Component#destroy} function.
+     * Defaults to the value of this Container's {@link #autoDestroy} config.
+     * @return {Ext.Component} component The Component that was removed.
+     */
+    remove : function(comp, autoDestroy){
+        this.initItems();
+        var c = this.getComponent(comp);
+        if(c && this.fireEvent('beforeremove', this, c) !== false){
+            this.doRemove(c, autoDestroy);
+            this.fireEvent('remove', this, c);
+        }
+        return c;
+    },
+
+    onRemove: function(c){
+        // Empty template method
+    },
+
+    // private
+    doRemove: function(c, autoDestroy){
+        var l = this.layout,
+            hasLayout = l && this.rendered;
+
+        if(hasLayout){
+            l.onRemove(c);
+        }
+        this.items.remove(c);
+        c.onRemoved();
+        this.onRemove(c);
+        if(autoDestroy === true || (autoDestroy !== false && this.autoDestroy)){
+            c.destroy();
+        }
+        if(hasLayout){
+            l.afterRemove(c);
+        }
+    },
+
+    /**
+     * Removes all components from this container.
+     * @param {Boolean} autoDestroy (optional) True to automatically invoke the removed Component's {@link Ext.Component#destroy} function.
+     * Defaults to the value of this Container's {@link #autoDestroy} config.
+     * @return {Array} Array of the destroyed components
+     */
+    removeAll: function(autoDestroy){
+        this.initItems();
+        var item, rem = [], items = [];
+        this.items.each(function(i){
+            rem.push(i);
+        });
+        for (var i = 0, len = rem.length; i < len; ++i){
+            item = rem[i];
+            this.remove(item, autoDestroy);
+            if(item.ownerCt !== this){
+                items.push(item);
+            }
+        }
+        return items;
+    },
+
+    /**
+     * Examines this container's <code>{@link #items}</code> <b>property</b>
+     * and gets a direct child component of this container.
+     * @param {String/Number} comp This parameter may be any of the following:
+     * <div><ul class="mdetail-params">
+     * <li>a <b><code>String</code></b> : representing the <code>{@link Ext.Component#itemId itemId}</code>
+     * or <code>{@link Ext.Component#id id}</code> of the child component </li>
+     * <li>a <b><code>Number</code></b> : representing the position of the child component
+     * within the <code>{@link #items}</code> <b>property</b></li>
+     * </ul></div>
+     * <p>For additional information see {@link Ext.util.MixedCollection#get}.
+     * @return Ext.Component The component (if found).
+     */
+    getComponent : function(comp){
+        if(Ext.isObject(comp)){
+            comp = comp.getItemId();
+        }
+        return this.items.get(comp);
+    },
+
+    // private
+    lookupComponent : function(comp){
+        if(Ext.isString(comp)){
+            return Ext.ComponentMgr.get(comp);
+        }else if(!comp.events){
+            return this.createComponent(comp);
+        }
+        return comp;
+    },
+
+    // private
+    createComponent : function(config, defaultType){
+        // add in ownerCt at creation time but then immediately
+        // remove so that onBeforeAdd can handle it
+        var c = config.render ? config : Ext.create(Ext.apply({
+            ownerCt: this
+        }, config), defaultType || this.defaultType);
+        delete c.ownerCt;
+        return c;
+    },
+
+    /**
+    * We can only lay out if there is a view area in which to layout.
+    * display:none on the layout target, *or any of its parent elements* will mean it has no view area.
+    */
+
+    // private
+    canLayout : function() {
+        var el = this.getVisibilityEl();
+        return el && el.dom && !el.isStyle("display", "none");
+    },
+
+    /**
+     * Force this container's layout to be recalculated. A call to this function is required after adding a new component
+     * to an already rendered container, or possibly after changing sizing/position properties of child components.
+     * @param {Boolean} shallow (optional) True to only calc the layout of this component, and let child components auto
+     * calc layouts as required (defaults to false, which calls doLayout recursively for each subcontainer)
+     * @param {Boolean} force (optional) True to force a layout to occur, even if the item is hidden.
+     * @return {Ext.Container} this
+     */
+
+    doLayout : function(shallow, force){
+        var rendered = this.rendered,
+            forceLayout = force || this.forceLayout;
+
+        if(this.collapsed || !this.canLayout()){
+            this.deferLayout = this.deferLayout || !shallow;
+            if(!forceLayout){
+                return;
+            }
+            shallow = shallow && !this.deferLayout;
+        } else {
+            delete this.deferLayout;
+        }
+        if(rendered && this.layout){
+            this.layout.layout();
+        }
+        if(shallow !== true && this.items){
+            var cs = this.items.items;
+            for(var i = 0, len = cs.length; i < len; i++){
+                var c = cs[i];
+                if(c.doLayout){
+                    c.doLayout(false, forceLayout);
+                }
+            }
+        }
+        if(rendered){
+            this.onLayout(shallow, forceLayout);
+        }
+        // Initial layout completed
+        this.hasLayout = true;
+        delete this.forceLayout;
+    },
+
+    onLayout : Ext.emptyFn,
+
+    // private
+    shouldBufferLayout: function(){
+        /*
+         * Returns true if the container should buffer a layout.
+         * This is true only if the container has previously been laid out
+         * and has a parent container that is pending a layout.
+         */
+        var hl = this.hasLayout;
+        if(this.ownerCt){
+            // Only ever buffer if we've laid out the first time and we have one pending.
+            return hl ? !this.hasLayoutPending() : false;
+        }
+        // Never buffer initial layout
+        return hl;
+    },
+
+    // private
+    hasLayoutPending: function(){
+        // Traverse hierarchy to see if any parent container has a pending layout.
+        var pending = false;
+        this.ownerCt.bubble(function(c){
+            if(c.layoutPending){
+                pending = true;
+                return false;
+            }
+        });
+        return pending;
+    },
+
+    onShow : function(){
+        // removes css classes that were added to hide
+        Ext.Container.superclass.onShow.call(this);
+        // If we were sized during the time we were hidden, layout.
+        if(Ext.isDefined(this.deferLayout)){
+            delete this.deferLayout;
+            this.doLayout(true);
+        }
+    },
+
+    /**
+     * Returns the layout currently in use by the container.  If the container does not currently have a layout
+     * set, a default {@link Ext.layout.ContainerLayout} will be created and set as the container's layout.
+     * @return {ContainerLayout} layout The container's layout
+     */
+    getLayout : function(){
+        if(!this.layout){
+            var layout = new Ext.layout.ContainerLayout(this.layoutConfig);
+            this.setLayout(layout);
+        }
+        return this.layout;
+    },
+
+    // private
+    beforeDestroy : function(){
+        var c;
+        if(this.items){
+            while(c = this.items.first()){
+                this.doRemove(c, true);
+            }
+        }
+        if(this.monitorResize){
+            Ext.EventManager.removeResizeListener(this.doLayout, this);
+        }
+        Ext.destroy(this.layout);
+        Ext.Container.superclass.beforeDestroy.call(this);
+    },
+
+    /**
+     * Bubbles up the component/container heirarchy, calling the specified function with each component. The scope (<i>this</i>) of
+     * function call will be the scope provided or the current component. The arguments to the function
+     * will be the args provided or the current component. If the function returns false at any point,
+     * the bubble is stopped.
+     * @param {Function} fn The function to call
+     * @param {Object} scope (optional) The scope of the function (defaults to current node)
+     * @param {Array} args (optional) The args to call the function with (default to passing the current component)
+     * @return {Ext.Container} this
+     */
+    bubble : function(fn, scope, args){
+        var p = this;
+        while(p){
+            if(fn.apply(scope || p, args || [p]) === false){
+                break;
+            }
+            p = p.ownerCt;
+        }
+        return this;
+    },
+
+    /**
+     * Cascades down the component/container heirarchy from this component (called first), calling the specified function with
+     * each component. The scope (<i>this</i>) of
+     * function call will be the scope provided or the current component. The arguments to the function
+     * will be the args provided or the current component. If the function returns false at any point,
+     * the cascade is stopped on that branch.
+     * @param {Function} fn The function to call
+     * @param {Object} scope (optional) The scope of the function (defaults to current component)
+     * @param {Array} args (optional) The args to call the function with (defaults to passing the current component)
+     * @return {Ext.Container} this
+     */
+    cascade : function(fn, scope, args){
+        if(fn.apply(scope || this, args || [this]) !== false){
+            if(this.items){
+                var cs = this.items.items;
+                for(var i = 0, len = cs.length; i < len; i++){
+                    if(cs[i].cascade){
+                        cs[i].cascade(fn, scope, args);
+                    }else{
+                        fn.apply(scope || cs[i], args || [cs[i]]);
+                    }
+                }
+            }
+        }
+        return this;
+    },
+
+    /**
+     * Find a component under this container at any level by id
+     * @param {String} id
+     * @return Ext.Component
+     */
+    findById : function(id){
+        var m, ct = this;
+        this.cascade(function(c){
+            if(ct != c && c.id === id){
+                m = c;
+                return false;
+            }
+        });
+        return m || null;
+    },
+
+    /**
+     * Find a component under this container at any level by xtype or class
+     * @param {String/Class} xtype The xtype string for a component, or the class of the component directly
+     * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is
+     * the default), or true to check whether this Component is directly of the specified xtype.
+     * @return {Array} Array of Ext.Components
+     */
+    findByType : function(xtype, shallow){
+        return this.findBy(function(c){
+            return c.isXType(xtype, shallow);
+        });
+    },
+
+    /**
+     * Find a component under this container at any level by property
+     * @param {String} prop
+     * @param {String} value
+     * @return {Array} Array of Ext.Components
+     */
+    find : function(prop, value){
+        return this.findBy(function(c){
+            return c[prop] === value;
+        });
+    },
+
+    /**
+     * Find a component under this container at any level by a custom function. If the passed function returns
+     * true, the component will be included in the results. The passed function is called with the arguments (component, this container).
+     * @param {Function} fn The function to call
+     * @param {Object} scope (optional)
+     * @return {Array} Array of Ext.Components
+     */
+    findBy : function(fn, scope){
+        var m = [], ct = this;
+        this.cascade(function(c){
+            if(ct != c && fn.call(scope || c, c, ct) === true){
+                m.push(c);
+            }
+        });
+        return m;
+    },
+
+    /**
+     * Get a component contained by this container (alias for items.get(key))
+     * @param {String/Number} key The index or id of the component
+     * @return {Ext.Component} Ext.Component
+     */
+    get : function(key){
+        return this.items.get(key);
+    }
+});
+
+Ext.Container.LAYOUTS = {};
+Ext.reg('container', Ext.Container);
 /**
  * @class Ext.layout.ContainerLayout
- * <p>The ContainerLayout class is the default layout manager delegated by {@link Ext.Container} to
- * render any child Components when no <tt>{@link Ext.Container#layout layout}</tt> is configured into
- * a {@link Ext.Container Container}. ContainerLayout provides the basic foundation for all other layout
- * classes in Ext. It simply renders all child Components into the Container, performing no sizing or
- * positioning services. To utilize a layout that provides sizing and positioning of child Components,
- * specify an appropriate <tt>{@link Ext.Container#layout layout}</tt>.</p>
  * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>
  * configuration property.  See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
  */
-Ext.layout.ContainerLayout = function(config){
-    Ext.apply(this, config);
-};
-
-Ext.layout.ContainerLayout.prototype = {
+Ext.layout.ContainerLayout = Ext.extend(Object, {
     /**
      * @cfg {String} extraCls
      * <p>An optional extra CSS class that will be added to the container. This can be useful for adding
@@ -18309,11 +19138,49 @@ Ext.layout.ContainerLayout.prototype = {
     // private
     activeItem : null,
 
+    constructor : function(config){
+        this.id = Ext.id(null, 'ext-layout-');
+        Ext.apply(this, config);
+    },
+
+    type: 'container',
+
+    /* Workaround for how IE measures autoWidth elements.  It prefers bottom-up measurements
+      whereas other browser prefer top-down.  We will hide all target child elements before we measure and
+      put them back to get an accurate measurement.
+    */
+    IEMeasureHack : function(target, viewFlag) {
+        var tChildren = target.dom.childNodes, tLen = tChildren.length, c, d = [], e, i, ret;
+        for (i = 0 ; i < tLen ; i++) {
+            c = tChildren[i];
+            e = Ext.get(c);
+            if (e) {
+                d[i] = e.getStyle('display');
+                e.setStyle({display: 'none'});
+            }
+        }
+        ret = target ? target.getViewSize(viewFlag) : {};
+        for (i = 0 ; i < tLen ; i++) {
+            c = tChildren[i];
+            e = Ext.get(c);
+            if (e) {
+                e.setStyle({display: d[i]});
+            }
+        }
+        return ret;
+    },
+
+    // Placeholder for the derived layouts
+    getLayoutTargetSize : Ext.EmptyFn,
+
     // private
     layout : function(){
-        var target = this.container.getLayoutTarget();
-        this.onLayout(this.container, target);
-        this.container.fireEvent('afterlayout', this.container, this);
+        var ct = this.container, target = ct.getLayoutTarget();
+        if(!(this.hasLayout || Ext.isEmpty(this.targetCls))){
+            target.addClass(this.targetCls);
+        }
+        this.onLayout(ct, target);
+        ct.fireEvent('afterlayout', ct, this);
     },
 
     // private
@@ -18323,14 +19190,14 @@ Ext.layout.ContainerLayout.prototype = {
 
     // private
     isValidParent : function(c, target){
-               return target && c.getDomPositionEl().dom.parentNode == (target.dom || target);
+        return target && c.getPositionEl().dom.parentNode == (target.dom || target);
     },
 
     // private
     renderAll : function(ct, target){
-        var items = ct.items.items;
-        for(var i = 0, len = items.length; i < len; i++) {
-            var c = items[i];
+        var items = ct.items.items, i, c, len = items.length;
+        for(i = 0; i < len; i++) {
+            c = items[i];
             if(c && (!c.rendered || !this.isValidParent(c, target))){
                 this.renderItem(c, i, target);
             }
@@ -18339,33 +19206,48 @@ Ext.layout.ContainerLayout.prototype = {
 
     // private
     renderItem : function(c, position, target){
-        if(c && !c.rendered){
-            c.render(target, position);
-            this.configureItem(c, position);
-        }else if(c && !this.isValidParent(c, target)){
-            if(Ext.isNumber(position)){
-                position = target.dom.childNodes[position];
+        if(c){
+            if(!c.rendered){
+                c.render(target, position);
+                this.configureItem(c, position);
+            }else if(!this.isValidParent(c, target)){
+                if(Ext.isNumber(position)){
+                    position = target.dom.childNodes[position];
+                }
+                target.dom.insertBefore(c.getPositionEl().dom, position || null);
+                c.container = target;
+                this.configureItem(c, position);
             }
-            target.dom.insertBefore(c.getDomPositionEl().dom, position || null);
-            c.container = target;
-            this.configureItem(c, position);
         }
     },
-    
+
+    // private.
+    // Get all rendered items to lay out.
+    getRenderedItems: function(ct){
+        var t = ct.getLayoutTarget(), cti = ct.items.items, len = cti.length, i, c, items = [];
+        for (i = 0; i < len; i++) {
+            if((c = cti[i]).rendered && this.isValidParent(c, t)){
+                items.push(c);
+            }
+        };
+        return items;
+    },
+
     // private
     configureItem: function(c, position){
         if(this.extraCls){
             var t = c.getPositionEl ? c.getPositionEl() : c;
             t.addClass(this.extraCls);
         }
+        // If we are forcing a layout, do so *before* we hide so elements have height/width
+        if(c.doLayout && this.forceLayout){
+            c.doLayout();
+        }
         if (this.renderHidden && c != this.activeItem) {
             c.hide();
         }
-        if(c.doLayout && this.forceLayout){
-            c.doLayout(false, true);
-        }
     },
-    
+
     onRemove: function(c){
          if(this.activeItem == c){
             delete this.activeItem;
@@ -18376,11 +19258,17 @@ Ext.layout.ContainerLayout.prototype = {
         }
     },
 
+    afterRemove: function(c){
+        if(c.removeRestore){
+            c.removeMode = 'container';
+            delete c.removeRestore;
+        }
+    },
+
     // private
     onResize: function(){
         var ct = this.container,
             b;
-            
         if(ct.collapsed){
             return;
         }
@@ -18395,19 +19283,33 @@ Ext.layout.ContainerLayout.prototype = {
                 this.resizeTask.delay(this.resizeBuffer);
             }
         }else{
-            ct.doLayout();
+            this.runLayout();
         }
     },
-    
-    // private
+
     runLayout: function(){
         var ct = this.container;
+        // AutoLayout is known to require the recursive doLayout call, others need this currently (BorderLayout for example)
+        // but shouldn't.  A more extensive review will take place for 3.2 which requires a ContainerMgr with hierarchy lookups.
+        //this.layout();
+        //ct.onLayout();
         ct.doLayout();
         delete ct.layoutPending;
     },
 
     // private
     setContainer : function(ct){
+        if (!Ext.LayoutManager) {
+            Ext.LayoutManager = {};
+        }
+
+        /* This monitorResize flag will be renamed soon as to avoid confusion
+        * with the Container version which hooks onWindowResize to doLayout
+        *
+        * monitorResize flag in this context attaches the resize event between
+        * a container and it's layout
+        */
+
         if(this.monitorResize && ct != this.container){
             var old = this.container;
             if(old){
@@ -18428,15 +19330,11 @@ Ext.layout.ContainerLayout.prototype = {
         var ms = v.split(' ');
         var len = ms.length;
         if(len == 1){
-            ms[1] = ms[0];
-            ms[2] = ms[0];
-            ms[3] = ms[0];
-        }
-        if(len == 2){
+            ms[1] = ms[2] = ms[3] = ms[0];
+        } else if(len == 2){
             ms[2] = ms[0];
             ms[3] = ms[1];
-        }
-        if(len == 3){
+        } else if(len == 3){
             ms[3] = ms[1];
         }
         return {
@@ -18467,15 +19365,39 @@ Ext.layout.ContainerLayout.prototype = {
         t.disableFormats = true;
         return t.compile();
     })(),
-       
+
     /*
      * Destroys this layout. This is a template method that is empty by default, but should be implemented
      * by subclasses that require explicit destruction to purge event handlers or remove DOM nodes.
      * @protected
      */
-    destroy : Ext.emptyFn
-};
-Ext.Container.LAYOUTS['auto'] = Ext.layout.ContainerLayout;/**\r
+    destroy : function(){
+        if(!Ext.isEmpty(this.targetCls)){
+            var target = this.container.getLayoutTarget();
+            if(target){
+                target.removeClass(this.targetCls);
+            }
+        }
+    }
+});/**
+ * @class Ext.layout.AutoLayout
+ * <p>The AutoLayout is the default layout manager delegated by {@link Ext.Container} to
+ * render any child Components when no <tt>{@link Ext.Container#layout layout}</tt> is configured into
+ * a {@link Ext.Container Container}. ContainerLayout provides the basic foundation for all other layout
+ * classes in Ext. It simply renders all child Components into the Container, performing no sizing or
+ * positioning services. To utilize a layout that provides sizing and positioning of child Components,
+ * specify an appropriate <tt>{@link Ext.Container#layout layout}</tt>.</p>
+ */
+Ext.layout.AutoLayout = Ext.extend(Ext.layout.ContainerLayout, {
+    runLayout: function(){
+        var ct = this.container;
+        ct.doLayout();
+        delete ct.layoutPending;
+    }
+});
+
+Ext.Container.LAYOUTS['auto'] = Ext.layout.AutoLayout;
+/**\r
  * @class Ext.layout.FitLayout\r
  * @extends Ext.layout.ContainerLayout\r
  * <p>This is a base class for layouts that contain <b>a single item</b> that automatically expands to fill the layout's\r
@@ -18500,12 +19422,22 @@ Ext.layout.FitLayout = Ext.extend(Ext.layout.ContainerLayout, {
     // private\r
     monitorResize:true,\r
 \r
+    type: 'fit',\r
+\r
+    getLayoutTargetSize : function() {\r
+        var target = this.container.getLayoutTarget();\r
+        if (!target) {\r
+            return {};\r
+        }\r
+        // Style Sized (scrollbars not included)\r
+        return target.getStyleSize();\r
+    },\r
+\r
     // private\r
     onLayout : function(ct, target){\r
         Ext.layout.FitLayout.superclass.onLayout.call(this, ct, target);\r
-        if(!this.container.collapsed){\r
-            var sz = (Ext.isIE6 && Ext.isStrict && target.dom == document.body) ? target.getViewSize() : target.getStyleSize();\r
-            this.setItemSize(this.activeItem || ct.items.itemAt(0), sz);\r
+        if(!ct.collapsed){\r
+            this.setItemSize(this.activeItem || ct.items.itemAt(0), this.getLayoutTargetSize());\r
         }\r
     },\r
 \r
@@ -18590,7 +19522,7 @@ Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {
      * true might improve performance.\r
      */\r
     deferredRender : false,\r
-    \r
+\r
     /**\r
      * @cfg {Boolean} layoutOnCardChange\r
      * True to force a layout of the active item when the active card is changed. Defaults to false.\r
@@ -18602,10 +19534,11 @@ Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {
      */\r
     // private\r
     renderHidden : true,\r
-    \r
+\r
+    type: 'card',\r
+\r
     constructor: function(config){\r
         Ext.layout.CardLayout.superclass.constructor.call(this, config);\r
-        this.forceLayout = (this.deferredRender === false);\r
     },\r
 \r
     /**\r
@@ -18613,18 +19546,37 @@ Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {
      * @param {String/Number} item The string component id or numeric index of the item to activate\r
      */\r
     setActiveItem : function(item){\r
-        item = this.container.getComponent(item);\r
-        if(this.activeItem != item){\r
-            if(this.activeItem){\r
-                this.activeItem.hide();\r
+        var ai = this.activeItem,\r
+            ct = this.container;\r
+        item = ct.getComponent(item);\r
+\r
+        // Is this a valid, different card?\r
+        if(item && ai != item){\r
+\r
+            // Changing cards, hide the current one\r
+            if(ai){\r
+                ai.hide();\r
+                if (ai.hidden !== true) {\r
+                    return false;\r
+                }\r
+                ai.fireEvent('deactivate', ai);\r
             }\r
-            var layout = item.doLayout && (this.layoutOnCardChange || !item.rendered);\r
+            // Change activeItem reference\r
             this.activeItem = item;\r
+\r
+            // The container is about to get a recursive layout, remove any deferLayout reference\r
+            // because it will trigger a redundant layout.\r
+            delete item.deferLayout;\r
+\r
+            // Show the new component\r
             item.show();\r
+\r
             this.layout();\r
-            if(layout){\r
+\r
+            if(item.doLayout){\r
                 item.doLayout();\r
             }\r
+            item.fireEvent('activate', item);\r
         }\r
     },\r
 \r
@@ -18637,200 +19589,205 @@ Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {
         }\r
     }\r
 });\r
-Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;/**\r
- * @class Ext.layout.AnchorLayout\r
- * @extends Ext.layout.ContainerLayout\r
- * <p>This is a layout that enables anchoring of contained elements relative to the container's dimensions.\r
- * If the container is resized, all anchored items are automatically rerendered according to their\r
- * <b><tt>{@link #anchor}</tt></b> rules.</p>\r
- * <p>This class is intended to be extended or created via the layout:'anchor' {@link Ext.Container#layout}\r
- * config, and should generally not need to be created directly via the new keyword.</p>\r
- * <p>AnchorLayout does not have any direct config options (other than inherited ones). By default,\r
- * AnchorLayout will calculate anchor measurements based on the size of the container itself. However, the\r
- * container using the AnchorLayout can supply an anchoring-specific config property of <b>anchorSize</b>.\r
- * If anchorSize is specifed, the layout will use it as a virtual container for the purposes of calculating\r
- * anchor measurements based on it instead, allowing the container to be sized independently of the anchoring\r
- * logic if necessary.  For example:</p>\r
- * <pre><code>\r
-var viewport = new Ext.Viewport({\r
-    layout:'anchor',\r
-    anchorSize: {width:800, height:600},\r
-    items:[{\r
-        title:'Item 1',\r
-        html:'Content 1',\r
-        width:800,\r
-        anchor:'right 20%'\r
-    },{\r
-        title:'Item 2',\r
-        html:'Content 2',\r
-        width:300,\r
-        anchor:'50% 30%'\r
-    },{\r
-        title:'Item 3',\r
-        html:'Content 3',\r
-        width:600,\r
-        anchor:'-100 50%'\r
-    }]\r
-});\r
- * </code></pre>\r
- */\r
-Ext.layout.AnchorLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
-    /**\r
-     * @cfg {String} anchor\r
-     * <p>This configuation option is to be applied to <b>child <tt>items</tt></b> of a container managed by\r
-     * this layout (ie. configured with <tt>layout:'anchor'</tt>).</p><br/>\r
-     * \r
-     * <p>This value is what tells the layout how an item should be anchored to the container. <tt>items</tt>\r
-     * added to an AnchorLayout accept an anchoring-specific config property of <b>anchor</b> which is a string\r
-     * containing two values: the horizontal anchor value and the vertical anchor value (for example, '100% 50%').\r
-     * The following types of anchor values are supported:<div class="mdetail-params"><ul>\r
-     * \r
-     * <li><b>Percentage</b> : Any value between 1 and 100, expressed as a percentage.<div class="sub-desc">\r
-     * The first anchor is the percentage width that the item should take up within the container, and the\r
-     * second is the percentage height.  For example:<pre><code>\r
-// two values specified\r
-anchor: '100% 50%' // render item complete width of the container and\r
-                   // 1/2 height of the container\r
-// one value specified\r
-anchor: '100%'     // the width value; the height will default to auto\r
-     * </code></pre></div></li>\r
-     * \r
-     * <li><b>Offsets</b> : Any positive or negative integer value.<div class="sub-desc">\r
-     * This is a raw adjustment where the first anchor is the offset from the right edge of the container,\r
-     * and the second is the offset from the bottom edge. For example:<pre><code>\r
-// two values specified\r
-anchor: '-50 -100' // render item the complete width of the container\r
-                   // minus 50 pixels and\r
-                   // the complete height minus 100 pixels.\r
-// one value specified\r
-anchor: '-50'      // anchor value is assumed to be the right offset value\r
-                   // bottom offset will default to 0\r
-     * </code></pre></div></li>\r
-     * \r
-     * <li><b>Sides</b> : Valid values are <tt>'right'</tt> (or <tt>'r'</tt>) and <tt>'bottom'</tt>\r
-     * (or <tt>'b'</tt>).<div class="sub-desc">\r
-     * Either the container must have a fixed size or an anchorSize config value defined at render time in\r
-     * order for these to have any effect.</div></li>\r
-     *\r
-     * <li><b>Mixed</b> : <div class="sub-desc">\r
-     * Anchor values can also be mixed as needed.  For example, to render the width offset from the container\r
-     * right edge by 50 pixels and 75% of the container's height use:\r
-     * <pre><code>\r
-anchor: '-50 75%' \r
-     * </code></pre></div></li>\r
-     * \r
-     * \r
-     * </ul></div>\r
-     */\r
-    \r
-    // private\r
-    monitorResize:true,\r
-\r
-    // private\r
-    getAnchorViewSize : function(ct, target){\r
-        return target.dom == document.body ?\r
-                   target.getViewSize() : target.getStyleSize();\r
-    },\r
-\r
-    // private\r
-    onLayout : function(ct, target){\r
-        Ext.layout.AnchorLayout.superclass.onLayout.call(this, ct, target);\r
-\r
-        var size = this.getAnchorViewSize(ct, target);\r
-\r
-        var w = size.width, h = size.height;\r
-\r
-        if(w < 20 && h < 20){\r
-            return;\r
-        }\r
-\r
-        // find the container anchoring size\r
-        var aw, ah;\r
-        if(ct.anchorSize){\r
-            if(typeof ct.anchorSize == 'number'){\r
-                aw = ct.anchorSize;\r
-            }else{\r
-                aw = ct.anchorSize.width;\r
-                ah = ct.anchorSize.height;\r
-            }\r
-        }else{\r
-            aw = ct.initialConfig.width;\r
-            ah = ct.initialConfig.height;\r
-        }\r
-\r
-        var cs = ct.items.items, len = cs.length, i, c, a, cw, ch;\r
-        for(i = 0; i < len; i++){\r
-            c = cs[i];\r
-            if(c.anchor){\r
-                a = c.anchorSpec;\r
-                if(!a){ // cache all anchor values\r
-                    var vs = c.anchor.split(' ');\r
-                    c.anchorSpec = a = {\r
-                        right: this.parseAnchor(vs[0], c.initialConfig.width, aw),\r
-                        bottom: this.parseAnchor(vs[1], c.initialConfig.height, ah)\r
-                    };\r
-                }\r
-                cw = a.right ? this.adjustWidthAnchor(a.right(w), c) : undefined;\r
-                ch = a.bottom ? this.adjustHeightAnchor(a.bottom(h), c) : undefined;\r
-\r
-                if(cw || ch){\r
-                    c.setSize(cw || undefined, ch || undefined);\r
-                }\r
-            }\r
-        }\r
-    },\r
-\r
-    // private\r
-    parseAnchor : function(a, start, cstart){\r
-        if(a && a != 'none'){\r
-            var last;\r
-            if(/^(r|right|b|bottom)$/i.test(a)){   // standard anchor\r
-                var diff = cstart - start;\r
-                return function(v){\r
-                    if(v !== last){\r
-                        last = v;\r
-                        return v - diff;\r
-                    }\r
-                }\r
-            }else if(a.indexOf('%') != -1){\r
-                var ratio = parseFloat(a.replace('%', ''))*.01;   // percentage\r
-                return function(v){\r
-                    if(v !== last){\r
-                        last = v;\r
-                        return Math.floor(v*ratio);\r
-                    }\r
-                }\r
-            }else{\r
-                a = parseInt(a, 10);\r
-                if(!isNaN(a)){                            // simple offset adjustment\r
-                    return function(v){\r
-                        if(v !== last){\r
-                            last = v;\r
-                            return v + a;\r
-                        }\r
-                    }\r
-                }\r
-            }\r
-        }\r
-        return false;\r
-    },\r
-\r
-    // private\r
-    adjustWidthAnchor : function(value, comp){\r
-        return value;\r
-    },\r
-\r
-    // private\r
-    adjustHeightAnchor : function(value, comp){\r
-        return value;\r
-    }\r
-    \r
-    /**\r
-     * @property activeItem\r
-     * @hide\r
-     */\r
-});\r
-Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout;/**\r
+Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;/**
+ * @class Ext.layout.AnchorLayout
+ * @extends Ext.layout.ContainerLayout
+ * <p>This is a layout that enables anchoring of contained elements relative to the container's dimensions.
+ * If the container is resized, all anchored items are automatically rerendered according to their
+ * <b><tt>{@link #anchor}</tt></b> rules.</p>
+ * <p>This class is intended to be extended or created via the layout:'anchor' {@link Ext.Container#layout}
+ * config, and should generally not need to be created directly via the new keyword.</p>
+ * <p>AnchorLayout does not have any direct config options (other than inherited ones). By default,
+ * AnchorLayout will calculate anchor measurements based on the size of the container itself. However, the
+ * container using the AnchorLayout can supply an anchoring-specific config property of <b>anchorSize</b>.
+ * If anchorSize is specifed, the layout will use it as a virtual container for the purposes of calculating
+ * anchor measurements based on it instead, allowing the container to be sized independently of the anchoring
+ * logic if necessary.  For example:</p>
+ * <pre><code>
+var viewport = new Ext.Viewport({
+    layout:'anchor',
+    anchorSize: {width:800, height:600},
+    items:[{
+        title:'Item 1',
+        html:'Content 1',
+        width:800,
+        anchor:'right 20%'
+    },{
+        title:'Item 2',
+        html:'Content 2',
+        width:300,
+        anchor:'50% 30%'
+    },{
+        title:'Item 3',
+        html:'Content 3',
+        width:600,
+        anchor:'-100 50%'
+    }]
+});
+ * </code></pre>
+ */
+Ext.layout.AnchorLayout = Ext.extend(Ext.layout.ContainerLayout, {
+    /**
+     * @cfg {String} anchor
+     * <p>This configuation option is to be applied to <b>child <tt>items</tt></b> of a container managed by
+     * this layout (ie. configured with <tt>layout:'anchor'</tt>).</p><br/>
+     *
+     * <p>This value is what tells the layout how an item should be anchored to the container. <tt>items</tt>
+     * added to an AnchorLayout accept an anchoring-specific config property of <b>anchor</b> which is a string
+     * containing two values: the horizontal anchor value and the vertical anchor value (for example, '100% 50%').
+     * The following types of anchor values are supported:<div class="mdetail-params"><ul>
+     *
+     * <li><b>Percentage</b> : Any value between 1 and 100, expressed as a percentage.<div class="sub-desc">
+     * The first anchor is the percentage width that the item should take up within the container, and the
+     * second is the percentage height.  For example:<pre><code>
+// two values specified
+anchor: '100% 50%' // render item complete width of the container and
+                   // 1/2 height of the container
+// one value specified
+anchor: '100%'     // the width value; the height will default to auto
+     * </code></pre></div></li>
+     *
+     * <li><b>Offsets</b> : Any positive or negative integer value.<div class="sub-desc">
+     * This is a raw adjustment where the first anchor is the offset from the right edge of the container,
+     * and the second is the offset from the bottom edge. For example:<pre><code>
+// two values specified
+anchor: '-50 -100' // render item the complete width of the container
+                   // minus 50 pixels and
+                   // the complete height minus 100 pixels.
+// one value specified
+anchor: '-50'      // anchor value is assumed to be the right offset value
+                   // bottom offset will default to 0
+     * </code></pre></div></li>
+     *
+     * <li><b>Sides</b> : Valid values are <tt>'right'</tt> (or <tt>'r'</tt>) and <tt>'bottom'</tt>
+     * (or <tt>'b'</tt>).<div class="sub-desc">
+     * Either the container must have a fixed size or an anchorSize config value defined at render time in
+     * order for these to have any effect.</div></li>
+     *
+     * <li><b>Mixed</b> : <div class="sub-desc">
+     * Anchor values can also be mixed as needed.  For example, to render the width offset from the container
+     * right edge by 50 pixels and 75% of the container's height use:
+     * <pre><code>
+anchor: '-50 75%'
+     * </code></pre></div></li>
+     *
+     *
+     * </ul></div>
+     */
+
+    // private
+    monitorResize:true,
+    type: 'anchor',
+
+    getLayoutTargetSize : function() {
+        var target = this.container.getLayoutTarget();
+        if (!target) {
+            return {};
+        }
+        // Style Sized (scrollbars not included)
+        return target.getStyleSize();
+    },
+
+    // private
+    onLayout : function(ct, target){
+        Ext.layout.AnchorLayout.superclass.onLayout.call(this, ct, target);
+        var size = this.getLayoutTargetSize();
+
+        var w = size.width, h = size.height;
+
+        if(w < 20 && h < 20){
+            return;
+        }
+
+        // find the container anchoring size
+        var aw, ah;
+        if(ct.anchorSize){
+            if(typeof ct.anchorSize == 'number'){
+                aw = ct.anchorSize;
+            }else{
+                aw = ct.anchorSize.width;
+                ah = ct.anchorSize.height;
+            }
+        }else{
+            aw = ct.initialConfig.width;
+            ah = ct.initialConfig.height;
+        }
+
+        var cs = this.getRenderedItems(ct), len = cs.length, i, c, a, cw, ch, el, vs;
+        for(i = 0; i < len; i++){
+            c = cs[i];
+            el = c.getPositionEl();
+            if(c.anchor){
+                a = c.anchorSpec;
+                if(!a){ // cache all anchor values
+                    vs = c.anchor.split(' ');
+                    c.anchorSpec = a = {
+                        right: this.parseAnchor(vs[0], c.initialConfig.width, aw),
+                        bottom: this.parseAnchor(vs[1], c.initialConfig.height, ah)
+                    };
+                }
+                cw = a.right ? this.adjustWidthAnchor(a.right(w) - el.getMargins('lr'), c) : undefined;
+                ch = a.bottom ? this.adjustHeightAnchor(a.bottom(h) - el.getMargins('tb'), c) : undefined;
+
+                if(cw || ch){
+                    c.setSize(cw || undefined, ch || undefined);
+                }
+            }
+        }
+    },
+
+    // private
+    parseAnchor : function(a, start, cstart){
+        if(a && a != 'none'){
+            var last;
+            if(/^(r|right|b|bottom)$/i.test(a)){   // standard anchor
+                var diff = cstart - start;
+                return function(v){
+                    if(v !== last){
+                        last = v;
+                        return v - diff;
+                    }
+                }
+            }else if(a.indexOf('%') != -1){
+                var ratio = parseFloat(a.replace('%', ''))*.01;   // percentage
+                return function(v){
+                    if(v !== last){
+                        last = v;
+                        return Math.floor(v*ratio);
+                    }
+                }
+            }else{
+                a = parseInt(a, 10);
+                if(!isNaN(a)){                            // simple offset adjustment
+                    return function(v){
+                        if(v !== last){
+                            last = v;
+                            return v + a;
+                        }
+                    }
+                }
+            }
+        }
+        return false;
+    },
+
+    // private
+    adjustWidthAnchor : function(value, comp){
+        return value;
+    },
+
+    // private
+    adjustHeightAnchor : function(value, comp){
+        return value;
+    }
+
+    /**
+     * @property activeItem
+     * @hide
+     */
+});
+Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout;
+/**\r
  * @class Ext.layout.ColumnLayout\r
  * @extends Ext.layout.ContainerLayout\r
  * <p>This is the layout style of choice for creating structural layouts in a multi-column format where the width of\r
@@ -18859,7 +19816,7 @@ var p = new Ext.Panel({
     layout:'column',\r
     items: [{\r
         title: 'Column 1',\r
-        columnWidth: .25 \r
+        columnWidth: .25\r
     },{\r
         title: 'Column 2',\r
         columnWidth: .6\r
@@ -18891,49 +19848,66 @@ var p = new Ext.Panel({
 Ext.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
     // private\r
     monitorResize:true,\r
-    \r
+\r
+    type: 'column',\r
+\r
     extraCls: 'x-column',\r
 \r
     scrollOffset : 0,\r
 \r
     // private\r
+\r
+    targetCls: 'x-column-layout-ct',\r
+\r
     isValidParent : function(c, target){\r
-        return (c.getPositionEl ? c.getPositionEl() : c.getEl()).dom.parentNode == this.innerCt.dom;\r
+        return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;\r
     },\r
 \r
-    // private\r
-    onLayout : function(ct, target){\r
-        var cs = ct.items.items, len = cs.length, c, i;\r
+    getLayoutTargetSize : function() {\r
+        var target = this.container.getLayoutTarget(), ret;\r
+        if (target) {\r
+            ret = target.getViewSize();\r
+            ret.width -= target.getPadding('lr');\r
+            ret.height -= target.getPadding('tb');\r
+        }\r
+        return ret;\r
+    },\r
 \r
+    renderAll : function(ct, target) {\r
         if(!this.innerCt){\r
-            target.addClass('x-column-layout-ct');\r
-\r
             // the innerCt prevents wrapping and shuffling while\r
             // the container is resizing\r
             this.innerCt = target.createChild({cls:'x-column-inner'});\r
             this.innerCt.createChild({cls:'x-clear'});\r
         }\r
-        this.renderAll(ct, this.innerCt);\r
+        Ext.layout.ColumnLayout.superclass.renderAll.call(this, ct, this.innerCt);\r
+    },\r
+\r
+    // private\r
+    onLayout : function(ct, target){\r
+        var cs = ct.items.items, len = cs.length, c, i;\r
 \r
-        var size = Ext.isIE && target.dom != Ext.getBody().dom ? target.getStyleSize() : target.getViewSize();\r
+        this.renderAll(ct, target);\r
+\r
+        var size = this.getLayoutTargetSize();\r
 \r
         if(size.width < 1 && size.height < 1){ // display none?\r
             return;\r
         }\r
 \r
-        var w = size.width - target.getPadding('lr') - this.scrollOffset,\r
-            h = size.height - target.getPadding('tb'),\r
+        var w = size.width - this.scrollOffset,\r
+            h = size.height,\r
             pw = w;\r
 \r
         this.innerCt.setWidth(w);\r
-        \r
+\r
         // some columns can be percentages while others are fixed\r
         // so we need to make 2 passes\r
 \r
         for(i = 0; i < len; i++){\r
             c = cs[i];\r
             if(!c.columnWidth){\r
-                pw -= (c.getSize().width + c.getEl().getMargins('lr'));\r
+                pw -= (c.getWidth() + c.getPositionEl().getMargins('lr'));\r
             }\r
         }\r
 \r
@@ -18942,11 +19916,24 @@ Ext.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {
         for(i = 0; i < len; i++){\r
             c = cs[i];\r
             if(c.columnWidth){\r
-                c.setSize(Math.floor(c.columnWidth*pw) - c.getEl().getMargins('lr'));\r
+                c.setSize(Math.floor(c.columnWidth * pw) - c.getPositionEl().getMargins('lr'));\r
+            }\r
+        }\r
+\r
+        // Browsers differ as to when they account for scrollbars.  We need to re-measure to see if the scrollbar\r
+        // spaces were accounted for properly.  If not, re-layout.\r
+        if (Ext.isIE) {\r
+            if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {\r
+                var ts = this.getLayoutTargetSize();\r
+                if (ts.width != size.width){\r
+                    this.adjustmentPass = true;\r
+                    this.onLayout(ct, target);\r
+                }\r
             }\r
         }\r
+        delete this.adjustmentPass;\r
     }\r
-    \r
+\r
     /**\r
      * @property activeItem\r
      * @hide\r
@@ -18980,7 +19967,7 @@ var myBorderPanel = new Ext.Panel({
         {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}: 'south',     // position for region
         {@link Ext.BoxComponent#height height}: 100,
         {@link Ext.layout.BorderLayout.Region#split split}: true,         // enable resizing
-        {@link Ext.SplitBar#minSize minSize}: 75,         // defaults to {@link Ext.layout.BorderLayout.Region#minHeight 50} 
+        {@link Ext.SplitBar#minSize minSize}: 75,         // defaults to {@link Ext.layout.BorderLayout.Region#minHeight 50}
         {@link Ext.SplitBar#maxSize maxSize}: 150,
         {@link Ext.layout.BorderLayout.Region#margins margins}: '0 5 5 5'
     },{
@@ -19038,23 +20025,30 @@ Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {
     // private
     rendered : false,
 
+    type: 'border',
+
+    targetCls: 'x-border-layout-ct',
+
+    getLayoutTargetSize : function() {
+        var target = this.container.getLayoutTarget();
+        return target ? target.getViewSize() : {};
+    },
+
     // private
     onLayout : function(ct, target){
-        var collapsed;
+        var collapsed, i, c, pos, items = ct.items.items, len = items.length;
         if(!this.rendered){
-            target.addClass('x-border-layout-ct');
-            var items = ct.items.items;
             collapsed = [];
-            for(var i = 0, len = items.length; i < len; i++) {
-                var c = items[i];
-                var pos = c.region;
+            for(i = 0; i < len; i++) {
+                c = items[i];
+                pos = c.region;
                 if(c.collapsed){
                     collapsed.push(c);
                 }
                 c.collapsed = false;
                 if(!c.rendered){
                     c.render(target, i);
-                    c.getDomPositionEl().addClass('x-border-panel');
+                    c.getPositionEl().addClass('x-border-panel');
                 }
                 this[pos] = pos != 'center' && c.split ?
                     new Ext.layout.BorderLayout.SplitRegion(this, c.initialConfig, pos) :
@@ -19064,7 +20058,7 @@ Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {
             this.rendered = true;
         }
 
-        var size = target.getViewSize();
+        var size = this.getLayoutTargetSize();
         if(size.width < 20 || size.height < 20){ // display none?
             if(collapsed){
                 this.restoreCollapsed = collapsed;
@@ -19075,17 +20069,17 @@ Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {
             delete this.restoreCollapsed;
         }
 
-        var w = size.width, h = size.height;
-        var centerW = w, centerH = h, centerY = 0, centerX = 0;
-
-        var n = this.north, s = this.south, west = this.west, e = this.east, c = this.center;
+        var w = size.width, h = size.height,
+            centerW = w, centerH = h, centerY = 0, centerX = 0,
+            n = this.north, s = this.south, west = this.west, e = this.east, c = this.center,
+            b, m, totalWidth, totalHeight;
         if(!c && Ext.layout.BorderLayout.WARN !== false){
             throw 'No center region defined in BorderLayout ' + ct.id;
         }
 
         if(n && n.isVisible()){
-            var b = n.getSize();
-            var m = n.getMargins();
+            b = n.getSize();
+            m = n.getMargins();
             b.width = w - (m.left+m.right);
             b.x = m.left;
             b.y = m.top;
@@ -19094,38 +20088,38 @@ Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {
             n.applyLayout(b);
         }
         if(s && s.isVisible()){
-            var b = s.getSize();
-            var m = s.getMargins();
+            b = s.getSize();
+            m = s.getMargins();
             b.width = w - (m.left+m.right);
             b.x = m.left;
-            var totalHeight = (b.height + m.top + m.bottom);
+            totalHeight = (b.height + m.top + m.bottom);
             b.y = h - totalHeight + m.top;
             centerH -= totalHeight;
             s.applyLayout(b);
         }
         if(west && west.isVisible()){
-            var b = west.getSize();
-            var m = west.getMargins();
+            b = west.getSize();
+            m = west.getMargins();
             b.height = centerH - (m.top+m.bottom);
             b.x = m.left;
             b.y = centerY + m.top;
-            var totalWidth = (b.width + m.left + m.right);
+            totalWidth = (b.width + m.left + m.right);
             centerX += totalWidth;
             centerW -= totalWidth;
             west.applyLayout(b);
         }
         if(e && e.isVisible()){
-            var b = e.getSize();
-            var m = e.getMargins();
+            b = e.getSize();
+            m = e.getMargins();
             b.height = centerH - (m.top+m.bottom);
-            var totalWidth = (b.width + m.left + m.right);
+            totalWidth = (b.width + m.left + m.right);
             b.x = w - totalWidth + m.left;
             b.y = centerY + m.top;
             centerW -= totalWidth;
             e.applyLayout(b);
         }
         if(c){
-            var m = c.getMargins();
+            m = c.getMargins();
             var centerBox = {
                 x: centerX + m.left,
                 y: centerY + m.top,
@@ -19135,19 +20129,28 @@ Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {
             c.applyLayout(centerBox);
         }
         if(collapsed){
-            for(var i = 0, len = collapsed.length; i < len; i++){
+            for(i = 0, len = collapsed.length; i < len; i++){
                 collapsed[i].collapse(false);
             }
         }
         if(Ext.isIE && Ext.isStrict){ // workaround IE strict repainting issue
             target.repaint();
         }
+        // Putting a border layout into an overflowed container is NOT correct and will make a second layout pass necessary.
+        if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
+            var ts = this.getLayoutTargetSize();
+            if (ts.width != size.width || ts.height != size.height){
+                this.adjustmentPass = true;
+                this.onLayout(ct, target);
+            }
+        }
+        delete this.adjustmentPass;
     },
 
     destroy: function() {
-        var r = ['north', 'south', 'east', 'west'];
-        for (var i = 0; i < r.length; i++) {
-            var region = this[r[i]];
+        var r = ['north', 'south', 'east', 'west'], i, region;
+        for (i = 0; i < r.length; i++) {
+            region = this[r[i]];
             if(region){
                 if(region.destroy){
                     region.destroy();
@@ -19291,19 +20294,19 @@ Ext.layout.BorderLayout.Region.prototype = {
     collapsible : false,
     /**
      * @cfg {Boolean} split
-     * <p><tt>true</tt> to create a {@link Ext.layout.BorderLayout.SplitRegion SplitRegion} and 
+     * <p><tt>true</tt> to create a {@link Ext.layout.BorderLayout.SplitRegion SplitRegion} and
      * display a 5px wide {@link Ext.SplitBar} between this region and its neighbor, allowing the user to
      * resize the regions dynamically.  Defaults to <tt>false</tt> creating a
      * {@link Ext.layout.BorderLayout.Region Region}.</p><br>
      * <p><b>Notes</b>:</p><div class="mdetail-params"><ul>
-     * <li>this configuration option is ignored if <tt>region='center'</tt></li> 
+     * <li>this configuration option is ignored if <tt>region='center'</tt></li>
      * <li>when <tt>split == true</tt>, it is common to specify a
      * <tt>{@link Ext.SplitBar#minSize minSize}</tt> and <tt>{@link Ext.SplitBar#maxSize maxSize}</tt>
      * for the {@link Ext.BoxComponent BoxComponent} representing the region. These are not native
      * configs of {@link Ext.BoxComponent BoxComponent}, and are used only by this class.</li>
      * <li>if <tt>{@link #collapseMode} = 'mini'</tt> requires <tt>split = true</tt> to reserve space
-     * for the collapse tool</tt></li> 
-     * </ul></div> 
+     * for the collapse tool</tt></li>
+     * </ul></div>
      */
     split:false,
     /**
@@ -19317,8 +20320,8 @@ Ext.layout.BorderLayout.Region.prototype = {
      * @cfg {Number} minWidth
      * <p>The minimum allowable width in pixels for this region (defaults to <tt>50</tt>).
      * <tt>maxWidth</tt> may also be specified.</p><br>
-     * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> / 
-     * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified 
+     * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> /
+     * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified
      * <tt>minWidth</tt> / <tt>maxWidth</tt>.</p>
      */
     minWidth:50,
@@ -19326,8 +20329,8 @@ Ext.layout.BorderLayout.Region.prototype = {
      * @cfg {Number} minHeight
      * The minimum allowable height in pixels for this region (defaults to <tt>50</tt>)
      * <tt>maxHeight</tt> may also be specified.</p><br>
-     * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> / 
-     * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified 
+     * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> /
+     * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified
      * <tt>minHeight</tt> / <tt>maxHeight</tt>.</p>
      */
     minHeight:50,
@@ -19442,7 +20445,6 @@ Ext.layout.BorderLayout.Region.prototype = {
     // private
     onExpandClick : function(e){
         if(this.isSlid){
-            this.afterSlideIn();
             this.panel.expand(false);
         }else{
             this.panel.expand();
@@ -19461,7 +20463,9 @@ Ext.layout.BorderLayout.Region.prototype = {
             this.splitEl.hide();
         }
         this.getCollapsedEl().show();
-        this.panel.el.setStyle('z-index', 100);
+        var el = this.panel.getEl();
+        this.originalZIndex = el.getStyle('z-index');
+        el.setStyle('z-index', 100);
         this.isCollapsed = true;
         this.layout.layout();
     },
@@ -19480,6 +20484,9 @@ Ext.layout.BorderLayout.Region.prototype = {
 
     // private
     beforeExpand : function(animate){
+        if(this.isSlid){
+            this.afterSlideIn();
+        }
         var c = this.getCollapsedEl();
         this.el.show();
         if(this.position == 'east' || this.position == 'west'){
@@ -19499,7 +20506,7 @@ Ext.layout.BorderLayout.Region.prototype = {
             this.splitEl.show();
         }
         this.layout.layout();
-        this.panel.el.setStyle('z-index', 1);
+        this.panel.el.setStyle('z-index', this.originalZIndex);
         this.state.collapsed = false;
         this.panel.saveState();
     },
@@ -19631,6 +20638,7 @@ Ext.layout.BorderLayout.Region.prototype = {
                 };
             }
             this.el.on(this.autoHideHd);
+            this.collapsedEl.on(this.autoHideHd);
         }
     },
 
@@ -19639,6 +20647,8 @@ Ext.layout.BorderLayout.Region.prototype = {
         if(this.autoHide !== false){
             this.el.un("mouseout", this.autoHideHd.mouseout);
             this.el.un("mouseover", this.autoHideHd.mouseover);
+            this.collapsedEl.un("mouseout", this.autoHideHd.mouseout);
+            this.collapsedEl.un("mouseover", this.autoHideHd.mouseover);
         }
     },
 
@@ -19657,16 +20667,32 @@ Ext.layout.BorderLayout.Region.prototype = {
             return;
         }
         this.isSlid = true;
-        var ts = this.panel.tools;
+        var ts = this.panel.tools, dh, pc;
         if(ts && ts.toggle){
             ts.toggle.hide();
         }
         this.el.show();
+
+        // Temporarily clear the collapsed flag so we can onResize the panel on the slide
+        pc = this.panel.collapsed;
+        this.panel.collapsed = false;
+
         if(this.position == 'east' || this.position == 'west'){
+            // Temporarily clear the deferHeight flag so we can size the height on the slide
+            dh = this.panel.deferHeight;
+            this.panel.deferHeight = false;
+
             this.panel.setSize(undefined, this.collapsedEl.getHeight());
+
+            // Put the deferHeight flag back after setSize
+            this.panel.deferHeight = dh;
         }else{
             this.panel.setSize(this.collapsedEl.getWidth(), undefined);
         }
+
+        // Put the collapsed flag back after onResize
+        this.panel.collapsed = pc;
+
         this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top];
         this.el.alignTo(this.collapsedEl, this.getCollapseAnchor());
         this.el.setStyle("z-index", this.floatingZIndex+2);
@@ -19814,6 +20840,10 @@ Ext.layout.BorderLayout.Region.prototype = {
                 return [0, cm.top+cm.bottom+c.getHeight()];
             break;
         }
+    },
+
+    destroy : function(){
+        Ext.destroy(this.miniCollapsedEl, this.collapsedEl);
     }
 };
 
@@ -20046,11 +21076,8 @@ Ext.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region,
 
     // inherit docs
     destroy : function() {
-        Ext.destroy(
-            this.miniSplitEl,
-            this.split,
-            this.splitEl
-        );
+        Ext.destroy(this.miniSplitEl, this.split, this.splitEl);
+        Ext.layout.BorderLayout.SplitRegion.superclass.destroy.call(this);
     }
 });
 
@@ -20164,17 +21191,19 @@ Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {
      * @type String
      * @property labelStyle
      */
-    
+
     /**
      * @cfg {Boolean} trackLabels
      * True to show/hide the field label when the field is hidden. Defaults to <tt>false</tt>.
      */
     trackLabels: false,
-    
+
+    type: 'form',
+
 
     onRemove: function(c){
         Ext.layout.FormLayout.superclass.onRemove.call(this, c);
-        if(this.trackLabels && !this.isHide(c)){
+        if(this.trackLabels){
             c.un('show', this.onFieldShow, this);
             c.un('hide', this.onFieldHide, this);
         }
@@ -20182,7 +21211,9 @@ Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {
         var el = c.getPositionEl(),
                 ct = c.getItemCt && c.getItemCt();
         if(c.rendered && ct){
-            el.insertAfter(ct);
+            if (el && el.dom) {
+                el.insertAfter(ct);
+            }
             Ext.destroy(ct);
             Ext.destroyMembers(c, 'label', 'itemCt');
             if(c.customItemCt){
@@ -20190,7 +21221,7 @@ Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {
             }
         }
     },
-    
+
     // private
     setContainer : function(ct){
         Ext.layout.FormLayout.superclass.setContainer.call(this, ct);
@@ -20224,17 +21255,18 @@ Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {
             }
         }
     },
-    
+
+    // private
     isHide: function(c){
         return c.hideLabel || this.container.hideLabels;
     },
-    
+
     onFieldShow: function(c){
         c.getItemCt().removeClass('x-hide-' + c.hideMode);
     },
-    
+
     onFieldHide: function(c){
-        c.getItemCt().addClass('x-hide-' + c.hideMode);   
+        c.getItemCt().addClass('x-hide-' + c.hideMode);
     },
 
     //private
@@ -20297,11 +21329,6 @@ new Ext.Template(
             }else{
                 c.itemCt = this.fieldTpl.append(target, args, true);
             }
-            if(!c.rendered){
-                c.render('x-form-el-' + c.id);
-            }else if(!this.isValidParent(c, target)){
-                Ext.fly('x-form-el-' + c.id).appendChild(c.getPositionEl());
-            }
             if(!c.getItemCt){
                 // Non form fields don't have getItemCt, apply it here
                 // This will get cleaned up in onRemove
@@ -20313,7 +21340,12 @@ new Ext.Template(
                 });
             }
             c.label = c.getItemCt().child('label.x-form-item-label');
-            if(this.trackLabels && !this.isHide(c)){
+            if(!c.rendered){
+                c.render('x-form-el-' + c.id);
+            }else if(!this.isValidParent(c, target)){
+                Ext.fly('x-form-el-' + c.id).appendChild(c.getPositionEl());
+            }
+            if(this.trackLabels){
                 if(c.hidden){
                     this.onFieldHide(c);
                 }
@@ -20351,7 +21383,7 @@ new Ext.Template(
      * <li><b><tt>clearCls</tt></b> : String<div class="sub-desc">The CSS class to apply to the special clearing div
      * rendered directly after each form field wrapper (defaults to <tt>'x-form-clear-left'</tt>)</div></li>
      * </ul></div>
-     * @param field The {@link Field Ext.form.Field} being rendered.
+     * @param (Ext.form.Field} field The {@link Ext.form.Field Field} being rendered.
      * @return An object hash containing the properties required to render the Field.
      */
     getTemplateArgs: function(field) {
@@ -20375,7 +21407,7 @@ new Ext.Template(
         }
         return value;
     },
-    
+
     adjustHeightAnchor : function(value, c){
         if(c.label && !this.isHide(c) && (this.container.labelAlign == 'top')){
             return value - c.label.getHeight();
@@ -20385,7 +21417,7 @@ new Ext.Template(
 
     // private
     isValidParent : function(c, target){
-        return target && this.container.getEl().contains(c.getDomPositionEl());
+        return target && this.container.getEl().contains(c.getPositionEl());
     }
 
     /**
@@ -20394,7 +21426,8 @@ new Ext.Template(
      */
 });
 
-Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;/**\r
+Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;
+/**\r
  * @class Ext.layout.AccordionLayout\r
  * @extends Ext.layout.FitLayout\r
  * <p>This is a layout that manages multiple Panels in an expandable accordion style such that only\r
@@ -20482,6 +21515,8 @@ Ext.layout.AccordionLayout = Ext.extend(Ext.layout.FitLayout, {
      */\r
     activeOnTop : false,\r
 \r
+    type: 'accordion',\r
+\r
     renderItem : function(c){\r
         if(this.animate === false){\r
             c.animCollapse = false;\r
@@ -20500,7 +21535,7 @@ Ext.layout.AccordionLayout = Ext.extend(Ext.layout.FitLayout, {
             c.collapseFirst = this.collapseFirst;\r
         }\r
         if(!this.activeItem && !c.collapsed){\r
-            this.activeItem = c;\r
+            this.setActiveItem(c, true);\r
         }else if(this.activeItem && this.activeItem != c){\r
             c.collapsed = true;\r
         }\r
@@ -20508,7 +21543,7 @@ Ext.layout.AccordionLayout = Ext.extend(Ext.layout.FitLayout, {
         c.header.addClass('x-accordion-hd');\r
         c.on('beforeexpand', this.beforeExpand, this);\r
     },\r
-    \r
+\r
     onRemove: function(c){\r
         Ext.layout.AccordionLayout.superclass.onRemove.call(this, c);\r
         if(c.rendered){\r
@@ -20533,23 +21568,28 @@ Ext.layout.AccordionLayout = Ext.extend(Ext.layout.FitLayout, {
                 ai.collapse(this.animate);\r
             }\r
         }\r
-        this.activeItem = p;\r
+        this.setActive(p);\r
         if(this.activeOnTop){\r
             p.el.dom.parentNode.insertBefore(p.el.dom, p.el.dom.parentNode.firstChild);\r
         }\r
+        // Items have been hidden an possibly rearranged, we need to get the container size again.\r
         this.layout();\r
     },\r
 \r
     // private\r
     setItemSize : function(item, size){\r
         if(this.fill && item){\r
-            var hh = 0;\r
-            this.container.items.each(function(p){\r
-                if(p != item){\r
+            var hh = 0, i, ct = this.getRenderedItems(this.container), len = ct.length, p;\r
+            // Add up all the header heights\r
+            for (i = 0; i < len; i++) {\r
+                if((p = ct[i]) != item){\r
                     hh += p.header.getHeight();\r
-                }    \r
-            });\r
+                }\r
+            };\r
+            // Subtract the header heights from the container size\r
             size.height -= hh;\r
+            // Call setSize on the container to set the correct height.  For Panels, deferedHeight\r
+            // will simply store this size for when the expansion is done.\r
             item.setSize(size);\r
         }\r
     },\r
@@ -20559,15 +21599,24 @@ Ext.layout.AccordionLayout = Ext.extend(Ext.layout.FitLayout, {
      * @param {String/Number} item The string component id or numeric index of the item to activate\r
      */\r
     setActiveItem : function(item){\r
+        this.setActive(item, true);\r
+    },\r
+\r
+    // private\r
+    setActive : function(item, expand){\r
+        var ai = this.activeItem;\r
         item = this.container.getComponent(item);\r
-        if(this.activeItem != item){\r
-            if(item.rendered && item.collapsed){\r
+        if(ai != item){\r
+            if(item.rendered && item.collapsed && expand){\r
                 item.expand();\r
             }else{\r
+                if(ai){\r
+                   ai.fireEvent('deactivate', ai);\r
+                }\r
                 this.activeItem = item;\r
+                item.fireEvent('activate', item);\r
             }\r
         }\r
-\r
     }\r
 });\r
 Ext.Container.LAYOUTS.accordion = Ext.layout.AccordionLayout;\r
@@ -20642,6 +21691,10 @@ Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {
     // private\r
     monitorResize:false,\r
 \r
+    type: 'table',\r
+\r
+    targetCls: 'x-table-layout-ct',\r
+\r
     /**\r
      * @cfg {Object} tableAttrs\r
      * <p>An object containing properties which are added to the {@link Ext.DomHelper DomHelper} specification\r
@@ -20651,16 +21704,16 @@ Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {
     layout: 'table',\r
     layoutConfig: {\r
         tableAttrs: {\r
-               style: {\r
-                       width: '100%'\r
-               }\r
+            style: {\r
+                width: '100%'\r
+            }\r
         },\r
         columns: 3\r
     }\r
 }</code></pre>\r
      */\r
     tableAttrs:null,\r
-    \r
+\r
     // private\r
     setContainer : function(ct){\r
         Ext.layout.TableLayout.superclass.setContainer.call(this, ct);\r
@@ -20669,7 +21722,7 @@ Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {
         this.currentColumn = 0;\r
         this.cells = [];\r
     },\r
-\r
+    \r
     // private\r
     onLayout : function(ct, target){\r
         var cs = ct.items.items, len = cs.length, c, i;\r
@@ -20723,7 +21776,7 @@ Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {
         this.getRow(curRow).appendChild(td);\r
         return td;\r
     },\r
-    \r
+\r
     // private\r
     getNextNonSpan: function(colIndex, rowIndex){\r
         var cols = this.columns;\r
@@ -20740,12 +21793,17 @@ Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {
 \r
     // private\r
     renderItem : function(c, position, target){\r
+        // Ensure we have our inner table to get cells to render into.\r
+        if(!this.table){\r
+            this.table = target.createChild(\r
+                Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);\r
+        }\r
         if(c && !c.rendered){\r
             c.render(this.getNextCell(c));\r
             this.configureItem(c, position);\r
         }else if(c && !this.isValidParent(c, target)){\r
             var container = this.getNextCell(c);\r
-            container.insertBefore(c.getDomPositionEl().dom, null);\r
+            container.insertBefore(c.getPositionEl().dom, null);\r
             c.container = Ext.get(container);\r
             this.configureItem(c, position);\r
         }\r
@@ -20753,7 +21811,7 @@ Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {
 \r
     // private\r
     isValidParent : function(c, target){\r
-        return c.getDomPositionEl().up('table', 5).dom.parentNode === (target.dom || target);\r
+        return c.getPositionEl().up('table', 5).dom.parentNode === (target.dom || target);\r
     }\r
 \r
     /**\r
@@ -20762,615 +21820,1000 @@ Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {
      */\r
 });\r
 \r
-Ext.Container.LAYOUTS['table'] = Ext.layout.TableLayout;/**\r
- * @class Ext.layout.AbsoluteLayout\r
- * @extends Ext.layout.AnchorLayout\r
- * <p>This is a layout that inherits the anchoring of <b>{@link Ext.layout.AnchorLayout}</b> and adds the\r
- * ability for x/y positioning using the standard x and y component config options.</p>\r
- * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>\r
- * configuration property.  See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>\r
- * <p>Example usage:</p>\r
- * <pre><code>\r
-var form = new Ext.form.FormPanel({\r
-    title: 'Absolute Layout',\r
-    layout:'absolute',\r
-    layoutConfig: {\r
-        // layout-specific configs go here\r
-        extraCls: 'x-abs-layout-item',\r
-    },\r
-    baseCls: 'x-plain',\r
-    url:'save-form.php',\r
-    defaultType: 'textfield',\r
-    items: [{\r
-        x: 0,\r
-        y: 5,\r
-        xtype:'label',\r
-        text: 'Send To:'\r
-    },{\r
-        x: 60,\r
-        y: 0,\r
-        name: 'to',\r
-        anchor:'100%'  // anchor width by percentage\r
-    },{\r
-        x: 0,\r
-        y: 35,\r
-        xtype:'label',\r
-        text: 'Subject:'\r
-    },{\r
-        x: 60,\r
-        y: 30,\r
-        name: 'subject',\r
-        anchor: '100%'  // anchor width by percentage\r
-    },{\r
-        x:0,\r
-        y: 60,\r
-        xtype: 'textarea',\r
-        name: 'msg',\r
-        anchor: '100% 100%'  // anchor width and height\r
-    }]\r
-});\r
-</code></pre>\r
- */\r
-Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {\r
-\r
-    extraCls: 'x-abs-layout-item',\r
-\r
-    onLayout : function(ct, target){\r
-        target.position();\r
-        this.paddingLeft = target.getPadding('l');\r
-        this.paddingTop = target.getPadding('t');\r
-\r
-        Ext.layout.AbsoluteLayout.superclass.onLayout.call(this, ct, target);\r
-    },\r
-\r
-    // private\r
-    adjustWidthAnchor : function(value, comp){\r
-        return value ? value - comp.getPosition(true)[0] + this.paddingLeft : value;\r
-    },\r
-\r
-    // private\r
-    adjustHeightAnchor : function(value, comp){\r
-        return  value ? value - comp.getPosition(true)[1] + this.paddingTop : value;\r
-    }\r
-    /**\r
-     * @property activeItem\r
-     * @hide\r
-     */\r
-});\r
+Ext.Container.LAYOUTS['table'] = Ext.layout.TableLayout;/**
+ * @class Ext.layout.AbsoluteLayout
+ * @extends Ext.layout.AnchorLayout
+ * <p>This is a layout that inherits the anchoring of <b>{@link Ext.layout.AnchorLayout}</b> and adds the
+ * ability for x/y positioning using the standard x and y component config options.</p>
+ * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>
+ * configuration property.  See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
+ * <p>Example usage:</p>
+ * <pre><code>
+var form = new Ext.form.FormPanel({
+    title: 'Absolute Layout',
+    layout:'absolute',
+    layoutConfig: {
+        // layout-specific configs go here
+        extraCls: 'x-abs-layout-item',
+    },
+    baseCls: 'x-plain',
+    url:'save-form.php',
+    defaultType: 'textfield',
+    items: [{
+        x: 0,
+        y: 5,
+        xtype:'label',
+        text: 'Send To:'
+    },{
+        x: 60,
+        y: 0,
+        name: 'to',
+        anchor:'100%'  // anchor width by percentage
+    },{
+        x: 0,
+        y: 35,
+        xtype:'label',
+        text: 'Subject:'
+    },{
+        x: 60,
+        y: 30,
+        name: 'subject',
+        anchor: '100%'  // anchor width by percentage
+    },{
+        x:0,
+        y: 60,
+        xtype: 'textarea',
+        name: 'msg',
+        anchor: '100% 100%'  // anchor width and height
+    }]
+});
+</code></pre>
+ */
+Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {
+
+    extraCls: 'x-abs-layout-item',
+
+    type: 'anchor',
+
+    onLayout : function(ct, target){
+        target.position();
+        this.paddingLeft = target.getPadding('l');
+        this.paddingTop = target.getPadding('t');
+        Ext.layout.AbsoluteLayout.superclass.onLayout.call(this, ct, target);
+    },
+
+    // private
+    adjustWidthAnchor : function(value, comp){
+        return value ? value - comp.getPosition(true)[0] + this.paddingLeft : value;
+    },
+
+    // private
+    adjustHeightAnchor : function(value, comp){
+        return  value ? value - comp.getPosition(true)[1] + this.paddingTop : value;
+    }
+    /**
+     * @property activeItem
+     * @hide
+     */
+});
 Ext.Container.LAYOUTS['absolute'] = Ext.layout.AbsoluteLayout;
-/**\r
- * @class Ext.layout.BoxLayout\r
- * @extends Ext.layout.ContainerLayout\r
- * <p>Base Class for HBoxLayout and VBoxLayout Classes. Generally it should not need to be used directly.</p>\r
- */\r
-Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
-    /**\r
-     * @cfg {Object} defaultMargins\r
-     * <p>If the individual contained items do not have a <tt>margins</tt>\r
-     * property specified, the default margins from this property will be\r
-     * applied to each item.</p>\r
-     * <br><p>This property may be specified as an object containing margins\r
-     * to apply in the format:</p><pre><code>\r
-{\r
-    top: (top margin),\r
-    right: (right margin),\r
-    bottom: (bottom margin),\r
-    left: (left margin)\r
-}</code></pre>\r
-     * <p>This property may also be specified as a string containing\r
-     * space-separated, numeric margin values. The order of the sides associated\r
-     * with each value matches the way CSS processes margin values:</p>\r
-     * <div class="mdetail-params"><ul>\r
-     * <li>If there is only one value, it applies to all sides.</li>\r
-     * <li>If there are two values, the top and bottom borders are set to the\r
-     * first value and the right and left are set to the second.</li>\r
-     * <li>If there are three values, the top is set to the first value, the left\r
-     * and right are set to the second, and the bottom is set to the third.</li>\r
-     * <li>If there are four values, they apply to the top, right, bottom, and\r
-     * left, respectively.</li>\r
-     * </ul></div>\r
-     * <p>Defaults to:</p><pre><code>\r
-     * {top:0, right:0, bottom:0, left:0}\r
-     * </code></pre>\r
-     */\r
-    defaultMargins : {left:0,top:0,right:0,bottom:0},\r
-    /**\r
-     * @cfg {String} padding\r
-     * <p>Sets the padding to be applied to all child items managed by this layout.</p> \r
-     * <p>This property must be specified as a string containing\r
-     * space-separated, numeric padding values. The order of the sides associated\r
-     * with each value matches the way CSS processes padding values:</p>\r
-     * <div class="mdetail-params"><ul>\r
-     * <li>If there is only one value, it applies to all sides.</li>\r
-     * <li>If there are two values, the top and bottom borders are set to the\r
-     * first value and the right and left are set to the second.</li>\r
-     * <li>If there are three values, the top is set to the first value, the left\r
-     * and right are set to the second, and the bottom is set to the third.</li>\r
-     * <li>If there are four values, they apply to the top, right, bottom, and\r
-     * left, respectively.</li>\r
-     * </ul></div>\r
-     * <p>Defaults to: <code>"0"</code></p>\r
-     */\r
-    padding : '0',\r
-    // documented in subclasses\r
-    pack : 'start',\r
-\r
-    // private\r
-    monitorResize : true,\r
-    scrollOffset : 0,\r
-    extraCls : 'x-box-item',\r
-    ctCls : 'x-box-layout-ct',\r
-    innerCls : 'x-box-inner',\r
-    \r
-    constructor : function(config){\r
-        Ext.layout.BoxLayout.superclass.constructor.call(this, config);\r
-        if(Ext.isString(this.defaultMargins)){\r
-            this.defaultMargins = this.parseMargins(this.defaultMargins);\r
-        }\r
-    },\r
-\r
-    // private\r
-    isValidParent : function(c, target){\r
-        return c.getEl().dom.parentNode == this.innerCt.dom;\r
-    },\r
-\r
-    // private\r
-    onLayout : function(ct, target){\r
-        var cs = ct.items.items, len = cs.length, c, i, last = len-1, cm;\r
-\r
-        if(!this.innerCt){\r
-            target.addClass(this.ctCls);\r
-\r
-            // the innerCt prevents wrapping and shuffling while\r
-            // the container is resizing\r
-            this.innerCt = target.createChild({cls:this.innerCls});\r
-            this.padding = this.parseMargins(this.padding); \r
-        }\r
-        this.renderAll(ct, this.innerCt);\r
-    },\r
-\r
-    // private\r
-    renderItem : function(c){\r
-        if(Ext.isString(c.margins)){\r
-            c.margins = this.parseMargins(c.margins);\r
-        }else if(!c.margins){\r
-            c.margins = this.defaultMargins;\r
-        }\r
-        Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments);\r
-    },\r
-\r
-    getTargetSize : function(target){
-        return (Ext.isIE6 && Ext.isStrict && target.dom == document.body) ? target.getStyleSize() : target.getViewSize();\r
-    },\r
-    \r
-    getItems: function(ct){\r
-        var items = [];\r
-        ct.items.each(function(c){\r
-            if(c.isVisible()){\r
-                items.push(c);\r
-            }\r
-        });\r
-        return items;\r
-    }\r
-\r
-    /**\r
-     * @property activeItem\r
-     * @hide\r
-     */\r
-});\r
-\r
-/**\r
- * @class Ext.layout.VBoxLayout\r
- * @extends Ext.layout.BoxLayout\r
- * <p>A layout that arranges items vertically down a Container. This layout optionally divides available vertical\r
- * space between child items containing a numeric <code>flex</code> configuration.</p>\r
- * This layout may also be used to set the widths of child items by configuring it with the {@link #align} option.\r
- */\r
-Ext.layout.VBoxLayout = Ext.extend(Ext.layout.BoxLayout, {\r
-    /**\r
-     * @cfg {String} align\r
-     * Controls how the child items of the container are aligned. Acceptable configuration values for this\r
-     * property are:\r
-     * <div class="mdetail-params"><ul>\r
-     * <li><b><tt>left</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned horizontally\r
-     * at the <b>left</b> side of the container</div></li>\r
-     * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are aligned horizontally at the\r
-     * <b>mid-width</b> of the container</div></li>\r
-     * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched horizontally to fill\r
-     * the width of the container</div></li>\r
-     * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched horizontally to\r
-     * the size of the largest item.</div></li>\r
-     * </ul></div>\r
-     */\r
-    align : 'left', // left, center, stretch, strechmax\r
-    /**\r
-     * @cfg {String} pack\r
-     * Controls how the child items of the container are packed together. Acceptable configuration values\r
-     * for this property are:\r
-     * <div class="mdetail-params"><ul>\r
-     * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at\r
-     * <b>top</b> side of container</div></li>\r
-     * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at\r
-     * <b>mid-height</b> of container</div></li>\r
-     * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>bottom</b>\r
-     * side of container</div></li>\r
-     * </ul></div>\r
-     */\r
-    /**\r
-     * @cfg {Number} flex\r
-     * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed\r
-     * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>vertically</b>\r
-     * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with\r
-     * a <tt>flex</tt> value specified.  Any child items that have either a <tt>flex = 0</tt> or\r
-     * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).\r
-     */\r
-\r
-    // private\r
-    onLayout : function(ct, target){\r
-        Ext.layout.VBoxLayout.superclass.onLayout.call(this, ct, target);\r
-                    \r
-        \r
-        var cs = this.getItems(ct), cm, ch, margin,\r
-            size = this.getTargetSize(target),\r
-            w = size.width - target.getPadding('lr'),\r
-            h = size.height - target.getPadding('tb') - this.scrollOffset,\r
-            l = this.padding.left, t = this.padding.top,\r
-            isStart = this.pack == 'start',\r
-            isRestore = ['stretch', 'stretchmax'].indexOf(this.align) == -1,\r
-            stretchWidth = w - (this.padding.left + this.padding.right),\r
-            extraHeight = 0,\r
-            maxWidth = 0,\r
-            totalFlex = 0,\r
-            flexHeight = 0,\r
-            usedHeight = 0;\r
-            \r
-        Ext.each(cs, function(c){\r
-            cm = c.margins;\r
-            totalFlex += c.flex || 0;\r
-            ch = c.getHeight();\r
-            margin = cm.top + cm.bottom;\r
-            extraHeight += ch + margin;\r
-            flexHeight += margin + (c.flex ? 0 : ch);\r
-            maxWidth = Math.max(maxWidth, c.getWidth() + cm.left + cm.right);\r
-        });\r
-        extraHeight = h - extraHeight - this.padding.top - this.padding.bottom;\r
-        \r
-        var innerCtWidth = maxWidth + this.padding.left + this.padding.right;\r
-        switch(this.align){\r
-            case 'stretch':\r
-                this.innerCt.setSize(w, h);\r
-                break;\r
-            case 'stretchmax':\r
-            case 'left':\r
-                this.innerCt.setSize(innerCtWidth, h);\r
-                break;\r
-            case 'center':\r
-                this.innerCt.setSize(w = Math.max(w, innerCtWidth), h);\r
-                break;\r
-        }\r
-\r
-        var availHeight = Math.max(0, h - this.padding.top - this.padding.bottom - flexHeight),\r
-            leftOver = availHeight,\r
-            heights = [],\r
-            restore = [],\r
-            idx = 0,\r
-            availableWidth = Math.max(0, w - this.padding.left - this.padding.right);\r
-            \r
-\r
-        Ext.each(cs, function(c){\r
-            if(isStart && c.flex){\r
-                ch = Math.floor(availHeight * (c.flex / totalFlex));\r
-                leftOver -= ch;\r
-                heights.push(ch);\r
-            }\r
-        }); \r
-        \r
-        if(this.pack == 'center'){\r
-            t += extraHeight ? extraHeight / 2 : 0;\r
-        }else if(this.pack == 'end'){\r
-            t += extraHeight;\r
-        }\r
-        Ext.each(cs, function(c){\r
-            cm = c.margins;\r
-            t += cm.top;\r
-            c.setPosition(l + cm.left, t);\r
-            if(isStart && c.flex){\r
-                ch = Math.max(0, heights[idx++] + (leftOver-- > 0 ? 1 : 0));\r
-                if(isRestore){\r
-                    restore.push(c.getWidth());\r
-                }\r
-                c.setSize(availableWidth, ch);\r
-            }else{\r
-                ch = c.getHeight();\r
-            }\r
-            t += ch + cm.bottom;\r
-        });\r
-        \r
-        idx = 0;\r
-        Ext.each(cs, function(c){\r
-            cm = c.margins;\r
-            if(this.align == 'stretch'){\r
-                c.setWidth((stretchWidth - (cm.left + cm.right)).constrain(\r
-                    c.minWidth || 0, c.maxWidth || 1000000));\r
-            }else if(this.align == 'stretchmax'){\r
-                c.setWidth((maxWidth - (cm.left + cm.right)).constrain(\r
-                    c.minWidth || 0, c.maxWidth || 1000000));\r
-            }else{\r
-                if(this.align == 'center'){\r
-                    var diff = availableWidth - (c.getWidth() + cm.left + cm.right);\r
-                    if(diff > 0){\r
-                        c.setPosition(l + cm.left + (diff/2), c.y);\r
-                    }\r
-                }\r
-                if(isStart && c.flex){\r
-                    c.setWidth(restore[idx++]);\r
-                }\r
-            }\r
-        }, this);\r
-    }\r
-    /**\r
-     * @property activeItem\r
-     * @hide\r
-     */\r
-});\r
-\r
-Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout;\r
-\r
-/**\r
- * @class Ext.layout.HBoxLayout\r
- * @extends Ext.layout.BoxLayout\r
- * <p>A layout that arranges items horizontally across a Container. This layout optionally divides available horizontal\r
- * space between child items containing a numeric <code>flex</code> configuration.</p>\r
- * This layout may also be used to set the heights of child items by configuring it with the {@link #align} option.\r
- */\r
-Ext.layout.HBoxLayout = Ext.extend(Ext.layout.BoxLayout, {\r
-    /**\r
-     * @cfg {String} align\r
-     * Controls how the child items of the container are aligned. Acceptable configuration values for this\r
-     * property are:\r
-     * <div class="mdetail-params"><ul>\r
-     * <li><b><tt>top</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned vertically\r
-     * at the <b>left</b> side of the container</div></li>\r
-     * <li><b><tt>middle</tt></b> : <div class="sub-desc">child items are aligned vertically at the\r
-     * <b>mid-height</b> of the container</div></li>\r
-     * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched vertically to fill\r
-     * the height of the container</div></li>\r
-     * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched vertically to\r
-     * the size of the largest item.</div></li>\r
-     */\r
-    align : 'top', // top, middle, stretch, strechmax\r
-    /**\r
-     * @cfg {String} pack\r
-     * Controls how the child items of the container are packed together. Acceptable configuration values\r
-     * for this property are:\r
-     * <div class="mdetail-params"><ul>\r
-     * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at\r
-     * <b>left</b> side of container</div></li>\r
-     * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at\r
-     * <b>mid-width</b> of container</div></li>\r
-     * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>right</b>\r
-     * side of container</div></li>\r
-     * </ul></div>\r
-     */\r
-    /**\r
-     * @cfg {Number} flex\r
-     * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed\r
-     * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>horizontally</b>\r
-     * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with\r
-     * a <tt>flex</tt> value specified.  Any child items that have either a <tt>flex = 0</tt> or\r
-     * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).\r
-     */\r
-\r
-    // private\r
-    onLayout : function(ct, target){\r
-        Ext.layout.HBoxLayout.superclass.onLayout.call(this, ct, target);\r
-        \r
-        var cs = this.getItems(ct), cm, cw, margin,\r
-            size = this.getTargetSize(target),\r
-            w = size.width - target.getPadding('lr') - this.scrollOffset,\r
-            h = size.height - target.getPadding('tb'),\r
-            l = this.padding.left, t = this.padding.top,\r
-            isStart = this.pack == 'start',\r
-            isRestore = ['stretch', 'stretchmax'].indexOf(this.align) == -1,\r
-            stretchHeight = h - (this.padding.top + this.padding.bottom),\r
-            extraWidth = 0,\r
-            maxHeight = 0,\r
-            totalFlex = 0,\r
-            flexWidth = 0,\r
-            usedWidth = 0;\r
-        \r
-        Ext.each(cs, function(c){\r
-            cm = c.margins;\r
-            totalFlex += c.flex || 0;\r
-            cw = c.getWidth();\r
-            margin = cm.left + cm.right;\r
-            extraWidth += cw + margin;\r
-            flexWidth += margin + (c.flex ? 0 : cw);\r
-            maxHeight = Math.max(maxHeight, c.getHeight() + cm.top + cm.bottom);\r
-        });\r
-        extraWidth = w - extraWidth - this.padding.left - this.padding.right;\r
-        \r
-        var innerCtHeight = maxHeight + this.padding.top + this.padding.bottom;\r
-        switch(this.align){\r
-            case 'stretch':\r
-                this.innerCt.setSize(w, h);\r
-                break;\r
-            case 'stretchmax':\r
-            case 'top':\r
-                this.innerCt.setSize(w, innerCtHeight);\r
-                break;\r
-            case 'middle':\r
-                this.innerCt.setSize(w, h = Math.max(h, innerCtHeight));\r
-                break;\r
-        }\r
-        \r
-\r
-        var availWidth = Math.max(0, w - this.padding.left - this.padding.right - flexWidth),\r
-            leftOver = availWidth,\r
-            widths = [],\r
-            restore = [],\r
-            idx = 0,\r
-            availableHeight = Math.max(0, h - this.padding.top - this.padding.bottom);\r
-            \r
-\r
-        Ext.each(cs, function(c){\r
-            if(isStart && c.flex){\r
-                cw = Math.floor(availWidth * (c.flex / totalFlex));\r
-                leftOver -= cw;\r
-                widths.push(cw);\r
-            }\r
-        }); \r
-        \r
-        if(this.pack == 'center'){\r
-            l += extraWidth ? extraWidth / 2 : 0;\r
-        }else if(this.pack == 'end'){\r
-            l += extraWidth;\r
-        }\r
-        Ext.each(cs, function(c){\r
-            cm = c.margins;\r
-            l += cm.left;\r
-            c.setPosition(l, t + cm.top);\r
-            if(isStart && c.flex){\r
-                cw = Math.max(0, widths[idx++] + (leftOver-- > 0 ? 1 : 0));\r
-                if(isRestore){\r
-                    restore.push(c.getHeight());\r
-                }\r
-                c.setSize(cw, availableHeight);\r
-            }else{\r
-                cw = c.getWidth();\r
-            }\r
-            l += cw + cm.right;\r
-        });\r
-        \r
-        idx = 0;\r
-        Ext.each(cs, function(c){\r
-            var cm = c.margins;\r
-            if(this.align == 'stretch'){\r
-                c.setHeight((stretchHeight - (cm.top + cm.bottom)).constrain(\r
-                    c.minHeight || 0, c.maxHeight || 1000000));\r
-            }else if(this.align == 'stretchmax'){\r
-                c.setHeight((maxHeight - (cm.top + cm.bottom)).constrain(\r
-                    c.minHeight || 0, c.maxHeight || 1000000));\r
-            }else{\r
-                if(this.align == 'middle'){\r
-                    var diff = availableHeight - (c.getHeight() + cm.top + cm.bottom);\r
-                    if(diff > 0){\r
-                        c.setPosition(c.x, t + cm.top + (diff/2));\r
-                    }\r
-                }\r
-                if(isStart && c.flex){\r
-                    c.setHeight(restore[idx++]);\r
-                }\r
-            }\r
-        }, this);\r
-    }\r
-\r
-    /**\r
-     * @property activeItem\r
-     * @hide\r
-     */\r
-});\r
-\r
-Ext.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout;
-/**\r
- * @class Ext.Viewport\r
- * @extends Ext.Container\r
- * <p>A specialized container representing the viewable application area (the browser viewport).</p>\r
- * <p>The Viewport renders itself to the document body, and automatically sizes itself to the size of\r
- * the browser viewport and manages window resizing. There may only be one Viewport created\r
- * in a page. Inner layouts are available by virtue of the fact that all {@link Ext.Panel Panel}s\r
- * added to the Viewport, either through its {@link #items}, or through the items, or the {@link #add}\r
- * method of any of its child Panels may themselves have a layout.</p>\r
- * <p>The Viewport does not provide scrolling, so child Panels within the Viewport should provide\r
- * for scrolling if needed using the {@link #autoScroll} config.</p>\r
- * <p>An example showing a classic application border layout:</p><pre><code>\r
-new Ext.Viewport({\r
-    layout: 'border',\r
-    items: [{\r
-        region: 'north',\r
-        html: '&lt;h1 class="x-panel-header">Page Title&lt;/h1>',\r
-        autoHeight: true,\r
-        border: false,\r
-        margins: '0 0 5 0'\r
-    }, {\r
-        region: 'west',\r
-        collapsible: true,\r
-        title: 'Navigation',\r
-        width: 200\r
-        // the west region might typically utilize a {@link Ext.tree.TreePanel TreePanel} or a Panel with {@link Ext.layout.AccordionLayout Accordion layout} \r
-    }, {\r
-        region: 'south',\r
-        title: 'Title for Panel',\r
-        collapsible: true,\r
-        html: 'Information goes here',\r
-        split: true,\r
-        height: 100,\r
-        minHeight: 100\r
-    }, {\r
-        region: 'east',\r
-        title: 'Title for the Grid Panel',\r
-        collapsible: true,\r
-        split: true,\r
-        width: 200,\r
-        xtype: 'grid',\r
-        // remaining grid configuration not shown ...\r
-        // notice that the GridPanel is added directly as the region\r
-        // it is not "overnested" inside another Panel\r
-    }, {\r
-        region: 'center',\r
-        xtype: 'tabpanel', // TabPanel itself has no title\r
-        items: {\r
-            title: 'Default Tab',\r
-            html: 'The first tab\'s content. Others may be added dynamically'\r
-        }\r
-    }]\r
-});\r
-</code></pre>\r
- * @constructor\r
- * Create a new Viewport\r
- * @param {Object} config The config object\r
- * @xtype viewport\r
- */\r
-Ext.Viewport = Ext.extend(Ext.Container, {\r
-       /*\r
-        * Privatize config options which, if used, would interfere with the\r
-        * correct operation of the Viewport as the sole manager of the\r
-        * layout of the document body.\r
-        */\r
-    /**\r
-     * @cfg {Mixed} applyTo @hide\r
-        */\r
-    /**\r
-     * @cfg {Boolean} allowDomMove @hide\r
-        */\r
-    /**\r
-     * @cfg {Boolean} hideParent @hide\r
-        */\r
-    /**\r
-     * @cfg {Mixed} renderTo @hide\r
-        */\r
-    /**\r
-     * @cfg {Boolean} hideParent @hide\r
-        */\r
-    /**\r
-     * @cfg {Number} height @hide\r
-        */\r
-    /**\r
-     * @cfg {Number} width @hide\r
-        */\r
-    /**\r
-     * @cfg {Boolean} autoHeight @hide\r
-        */\r
-    /**\r
-     * @cfg {Boolean} autoWidth @hide\r
-        */\r
-    /**\r
-     * @cfg {Boolean} deferHeight @hide\r
-        */\r
-    /**\r
-     * @cfg {Boolean} monitorResize @hide\r
-        */\r
-    initComponent : function() {\r
+/**
+ * @class Ext.layout.BoxLayout
+ * @extends Ext.layout.ContainerLayout
+ * <p>Base Class for HBoxLayout and VBoxLayout Classes. Generally it should not need to be used directly.</p>
+ */
+Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
+    /**
+     * @cfg {Object} defaultMargins
+     * <p>If the individual contained items do not have a <tt>margins</tt>
+     * property specified, the default margins from this property will be
+     * applied to each item.</p>
+     * <br><p>This property may be specified as an object containing margins
+     * to apply in the format:</p><pre><code>
+{
+    top: (top margin),
+    right: (right margin),
+    bottom: (bottom margin),
+    left: (left margin)
+}</code></pre>
+     * <p>This property may also be specified as a string containing
+     * space-separated, numeric margin values. The order of the sides associated
+     * with each value matches the way CSS processes margin values:</p>
+     * <div class="mdetail-params"><ul>
+     * <li>If there is only one value, it applies to all sides.</li>
+     * <li>If there are two values, the top and bottom borders are set to the
+     * first value and the right and left are set to the second.</li>
+     * <li>If there are three values, the top is set to the first value, the left
+     * and right are set to the second, and the bottom is set to the third.</li>
+     * <li>If there are four values, they apply to the top, right, bottom, and
+     * left, respectively.</li>
+     * </ul></div>
+     * <p>Defaults to:</p><pre><code>
+     * {top:0, right:0, bottom:0, left:0}
+     * </code></pre>
+     */
+    defaultMargins : {left:0,top:0,right:0,bottom:0},
+    /**
+     * @cfg {String} padding
+     * <p>Sets the padding to be applied to all child items managed by this layout.</p>
+     * <p>This property must be specified as a string containing
+     * space-separated, numeric padding values. The order of the sides associated
+     * with each value matches the way CSS processes padding values:</p>
+     * <div class="mdetail-params"><ul>
+     * <li>If there is only one value, it applies to all sides.</li>
+     * <li>If there are two values, the top and bottom borders are set to the
+     * first value and the right and left are set to the second.</li>
+     * <li>If there are three values, the top is set to the first value, the left
+     * and right are set to the second, and the bottom is set to the third.</li>
+     * <li>If there are four values, they apply to the top, right, bottom, and
+     * left, respectively.</li>
+     * </ul></div>
+     * <p>Defaults to: <code>"0"</code></p>
+     */
+    padding : '0',
+    // documented in subclasses
+    pack : 'start',
+
+    // private
+    monitorResize : true,
+    type: 'box',
+    scrollOffset : 0,
+    extraCls : 'x-box-item',
+    targetCls : 'x-box-layout-ct',
+    innerCls : 'x-box-inner',
+
+    constructor : function(config){
+        Ext.layout.BoxLayout.superclass.constructor.call(this, config);
+        if(Ext.isString(this.defaultMargins)){
+            this.defaultMargins = this.parseMargins(this.defaultMargins);
+        }
+    },
+
+    // private
+    isValidParent : function(c, target){
+        return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
+    },
+
+    // private
+    renderAll : function(ct, target){
+        if(!this.innerCt){
+            // the innerCt prevents wrapping and shuffling while
+            // the container is resizing
+            this.innerCt = target.createChild({cls:this.innerCls});
+            this.padding = this.parseMargins(this.padding);
+        }
+        Ext.layout.BoxLayout.superclass.renderAll.call(this, ct, this.innerCt);
+    },
+
+    onLayout : function(ct, target){
+        this.renderAll(ct, target);
+    },
+
+    getLayoutTargetSize : function(){
+        var target = this.container.getLayoutTarget(), ret;
+        if (target) {
+            ret = target.getViewSize();
+            ret.width -= target.getPadding('lr');
+            ret.height -= target.getPadding('tb');
+        }
+        return ret;
+    },
+
+    // private
+    renderItem : function(c){
+        if(Ext.isString(c.margins)){
+            c.margins = this.parseMargins(c.margins);
+        }else if(!c.margins){
+            c.margins = this.defaultMargins;
+        }
+        Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments);
+    }
+});
+
+/**
+ * @class Ext.layout.VBoxLayout
+ * @extends Ext.layout.BoxLayout
+ * <p>A layout that arranges items vertically down a Container. This layout optionally divides available vertical
+ * space between child items containing a numeric <code>flex</code> configuration.</p>
+ * This layout may also be used to set the widths of child items by configuring it with the {@link #align} option.
+ */
+Ext.layout.VBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
+    /**
+     * @cfg {String} align
+     * Controls how the child items of the container are aligned. Acceptable configuration values for this
+     * property are:
+     * <div class="mdetail-params"><ul>
+     * <li><b><tt>left</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned horizontally
+     * at the <b>left</b> side of the container</div></li>
+     * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are aligned horizontally at the
+     * <b>mid-width</b> of the container</div></li>
+     * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched horizontally to fill
+     * the width of the container</div></li>
+     * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched horizontally to
+     * the size of the largest item.</div></li>
+     * </ul></div>
+     */
+    align : 'left', // left, center, stretch, strechmax
+    type: 'vbox',
+    /**
+     * @cfg {String} pack
+     * Controls how the child items of the container are packed together. Acceptable configuration values
+     * for this property are:
+     * <div class="mdetail-params"><ul>
+     * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at
+     * <b>top</b> side of container</div></li>
+     * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at
+     * <b>mid-height</b> of container</div></li>
+     * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>bottom</b>
+     * side of container</div></li>
+     * </ul></div>
+     */
+    /**
+     * @cfg {Number} flex
+     * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed
+     * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>vertically</b>
+     * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with
+     * a <tt>flex</tt> value specified.  Any child items that have either a <tt>flex = 0</tt> or
+     * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).
+     */
+
+    // private
+    onLayout : function(ct, target){
+        Ext.layout.VBoxLayout.superclass.onLayout.call(this, ct, target);
+
+        var cs = this.getRenderedItems(ct), csLen = cs.length,
+            c, i, cm, ch, margin, cl, diff, aw, availHeight,
+            size = this.getLayoutTargetSize(),
+            w = size.width,
+            h = size.height - this.scrollOffset,
+            l = this.padding.left,
+            t = this.padding.top,
+            isStart = this.pack == 'start',
+            extraHeight = 0,
+            maxWidth = 0,
+            totalFlex = 0,
+            usedHeight = 0,
+            idx = 0,
+            heights = [],
+            restore = [];
+
+        // Do only width calculations and apply those first, as they can affect height
+        for (i = 0 ; i < csLen; i++) {
+            c = cs[i];
+            cm = c.margins;
+            margin = cm.top + cm.bottom;
+            // Max height for align
+            maxWidth = Math.max(maxWidth, c.getWidth() + cm.left + cm.right);
+        }
+
+        var innerCtWidth = maxWidth + this.padding.left + this.padding.right;
+        switch(this.align){
+            case 'stretch':
+                this.innerCt.setSize(w, h);
+                break;
+            case 'stretchmax':
+            case 'left':
+                this.innerCt.setSize(innerCtWidth, h);
+                break;
+            case 'center':
+                this.innerCt.setSize(w = Math.max(w, innerCtWidth), h);
+                break;
+        }
+
+        var availableWidth = Math.max(0, w - this.padding.left - this.padding.right);
+        // Apply widths
+        for (i = 0 ; i < csLen; i++) {
+            c = cs[i];
+            cm = c.margins;
+            if(this.align == 'stretch'){
+                c.setWidth(((w - (this.padding.left + this.padding.right)) - (cm.left + cm.right)).constrain(
+                    c.minWidth || 0, c.maxWidth || 1000000));
+            }else if(this.align == 'stretchmax'){
+                c.setWidth((maxWidth - (cm.left + cm.right)).constrain(
+                    c.minWidth || 0, c.maxWidth || 1000000));
+            }else if(isStart && c.flex){
+                c.setWidth();
+            }
+
+        }
+
+        // Height calculations
+        for (i = 0 ; i < csLen; i++) {
+            c = cs[i];
+            // Total of all the flex values
+            totalFlex += c.flex || 0;
+            // Don't run height calculations on flexed items
+            if (!c.flex) {
+                // Render and layout sub-containers without a flex or height, once
+                if (!c.height && !c.hasLayout && c.doLayout) {
+                    c.doLayout();
+                }
+                ch = c.getHeight();
+            } else {
+                ch = 0;
+            }
+
+            cm = c.margins;
+            // Determine how much height is available to flex
+            extraHeight += ch + cm.top + cm.bottom;
+        }
+        // Final avail height calc
+        availHeight = Math.max(0, (h - extraHeight - this.padding.top - this.padding.bottom));
+
+        var leftOver = availHeight;
+        for (i = 0 ; i < csLen; i++) {
+            c = cs[i];
+            if(isStart && c.flex){
+                ch = Math.floor(availHeight * (c.flex / totalFlex));
+                leftOver -= ch;
+                heights.push(ch);
+            }
+        }
+        if(this.pack == 'center'){
+            t += availHeight ? availHeight / 2 : 0;
+        }else if(this.pack == 'end'){
+            t += availHeight;
+        }
+        idx = 0;
+        // Apply heights
+        for (i = 0 ; i < csLen; i++) {
+            c = cs[i];
+            cm = c.margins;
+            t += cm.top;
+            aw = availableWidth;
+            cl = l + cm.left // default left pos
+
+            // Adjust left pos for centering
+            if(this.align == 'center'){
+                if((diff = availableWidth - (c.getWidth() + cm.left + cm.right)) > 0){
+                    cl += (diff/2);
+                    aw -= diff;
+                }
+            }
+
+            c.setPosition(cl, t);
+            if(isStart && c.flex){
+                ch = Math.max(0, heights[idx++] + (leftOver-- > 0 ? 1 : 0));
+                c.setSize(aw, ch);
+            }else{
+                ch = c.getHeight();
+            }
+            t += ch + cm.bottom;
+        }
+        // Putting a box layout into an overflowed container is NOT correct and will make a second layout pass necessary.
+        if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
+            var ts = this.getLayoutTargetSize();
+            if (ts.width != size.width || ts.height != size.height){
+                this.adjustmentPass = true;
+                this.onLayout(ct, target);
+            }
+        }
+        delete this.adjustmentPass;
+    }
+});
+
+Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout;
+
+/**
+ * @class Ext.layout.HBoxLayout
+ * @extends Ext.layout.BoxLayout
+ * <p>A layout that arranges items horizontally across a Container. This layout optionally divides available horizontal
+ * space between child items containing a numeric <code>flex</code> configuration.</p>
+ * This layout may also be used to set the heights of child items by configuring it with the {@link #align} option.
+ */
+Ext.layout.HBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
+    /**
+     * @cfg {String} align
+     * Controls how the child items of the container are aligned. Acceptable configuration values for this
+     * property are:
+     * <div class="mdetail-params"><ul>
+     * <li><b><tt>top</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned vertically
+     * at the <b>top</b> of the container</div></li>
+     * <li><b><tt>middle</tt></b> : <div class="sub-desc">child items are aligned vertically in the
+     * <b>middle</b> of the container</div></li>
+     * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched vertically to fill
+     * the height of the container</div></li>
+     * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched vertically to
+     * the height of the largest item.</div></li>
+     */
+    align : 'top', // top, middle, stretch, strechmax
+    type: 'hbox',
+    /**
+     * @cfg {String} pack
+     * Controls how the child items of the container are packed together. Acceptable configuration values
+     * for this property are:
+     * <div class="mdetail-params"><ul>
+     * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at
+     * <b>left</b> side of container</div></li>
+     * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at
+     * <b>mid-width</b> of container</div></li>
+     * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>right</b>
+     * side of container</div></li>
+     * </ul></div>
+     */
+    /**
+     * @cfg {Number} flex
+     * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed
+     * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>horizontally</b>
+     * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with
+     * a <tt>flex</tt> value specified.  Any child items that have either a <tt>flex = 0</tt> or
+     * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).
+     */
+
+    // private
+    onLayout : function(ct, target){
+        Ext.layout.HBoxLayout.superclass.onLayout.call(this, ct, target);
+
+        var cs = this.getRenderedItems(ct), csLen = cs.length,
+            c, i, cm, cw, ch, diff, availWidth,
+            size = this.getLayoutTargetSize(),
+            w = size.width - this.scrollOffset,
+            h = size.height,
+            l = this.padding.left,
+            t = this.padding.top,
+            isStart = this.pack == 'start',
+            isRestore = ['stretch', 'stretchmax'].indexOf(this.align) == -1,
+            extraWidth = 0,
+            maxHeight = 0,
+            totalFlex = 0,
+            usedWidth = 0;
+
+        for (i = 0 ; i < csLen; i++) {
+            c = cs[i];
+            // Total of all the flex values
+            totalFlex += c.flex || 0;
+            // Don't run width calculations on flexed items
+            if (!c.flex) {
+                // Render and layout sub-containers without a flex or width, once
+                if (!c.width && !c.hasLayout && c.doLayout) {
+                    c.doLayout();
+                }
+                cw = c.getWidth();
+            } else {
+                cw = 0;
+            }
+            cm = c.margins;
+            // Determine how much width is available to flex
+            extraWidth += cw + cm.left + cm.right;
+            // Max height for align
+            maxHeight = Math.max(maxHeight, c.getHeight() + cm.top + cm.bottom);
+        }
+        // Final avail width calc
+        availWidth = Math.max(0, (w - extraWidth - this.padding.left - this.padding.right));
+
+        var innerCtHeight = maxHeight + this.padding.top + this.padding.bottom;
+        switch(this.align){
+            case 'stretch':
+                this.innerCt.setSize(w, h);
+                break;
+            case 'stretchmax':
+            case 'top':
+                this.innerCt.setSize(w, innerCtHeight);
+                break;
+            case 'middle':
+                this.innerCt.setSize(w, h = Math.max(h, innerCtHeight));
+                break;
+        }
+
+        var leftOver = availWidth,
+            widths = [],
+            restore = [],
+            idx = 0,
+            availableHeight = Math.max(0, h - this.padding.top - this.padding.bottom);
+
+        for (i = 0 ; i < csLen; i++) {
+            c = cs[i];
+            if(isStart && c.flex){
+                cw = Math.floor(availWidth * (c.flex / totalFlex));
+                leftOver -= cw;
+                widths.push(cw);
+            }
+        }
+
+        if(this.pack == 'center'){
+            l += availWidth ? availWidth / 2 : 0;
+        }else if(this.pack == 'end'){
+            l += availWidth;
+        }
+        for (i = 0 ; i < csLen; i++) {
+            c = cs[i];
+            cm = c.margins;
+            l += cm.left;
+            c.setPosition(l, t + cm.top);
+            if(isStart && c.flex){
+                cw = Math.max(0, widths[idx++] + (leftOver-- > 0 ? 1 : 0));
+                if(isRestore){
+                    restore.push(c.getHeight());
+                }
+                c.setSize(cw, availableHeight);
+            }else{
+                cw = c.getWidth();
+            }
+            l += cw + cm.right;
+        }
+
+        idx = 0;
+        for (i = 0 ; i < csLen; i++) {
+            c = cs[i];
+            cm = c.margins;
+            ch = c.getHeight();
+            if(isStart && c.flex){
+                ch = restore[idx++];
+            }
+            if(this.align == 'stretch'){
+                c.setHeight(((h - (this.padding.top + this.padding.bottom)) - (cm.top + cm.bottom)).constrain(
+                    c.minHeight || 0, c.maxHeight || 1000000));
+            }else if(this.align == 'stretchmax'){
+                c.setHeight((maxHeight - (cm.top + cm.bottom)).constrain(
+                    c.minHeight || 0, c.maxHeight || 1000000));
+            }else{
+                if(this.align == 'middle'){
+                    diff = availableHeight - (ch + cm.top + cm.bottom);
+                    ch = t + cm.top + (diff/2);
+                    if(diff > 0){
+                        c.setPosition(c.x, ch);
+                    }
+                }
+                if(isStart && c.flex){
+                    c.setHeight(ch);
+                }
+            }
+        }
+        // Putting a box layout into an overflowed container is NOT correct and will make a second layout pass necessary.
+        if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
+            var ts = this.getLayoutTargetSize();
+            if (ts.width != size.width || ts.height != size.height){
+                this.adjustmentPass = true;
+                this.onLayout(ct, target);
+            }
+        }
+        delete this.adjustmentPass;
+    }
+});
+
+Ext.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout;
+/**
+ * @class Ext.layout.ToolbarLayout
+ * @extends Ext.layout.ContainerLayout
+ * Layout manager implicitly used by Ext.Toolbar.
+ */
+Ext.layout.ToolbarLayout = Ext.extend(Ext.layout.ContainerLayout, {
+    monitorResize : true,
+    triggerWidth : 18,
+    lastOverflow : false,
+
+    noItemsMenuText : '<div class="x-toolbar-no-items">(None)</div>',
+
+    // private
+    onLayout : function(ct, target){
+        if(!this.leftTr){
+            var align = ct.buttonAlign == 'center' ? 'center' : 'left';
+            target.addClass('x-toolbar-layout-ct');
+            target.insertHtml('beforeEnd',
+                 '<table cellspacing="0" class="x-toolbar-ct"><tbody><tr><td class="x-toolbar-left" align="' + align + '"><table cellspacing="0"><tbody><tr class="x-toolbar-left-row"></tr></tbody></table></td><td class="x-toolbar-right" align="right"><table cellspacing="0" class="x-toolbar-right-ct"><tbody><tr><td><table cellspacing="0"><tbody><tr class="x-toolbar-right-row"></tr></tbody></table></td><td><table cellspacing="0"><tbody><tr class="x-toolbar-extras-row"></tr></tbody></table></td></tr></tbody></table></td></tr></tbody></table>');
+            this.leftTr = target.child('tr.x-toolbar-left-row', true);
+            this.rightTr = target.child('tr.x-toolbar-right-row', true);
+            this.extrasTr = target.child('tr.x-toolbar-extras-row', true);
+        }
+
+        var side = ct.buttonAlign == 'right' ? this.rightTr : this.leftTr,
+            pos = 0,
+            items = ct.items.items;
+
+        for(var i = 0, len = items.length, c; i < len; i++, pos++) {
+            c = items[i];
+            if(c.isFill){
+                side = this.rightTr;
+                pos = -1;
+            }else if(!c.rendered){
+                c.render(this.insertCell(c, side, pos));
+            }else{
+                if(!c.xtbHidden && !this.isValidParent(c, side.childNodes[pos])){
+                    var td = this.insertCell(c, side, pos);
+                    td.appendChild(c.getPositionEl().dom);
+                    c.container = Ext.get(td);
+                }
+            }
+        }
+        //strip extra empty cells
+        this.cleanup(this.leftTr);
+        this.cleanup(this.rightTr);
+        this.cleanup(this.extrasTr);
+        this.fitToSize(target);
+    },
+
+    cleanup : function(row){
+        var cn = row.childNodes, i, c;
+        for(i = cn.length-1; i >= 0 && (c = cn[i]); i--){
+            if(!c.firstChild){
+                row.removeChild(c);
+            }
+        }
+    },
+
+    insertCell : function(c, side, pos){
+        var td = document.createElement('td');
+        td.className='x-toolbar-cell';
+        side.insertBefore(td, side.childNodes[pos]||null);
+        return td;
+    },
+
+    hideItem : function(item){
+        var h = (this.hiddens = this.hiddens || []);
+        h.push(item);
+        item.xtbHidden = true;
+        item.xtbWidth = item.getPositionEl().dom.parentNode.offsetWidth;
+        item.hide();
+    },
+
+    unhideItem : function(item){
+        item.show();
+        item.xtbHidden = false;
+        this.hiddens.remove(item);
+        if(this.hiddens.length < 1){
+            delete this.hiddens;
+        }
+    },
+
+    getItemWidth : function(c){
+        return c.hidden ? (c.xtbWidth || 0) : c.getPositionEl().dom.parentNode.offsetWidth;
+    },
+
+    fitToSize : function(t){
+        if(this.container.enableOverflow === false){
+            return;
+        }
+        var w = t.dom.clientWidth,
+            lw = this.lastWidth || 0,
+            iw = t.dom.firstChild.offsetWidth,
+            clipWidth = w - this.triggerWidth,
+            hideIndex = -1;
+
+        this.lastWidth = w;
+
+        if(iw > w || (this.hiddens && w >= lw)){
+            var i, items = this.container.items.items,
+                len = items.length, c,
+                loopWidth = 0;
+
+            for(i = 0; i < len; i++) {
+                c = items[i];
+                if(!c.isFill){
+                    loopWidth += this.getItemWidth(c);
+                    if(loopWidth > clipWidth){
+                        if(!(c.hidden || c.xtbHidden)){
+                            this.hideItem(c);
+                        }
+                    }else if(c.xtbHidden){
+                        this.unhideItem(c);
+                    }
+                }
+            }
+        }
+        if(this.hiddens){
+            this.initMore();
+            if(!this.lastOverflow){
+                this.container.fireEvent('overflowchange', this.container, true);
+                this.lastOverflow = true;
+            }
+        }else if(this.more){
+            this.clearMenu();
+            this.more.destroy();
+            delete this.more;
+            if(this.lastOverflow){
+                this.container.fireEvent('overflowchange', this.container, false);
+                this.lastOverflow = false;
+            }
+        }
+    },
+
+    createMenuConfig : function(c, hideOnClick){
+        var cfg = Ext.apply({}, c.initialConfig),
+            group = c.toggleGroup;
+
+        Ext.apply(cfg, {
+            text: c.overflowText || c.text,
+            iconCls: c.iconCls,
+            icon: c.icon,
+            itemId: c.itemId,
+            disabled: c.disabled,
+            handler: c.handler,
+            scope: c.scope,
+            menu: c.menu,
+            hideOnClick: hideOnClick
+        });
+        if(group || c.enableToggle){
+            Ext.apply(cfg, {
+                group: group,
+                checked: c.pressed,
+                listeners: {
+                    checkchange: function(item, checked){
+                        c.toggle(checked);
+                    }
+                }
+            });
+        }
+        delete cfg.ownerCt;
+        delete cfg.xtype;
+        delete cfg.id;
+        return cfg;
+    },
+
+    // private
+    addComponentToMenu : function(m, c){
+        if(c instanceof Ext.Toolbar.Separator){
+            m.add('-');
+        }else if(Ext.isFunction(c.isXType)){
+            if(c.isXType('splitbutton')){
+                m.add(this.createMenuConfig(c, true));
+            }else if(c.isXType('button')){
+                m.add(this.createMenuConfig(c, !c.menu));
+            }else if(c.isXType('buttongroup')){
+                c.items.each(function(item){
+                     this.addComponentToMenu(m, item);
+                }, this);
+            }
+        }
+    },
+
+    clearMenu : function(){
+        var m = this.moreMenu;
+        if(m && m.items){
+            m.items.each(function(item){
+                delete item.menu;
+            });
+        }
+    },
+
+    // private
+    beforeMoreShow : function(m){
+        var h = this.container.items.items,
+            len = h.length,
+            c,
+            prev,
+            needsSep = function(group, item){
+                return group.isXType('buttongroup') && !(item instanceof Ext.Toolbar.Separator);
+            };
+
+        this.clearMenu();
+        m.removeAll();
+        for(var i = 0; i < len; i++){
+            c = h[i];
+            if(c.xtbHidden){
+                if(prev && (needsSep(c, prev) || needsSep(prev, c))){
+                    m.add('-');
+                }
+                this.addComponentToMenu(m, c);
+                prev = c;
+            }
+        }
+        // put something so the menu isn't empty
+        // if no compatible items found
+        if(m.items.length < 1){
+            m.add(this.noItemsMenuText);
+        }
+    },
+
+    initMore : function(){
+        if(!this.more){
+            this.moreMenu = new Ext.menu.Menu({
+                ownerCt : this.container,
+                listeners: {
+                    beforeshow: this.beforeMoreShow,
+                    scope: this
+                }
+
+            });
+            this.more = new Ext.Button({
+                iconCls : 'x-toolbar-more-icon',
+                cls     : 'x-toolbar-more',
+                menu    : this.moreMenu,
+                ownerCt : this.container
+            });
+            var td = this.insertCell(this.more, this.extrasTr, 100);
+            this.more.render(td);
+        }
+    },
+
+    destroy : function(){
+        Ext.destroy(this.more, this.moreMenu);
+        delete this.leftTr;
+        delete this.rightTr;
+        delete this.extrasTr;
+        Ext.layout.ToolbarLayout.superclass.destroy.call(this);
+    }
+});
+
+Ext.Container.LAYOUTS.toolbar = Ext.layout.ToolbarLayout;/**
+ * @class Ext.layout.MenuLayout
+ * @extends Ext.layout.ContainerLayout
+ * <p>Layout manager used by {@link Ext.menu.Menu}. Generally this class should not need to be used directly.</p>
+ */
+ Ext.layout.MenuLayout = Ext.extend(Ext.layout.ContainerLayout, {
+    monitorResize : true,
+
+    setContainer : function(ct){
+        this.monitorResize = !ct.floating;
+        // This event is only fired by the menu in IE, used so we don't couple
+        // the menu with the layout.
+        ct.on('autosize', this.doAutoSize, this);
+        Ext.layout.MenuLayout.superclass.setContainer.call(this, ct);
+    },
+
+    renderItem : function(c, position, target){
+        if (!this.itemTpl) {
+            this.itemTpl = Ext.layout.MenuLayout.prototype.itemTpl = new Ext.XTemplate(
+                '<li id="{itemId}" class="{itemCls}">',
+                    '<tpl if="needsIcon">',
+                        '<img src="{icon}" class="{iconCls}"/>',
+                    '</tpl>',
+                '</li>'
+            );
+        }
+
+        if(c && !c.rendered){
+            if(Ext.isNumber(position)){
+                position = target.dom.childNodes[position];
+            }
+            var a = this.getItemArgs(c);
+
+//          The Component's positionEl is the <li> it is rendered into
+            c.render(c.positionEl = position ?
+                this.itemTpl.insertBefore(position, a, true) :
+                this.itemTpl.append(target, a, true));
+
+//          Link the containing <li> to the item.
+            c.positionEl.menuItemId = c.getItemId();
+
+//          If rendering a regular Component, and it needs an icon,
+//          move the Component rightwards.
+            if (!a.isMenuItem && a.needsIcon) {
+                c.positionEl.addClass('x-menu-list-item-indent');
+            }
+            this.configureItem(c, position);
+        }else if(c && !this.isValidParent(c, target)){
+            if(Ext.isNumber(position)){
+                position = target.dom.childNodes[position];
+            }
+            target.dom.insertBefore(c.getActionEl().dom, position || null);
+        }
+    },
+
+    getItemArgs : function(c) {
+        var isMenuItem = c instanceof Ext.menu.Item;
+        return {
+            isMenuItem: isMenuItem,
+            needsIcon: !isMenuItem && (c.icon || c.iconCls),
+            icon: c.icon || Ext.BLANK_IMAGE_URL,
+            iconCls: 'x-menu-item-icon ' + (c.iconCls || ''),
+            itemId: 'x-menu-el-' + c.id,
+            itemCls: 'x-menu-list-item '
+        };
+    },
+
+    //  Valid if the Component is in a <li> which is part of our target <ul>
+    isValidParent : function(c, target) {
+        return c.el.up('li.x-menu-list-item', 5).dom.parentNode === (target.dom || target);
+    },
+
+    onLayout : function(ct, target){
+        Ext.layout.MenuLayout.superclass.onLayout.call(this, ct, target);
+        this.doAutoSize();
+    },
+
+    doAutoSize : function(){
+        var ct = this.container, w = ct.width;
+        if(ct.floating){
+            if(w){
+                ct.setWidth(w);
+            }else if(Ext.isIE){
+                ct.setWidth(Ext.isStrict && (Ext.isIE7 || Ext.isIE8) ? 'auto' : ct.minWidth);
+                var el = ct.getEl(), t = el.dom.offsetWidth; // force recalc
+                ct.setWidth(ct.getLayoutTarget().getWidth() + el.getFrameWidth('lr'));
+            }
+        }
+    }
+});
+Ext.Container.LAYOUTS['menu'] = Ext.layout.MenuLayout;/**\r
+ * @class Ext.Viewport\r
+ * @extends Ext.Container\r
+ * <p>A specialized container representing the viewable application area (the browser viewport).</p>\r
+ * <p>The Viewport renders itself to the document body, and automatically sizes itself to the size of\r
+ * the browser viewport and manages window resizing. There may only be one Viewport created\r
+ * in a page. Inner layouts are available by virtue of the fact that all {@link Ext.Panel Panel}s\r
+ * added to the Viewport, either through its {@link #items}, or through the items, or the {@link #add}\r
+ * method of any of its child Panels may themselves have a layout.</p>\r
+ * <p>The Viewport does not provide scrolling, so child Panels within the Viewport should provide\r
+ * for scrolling if needed using the {@link #autoScroll} config.</p>\r
+ * <p>An example showing a classic application border layout:</p><pre><code>\r
+new Ext.Viewport({\r
+    layout: 'border',\r
+    items: [{\r
+        region: 'north',\r
+        html: '&lt;h1 class="x-panel-header">Page Title&lt;/h1>',\r
+        autoHeight: true,\r
+        border: false,\r
+        margins: '0 0 5 0'\r
+    }, {\r
+        region: 'west',\r
+        collapsible: true,\r
+        title: 'Navigation',\r
+        width: 200\r
+        // the west region might typically utilize a {@link Ext.tree.TreePanel TreePanel} or a Panel with {@link Ext.layout.AccordionLayout Accordion layout}\r
+    }, {\r
+        region: 'south',\r
+        title: 'Title for Panel',\r
+        collapsible: true,\r
+        html: 'Information goes here',\r
+        split: true,\r
+        height: 100,\r
+        minHeight: 100\r
+    }, {\r
+        region: 'east',\r
+        title: 'Title for the Grid Panel',\r
+        collapsible: true,\r
+        split: true,\r
+        width: 200,\r
+        xtype: 'grid',\r
+        // remaining grid configuration not shown ...\r
+        // notice that the GridPanel is added directly as the region\r
+        // it is not "overnested" inside another Panel\r
+    }, {\r
+        region: 'center',\r
+        xtype: 'tabpanel', // TabPanel itself has no title\r
+        items: {\r
+            title: 'Default Tab',\r
+            html: 'The first tab\'s content. Others may be added dynamically'\r
+        }\r
+    }]\r
+});\r
+</code></pre>\r
+ * @constructor\r
+ * Create a new Viewport\r
+ * @param {Object} config The config object\r
+ * @xtype viewport\r
+ */\r
+Ext.Viewport = Ext.extend(Ext.Container, {\r
+    /*\r
+     * Privatize config options which, if used, would interfere with the\r
+     * correct operation of the Viewport as the sole manager of the\r
+     * layout of the document body.\r
+     */\r
+    /**\r
+     * @cfg {Mixed} applyTo @hide\r
+     */\r
+    /**\r
+     * @cfg {Boolean} allowDomMove @hide\r
+     */\r
+    /**\r
+     * @cfg {Boolean} hideParent @hide\r
+     */\r
+    /**\r
+     * @cfg {Mixed} renderTo @hide\r
+     */\r
+    /**\r
+     * @cfg {Boolean} hideParent @hide\r
+     */\r
+    /**\r
+     * @cfg {Number} height @hide\r
+     */\r
+    /**\r
+     * @cfg {Number} width @hide\r
+     */\r
+    /**\r
+     * @cfg {Boolean} autoHeight @hide\r
+     */\r
+    /**\r
+     * @cfg {Boolean} autoWidth @hide\r
+     */\r
+    /**\r
+     * @cfg {Boolean} deferHeight @hide\r
+     */\r
+    /**\r
+     * @cfg {Boolean} monitorResize @hide\r
+     */\r
+\r
+    initComponent : function() {\r
         Ext.Viewport.superclass.initComponent.call(this);\r
         document.getElementsByTagName('html')[0].className += ' x-viewport';\r
         this.el = Ext.getBody();\r
@@ -21389,7 +22832,8 @@ Ext.Viewport = Ext.extend(Ext.Container, {
         this.fireEvent('resize', this, w, h, w, h);\r
     }\r
 });\r
-Ext.reg('viewport', Ext.Viewport);/**
+Ext.reg('viewport', Ext.Viewport);\r
+/**
  * @class Ext.Panel
  * @extends Ext.Container
  * <p>Panel is a container that has specific functionality and structural components that make
@@ -21744,7 +23188,7 @@ var w = new Ext.Window({
      * <li><b>event</b> : Ext.EventObject<div class="sub-desc">The click event.</div></li>
      * <li><b>toolEl</b> : Ext.Element<div class="sub-desc">The tool Element.</div></li>
      * <li><b>panel</b> : Ext.Panel<div class="sub-desc">The host Panel</div></li>
-     * <li><b>tc</b> : Ext.Panel<div class="sub-desc">The tool configuration object</div></li>
+     * <li><b>tc</b> : Object<div class="sub-desc">The tool configuration object</div></li>
      * </ul></div></li>
      * <li><b>stopEvent</b> : Boolean<div class="sub-desc">Defaults to true. Specify as false to allow click event to propagate.</div></li>
      * <li><b>scope</b> : Object<div class="sub-desc">The scope in which to call the handler.</div></li>
@@ -21829,11 +23273,7 @@ var win = new Ext.Window({
      * {@link Ext.layout.BorderLayout.Region BorderLayout.Region}
      * <code>{@link Ext.layout.BorderLayout.Region#floatable floatable}</code> config option.
      */
-    /**
-     * @cfg {Boolean} autoScroll
-     * <code>true</code> to use overflow:'auto' on the panel's body element and show scroll bars automatically when
-     * necessary, <code>false</code> to clip any overflowing content (defaults to <code>false</code>).
-     */
+
     /**
      * @cfg {Mixed} floating
      * <p>This property is used to configure the underlying {@link Ext.Layer}. Acceptable values for this
@@ -21869,33 +23309,6 @@ var win = new Ext.Window({
      * <code>false</code> to disable the iframe shim in browsers which need one (defaults to <code>true</code>).
      * Note that this option only applies when <code>{@link #floating} = true</code>.
      */
-    /**
-     * @cfg {String/Object} html
-     * An HTML fragment, or a {@link Ext.DomHelper DomHelper} specification to use as the panel's body
-     * content (defaults to ''). The HTML content is added by the Panel's {@link #afterRender} method,
-     * and so the document will not contain this HTML at the time the {@link #render} event is fired.
-     * This content is inserted into the body <i>before</i> any configured {@link #contentEl} is appended.
-     */
-    /**
-     * @cfg {String} contentEl
-     * <p>Optional. Specify an existing HTML element, or the <code>id</code> of an existing HTML element to use as this Panel's
-     * <code><b>{@link #body}</b></code> content.</p>
-     * <ul>
-     * <li><b>Description</b> :
-     * <div class="sub-desc">This config option is used to take an existing HTML element and place it in the body
-     * of a new panel (it simply moves the specified DOM element into the body element of the Panel
-     * <i>after the Panel is rendered</i> to use as the content (it is not going to be the actual panel itself).</div></li>
-     * <li><b>Notes</b> :
-     * <div class="sub-desc">The specified HTML element is appended to the Panel's {@link #body} Element by the
-     * Panel's <code>afterRender</code> method <i>after any configured {@link #html HTML} has
-     * been inserted</i>, and so the document will not contain this element at the time the
-     * {@link #render} event is fired.</div>
-     * <div class="sub-desc">The specified HTML element used will not participate in any <code><b>{@link Ext.Container#layout layout}</b></code>
-     * scheme that the Panel may use. It is just HTML. Layouts operate on child <code><b>{@link Ext.Container#items items}</b></code>.</div>
-     * <div class="sub-desc">Add either the <code>x-hidden</code> or the <code>x-hide-display</code> CSS class to
-     * prevent a brief flicker of the content before it is rendered to the panel.</div></li>
-     * </ul>
-     */
     /**
      * @cfg {Object/Array} keys
      * A {@link Ext.KeyMap} config object (in the format expected by {@link Ext.KeyMap#addBinding}
@@ -22065,7 +23478,16 @@ new Ext.Panel({
      * footer, etc.).
      */
     preventBodyReset : false,
-    
+
+    /**
+     * @cfg {Number/String} padding
+     * A shortcut for setting a padding style on the body element. The value can either be
+     * a number to be applied to all sides, or a normal css string describing padding.
+     * Defaults to <tt>undefined</tt>.
+     *
+     */
+    padding: undefined,
+
     /** @cfg {String} resizeEvent
      * The event to listen to for resizing in layouts. Defaults to <tt>'bodyresize'</tt>.
      */
@@ -22099,8 +23521,8 @@ new Ext.Panel({
              * @event bodyresize
              * Fires after the Panel has been resized.
              * @param {Ext.Panel} p the Panel which has been resized.
-             * @param {Number} width The Panel's new width.
-             * @param {Number} height The Panel's new height.
+             * @param {Number} width The Panel body's new width.
+             * @param {Number} height The Panel body's new height.
              */
             'bodyresize',
             /**
@@ -22184,19 +23606,18 @@ new Ext.Panel({
             this.baseCls = 'x-plain';
         }
 
+
+        this.toolbars = [];
         // shortcuts
         if(this.tbar){
             this.elements += ',tbar';
-            if(Ext.isObject(this.tbar)){
-                this.topToolbar = this.tbar;
-            }
+            this.topToolbar = this.createToolbar(this.tbar);
             delete this.tbar;
+
         }
         if(this.bbar){
             this.elements += ',bbar';
-            if(Ext.isObject(this.bbar)){
-                this.bottomToolbar = this.bbar;
-            }
+            this.bottomToolbar = this.createToolbar(this.bbar);
             delete this.bbar;
         }
 
@@ -22213,33 +23634,59 @@ new Ext.Panel({
         }
 
         if(this.buttons){
-            this.elements += ',footer';
-            var btns = this.buttons;
-            /**
-             * This Panel's Array of buttons as created from the <code>{@link #buttons}</code>
-             * config property. Read only.
-             * @type Array
-             * @property buttons
-             */
-            this.buttons = [];
-            Ext.each(btns, function(btn){
-                if(btn.render){ // button instance
-                    this.buttons.push(btn);
-                }else if(btn.xtype){
-                    this.buttons.push(Ext.create(btn, 'button'));
-                }else{
-                    this.addButton(btn);
-                }
-            }, this);
+            this.fbar = this.buttons;
+            delete this.buttons;
         }
         if(this.fbar){
-            this.elements += ',footer';
+            this.createFbar(this.fbar);
         }
         if(this.autoLoad){
             this.on('render', this.doAutoLoad, this, {delay:10});
         }
     },
 
+    // private
+    createFbar : function(fbar){
+        var min = this.minButtonWidth;
+        this.elements += ',footer';
+        this.fbar = this.createToolbar(fbar, {
+            buttonAlign: this.buttonAlign,
+            toolbarCls: 'x-panel-fbar',
+            enableOverflow: false,
+            defaults: function(c){
+                return {
+                    minWidth: c.minWidth || min
+                };
+            }
+        });
+        //@compat addButton and buttons could possibly be removed
+        //@target 4.0
+        /**
+         * This Panel's Array of buttons as created from the <code>{@link #buttons}</code>
+         * config property. Read only.
+         * @type Array
+         * @property buttons
+         */
+        this.fbar.items.each(function(c){
+            c.minWidth = c.minWidth || this.minButtonWidth;
+        }, this);
+        this.buttons = this.fbar.items.items;
+    },
+
+    // private
+    createToolbar: function(tb, options){
+        var result;
+        // Convert array to proper toolbar config
+        if(Ext.isArray(tb)){
+            tb = {
+                items: tb
+            };
+        }
+        result = tb.events ? Ext.apply(tb, options) : this.createComponent(Ext.apply({}, tb, options), 'toolbar');
+        this.toolbars.push(result);
+        return result;
+    },
+
     // private
     createElement : function(name, pnode){
         if(this[name]){
@@ -22273,23 +23720,23 @@ new Ext.Panel({
             d = el.dom,
             bw,
             ts;
-            
-            
+
+
         if(this.collapsible && !this.hideCollapseTool){
             this.tools = this.tools ? this.tools.slice(0) : [];
             this.tools[this.collapseFirst?'unshift':'push']({
                 id: 'toggle',
                 handler : this.toggleCollapse,
                 scope: this
-            });   
+            });
         }
-        
+
         if(this.tools){
             ts = this.tools;
             this.elements += (this.header !== false) ? ',header' : '';
         }
         this.tools = {};
-            
+
         el.addClass(this.baseCls);
         if(d.firstChild){ // existing markup
             this.header = el.down('.'+this.headerCls);
@@ -22342,7 +23789,7 @@ new Ext.Panel({
              * b) The last element is reported incorrectly when using a loadmask
              */
             this.ft = Ext.get(this.bwrap.dom.lastChild);
-            this.mc = Ext.get(this.bwrap.dom.firstChild.firstChild.firstChild);
+            this.mc = Ext.get(mc);
         }else{
             this.createElement('header', d);
             this.createElement('bwrap', d);
@@ -22415,49 +23862,20 @@ new Ext.Panel({
             this.addTool.apply(this, ts);
         }
 
-        if(this.buttons && this.buttons.length > 0){
-            this.fbar = new Ext.Toolbar({
-                items: this.buttons,
-                toolbarCls: 'x-panel-fbar'
-            });
-        }
-        this.toolbars = [];
+        // Render Toolbars.
         if(this.fbar){
-            this.fbar = Ext.create(this.fbar, 'toolbar');
-            this.fbar.enableOverflow = false;
-            if(this.fbar.items){
-                this.fbar.items.each(function(c){
-                    c.minWidth = c.minWidth || this.minButtonWidth;
-                }, this);
-            }
-            this.fbar.toolbarCls = 'x-panel-fbar';
-
-            var bct = this.footer.createChild({cls: 'x-panel-btns x-panel-btns-'+this.buttonAlign});
+            this.footer.addClass('x-panel-btns');
             this.fbar.ownerCt = this;
-            this.fbar.render(bct);
-            bct.createChild({cls:'x-clear'});
-            this.toolbars.push(this.fbar);
+            this.fbar.render(this.footer);
+            this.footer.createChild({cls:'x-clear'});
         }
-
         if(this.tbar && this.topToolbar){
-            if(Ext.isArray(this.topToolbar)){
-                this.topToolbar = new Ext.Toolbar(this.topToolbar);
-            }else if(!this.topToolbar.events){
-                this.topToolbar = Ext.create(this.topToolbar, 'toolbar');
-            }
             this.topToolbar.ownerCt = this;
             this.topToolbar.render(this.tbar);
-            this.toolbars.push(this.topToolbar);
         }
         if(this.bbar && this.bottomToolbar){
-            if(Ext.isArray(this.bottomToolbar)){
-                this.bottomToolbar = new Ext.Toolbar(this.bottomToolbar);
-            }else if(!this.bottomToolbar.events){
-                this.bottomToolbar = Ext.create(this.bottomToolbar, 'toolbar');
-            }
             this.bottomToolbar.ownerCt = this;
             this.bottomToolbar.render(this.bbar);
-            this.toolbars.push(this.bottomToolbar);
         }
     },
 
@@ -22491,14 +23909,12 @@ new Ext.Panel({
     // private
     makeFloating : function(cfg){
         this.floating = true;
-        this.el = new Ext.Layer(
-            Ext.isObject(cfg) ? cfg : {
-                shadow: Ext.isDefined(this.shadow) ? this.shadow : 'sides',
-                shadowOffset: this.shadowOffset,
-                constrain:false,
-                shim: this.shim === false ? false : undefined
-            }, this.el
-        );
+        this.el = new Ext.Layer(Ext.apply({}, cfg, {
+            shadow: Ext.isDefined(this.shadow) ? this.shadow : 'sides',
+            shadowOffset: this.shadowOffset,
+            constrain:false,
+            shim: this.shim === false ? false : undefined
+        }), this.el);
     },
 
     /**
@@ -22523,27 +23939,23 @@ new Ext.Panel({
      * @param {String/Object} config A valid {@link Ext.Button} config.  A string will become the text for a default
      * button config, an object will be treated as a button config object.
      * @param {Function} handler The function to be called on button {@link Ext.Button#click}
-     * @param {Object} scope The scope to use for the button handler function
+     * @param {Object} scope The scope (<code>this</code> reference) in which the button handler function is executed. Defaults to the Button.
      * @return {Ext.Button} The button that was added
      */
     addButton : function(config, handler, scope){
-        var bc = {
-            handler: handler,
-            scope: scope,
-            minWidth: this.minButtonWidth,
-            hideParent:true
-        };
-        if(Ext.isString(config)){
-            bc.text = config;
-        }else{
-            Ext.apply(bc, config);
+        if(!this.fbar){
+            this.createFbar([]);
         }
-        var btn = new Ext.Button(bc);
-        if(!this.buttons){
-            this.buttons = [];
+        if(handler){
+            if(Ext.isString(config)){
+                config = {text: config};
+            }
+            config = Ext.apply({
+                handler: handler,
+                scope: scope
+            }, config)
         }
-        this.buttons.push(btn);
-        return btn;
+        return this.fbar.add(config);
     },
 
     // private
@@ -22574,7 +23986,7 @@ new Ext.Panel({
             var tc = a[i];
             if(!this.tools[tc.id]){
                 var overCls = 'x-tool-'+tc.id+'-over';
-                var t = this.toolTemplate.insertFirst((tc.align !== 'left') ? this[this.toolTarget] : this[this.toolTarget].child('span'), tc, true);
+                var t = this.toolTemplate.insertFirst(this[this.toolTarget], tc, true);
                 this.tools[tc.id] = t;
                 t.enableDisplayMode('block');
                 this.mon(t, 'click',  this.createToolHandler(t, tc, overCls, this));
@@ -22599,6 +24011,7 @@ new Ext.Panel({
     },
 
     onLayout : function(shallow, force){
+        Ext.Panel.superclass.onLayout.apply(this, arguments);
         if(this.hasLayout && this.toolbars.length > 0){
             Ext.each(this.toolbars, function(tb){
                 tb.doLayout(undefined, force);
@@ -22610,13 +24023,14 @@ new Ext.Panel({
     syncHeight : function(){
         var h = this.toolbarHeight,
                 bd = this.body,
-                lsh = this.lastSize.height;
-                
+                lsh = this.lastSize.height,
+                sz;
+
         if(this.autoHeight || !Ext.isDefined(lsh) || lsh == 'auto'){
             return;
         }
-            
-           
+
+
         if(h != this.getToolbarHeight()){
             h = Math.max(0, this.adjustBodyHeight(lsh - this.getFrameHeight()));
             bd.setHeight(h);
@@ -22663,36 +24077,14 @@ new Ext.Panel({
         if(this.title){
             this.setTitle(this.title);
         }
-        this.setAutoScroll();
-        if(this.html){
-            this.body.update(Ext.isObject(this.html) ?
-                             Ext.DomHelper.markup(this.html) :
-                             this.html);
-            delete this.html;
-        }
-        if(this.contentEl){
-            var ce = Ext.getDom(this.contentEl);
-            Ext.fly(ce).removeClass(['x-hidden', 'x-hide-display']);
-            this.body.dom.appendChild(ce);
-        }
-        if(this.collapsed){
+        Ext.Panel.superclass.afterRender.call(this); // do sizing calcs last
+        if (this.collapsed) {
             this.collapsed = false;
             this.collapse(false);
         }
-        Ext.Panel.superclass.afterRender.call(this); // do sizing calcs last
         this.initEvents();
     },
 
-    // private
-    setAutoScroll : function(){
-        if(this.rendered && this.autoScroll){
-            var el = this.body || this.el;
-            if(el){
-                el.setOverflow('auto');
-            }
-        }
-    },
-
     // private
     getKeyMap : function(){
         if(!this.keyMap){
@@ -22718,10 +24110,9 @@ new Ext.Panel({
                     remove: this.syncHeight
                 });
             }, this);
-            if(!this.ownerCt){
-                this.syncHeight();
-            }
+            this.syncHeight();
         }
+
     },
 
     // private
@@ -22846,7 +24237,8 @@ new Ext.Panel({
     afterExpand : function(anim){
         this.collapsed = false;
         this.afterEffect(anim);
-        if(Ext.isDefined(this.deferLayout)){
+        if (this.deferLayout) {
+            delete this.deferLayout;
             this.doLayout(true);
         }
         this.fireEvent('expand', this);
@@ -22883,49 +24275,43 @@ new Ext.Panel({
     onResize : function(w, h){
         if(Ext.isDefined(w) || Ext.isDefined(h)){
             if(!this.collapsed){
+                // First, set the the Panel's body width.
+                // If we have auto-widthed it, get the resulting full offset width so we can size the Toolbars to match
+                // The Toolbars must not buffer this resize operation because we need to know their heights.
+
                 if(Ext.isNumber(w)){
-                    w = this.adjustBodyWidth(w - this.getFrameWidth());
-                    if(this.tbar){
-                        this.tbar.setWidth(w);
-                        if(this.topToolbar){
-                            this.topToolbar.setSize(w);
-                        }
+                    this.body.setWidth(w = this.adjustBodyWidth(w - this.getFrameWidth()));
+                } else if (w == 'auto') {
+                    w = this.body.setWidth('auto').dom.offsetWidth;
+                } else {
+                    w = this.body.dom.offsetWidth;
+                }
+
+                if(this.tbar){
+                    this.tbar.setWidth(w);
+                    if(this.topToolbar){
+                        this.topToolbar.setSize(w);
                     }
-                    if(this.bbar){
-                        this.bbar.setWidth(w);
-                        if(this.bottomToolbar){
-                            this.bottomToolbar.setSize(w);
+                }
+                if(this.bbar){
+                    this.bbar.setWidth(w);
+                    if(this.bottomToolbar){
+                        this.bottomToolbar.setSize(w);
+                        // The bbar does not move on resize without this.
+                        if (Ext.isIE) {
+                            this.bbar.setStyle('position', 'static');
+                            this.bbar.setStyle('position', '');
                         }
                     }
+                }
+                if(this.footer){
+                    this.footer.setWidth(w);
                     if(this.fbar){
-                        var f = this.fbar,
-                            fWidth = 1,
-                            strict = Ext.isStrict;
-                        if(this.buttonAlign == 'left'){
-                           fWidth = w - f.container.getFrameWidth('lr');
-                        }else{
-                            //center/right alignment off in webkit
-                            if(Ext.isIE || Ext.isWebKit){
-                                //center alignment ok on webkit.
-                                //right broken in both, center on IE
-                                if(!(this.buttonAlign == 'center' && Ext.isWebKit) && (!strict || (!Ext.isIE8 && strict))){
-                                    (function(){
-                                        f.setWidth(f.getEl().child('.x-toolbar-ct').getWidth());
-                                    }).defer(1);
-                                }else{
-                                    fWidth = 'auto';
-                                }
-                            }else{
-                                fWidth = 'auto';
-                            }
-                        }
-                        f.setWidth(fWidth);
+                        this.fbar.setSize(Ext.isIE ? (w - this.footer.getFrameWidth('lr')) : 'auto');
                     }
-                    this.body.setWidth(w);
-                }else if(w == 'auto'){
-                    this.body.setWidth(w);
                 }
 
+                // At this point, the Toolbars must be layed out for getFrameHeight to find a result.
                 if(Ext.isNumber(h)){
                     h = Math.max(0, this.adjustBodyHeight(h - this.getFrameHeight()));
                     this.body.setHeight(h);
@@ -22937,26 +24323,27 @@ new Ext.Panel({
                     this.el._mask.setSize(this.el.dom.clientWidth, this.el.getHeight());
                 }
             }else{
+                // Adds an event to set the correct height afterExpand.  This accounts for the deferHeight flag in panel
                 this.queuedBodySize = {width: w, height: h};
                 if(!this.queuedExpand && this.allowQueuedExpand !== false){
                     this.queuedExpand = true;
                     this.on('expand', function(){
                         delete this.queuedExpand;
                         this.onResize(this.queuedBodySize.width, this.queuedBodySize.height);
-                        this.doLayout();
                     }, this, {single:true});
                 }
             }
             this.onBodyResize(w, h);
         }
         this.syncShadow();
+        Ext.Panel.superclass.onResize.call(this);
     },
-    
+
     // private
     onBodyResize: function(w, h){
         this.fireEvent('bodyresize', this, w, h);
     },
-    
+
     // private
     getToolbarHeight: function(){
         var h = 0;
@@ -23048,6 +24435,11 @@ new Ext.Panel({
         return this.body;
     },
 
+    // private
+    getContentTarget : function(){
+        return this.body;
+    },
+
     /**
      * <p>Sets the title text for the panel and optionally the {@link #iconCls icon class}.</p>
      * <p>In order to be able to set the title, a header element must have been created
@@ -23105,38 +24497,50 @@ panel.load({
 
     // private
     beforeDestroy : function(){
+        Ext.Panel.superclass.beforeDestroy.call(this);
         if(this.header){
             this.header.removeAllListeners();
-            if(this.headerAsText){
-                Ext.Element.uncache(this.header.child('span'));
-            }
-        }
-        Ext.Element.uncache(
-            this.ft,
-            this.mc,
-            this.header,
-            this.tbar,
-            this.bbar,
-            this.footer,
-            this.body,
-            this.bwrap
-        );
+        }
         if(this.tools){
             for(var k in this.tools){
                 Ext.destroy(this.tools[k]);
             }
         }
-        if(this.buttons){
-            for(var b in this.buttons){
-                Ext.destroy(this.buttons[b]);
+        if(this.toolbars.length > 0){
+            Ext.each(this.toolbars, function(tb){
+                tb.un('afterlayout', this.syncHeight, this);
+                tb.un('remove', this.syncHeight, this);
+            }, this);
+        }
+        if(Ext.isArray(this.buttons)){
+            while(this.buttons.length) {
+                Ext.destroy(this.buttons[0]);
             }
         }
         if(this.rendered){
-            Ext.destroy(this.toolbars);
+            Ext.destroy(
+                this.ft,
+                this.header,
+                this.footer,
+                this.toolbars,
+                this.tbar,
+                this.bbar,
+                this.body,
+                this.mc,
+                this.bwrap
+            );
+            if (this.fbar) {
+                Ext.destroy(
+                    this.fbar,
+                    this.fbar.el
+                );
+            }
         }else{
-            Ext.destroy(this.topToolbar, this.bottomToolbar);
+            Ext.destroy(
+                this.topToolbar,
+                this.bottomToolbar
+            );
         }
-        Ext.Panel.superclass.beforeDestroy.call(this);
     },
 
     // private
@@ -23256,6 +24660,11 @@ Ext.extend(Ext.Editor, Ext.Component, {
      * The position to align to (see {@link Ext.Element#alignTo} for more details, defaults to "c-c?").
      */
     alignment: "c-c?",
+    /**
+     * @cfg {Array} offsets
+     * The offsets to use when aligning (see {@link Ext.Element#alignTo} for more details. Defaults to <tt>[0, 0]</tt>.
+     */
+    offsets: [0, 0],
     /**
      * @cfg {Boolean/String} shadow "sides" for sides/bottom only, "frame" for 4-way shadow, and "drop"
      * for bottom-right shadow (defaults to "frame")
@@ -23389,7 +24798,7 @@ Ext.extend(Ext.Editor, Ext.Component, {
                 this.cancelEdit();
             }
             if(field.triggerBlur){
-                field.triggerBlur(); 
+                field.triggerBlur();
             }
         }
         this.fireEvent('specialkey', field, e);
@@ -23412,9 +24821,9 @@ Ext.extend(Ext.Editor, Ext.Component, {
         }
         if(this.fireEvent("beforestartedit", this, this.boundEl, v) !== false){
             this.startValue = v;
+            this.field.reset();
             this.field.setValue(v);
-            this.doAutoSize();
-            this.el.alignTo(this.boundEl, this.alignment);
+            this.realign(true);
             this.editing = true;
             this.show();
         }
@@ -23461,9 +24870,13 @@ Ext.extend(Ext.Editor, Ext.Component, {
 
     /**
      * Realigns the editor to the bound field based on the current alignment config value.
+     * @param {Boolean} autoSize (optional) True to size the field to the dimensions of the bound element.
      */
-    realign : function(){
-        this.el.alignTo(this.boundEl, this.alignment);
+    realign : function(autoSize){
+        if(autoSize === true){
+            this.doAutoSize();
+        }
+        this.el.alignTo(this.boundEl, this.alignment, this.offsets);
     },
 
     /**
@@ -23519,7 +24932,7 @@ Ext.extend(Ext.Editor, Ext.Component, {
             this.fireEvent("canceledit", this, v, this.startValue);
         }
     },
-    
+
     // private
     hideEdit: function(remainVisible){
         if(remainVisible !== true){
@@ -23530,7 +24943,8 @@ Ext.extend(Ext.Editor, Ext.Component, {
 
     // private
     onBlur : function(){
-        if(this.allowBlur !== true && this.editing){
+        // selectSameEditor flag allows the same editor to be started without onBlur firing on itself
+        if(this.allowBlur !== true && this.editing && this.selectSameEditor !== true){
             this.completeEdit();
         }
     },
@@ -23568,11 +24982,14 @@ Ext.extend(Ext.Editor, Ext.Component, {
     },
 
     beforeDestroy : function(){
-        Ext.destroy(this.field);
-        this.field = null;
+        Ext.destroyMembers(this, 'field');
+
+        delete this.parentEl;
+        delete this.boundEl;
     }
 });
-Ext.reg('editor', Ext.Editor);/**
+Ext.reg('editor', Ext.Editor);
+/**
  * @class Ext.ColorPalette
  * @extends Ext.Component
  * Simple color palette class for choosing colors.  The palette can be rendered to any container.<br />
@@ -23590,23 +25007,7 @@ cp.on('select', function(palette, selColor){
  * @param {Object} config The config object
  * @xtype colorpalette
  */
-Ext.ColorPalette = function(config){
-    Ext.ColorPalette.superclass.constructor.call(this, config);
-    this.addEvents(
-        /**
-            * @event select
-            * Fires when a color is selected
-            * @param {ColorPalette} this
-            * @param {String} color The 6-digit color hex code (without the # symbol)
-            */
-        'select'
-    );
-
-    if(this.handler){
-        this.on('select', this.handler, this.scope, true);
-    }
-};
-Ext.extend(Ext.ColorPalette, Ext.Component, {
+Ext.ColorPalette = Ext.extend(Ext.Component, {
        /**
         * @cfg {String} tpl An existing XTemplate instance to be used in place of the default template for rendering the component.
         */
@@ -23621,6 +25022,11 @@ Ext.extend(Ext.ColorPalette, Ext.Component, {
      * the hex codes are case-sensitive.
      */
     value : null,
+    /**
+     * @cfg {String} clickEvent
+     * The DOM event that will cause a color to be selected. This can be any valid event name (dblclick, contextmenu). 
+     * Defaults to <tt>'click'</tt>.
+     */
     clickEvent :'click',
     // private
     ctype : 'Ext.ColorPalette',
@@ -23669,18 +25075,36 @@ cp.colors = ['000000', '993300', '333300'];
      * The scope (<tt><b>this</b></tt> reference) in which the <code>{@link #handler}</code>
      * function will be called.  Defaults to this ColorPalette instance.
      */
+    
+    // private
+    initComponent : function(){
+        Ext.ColorPalette.superclass.initComponent.call(this);
+        this.addEvents(
+            /**
+             * @event select
+             * Fires when a color is selected
+             * @param {ColorPalette} this
+             * @param {String} color The 6-digit color hex code (without the # symbol)
+             */
+            'select'
+        );
+
+        if(this.handler){
+            this.on('select', this.handler, this.scope, true);
+        }    
+    },
 
     // private
     onRender : function(container, position){
+        this.autoEl = {
+            tag: 'div',
+            cls: this.itemCls
+        };
+        Ext.ColorPalette.superclass.onRender.call(this, container, position);
         var t = this.tpl || new Ext.XTemplate(
             '<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on">&#160;</span></em></a></tpl>'
         );
-        var el = document.createElement('div');
-        el.id = this.getId();
-        el.className = this.itemCls;
-        t.overwrite(el, this.colors);
-        container.dom.insertBefore(el, position);
-        this.el = Ext.get(el);
+        t.overwrite(this.el, this.colors);
         this.mon(this.el, this.clickEvent, this.handleClick, this, {delegate: 'a'});
         if(this.clickEvent != 'click'){
                this.mon(this.el, 'click', Ext.emptyFn, this, {delegate: 'a', preventDefault: true});
@@ -23728,841 +25152,860 @@ cp.colors = ['000000', '993300', '333300'];
      */
 });
 Ext.reg('colorpalette', Ext.ColorPalette);
-/**\r
- * @class Ext.DatePicker\r
- * @extends Ext.Component\r
- * Simple date picker class.\r
- * @constructor\r
- * Create a new DatePicker\r
- * @param {Object} config The config object\r
- * @xtype datepicker\r
- */\r
-Ext.DatePicker = Ext.extend(Ext.BoxComponent, {\r
-    /**\r
-     * @cfg {String} todayText\r
-     * The text to display on the button that selects the current date (defaults to <tt>'Today'</tt>)\r
-     */\r
-    todayText : 'Today',\r
-    /**\r
-     * @cfg {String} okText\r
-     * The text to display on the ok button (defaults to <tt>'&#160;OK&#160;'</tt> to give the user extra clicking room)\r
-     */\r
-    okText : '&#160;OK&#160;',\r
-    /**\r
-     * @cfg {String} cancelText\r
-     * The text to display on the cancel button (defaults to <tt>'Cancel'</tt>)\r
-     */\r
-    cancelText : 'Cancel',\r
-    /**\r
-     * @cfg {Function} handler\r
-     * Optional. A function that will handle the select event of this picker.\r
-     * The handler is passed the following parameters:<div class="mdetail-params"><ul>\r
-     * <li><code>picker</code> : DatePicker<div class="sub-desc">The Ext.DatePicker.</div></li>\r
-     * <li><code>date</code> : Date<div class="sub-desc">The selected date.</div></li>\r
-     * </ul></div>\r
-     */\r
-    /**\r
-     * @cfg {Object} scope\r
-     * The scope (<tt><b>this</b></tt> reference) in which the <code>{@link #handler}</code>\r
-     * function will be called.  Defaults to this DatePicker instance.\r
-     */ \r
-    /**\r
-     * @cfg {String} todayTip\r
-     * The tooltip to display for the button that selects the current date (defaults to <tt>'{current date} (Spacebar)'</tt>)\r
-     */\r
-    todayTip : '{0} (Spacebar)',\r
-    /**\r
-     * @cfg {String} minText\r
-     * The error text to display if the minDate validation fails (defaults to <tt>'This date is before the minimum date'</tt>)\r
-     */\r
-    minText : 'This date is before the minimum date',\r
-    /**\r
-     * @cfg {String} maxText\r
-     * The error text to display if the maxDate validation fails (defaults to <tt>'This date is after the maximum date'</tt>)\r
-     */\r
-    maxText : 'This date is after the maximum date',\r
-    /**\r
-     * @cfg {String} format\r
-     * The default date format string which can be overriden for localization support.  The format must be\r
-     * valid according to {@link Date#parseDate} (defaults to <tt>'m/d/y'</tt>).\r
-     */\r
-    format : 'm/d/y',\r
-    /**\r
-     * @cfg {String} disabledDaysText\r
-     * The tooltip to display when the date falls on a disabled day (defaults to <tt>'Disabled'</tt>)\r
-     */\r
-    disabledDaysText : 'Disabled',\r
-    /**\r
-     * @cfg {String} disabledDatesText\r
-     * The tooltip text to display when the date falls on a disabled date (defaults to <tt>'Disabled'</tt>)\r
-     */\r
-    disabledDatesText : 'Disabled',\r
-    /**\r
-     * @cfg {Array} monthNames\r
-     * An array of textual month names which can be overriden for localization support (defaults to Date.monthNames)\r
-     */\r
-    monthNames : Date.monthNames,\r
-    /**\r
-     * @cfg {Array} dayNames\r
-     * An array of textual day names which can be overriden for localization support (defaults to Date.dayNames)\r
-     */\r
-    dayNames : Date.dayNames,\r
-    /**\r
-     * @cfg {String} nextText\r
-     * The next month navigation button tooltip (defaults to <tt>'Next Month (Control+Right)'</tt>)\r
-     */\r
-    nextText : 'Next Month (Control+Right)',\r
-    /**\r
-     * @cfg {String} prevText\r
-     * The previous month navigation button tooltip (defaults to <tt>'Previous Month (Control+Left)'</tt>)\r
-     */\r
-    prevText : 'Previous Month (Control+Left)',\r
-    /**\r
-     * @cfg {String} monthYearText\r
-     * The header month selector tooltip (defaults to <tt>'Choose a month (Control+Up/Down to move years)'</tt>)\r
-     */\r
-    monthYearText : 'Choose a month (Control+Up/Down to move years)',\r
-    /**\r
-     * @cfg {Number} startDay\r
-     * Day index at which the week should begin, 0-based (defaults to 0, which is Sunday)\r
-     */\r
-    startDay : 0,\r
-    /**\r
-     * @cfg {Boolean} showToday\r
-     * False to hide the footer area containing the Today button and disable the keyboard handler for spacebar\r
-     * that selects the current date (defaults to <tt>true</tt>).\r
-     */\r
-    showToday : true,\r
-    /**\r
-     * @cfg {Date} minDate\r
-     * Minimum allowable date (JavaScript date object, defaults to null)\r
-     */\r
-    /**\r
-     * @cfg {Date} maxDate\r
-     * Maximum allowable date (JavaScript date object, defaults to null)\r
-     */\r
-    /**\r
-     * @cfg {Array} disabledDays\r
-     * An array of days to disable, 0-based. For example, [0, 6] disables Sunday and Saturday (defaults to null).\r
-     */\r
-    /**\r
-     * @cfg {RegExp} disabledDatesRE\r
-     * JavaScript regular expression used to disable a pattern of dates (defaults to null).  The {@link #disabledDates}\r
-     * config will generate this regex internally, but if you specify disabledDatesRE it will take precedence over the\r
-     * disabledDates value.\r
-     */\r
-    /**\r
-     * @cfg {Array} disabledDates\r
-     * An array of 'dates' to disable, as strings. These strings will be used to build a dynamic regular\r
-     * expression so they are very powerful. Some examples:\r
-     * <ul>\r
-     * <li>['03/08/2003', '09/16/2003'] would disable those exact dates</li>\r
-     * <li>['03/08', '09/16'] would disable those days for every year</li>\r
-     * <li>['^03/08'] would only match the beginning (useful if you are using short years)</li>\r
-     * <li>['03/../2006'] would disable every day in March 2006</li>\r
-     * <li>['^03'] would disable every day in every March</li>\r
-     * </ul>\r
-     * Note that the format of the dates included in the array should exactly match the {@link #format} config.\r
-     * In order to support regular expressions, if you are using a date format that has '.' in it, you will have to\r
-     * escape the dot when restricting dates. For example: ['03\\.08\\.03'].\r
-     */\r
-\r
-    // private\r
-    initComponent : function(){\r
-        Ext.DatePicker.superclass.initComponent.call(this);\r
-\r
-        this.value = this.value ?\r
-                 this.value.clearTime(true) : new Date().clearTime();\r
-\r
-        this.addEvents(\r
-            /**\r
-             * @event select\r
-             * Fires when a date is selected\r
-             * @param {DatePicker} this\r
-             * @param {Date} date The selected date\r
-             */\r
-            'select'\r
-        );\r
-\r
-        if(this.handler){\r
-            this.on('select', this.handler,  this.scope || this);\r
-        }\r
-\r
-        this.initDisabledDays();\r
-    },\r
-\r
-    // private\r
-    initDisabledDays : function(){\r
-        if(!this.disabledDatesRE && this.disabledDates){\r
-            var dd = this.disabledDates,\r
-                len = dd.length - 1,\r
-                re = '(?:';\r
-                \r
-            Ext.each(dd, function(d, i){\r
-                re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];\r
-                if(i != len){\r
-                    re += '|';\r
-                }\r
-            }, this);\r
-            this.disabledDatesRE = new RegExp(re + ')');\r
-        }\r
-    },\r
-\r
-    /**\r
-     * Replaces any existing disabled dates with new values and refreshes the DatePicker.\r
-     * @param {Array/RegExp} disabledDates An array of date strings (see the {@link #disabledDates} config\r
-     * for details on supported values), or a JavaScript regular expression used to disable a pattern of dates.\r
-     */\r
-    setDisabledDates : function(dd){\r
-        if(Ext.isArray(dd)){\r
-            this.disabledDates = dd;\r
-            this.disabledDatesRE = null;\r
-        }else{\r
-            this.disabledDatesRE = dd;\r
-        }\r
-        this.initDisabledDays();\r
-        this.update(this.value, true);\r
-    },\r
-\r
-    /**\r
-     * Replaces any existing disabled days (by index, 0-6) with new values and refreshes the DatePicker.\r
-     * @param {Array} disabledDays An array of disabled day indexes. See the {@link #disabledDays} config\r
-     * for details on supported values.\r
-     */\r
-    setDisabledDays : function(dd){\r
-        this.disabledDays = dd;\r
-        this.update(this.value, true);\r
-    },\r
-\r
-    /**\r
-     * Replaces any existing {@link #minDate} with the new value and refreshes the DatePicker.\r
-     * @param {Date} value The minimum date that can be selected\r
-     */\r
-    setMinDate : function(dt){\r
-        this.minDate = dt;\r
-        this.update(this.value, true);\r
-    },\r
-\r
-    /**\r
-     * Replaces any existing {@link #maxDate} with the new value and refreshes the DatePicker.\r
-     * @param {Date} value The maximum date that can be selected\r
-     */\r
-    setMaxDate : function(dt){\r
-        this.maxDate = dt;\r
-        this.update(this.value, true);\r
-    },\r
-\r
-    /**\r
-     * Sets the value of the date field\r
-     * @param {Date} value The date to set\r
-     */\r
-    setValue : function(value){\r
-        this.value = value.clearTime(true);\r
-        this.update(this.value);\r
-    },\r
-\r
-    /**\r
-     * Gets the current selected value of the date field\r
-     * @return {Date} The selected date\r
-     */\r
-    getValue : function(){\r
-        return this.value;\r
-    },\r
-\r
-    // private\r
-    focus : function(){\r
-        this.update(this.activeDate);\r
-    },\r
-    \r
-    // private\r
-    onEnable: function(initial){\r
-        Ext.DatePicker.superclass.onEnable.call(this);    \r
-        this.doDisabled(false);\r
-        this.update(initial ? this.value : this.activeDate);\r
-        if(Ext.isIE){\r
-            this.el.repaint();\r
-        }\r
-        \r
-    },\r
-    \r
-    // private\r
-    onDisable : function(){\r
-        Ext.DatePicker.superclass.onDisable.call(this);   \r
-        this.doDisabled(true);\r
-        if(Ext.isIE && !Ext.isIE8){\r
-            /* Really strange problem in IE6/7, when disabled, have to explicitly\r
-             * repaint each of the nodes to get them to display correctly, simply\r
-             * calling repaint on the main element doesn't appear to be enough.\r
-             */\r
-             Ext.each([].concat(this.textNodes, this.el.query('th span')), function(el){\r
-                 Ext.fly(el).repaint();\r
-             });\r
-        }\r
-    },\r
-    \r
-    // private\r
-    doDisabled : function(disabled){\r
-        this.keyNav.setDisabled(disabled);\r
-        this.prevRepeater.setDisabled(disabled);\r
-        this.nextRepeater.setDisabled(disabled);\r
-        if(this.showToday){\r
-            this.todayKeyListener.setDisabled(disabled);\r
-            this.todayBtn.setDisabled(disabled);\r
-        }\r
-    },\r
-\r
-    // private\r
-    onRender : function(container, position){\r
-        var m = [\r
-             '<table cellspacing="0">',\r
-                '<tr><td class="x-date-left"><a href="#" title="', this.prevText ,'">&#160;</a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="', this.nextText ,'">&#160;</a></td></tr>',\r
-                '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'],\r
-                dn = this.dayNames,\r
-                i;\r
-        for(i = 0; i < 7; i++){\r
-            var d = this.startDay+i;\r
-            if(d > 6){\r
-                d = d-7;\r
-            }\r
-            m.push('<th><span>', dn[d].substr(0,1), '</span></th>');\r
-        }\r
-        m[m.length] = '</tr></thead><tbody><tr>';\r
-        for(i = 0; i < 42; i++) {\r
-            if(i % 7 === 0 && i !== 0){\r
-                m[m.length] = '</tr><tr>';\r
-            }\r
-            m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';\r
-        }\r
-        m.push('</tr></tbody></table></td></tr>',\r
-                this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '',\r
-                '</table><div class="x-date-mp"></div>');\r
-\r
-        var el = document.createElement('div');\r
-        el.className = 'x-date-picker';\r
-        el.innerHTML = m.join('');\r
-\r
-        container.dom.insertBefore(el, position);\r
-\r
-        this.el = Ext.get(el);\r
-        this.eventEl = Ext.get(el.firstChild);\r
-\r
-        this.prevRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-left a'), {\r
-            handler: this.showPrevMonth,\r
-            scope: this,\r
-            preventDefault:true,\r
-            stopDefault:true\r
-        });\r
-\r
-        this.nextRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-right a'), {\r
-            handler: this.showNextMonth,\r
-            scope: this,\r
-            preventDefault:true,\r
-            stopDefault:true\r
-        });\r
-\r
-        this.monthPicker = this.el.down('div.x-date-mp');\r
-        this.monthPicker.enableDisplayMode('block');\r
-\r
-        this.keyNav = new Ext.KeyNav(this.eventEl, {\r
-            'left' : function(e){\r
-                if(e.ctrlKey){\r
-                    this.showPrevMonth();\r
-                }else{\r
-                    this.update(this.activeDate.add('d', -1));    \r
-                }\r
-            },\r
-\r
-            'right' : function(e){\r
-                if(e.ctrlKey){\r
-                    this.showNextMonth();\r
-                }else{\r
-                    this.update(this.activeDate.add('d', 1));    \r
-                }\r
-            },\r
-\r
-            'up' : function(e){\r
-                if(e.ctrlKey){\r
-                    this.showNextYear();\r
-                }else{\r
-                    this.update(this.activeDate.add('d', -7));\r
-                }\r
-            },\r
-\r
-            'down' : function(e){\r
-                if(e.ctrlKey){\r
-                    this.showPrevYear();\r
-                }else{\r
-                    this.update(this.activeDate.add('d', 7));\r
-                }\r
-            },\r
-\r
-            'pageUp' : function(e){\r
-                this.showNextMonth();\r
-            },\r
-\r
-            'pageDown' : function(e){\r
-                this.showPrevMonth();\r
-            },\r
-\r
-            'enter' : function(e){\r
-                e.stopPropagation();\r
-                return true;\r
-            },\r
-\r
-            scope : this\r
-        });\r
-\r
-        this.el.unselectable();\r
-\r
-        this.cells = this.el.select('table.x-date-inner tbody td');\r
-        this.textNodes = this.el.query('table.x-date-inner tbody span');\r
-\r
-        this.mbtn = new Ext.Button({\r
-            text: '&#160;',\r
-            tooltip: this.monthYearText,\r
-            renderTo: this.el.child('td.x-date-middle', true)\r
-        });\r
-        this.mbtn.el.child('em').addClass('x-btn-arrow');\r
-\r
-        if(this.showToday){\r
-            this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday,  this);\r
-            var today = (new Date()).dateFormat(this.format);\r
-            this.todayBtn = new Ext.Button({\r
-                renderTo: this.el.child('td.x-date-bottom', true),\r
-                text: String.format(this.todayText, today),\r
-                tooltip: String.format(this.todayTip, today),\r
-                handler: this.selectToday,\r
-                scope: this\r
-            });\r
-        }\r
-        this.mon(this.eventEl, 'mousewheel', this.handleMouseWheel, this);\r
-        this.mon(this.eventEl, 'click', this.handleDateClick,  this, {delegate: 'a.x-date-date'});\r
-        this.mon(this.mbtn, 'click', this.showMonthPicker, this);\r
-        this.onEnable(true);\r
-    },\r
-\r
-    // private\r
-    createMonthPicker : function(){\r
-        if(!this.monthPicker.dom.firstChild){\r
-            var buf = ['<table border="0" cellspacing="0">'];\r
-            for(var i = 0; i < 6; i++){\r
-                buf.push(\r
-                    '<tr><td class="x-date-mp-month"><a href="#">', Date.getShortMonthName(i), '</a></td>',\r
-                    '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', Date.getShortMonthName(i + 6), '</a></td>',\r
-                    i === 0 ?\r
-                    '<td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-prev"></a></td><td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-next"></a></td></tr>' :\r
-                    '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'\r
-                );\r
-            }\r
-            buf.push(\r
-                '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',\r
-                    this.okText,\r
-                    '</button><button type="button" class="x-date-mp-cancel">',\r
-                    this.cancelText,\r
-                    '</button></td></tr>',\r
-                '</table>'\r
-            );\r
-            this.monthPicker.update(buf.join(''));\r
-\r
-            this.mon(this.monthPicker, 'click', this.onMonthClick, this);\r
-            this.mon(this.monthPicker, 'dblclick', this.onMonthDblClick, this);\r
-\r
-            this.mpMonths = this.monthPicker.select('td.x-date-mp-month');\r
-            this.mpYears = this.monthPicker.select('td.x-date-mp-year');\r
-\r
-            this.mpMonths.each(function(m, a, i){\r
-                i += 1;\r
-                if((i%2) === 0){\r
-                    m.dom.xmonth = 5 + Math.round(i * 0.5);\r
-                }else{\r
-                    m.dom.xmonth = Math.round((i-1) * 0.5);\r
-                }\r
-            });\r
-        }\r
-    },\r
-\r
-    // private\r
-    showMonthPicker : function(){\r
-        if(!this.disabled){\r
-            this.createMonthPicker();\r
-            var size = this.el.getSize();\r
-            this.monthPicker.setSize(size);\r
-            this.monthPicker.child('table').setSize(size);\r
-\r
-            this.mpSelMonth = (this.activeDate || this.value).getMonth();\r
-            this.updateMPMonth(this.mpSelMonth);\r
-            this.mpSelYear = (this.activeDate || this.value).getFullYear();\r
-            this.updateMPYear(this.mpSelYear);\r
-\r
-            this.monthPicker.slideIn('t', {duration:0.2});\r
-        }\r
-    },\r
-\r
-    // private\r
-    updateMPYear : function(y){\r
-        this.mpyear = y;\r
-        var ys = this.mpYears.elements;\r
-        for(var i = 1; i <= 10; i++){\r
-            var td = ys[i-1], y2;\r
-            if((i%2) === 0){\r
-                y2 = y + Math.round(i * 0.5);\r
-                td.firstChild.innerHTML = y2;\r
-                td.xyear = y2;\r
-            }else{\r
-                y2 = y - (5-Math.round(i * 0.5));\r
-                td.firstChild.innerHTML = y2;\r
-                td.xyear = y2;\r
-            }\r
-            this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');\r
-        }\r
-    },\r
-\r
-    // private\r
-    updateMPMonth : function(sm){\r
-        this.mpMonths.each(function(m, a, i){\r
-            m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');\r
-        });\r
-    },\r
-\r
-    // private\r
-    selectMPMonth : function(m){\r
-\r
-    },\r
-\r
-    // private\r
-    onMonthClick : function(e, t){\r
-        e.stopEvent();\r
-        var el = new Ext.Element(t), pn;\r
-        if(el.is('button.x-date-mp-cancel')){\r
-            this.hideMonthPicker();\r
-        }\r
-        else if(el.is('button.x-date-mp-ok')){\r
-            var d = new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate());\r
-            if(d.getMonth() != this.mpSelMonth){\r
-                // 'fix' the JS rolling date conversion if needed\r
-                d = new Date(this.mpSelYear, this.mpSelMonth, 1).getLastDateOfMonth();\r
-            }\r
-            this.update(d);\r
-            this.hideMonthPicker();\r
-        }\r
-        else if((pn = el.up('td.x-date-mp-month', 2))){\r
-            this.mpMonths.removeClass('x-date-mp-sel');\r
-            pn.addClass('x-date-mp-sel');\r
-            this.mpSelMonth = pn.dom.xmonth;\r
-        }\r
-        else if((pn = el.up('td.x-date-mp-year', 2))){\r
-            this.mpYears.removeClass('x-date-mp-sel');\r
-            pn.addClass('x-date-mp-sel');\r
-            this.mpSelYear = pn.dom.xyear;\r
-        }\r
-        else if(el.is('a.x-date-mp-prev')){\r
-            this.updateMPYear(this.mpyear-10);\r
-        }\r
-        else if(el.is('a.x-date-mp-next')){\r
-            this.updateMPYear(this.mpyear+10);\r
-        }\r
-    },\r
-\r
-    // private\r
-    onMonthDblClick : function(e, t){\r
-        e.stopEvent();\r
-        var el = new Ext.Element(t), pn;\r
-        if((pn = el.up('td.x-date-mp-month', 2))){\r
-            this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));\r
-            this.hideMonthPicker();\r
-        }\r
-        else if((pn = el.up('td.x-date-mp-year', 2))){\r
-            this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));\r
-            this.hideMonthPicker();\r
-        }\r
-    },\r
-\r
-    // private\r
-    hideMonthPicker : function(disableAnim){\r
-        if(this.monthPicker){\r
-            if(disableAnim === true){\r
-                this.monthPicker.hide();\r
-            }else{\r
-                this.monthPicker.slideOut('t', {duration:0.2});\r
-            }\r
-        }\r
-    },\r
-\r
-    // private\r
-    showPrevMonth : function(e){\r
-        this.update(this.activeDate.add('mo', -1));\r
-    },\r
-\r
-    // private\r
-    showNextMonth : function(e){\r
-        this.update(this.activeDate.add('mo', 1));\r
-    },\r
-\r
-    // private\r
-    showPrevYear : function(){\r
-        this.update(this.activeDate.add('y', -1));\r
-    },\r
-\r
-    // private\r
-    showNextYear : function(){\r
-        this.update(this.activeDate.add('y', 1));\r
-    },\r
-\r
-    // private\r
-    handleMouseWheel : function(e){\r
-        e.stopEvent();\r
-        if(!this.disabled){\r
-            var delta = e.getWheelDelta();\r
-            if(delta > 0){\r
-                this.showPrevMonth();\r
-            } else if(delta < 0){\r
-                this.showNextMonth();\r
-            }\r
-        }\r
-    },\r
-\r
-    // private\r
-    handleDateClick : function(e, t){\r
-        e.stopEvent();\r
-        if(!this.disabled && t.dateValue && !Ext.fly(t.parentNode).hasClass('x-date-disabled')){\r
-            this.setValue(new Date(t.dateValue));\r
-            this.fireEvent('select', this, this.value);\r
-        }\r
-    },\r
-\r
-    // private\r
-    selectToday : function(){\r
-        if(this.todayBtn && !this.todayBtn.disabled){\r
-            this.setValue(new Date().clearTime());\r
-            this.fireEvent('select', this, this.value);\r
-        }\r
-    },\r
-\r
-    // private\r
-    update : function(date, forceRefresh){\r
-        if(this.rendered){\r
-               var vd = this.activeDate, vis = this.isVisible();\r
-               this.activeDate = date;\r
-               if(!forceRefresh && vd && this.el){\r
-                   var t = date.getTime();\r
-                   if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){\r
-                       this.cells.removeClass('x-date-selected');\r
-                       this.cells.each(function(c){\r
-                          if(c.dom.firstChild.dateValue == t){\r
-                              c.addClass('x-date-selected');\r
-                              if(vis){\r
-                                  Ext.fly(c.dom.firstChild).focus(50);\r
-                              }\r
-                              return false;\r
-                          }\r
-                       });\r
-                       return;\r
-                   }\r
-               }\r
-               var days = date.getDaysInMonth(),\r
-                   firstOfMonth = date.getFirstDateOfMonth(),\r
-                   startingPos = firstOfMonth.getDay()-this.startDay;\r
-       \r
-               if(startingPos < 0){\r
-                   startingPos += 7;\r
-               }\r
-               days += startingPos;\r
-       \r
-               var pm = date.add('mo', -1),\r
-                   prevStart = pm.getDaysInMonth()-startingPos,\r
-                   cells = this.cells.elements,\r
-                   textEls = this.textNodes,\r
-                   // convert everything to numbers so it's fast\r
-                   day = 86400000,\r
-                   d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart)).clearTime(),\r
-                   today = new Date().clearTime().getTime(),\r
-                   sel = date.clearTime(true).getTime(),\r
-                   min = this.minDate ? this.minDate.clearTime(true) : Number.NEGATIVE_INFINITY,\r
-                   max = this.maxDate ? this.maxDate.clearTime(true) : Number.POSITIVE_INFINITY,\r
-                   ddMatch = this.disabledDatesRE,\r
-                   ddText = this.disabledDatesText,\r
-                   ddays = this.disabledDays ? this.disabledDays.join('') : false,\r
-                   ddaysText = this.disabledDaysText,\r
-                   format = this.format;\r
-       \r
-               if(this.showToday){\r
-                   var td = new Date().clearTime(),\r
-                       disable = (td < min || td > max ||\r
-                       (ddMatch && format && ddMatch.test(td.dateFormat(format))) ||\r
-                       (ddays && ddays.indexOf(td.getDay()) != -1));\r
-       \r
-                   if(!this.disabled){\r
-                       this.todayBtn.setDisabled(disable);\r
-                       this.todayKeyListener[disable ? 'disable' : 'enable']();\r
-                   }\r
-               }\r
-       \r
-               var setCellClass = function(cal, cell){\r
-                   cell.title = '';\r
-                   var t = d.getTime();\r
-                   cell.firstChild.dateValue = t;\r
-                   if(t == today){\r
-                       cell.className += ' x-date-today';\r
-                       cell.title = cal.todayText;\r
-                   }\r
-                   if(t == sel){\r
-                       cell.className += ' x-date-selected';\r
-                       if(vis){\r
-                           Ext.fly(cell.firstChild).focus(50);\r
-                       }\r
-                   }\r
-                   // disabling\r
-                   if(t < min) {\r
-                       cell.className = ' x-date-disabled';\r
-                       cell.title = cal.minText;\r
-                       return;\r
-                   }\r
-                   if(t > max) {\r
-                       cell.className = ' x-date-disabled';\r
-                       cell.title = cal.maxText;\r
-                       return;\r
-                   }\r
-                   if(ddays){\r
-                       if(ddays.indexOf(d.getDay()) != -1){\r
-                           cell.title = ddaysText;\r
-                           cell.className = ' x-date-disabled';\r
-                       }\r
-                   }\r
-                   if(ddMatch && format){\r
-                       var fvalue = d.dateFormat(format);\r
-                       if(ddMatch.test(fvalue)){\r
-                           cell.title = ddText.replace('%0', fvalue);\r
-                           cell.className = ' x-date-disabled';\r
-                       }\r
-                   }\r
-               };\r
-       \r
-               var i = 0;\r
-               for(; i < startingPos; i++) {\r
-                   textEls[i].innerHTML = (++prevStart);\r
-                   d.setDate(d.getDate()+1);\r
-                   cells[i].className = 'x-date-prevday';\r
-                   setCellClass(this, cells[i]);\r
-               }\r
-               for(; i < days; i++){\r
-                   var intDay = i - startingPos + 1;\r
-                   textEls[i].innerHTML = (intDay);\r
-                   d.setDate(d.getDate()+1);\r
-                   cells[i].className = 'x-date-active';\r
-                   setCellClass(this, cells[i]);\r
-               }\r
-               var extraDays = 0;\r
-               for(; i < 42; i++) {\r
-                    textEls[i].innerHTML = (++extraDays);\r
-                    d.setDate(d.getDate()+1);\r
-                    cells[i].className = 'x-date-nextday';\r
-                    setCellClass(this, cells[i]);\r
-               }\r
-       \r
-               this.mbtn.setText(this.monthNames[date.getMonth()] + ' ' + date.getFullYear());\r
-       \r
-               if(!this.internalRender){\r
-                   var main = this.el.dom.firstChild,\r
-                       w = main.offsetWidth;\r
-                   this.el.setWidth(w + this.el.getBorderWidth('lr'));\r
-                   Ext.fly(main).setWidth(w);\r
-                   this.internalRender = true;\r
-                   // opera does not respect the auto grow header center column\r
-                   // then, after it gets a width opera refuses to recalculate\r
-                   // without a second pass\r
-                   if(Ext.isOpera && !this.secondPass){\r
-                       main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + 'px';\r
-                       this.secondPass = true;\r
-                       this.update.defer(10, this, [date]);\r
-                   }\r
-               }\r
-        }\r
-    },\r
-\r
-    // private\r
-    beforeDestroy : function() {\r
-        if(this.rendered){\r
-            this.keyNav.disable();\r
-            this.keyNav = null;\r
-            Ext.destroy(\r
-                this.leftClickRpt,\r
-                this.rightClickRpt,\r
-                this.monthPicker,\r
-                this.eventEl,\r
-                this.mbtn,\r
-                this.todayBtn\r
-            );\r
-        }\r
-    }\r
-\r
-    /**\r
-     * @cfg {String} autoEl @hide\r
-     */\r
-});\r
-\r
-Ext.reg('datepicker', Ext.DatePicker);\r
 /**
- * @class Ext.LoadMask
- * A simple utility class for generically masking elements while loading data.  If the {@link #store}
- * config option is specified, the masking will be automatically synchronized with the store's loading
- * process and the mask element will be cached for reuse.  For all other elements, this mask will replace the
- * element's Updater load indicator and will be destroyed after the initial load.
- * <p>Example usage:</p>
- *<pre><code>
-// Basic mask:
-var myMask = new Ext.LoadMask(Ext.getBody(), {msg:"Please wait..."});
-myMask.show();
-</code></pre>
+ * @class Ext.DatePicker
+ * @extends Ext.Component
+ * <p>A popup date picker. This class is used by the {@link Ext.form.DateField DateField} class
+ * to allow browsing and selection of valid dates.</p>
+ * <p>All the string values documented below may be overridden by including an Ext locale file in
+ * your page.</p>
  * @constructor
- * Create a new LoadMask
- * @param {Mixed} el The element or DOM node, or its id
+ * Create a new DatePicker
  * @param {Object} config The config object
+ * @xtype datepicker
  */
-Ext.LoadMask = function(el, config){
-    this.el = Ext.get(el);
-    Ext.apply(this, config);
-    if(this.store){
-        this.store.on('beforeload', this.onBeforeLoad, this);
-        this.store.on('load', this.onLoad, this);
-        this.store.on('exception', this.onLoad, this);
-        this.removeMask = Ext.value(this.removeMask, false);
-    }else{
-        var um = this.el.getUpdater();
-        um.showLoadIndicator = false; // disable the default indicator
-        um.on('beforeupdate', this.onBeforeLoad, this);
-        um.on('update', this.onLoad, this);
-        um.on('failure', this.onLoad, this);
-        this.removeMask = Ext.value(this.removeMask, true);
-    }
-};
-
-Ext.LoadMask.prototype = {
+Ext.DatePicker = Ext.extend(Ext.BoxComponent, {
     /**
-     * @cfg {Ext.data.Store} store
-     * Optional Store to which the mask is bound. The mask is displayed when a load request is issued, and
-     * hidden on either load sucess, or load fail.
+     * @cfg {String} todayText
+     * The text to display on the button that selects the current date (defaults to <code>'Today'</code>)
      */
+    todayText : 'Today',
     /**
-     * @cfg {Boolean} removeMask
-     * True to create a single-use mask that is automatically destroyed after loading (useful for page loads),
-     * False to persist the mask element reference for multiple uses (e.g., for paged data widgets).  Defaults to false.
+     * @cfg {String} okText
+     * The text to display on the ok button (defaults to <code>'&#160;OK&#160;'</code> to give the user extra clicking room)
      */
+    okText : '&#160;OK&#160;',
     /**
-     * @cfg {String} msg
-     * The text to display in a centered loading message box (defaults to 'Loading...')
+     * @cfg {String} cancelText
+     * The text to display on the cancel button (defaults to <code>'Cancel'</code>)
      */
-    msg : 'Loading...',
+    cancelText : 'Cancel',
     /**
-     * @cfg {String} msgCls
-     * The CSS class to apply to the loading message element (defaults to "x-mask-loading")
+     * @cfg {Function} handler
+     * Optional. A function that will handle the select event of this picker.
+     * The handler is passed the following parameters:<div class="mdetail-params"><ul>
+     * <li><code>picker</code> : DatePicker<div class="sub-desc">This DatePicker.</div></li>
+     * <li><code>date</code> : Date<div class="sub-desc">The selected date.</div></li>
+     * </ul></div>
      */
-    msgCls : 'x-mask-loading',
-
     /**
-     * Read-only. True if the mask is currently disabled so that it will not be displayed (defaults to false)
-     * @type Boolean
+     * @cfg {Object} scope
+     * The scope (<code><b>this</b></code> reference) in which the <code>{@link #handler}</code>
+     * function will be called.  Defaults to this DatePicker instance.
+     */ 
+    /**
+     * @cfg {String} todayTip
+     * A string used to format the message for displaying in a tooltip over the button that
+     * selects the current date. Defaults to <code>'{0} (Spacebar)'</code> where
+     * the <code>{0}</code> token is replaced by today's date.
      */
-    disabled: false,
+    todayTip : '{0} (Spacebar)',
+    /**
+     * @cfg {String} minText
+     * The error text to display if the minDate validation fails (defaults to <code>'This date is before the minimum date'</code>)
+     */
+    minText : 'This date is before the minimum date',
+    /**
+     * @cfg {String} maxText
+     * The error text to display if the maxDate validation fails (defaults to <code>'This date is after the maximum date'</code>)
+     */
+    maxText : 'This date is after the maximum date',
+    /**
+     * @cfg {String} format
+     * The default date format string which can be overriden for localization support.  The format must be
+     * valid according to {@link Date#parseDate} (defaults to <code>'m/d/y'</code>).
+     */
+    format : 'm/d/y',
+    /**
+     * @cfg {String} disabledDaysText
+     * The tooltip to display when the date falls on a disabled day (defaults to <code>'Disabled'</code>)
+     */
+    disabledDaysText : 'Disabled',
+    /**
+     * @cfg {String} disabledDatesText
+     * The tooltip text to display when the date falls on a disabled date (defaults to <code>'Disabled'</code>)
+     */
+    disabledDatesText : 'Disabled',
+    /**
+     * @cfg {Array} monthNames
+     * An array of textual month names which can be overriden for localization support (defaults to Date.monthNames)
+     */
+    monthNames : Date.monthNames,
+    /**
+     * @cfg {Array} dayNames
+     * An array of textual day names which can be overriden for localization support (defaults to Date.dayNames)
+     */
+    dayNames : Date.dayNames,
+    /**
+     * @cfg {String} nextText
+     * The next month navigation button tooltip (defaults to <code>'Next Month (Control+Right)'</code>)
+     */
+    nextText : 'Next Month (Control+Right)',
+    /**
+     * @cfg {String} prevText
+     * The previous month navigation button tooltip (defaults to <code>'Previous Month (Control+Left)'</code>)
+     */
+    prevText : 'Previous Month (Control+Left)',
+    /**
+     * @cfg {String} monthYearText
+     * The header month selector tooltip (defaults to <code>'Choose a month (Control+Up/Down to move years)'</code>)
+     */
+    monthYearText : 'Choose a month (Control+Up/Down to move years)',
+    /**
+     * @cfg {Number} startDay
+     * Day index at which the week should begin, 0-based (defaults to 0, which is Sunday)
+     */
+    startDay : 0,
+    /**
+     * @cfg {Boolean} showToday
+     * False to hide the footer area containing the Today button and disable the keyboard handler for spacebar
+     * that selects the current date (defaults to <code>true</code>).
+     */
+    showToday : true,
+    /**
+     * @cfg {Date} minDate
+     * Minimum allowable date (JavaScript date object, defaults to null)
+     */
+    /**
+     * @cfg {Date} maxDate
+     * Maximum allowable date (JavaScript date object, defaults to null)
+     */
+    /**
+     * @cfg {Array} disabledDays
+     * An array of days to disable, 0-based. For example, [0, 6] disables Sunday and Saturday (defaults to null).
+     */
+    /**
+     * @cfg {RegExp} disabledDatesRE
+     * JavaScript regular expression used to disable a pattern of dates (defaults to null).  The {@link #disabledDates}
+     * config will generate this regex internally, but if you specify disabledDatesRE it will take precedence over the
+     * disabledDates value.
+     */
+    /**
+     * @cfg {Array} disabledDates
+     * An array of 'dates' to disable, as strings. These strings will be used to build a dynamic regular
+     * expression so they are very powerful. Some examples:
+     * <ul>
+     * <li>['03/08/2003', '09/16/2003'] would disable those exact dates</li>
+     * <li>['03/08', '09/16'] would disable those days for every year</li>
+     * <li>['^03/08'] would only match the beginning (useful if you are using short years)</li>
+     * <li>['03/../2006'] would disable every day in March 2006</li>
+     * <li>['^03'] would disable every day in every March</li>
+     * </ul>
+     * Note that the format of the dates included in the array should exactly match the {@link #format} config.
+     * In order to support regular expressions, if you are using a date format that has '.' in it, you will have to
+     * escape the dot when restricting dates. For example: ['03\\.08\\.03'].
+     */
+    
+    // private
+    // Set by other components to stop the picker focus being updated when the value changes.
+    focusOnSelect: true,
+
+    // private
+    initComponent : function(){
+        Ext.DatePicker.superclass.initComponent.call(this);
+
+        this.value = this.value ?
+                 this.value.clearTime(true) : new Date().clearTime();
+
+        this.addEvents(
+            /**
+             * @event select
+             * Fires when a date is selected
+             * @param {DatePicker} this DatePicker
+             * @param {Date} date The selected date
+             */
+            'select'
+        );
+
+        if(this.handler){
+            this.on('select', this.handler,  this.scope || this);
+        }
+
+        this.initDisabledDays();
+    },
+
+    // private
+    initDisabledDays : function(){
+        if(!this.disabledDatesRE && this.disabledDates){
+            var dd = this.disabledDates,
+                len = dd.length - 1,
+                re = '(?:';
+                
+            Ext.each(dd, function(d, i){
+                re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];
+                if(i != len){
+                    re += '|';
+                }
+            }, this);
+            this.disabledDatesRE = new RegExp(re + ')');
+        }
+    },
+
+    /**
+     * Replaces any existing disabled dates with new values and refreshes the DatePicker.
+     * @param {Array/RegExp} disabledDates An array of date strings (see the {@link #disabledDates} config
+     * for details on supported values), or a JavaScript regular expression used to disable a pattern of dates.
+     */
+    setDisabledDates : function(dd){
+        if(Ext.isArray(dd)){
+            this.disabledDates = dd;
+            this.disabledDatesRE = null;
+        }else{
+            this.disabledDatesRE = dd;
+        }
+        this.initDisabledDays();
+        this.update(this.value, true);
+    },
+
+    /**
+     * Replaces any existing disabled days (by index, 0-6) with new values and refreshes the DatePicker.
+     * @param {Array} disabledDays An array of disabled day indexes. See the {@link #disabledDays} config
+     * for details on supported values.
+     */
+    setDisabledDays : function(dd){
+        this.disabledDays = dd;
+        this.update(this.value, true);
+    },
+
+    /**
+     * Replaces any existing {@link #minDate} with the new value and refreshes the DatePicker.
+     * @param {Date} value The minimum date that can be selected
+     */
+    setMinDate : function(dt){
+        this.minDate = dt;
+        this.update(this.value, true);
+    },
+
+    /**
+     * Replaces any existing {@link #maxDate} with the new value and refreshes the DatePicker.
+     * @param {Date} value The maximum date that can be selected
+     */
+    setMaxDate : function(dt){
+        this.maxDate = dt;
+        this.update(this.value, true);
+    },
+
+    /**
+     * Sets the value of the date field
+     * @param {Date} value The date to set
+     */
+    setValue : function(value){
+        this.value = value.clearTime(true);
+        this.update(this.value);
+    },
+
+    /**
+     * Gets the current selected value of the date field
+     * @return {Date} The selected date
+     */
+    getValue : function(){
+        return this.value;
+    },
+
+    // private
+    focus : function(){
+        this.update(this.activeDate);
+    },
+    
+    // private
+    onEnable: function(initial){
+        Ext.DatePicker.superclass.onEnable.call(this);    
+        this.doDisabled(false);
+        this.update(initial ? this.value : this.activeDate);
+        if(Ext.isIE){
+            this.el.repaint();
+        }
+        
+    },
+    
+    // private
+    onDisable : function(){
+        Ext.DatePicker.superclass.onDisable.call(this);   
+        this.doDisabled(true);
+        if(Ext.isIE && !Ext.isIE8){
+            /* Really strange problem in IE6/7, when disabled, have to explicitly
+             * repaint each of the nodes to get them to display correctly, simply
+             * calling repaint on the main element doesn't appear to be enough.
+             */
+             Ext.each([].concat(this.textNodes, this.el.query('th span')), function(el){
+                 Ext.fly(el).repaint();
+             });
+        }
+    },
+    
+    // private
+    doDisabled : function(disabled){
+        this.keyNav.setDisabled(disabled);
+        this.prevRepeater.setDisabled(disabled);
+        this.nextRepeater.setDisabled(disabled);
+        if(this.showToday){
+            this.todayKeyListener.setDisabled(disabled);
+            this.todayBtn.setDisabled(disabled);
+        }
+    },
+
+    // private
+    onRender : function(container, position){
+        var m = [
+             '<table cellspacing="0">',
+                '<tr><td class="x-date-left"><a href="#" title="', this.prevText ,'">&#160;</a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="', this.nextText ,'">&#160;</a></td></tr>',
+                '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'],
+                dn = this.dayNames,
+                i;
+        for(i = 0; i < 7; i++){
+            var d = this.startDay+i;
+            if(d > 6){
+                d = d-7;
+            }
+            m.push('<th><span>', dn[d].substr(0,1), '</span></th>');
+        }
+        m[m.length] = '</tr></thead><tbody><tr>';
+        for(i = 0; i < 42; i++) {
+            if(i % 7 === 0 && i !== 0){
+                m[m.length] = '</tr><tr>';
+            }
+            m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
+        }
+        m.push('</tr></tbody></table></td></tr>',
+                this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '',
+                '</table><div class="x-date-mp"></div>');
+
+        var el = document.createElement('div');
+        el.className = 'x-date-picker';
+        el.innerHTML = m.join('');
+
+        container.dom.insertBefore(el, position);
+
+        this.el = Ext.get(el);
+        this.eventEl = Ext.get(el.firstChild);
+
+        this.prevRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-left a'), {
+            handler: this.showPrevMonth,
+            scope: this,
+            preventDefault:true,
+            stopDefault:true
+        });
+
+        this.nextRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-right a'), {
+            handler: this.showNextMonth,
+            scope: this,
+            preventDefault:true,
+            stopDefault:true
+        });
+
+        this.monthPicker = this.el.down('div.x-date-mp');
+        this.monthPicker.enableDisplayMode('block');
+
+        this.keyNav = new Ext.KeyNav(this.eventEl, {
+            'left' : function(e){
+                if(e.ctrlKey){
+                    this.showPrevMonth();
+                }else{
+                    this.update(this.activeDate.add('d', -1));    
+                }
+            },
+
+            'right' : function(e){
+                if(e.ctrlKey){
+                    this.showNextMonth();
+                }else{
+                    this.update(this.activeDate.add('d', 1));    
+                }
+            },
+
+            'up' : function(e){
+                if(e.ctrlKey){
+                    this.showNextYear();
+                }else{
+                    this.update(this.activeDate.add('d', -7));
+                }
+            },
+
+            'down' : function(e){
+                if(e.ctrlKey){
+                    this.showPrevYear();
+                }else{
+                    this.update(this.activeDate.add('d', 7));
+                }
+            },
+
+            'pageUp' : function(e){
+                this.showNextMonth();
+            },
+
+            'pageDown' : function(e){
+                this.showPrevMonth();
+            },
+
+            'enter' : function(e){
+                e.stopPropagation();
+                return true;
+            },
+
+            scope : this
+        });
+
+        this.el.unselectable();
+
+        this.cells = this.el.select('table.x-date-inner tbody td');
+        this.textNodes = this.el.query('table.x-date-inner tbody span');
+
+        this.mbtn = new Ext.Button({
+            text: '&#160;',
+            tooltip: this.monthYearText,
+            renderTo: this.el.child('td.x-date-middle', true)
+        });
+        this.mbtn.el.child('em').addClass('x-btn-arrow');
+
+        if(this.showToday){
+            this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday,  this);
+            var today = (new Date()).dateFormat(this.format);
+            this.todayBtn = new Ext.Button({
+                renderTo: this.el.child('td.x-date-bottom', true),
+                text: String.format(this.todayText, today),
+                tooltip: String.format(this.todayTip, today),
+                handler: this.selectToday,
+                scope: this
+            });
+        }
+        this.mon(this.eventEl, 'mousewheel', this.handleMouseWheel, this);
+        this.mon(this.eventEl, 'click', this.handleDateClick,  this, {delegate: 'a.x-date-date'});
+        this.mon(this.mbtn, 'click', this.showMonthPicker, this);
+        this.onEnable(true);
+    },
+
+    // private
+    createMonthPicker : function(){
+        if(!this.monthPicker.dom.firstChild){
+            var buf = ['<table border="0" cellspacing="0">'];
+            for(var i = 0; i < 6; i++){
+                buf.push(
+                    '<tr><td class="x-date-mp-month"><a href="#">', Date.getShortMonthName(i), '</a></td>',
+                    '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', Date.getShortMonthName(i + 6), '</a></td>',
+                    i === 0 ?
+                    '<td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-prev"></a></td><td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-next"></a></td></tr>' :
+                    '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'
+                );
+            }
+            buf.push(
+                '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',
+                    this.okText,
+                    '</button><button type="button" class="x-date-mp-cancel">',
+                    this.cancelText,
+                    '</button></td></tr>',
+                '</table>'
+            );
+            this.monthPicker.update(buf.join(''));
+
+            this.mon(this.monthPicker, 'click', this.onMonthClick, this);
+            this.mon(this.monthPicker, 'dblclick', this.onMonthDblClick, this);
+
+            this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
+            this.mpYears = this.monthPicker.select('td.x-date-mp-year');
+
+            this.mpMonths.each(function(m, a, i){
+                i += 1;
+                if((i%2) === 0){
+                    m.dom.xmonth = 5 + Math.round(i * 0.5);
+                }else{
+                    m.dom.xmonth = Math.round((i-1) * 0.5);
+                }
+            });
+        }
+    },
+
+    // private
+    showMonthPicker : function(){
+        if(!this.disabled){
+            this.createMonthPicker();
+            var size = this.el.getSize();
+            this.monthPicker.setSize(size);
+            this.monthPicker.child('table').setSize(size);
+
+            this.mpSelMonth = (this.activeDate || this.value).getMonth();
+            this.updateMPMonth(this.mpSelMonth);
+            this.mpSelYear = (this.activeDate || this.value).getFullYear();
+            this.updateMPYear(this.mpSelYear);
+
+            this.monthPicker.slideIn('t', {duration:0.2});
+        }
+    },
+
+    // private
+    updateMPYear : function(y){
+        this.mpyear = y;
+        var ys = this.mpYears.elements;
+        for(var i = 1; i <= 10; i++){
+            var td = ys[i-1], y2;
+            if((i%2) === 0){
+                y2 = y + Math.round(i * 0.5);
+                td.firstChild.innerHTML = y2;
+                td.xyear = y2;
+            }else{
+                y2 = y - (5-Math.round(i * 0.5));
+                td.firstChild.innerHTML = y2;
+                td.xyear = y2;
+            }
+            this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');
+        }
+    },
+
+    // private
+    updateMPMonth : function(sm){
+        this.mpMonths.each(function(m, a, i){
+            m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');
+        });
+    },
+
+    // private
+    selectMPMonth : function(m){
+
+    },
+
+    // private
+    onMonthClick : function(e, t){
+        e.stopEvent();
+        var el = new Ext.Element(t), pn;
+        if(el.is('button.x-date-mp-cancel')){
+            this.hideMonthPicker();
+        }
+        else if(el.is('button.x-date-mp-ok')){
+            var d = new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate());
+            if(d.getMonth() != this.mpSelMonth){
+                // 'fix' the JS rolling date conversion if needed
+                d = new Date(this.mpSelYear, this.mpSelMonth, 1).getLastDateOfMonth();
+            }
+            this.update(d);
+            this.hideMonthPicker();
+        }
+        else if((pn = el.up('td.x-date-mp-month', 2))){
+            this.mpMonths.removeClass('x-date-mp-sel');
+            pn.addClass('x-date-mp-sel');
+            this.mpSelMonth = pn.dom.xmonth;
+        }
+        else if((pn = el.up('td.x-date-mp-year', 2))){
+            this.mpYears.removeClass('x-date-mp-sel');
+            pn.addClass('x-date-mp-sel');
+            this.mpSelYear = pn.dom.xyear;
+        }
+        else if(el.is('a.x-date-mp-prev')){
+            this.updateMPYear(this.mpyear-10);
+        }
+        else if(el.is('a.x-date-mp-next')){
+            this.updateMPYear(this.mpyear+10);
+        }
+    },
+
+    // private
+    onMonthDblClick : function(e, t){
+        e.stopEvent();
+        var el = new Ext.Element(t), pn;
+        if((pn = el.up('td.x-date-mp-month', 2))){
+            this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));
+            this.hideMonthPicker();
+        }
+        else if((pn = el.up('td.x-date-mp-year', 2))){
+            this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
+            this.hideMonthPicker();
+        }
+    },
+
+    // private
+    hideMonthPicker : function(disableAnim){
+        if(this.monthPicker){
+            if(disableAnim === true){
+                this.monthPicker.hide();
+            }else{
+                this.monthPicker.slideOut('t', {duration:0.2});
+            }
+        }
+    },
+
+    // private
+    showPrevMonth : function(e){
+        this.update(this.activeDate.add('mo', -1));
+    },
+
+    // private
+    showNextMonth : function(e){
+        this.update(this.activeDate.add('mo', 1));
+    },
+
+    // private
+    showPrevYear : function(){
+        this.update(this.activeDate.add('y', -1));
+    },
+
+    // private
+    showNextYear : function(){
+        this.update(this.activeDate.add('y', 1));
+    },
+
+    // private
+    handleMouseWheel : function(e){
+        e.stopEvent();
+        if(!this.disabled){
+            var delta = e.getWheelDelta();
+            if(delta > 0){
+                this.showPrevMonth();
+            } else if(delta < 0){
+                this.showNextMonth();
+            }
+        }
+    },
+
+    // private
+    handleDateClick : function(e, t){
+        e.stopEvent();
+        if(!this.disabled && t.dateValue && !Ext.fly(t.parentNode).hasClass('x-date-disabled')){
+            this.cancelFocus = this.focusOnSelect === false;
+            this.setValue(new Date(t.dateValue));
+            delete this.cancelFocus;
+            this.fireEvent('select', this, this.value);
+        }
+    },
+
+    // private
+    selectToday : function(){
+        if(this.todayBtn && !this.todayBtn.disabled){
+            this.setValue(new Date().clearTime());
+            this.fireEvent('select', this, this.value);
+        }
+    },
+
+    // private
+    update : function(date, forceRefresh){
+        if(this.rendered){
+               var vd = this.activeDate, vis = this.isVisible();
+               this.activeDate = date;
+               if(!forceRefresh && vd && this.el){
+                   var t = date.getTime();
+                   if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
+                       this.cells.removeClass('x-date-selected');
+                       this.cells.each(function(c){
+                          if(c.dom.firstChild.dateValue == t){
+                              c.addClass('x-date-selected');
+                              if(vis && !this.cancelFocus){
+                                  Ext.fly(c.dom.firstChild).focus(50);
+                              }
+                              return false;
+                          }
+                       }, this);
+                       return;
+                   }
+               }
+               var days = date.getDaysInMonth(),
+                   firstOfMonth = date.getFirstDateOfMonth(),
+                   startingPos = firstOfMonth.getDay()-this.startDay;
+       
+               if(startingPos < 0){
+                   startingPos += 7;
+               }
+               days += startingPos;
+       
+               var pm = date.add('mo', -1),
+                   prevStart = pm.getDaysInMonth()-startingPos,
+                   cells = this.cells.elements,
+                   textEls = this.textNodes,
+                   // convert everything to numbers so it's fast
+                   day = 86400000,
+                   d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart)).clearTime(),
+                   today = new Date().clearTime().getTime(),
+                   sel = date.clearTime(true).getTime(),
+                   min = this.minDate ? this.minDate.clearTime(true) : Number.NEGATIVE_INFINITY,
+                   max = this.maxDate ? this.maxDate.clearTime(true) : Number.POSITIVE_INFINITY,
+                   ddMatch = this.disabledDatesRE,
+                   ddText = this.disabledDatesText,
+                   ddays = this.disabledDays ? this.disabledDays.join('') : false,
+                   ddaysText = this.disabledDaysText,
+                   format = this.format;
+       
+               if(this.showToday){
+                   var td = new Date().clearTime(),
+                       disable = (td < min || td > max ||
+                       (ddMatch && format && ddMatch.test(td.dateFormat(format))) ||
+                       (ddays && ddays.indexOf(td.getDay()) != -1));
+       
+                   if(!this.disabled){
+                       this.todayBtn.setDisabled(disable);
+                       this.todayKeyListener[disable ? 'disable' : 'enable']();
+                   }
+               }
+       
+               var setCellClass = function(cal, cell){
+                   cell.title = '';
+                   var t = d.getTime();
+                   cell.firstChild.dateValue = t;
+                   if(t == today){
+                       cell.className += ' x-date-today';
+                       cell.title = cal.todayText;
+                   }
+                   if(t == sel){
+                       cell.className += ' x-date-selected';
+                       if(vis){
+                           Ext.fly(cell.firstChild).focus(50);
+                       }
+                   }
+                   // disabling
+                   if(t < min) {
+                       cell.className = ' x-date-disabled';
+                       cell.title = cal.minText;
+                       return;
+                   }
+                   if(t > max) {
+                       cell.className = ' x-date-disabled';
+                       cell.title = cal.maxText;
+                       return;
+                   }
+                   if(ddays){
+                       if(ddays.indexOf(d.getDay()) != -1){
+                           cell.title = ddaysText;
+                           cell.className = ' x-date-disabled';
+                       }
+                   }
+                   if(ddMatch && format){
+                       var fvalue = d.dateFormat(format);
+                       if(ddMatch.test(fvalue)){
+                           cell.title = ddText.replace('%0', fvalue);
+                           cell.className = ' x-date-disabled';
+                       }
+                   }
+               };
+       
+               var i = 0;
+               for(; i < startingPos; i++) {
+                   textEls[i].innerHTML = (++prevStart);
+                   d.setDate(d.getDate()+1);
+                   cells[i].className = 'x-date-prevday';
+                   setCellClass(this, cells[i]);
+               }
+               for(; i < days; i++){
+                   var intDay = i - startingPos + 1;
+                   textEls[i].innerHTML = (intDay);
+                   d.setDate(d.getDate()+1);
+                   cells[i].className = 'x-date-active';
+                   setCellClass(this, cells[i]);
+               }
+               var extraDays = 0;
+               for(; i < 42; i++) {
+                    textEls[i].innerHTML = (++extraDays);
+                    d.setDate(d.getDate()+1);
+                    cells[i].className = 'x-date-nextday';
+                    setCellClass(this, cells[i]);
+               }
+       
+               this.mbtn.setText(this.monthNames[date.getMonth()] + ' ' + date.getFullYear());
+       
+               if(!this.internalRender){
+                   var main = this.el.dom.firstChild,
+                       w = main.offsetWidth;
+                   this.el.setWidth(w + this.el.getBorderWidth('lr'));
+                   Ext.fly(main).setWidth(w);
+                   this.internalRender = true;
+                   // opera does not respect the auto grow header center column
+                   // then, after it gets a width opera refuses to recalculate
+                   // without a second pass
+                   if(Ext.isOpera && !this.secondPass){
+                       main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + 'px';
+                       this.secondPass = true;
+                       this.update.defer(10, this, [date]);
+                   }
+               }
+        }
+    },
+
+    // private
+    beforeDestroy : function() {
+        if(this.rendered){
+            Ext.destroy(
+                this.keyNav,
+                this.monthPicker,
+                this.eventEl,
+                this.mbtn,
+                this.nextRepeater,
+                this.prevRepeater,
+                this.cells.el,
+                this.todayBtn
+            );
+            delete this.textNodes;
+            delete this.cells.elements;
+        }
+    }
+
+    /**
+     * @cfg {String} autoEl @hide
+     */
+});
+
+Ext.reg('datepicker', Ext.DatePicker);
+/**
+ * @class Ext.LoadMask
+ * A simple utility class for generically masking elements while loading data.  If the {@link #store}
+ * config option is specified, the masking will be automatically synchronized with the store's loading
+ * process and the mask element will be cached for reuse.  For all other elements, this mask will replace the
+ * element's Updater load indicator and will be destroyed after the initial load.
+ * <p>Example usage:</p>
+ *<pre><code>
+// Basic mask:
+var myMask = new Ext.LoadMask(Ext.getBody(), {msg:"Please wait..."});
+myMask.show();
+</code></pre>
+ * @constructor
+ * Create a new LoadMask
+ * @param {Mixed} el The element or DOM node, or its id
+ * @param {Object} config The config object
+ */
+Ext.LoadMask = function(el, config){
+    this.el = Ext.get(el);
+    Ext.apply(this, config);
+    if(this.store){
+        this.store.on({
+            scope: this,
+            beforeload: this.onBeforeLoad,
+            load: this.onLoad,
+            exception: this.onLoad
+        });
+        this.removeMask = Ext.value(this.removeMask, false);
+    }else{
+        var um = this.el.getUpdater();
+        um.showLoadIndicator = false; // disable the default indicator
+        um.on({
+            scope: this,
+            beforeupdate: this.onBeforeLoad,
+            update: this.onLoad,
+            failure: this.onLoad
+        });
+        this.removeMask = Ext.value(this.removeMask, true);
+    }
+};
+
+Ext.LoadMask.prototype = {
+    /**
+     * @cfg {Ext.data.Store} store
+     * Optional Store to which the mask is bound. The mask is displayed when a load request is issued, and
+     * hidden on either load sucess, or load fail.
+     */
+    /**
+     * @cfg {Boolean} removeMask
+     * True to create a single-use mask that is automatically destroyed after loading (useful for page loads),
+     * False to persist the mask element reference for multiple uses (e.g., for paged data widgets).  Defaults to false.
+     */
+    /**
+     * @cfg {String} msg
+     * The text to display in a centered loading message box (defaults to 'Loading...')
+     */
+    msg : 'Loading...',
+    /**
+     * @cfg {String} msgCls
+     * The CSS class to apply to the loading message element (defaults to "x-mask-loading")
+     */
+    msgCls : 'x-mask-loading',
+
+    /**
+     * Read-only. True if the mask is currently disabled so that it will not be displayed (defaults to false)
+     * @type Boolean
+     */
+    disabled: false,
 
     /**
      * Disables the mask to prevent it from being displayed
@@ -24635,20 +26078,20 @@ new Ext.Slider({
 </code></pre>\r
  */\r
 Ext.Slider = Ext.extend(Ext.BoxComponent, {\r
-       /**\r
-        * @cfg {Number} value The value to initialize the slider with. Defaults to minValue.\r
-        */\r
-       /**\r
-        * @cfg {Boolean} vertical Orient the Slider vertically rather than horizontally, defaults to false.\r
-        */\r
+    /**\r
+     * @cfg {Number} value The value to initialize the slider with. Defaults to minValue.\r
+     */\r
+    /**\r
+     * @cfg {Boolean} vertical Orient the Slider vertically rather than horizontally, defaults to false.\r
+     */\r
     vertical: false,\r
-       /**\r
-        * @cfg {Number} minValue The minimum value for the Slider. Defaults to 0.\r
-        */\r
+    /**\r
+     * @cfg {Number} minValue The minimum value for the Slider. Defaults to 0.\r
+     */\r
     minValue: 0,\r
-       /**\r
-        * @cfg {Number} maxValue The maximum value for the Slider. Defaults to 100.\r
-        */\r
+    /**\r
+     * @cfg {Number} maxValue The maximum value for the Slider. Defaults to 100.\r
+     */\r
     maxValue: 100,\r
     /**\r
      * @cfg {Number/Boolean} decimalPrecision.\r
@@ -24656,23 +26099,23 @@ Ext.Slider = Ext.extend(Ext.BoxComponent, {
      * <p>To disable rounding, configure as <tt><b>false</b></tt>.</p>\r
      */\r
     decimalPrecision: 0,\r
-       /**\r
-        * @cfg {Number} keyIncrement How many units to change the Slider when adjusting with keyboard navigation. Defaults to 1. If the increment config is larger, it will be used instead.\r
-        */\r
+    /**\r
+     * @cfg {Number} keyIncrement How many units to change the Slider when adjusting with keyboard navigation. Defaults to 1. If the increment config is larger, it will be used instead.\r
+     */\r
     keyIncrement: 1,\r
-       /**\r
-        * @cfg {Number} increment How many units to change the slider when adjusting by drag and drop. Use this option to enable 'snapping'.\r
-        */\r
+    /**\r
+     * @cfg {Number} increment How many units to change the slider when adjusting by drag and drop. Use this option to enable 'snapping'.\r
+     */\r
     increment: 0,\r
-       // private\r
+    // private\r
     clickRange: [5,15],\r
-       /**\r
-        * @cfg {Boolean} clickToChange Determines whether or not clicking on the Slider axis will change the slider. Defaults to true\r
-        */\r
+    /**\r
+     * @cfg {Boolean} clickToChange Determines whether or not clicking on the Slider axis will change the slider. Defaults to true\r
+     */\r
     clickToChange : true,\r
-       /**\r
-        * @cfg {Boolean} animate Turn on or off animation. Defaults to true\r
-        */\r
+    /**\r
+     * @cfg {Boolean} animate Turn on or off animation. Defaults to true\r
+     */\r
     animate: true,\r
 \r
     /**\r
@@ -24693,54 +26136,54 @@ Ext.Slider = Ext.extend(Ext.BoxComponent, {
              * @event beforechange\r
              * Fires before the slider value is changed. By returning false from an event handler,\r
              * you can cancel the event and prevent the slider from changing.\r
-                        * @param {Ext.Slider} slider The slider\r
-                        * @param {Number} newValue The new value which the slider is being changed to.\r
-                        * @param {Number} oldValue The old value which the slider was previously.\r
+             * @param {Ext.Slider} slider The slider\r
+             * @param {Number} newValue The new value which the slider is being changed to.\r
+             * @param {Number} oldValue The old value which the slider was previously.\r
+             */\r
+            'beforechange',\r
+            /**\r
+             * @event change\r
+             * Fires when the slider value is changed.\r
+             * @param {Ext.Slider} slider The slider\r
+             * @param {Number} newValue The new value which the slider has been changed to.\r
+             */\r
+            'change',\r
+            /**\r
+             * @event changecomplete\r
+             * Fires when the slider value is changed by the user and any drag operations have completed.\r
+             * @param {Ext.Slider} slider The slider\r
+             * @param {Number} newValue The new value which the slider has been changed to.\r
              */\r
-                       'beforechange',\r
-                       /**\r
-                        * @event change\r
-                        * Fires when the slider value is changed.\r
-                        * @param {Ext.Slider} slider The slider\r
-                        * @param {Number} newValue The new value which the slider has been changed to.\r
-                        */\r
-                       'change',\r
-                       /**\r
-                        * @event changecomplete\r
-                        * Fires when the slider value is changed by the user and any drag operations have completed.\r
-                        * @param {Ext.Slider} slider The slider\r
-                        * @param {Number} newValue The new value which the slider has been changed to.\r
-                        */\r
-                       'changecomplete',\r
-                       /**\r
-                        * @event dragstart\r
+            'changecomplete',\r
+            /**\r
+             * @event dragstart\r
              * Fires after a drag operation has started.\r
-                        * @param {Ext.Slider} slider The slider\r
-                        * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker\r
-                        */\r
-                       'dragstart',\r
-                       /**\r
-                        * @event drag\r
+             * @param {Ext.Slider} slider The slider\r
+             * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker\r
+             */\r
+            'dragstart',\r
+            /**\r
+             * @event drag\r
              * Fires continuously during the drag operation while the mouse is moving.\r
-                        * @param {Ext.Slider} slider The slider\r
-                        * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker\r
-                        */\r
-                       'drag',\r
-                       /**\r
-                        * @event dragend\r
+             * @param {Ext.Slider} slider The slider\r
+             * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker\r
+             */\r
+            'drag',\r
+            /**\r
+             * @event dragend\r
              * Fires after the drag operation has completed.\r
-                        * @param {Ext.Slider} slider The slider\r
-                        * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker\r
-                        */\r
-                       'dragend'\r
-               );\r
+             * @param {Ext.Slider} slider The slider\r
+             * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker\r
+             */\r
+            'dragend'\r
+        );\r
 \r
         if(this.vertical){\r
             Ext.apply(this, Ext.Slider.Vertical);\r
         }\r
     },\r
 \r
-       // private override\r
+    // private override\r
     onRender : function(){\r
         this.autoEl = {\r
             cls: 'x-slider ' + (this.vertical ? 'x-slider-vert' : 'x-slider-horz'),\r
@@ -24755,7 +26198,7 @@ Ext.Slider = Ext.extend(Ext.BoxComponent, {
         this.initEvents();\r
     },\r
 \r
-       // private override\r
+    // private override\r
     initEvents : function(){\r
         this.thumb.addClassOnOver('x-slider-thumb-over');\r
         this.mon(this.el, {\r
@@ -24775,12 +26218,13 @@ Ext.Slider = Ext.extend(Ext.BoxComponent, {
             autoStart: 300\r
         });\r
         this.tracker.initEl(this.thumb);\r
-        this.on('beforedestroy', this.tracker.destroy, this.tracker);\r
     },\r
 \r
-       // private override\r
+    // private override\r
     onMouseDown : function(e){\r
-        if(this.disabled) {return;}\r
+        if(this.disabled){\r
+            return;\r
+        }\r
         if(this.clickToChange && e.target != this.thumb.dom){\r
             var local = this.innerEl.translatePoints(e.getXY());\r
             this.onClickChange(local);\r
@@ -24788,14 +26232,14 @@ Ext.Slider = Ext.extend(Ext.BoxComponent, {
         this.focus();\r
     },\r
 \r
-       // private\r
+    // private\r
     onClickChange : function(local){\r
         if(local.top > this.clickRange[0] && local.top < this.clickRange[1]){\r
             this.setValue(Ext.util.Format.round(this.reverseValue(local.left), this.decimalPrecision), undefined, true);\r
         }\r
     },\r
 \r
-       // private\r
+    // private\r
     onKeyDown : function(e){\r
         if(this.disabled){e.preventDefault();return;}\r
         var k = e.getKey();\r
@@ -24823,13 +26267,14 @@ Ext.Slider = Ext.extend(Ext.BoxComponent, {
         }\r
     },\r
 \r
-       // private\r
+    // private\r
     doSnap : function(value){\r
-        if(!this.increment || this.increment == 1 || !value) {\r
+        if(!(this.increment && value)){\r
             return value;\r
         }\r
-        var newValue = value, inc = this.increment;\r
-        var m = value % inc;\r
+        var newValue = value,\r
+            inc = this.increment,\r
+            m = value % inc;\r
         if(m != 0){\r
             newValue -= m;\r
             if(m * 2 > inc){\r
@@ -24841,7 +26286,7 @@ Ext.Slider = Ext.extend(Ext.BoxComponent, {
         return newValue.constrain(this.minValue,  this.maxValue);\r
     },\r
 \r
-       // private\r
+    // private\r
     afterRender : function(){\r
         Ext.Slider.superclass.afterRender.apply(this, arguments);\r
         if(this.value !== undefined){\r
@@ -24855,27 +26300,53 @@ Ext.Slider = Ext.extend(Ext.BoxComponent, {
         }\r
     },\r
 \r
-       // private\r
+    // private\r
     getRatio : function(){\r
-        var w = this.innerEl.getWidth();\r
-        var v = this.maxValue - this.minValue;\r
+        var w = this.innerEl.getWidth(),\r
+            v = this.maxValue - this.minValue;\r
         return v == 0 ? w : (w/v);\r
     },\r
 \r
-       // private\r
+    // private\r
     normalizeValue : function(v){\r
         v = this.doSnap(v);\r
         v = Ext.util.Format.round(v, this.decimalPrecision);\r
         v = v.constrain(this.minValue, this.maxValue);\r
         return v;\r
     },\r
+    \r
+    /**\r
+     * Sets the minimum value for the slider instance. If the current value is less than the \r
+     * minimum value, the current value will be changed.\r
+     * @param {Number} val The new minimum value\r
+     */\r
+    setMinValue : function(val){\r
+        this.minValue = val;\r
+        this.syncThumb();\r
+        if(this.value < val){\r
+            this.setValue(val);\r
+        }\r
+    },\r
+    \r
+    /**\r
+     * Sets the maximum value for the slider instance. If the current value is more than the \r
+     * maximum value, the current value will be changed.\r
+     * @param {Number} val The new maximum value\r
+     */\r
+    setMaxValue : function(val){\r
+        this.maxValue = val;\r
+        this.syncThumb();\r
+        if(this.value > val){\r
+            this.setValue(val);\r
+        }\r
+    },\r
 \r
-       /**\r
-        * Programmatically sets the value of the Slider. Ensures that the value is constrained within\r
-        * the minValue and maxValue.\r
-        * @param {Number} value The value to set the slider to. (This will be constrained within minValue and maxValue)\r
-        * @param {Boolean} animate Turn on or off animation, defaults to true\r
-        */\r
+    /**\r
+     * Programmatically sets the value of the Slider. Ensures that the value is constrained within\r
+     * the minValue and maxValue.\r
+     * @param {Number} value The value to set the slider to. (This will be constrained within minValue and maxValue)\r
+     * @param {Boolean} animate Turn on or off animation, defaults to true\r
+     */\r
     setValue : function(v, animate, changeComplete){\r
         v = this.normalizeValue(v);\r
         if(v !== this.value && this.fireEvent('beforechange', this, v, this.value) !== false){\r
@@ -24888,18 +26359,18 @@ Ext.Slider = Ext.extend(Ext.BoxComponent, {
         }\r
     },\r
 \r
-       // private\r
+    // private\r
     translateValue : function(v){\r
         var ratio = this.getRatio();\r
-        return (v * ratio)-(this.minValue * ratio)-this.halfThumb;\r
+        return (v * ratio) - (this.minValue * ratio) - this.halfThumb;\r
     },\r
 \r
-       reverseValue : function(pos){\r
+    reverseValue : function(pos){\r
         var ratio = this.getRatio();\r
-        return (pos+this.halfThumb+(this.minValue * ratio))/ratio;\r
+        return (pos + (this.minValue * ratio)) / ratio;\r
     },\r
 \r
-       // private\r
+    // private\r
     moveThumb: function(v, animate){\r
         if(!animate || this.animate === false){\r
             this.thumb.setLeft(v);\r
@@ -24908,17 +26379,17 @@ Ext.Slider = Ext.extend(Ext.BoxComponent, {
         }\r
     },\r
 \r
-       // private\r
+    // private\r
     focus : function(){\r
         this.focusEl.focus(10);\r
     },\r
 \r
-       // private\r
+    // private\r
     onBeforeDragStart : function(e){\r
         return !this.disabled;\r
     },\r
 \r
-       // private\r
+    // private\r
     onDragStart: function(e){\r
         this.thumb.addClass('x-slider-thumb-drag');\r
         this.dragging = true;\r
@@ -24926,14 +26397,14 @@ Ext.Slider = Ext.extend(Ext.BoxComponent, {
         this.fireEvent('dragstart', this, e);\r
     },\r
 \r
-       // private\r
+    // private\r
     onDrag: function(e){\r
         var pos = this.innerEl.translatePoints(this.tracker.getXY());\r
         this.setValue(Ext.util.Format.round(this.reverseValue(pos.left), this.decimalPrecision), false);\r
         this.fireEvent('drag', this, e);\r
     },\r
 \r
-       // private\r
+    // private\r
     onDragEnd: function(e){\r
         this.thumb.removeClass('x-slider-thumb-drag');\r
         this.dragging = false;\r
@@ -24943,12 +26414,13 @@ Ext.Slider = Ext.extend(Ext.BoxComponent, {
         }\r
     },\r
 \r
-       // private\r
+    // private\r
     onResize : function(w, h){\r
         this.innerEl.setWidth(w - (this.el.getPadding('l') + this.endEl.getPadding('r')));\r
         this.syncThumb();\r
+        Ext.Slider.superclass.onResize.apply(this, arguments);\r
     },\r
-    \r
+\r
     //private\r
     onDisable: function(){\r
         Ext.Slider.superclass.onDisable.call(this);\r
@@ -24960,26 +26432,26 @@ Ext.Slider = Ext.extend(Ext.BoxComponent, {
             this.thumb.hide();\r
             this.innerEl.addClass(this.disabledClass).dom.disabled = true;\r
             if (!this.thumbHolder){\r
-                this.thumbHolder = this.endEl.createChild({cls: 'x-slider-thumb ' + this.disabledClass});    \r
+                this.thumbHolder = this.endEl.createChild({cls: 'x-slider-thumb ' + this.disabledClass});\r
             }\r
             this.thumbHolder.show().setXY(xy);\r
         }\r
     },\r
-    \r
+\r
     //private\r
     onEnable: function(){\r
         Ext.Slider.superclass.onEnable.call(this);\r
         this.thumb.removeClass(this.disabledClass);\r
         if(Ext.isIE){\r
             this.innerEl.removeClass(this.disabledClass).dom.disabled = false;\r
-            if (this.thumbHolder){\r
+            if(this.thumbHolder){\r
                 this.thumbHolder.hide();\r
             }\r
             this.thumb.show();\r
             this.syncThumb();\r
         }\r
     },\r
-    \r
+\r
     /**\r
      * Synchronizes the thumb position to the proper proportion of the total component width based\r
      * on the current slider {@link #value}.  This will be called automatically when the Slider\r
@@ -24992,12 +26464,18 @@ Ext.Slider = Ext.extend(Ext.BoxComponent, {
         }\r
     },\r
 \r
-       /**\r
-        * Returns the current value of the slider\r
-        * @return {Number} The current value of the slider\r
-        */\r
+    /**\r
+     * Returns the current value of the slider\r
+     * @return {Number} The current value of the slider\r
+     */\r
     getValue : function(){\r
         return this.value;\r
+    },\r
+\r
+    // private\r
+    beforeDestroy : function(){\r
+        Ext.destroyMembers(this, 'endEl', 'innerEl', 'thumb', 'halfThumb', 'focusEl', 'tracker', 'thumbHolder');\r
+        Ext.Slider.superclass.beforeDestroy.call(this);\r
     }\r
 });\r
 Ext.reg('slider', Ext.Slider);\r
@@ -25010,8 +26488,8 @@ Ext.Slider.Vertical = {
     },\r
 \r
     getRatio : function(){\r
-        var h = this.innerEl.getHeight();\r
-        var v = this.maxValue - this.minValue;\r
+        var h = this.innerEl.getHeight(),\r
+            v = this.maxValue - this.minValue;\r
         return h/v;\r
     },\r
 \r
@@ -25024,15 +26502,15 @@ Ext.Slider.Vertical = {
     },\r
 \r
     onDrag: function(e){\r
-        var pos = this.innerEl.translatePoints(this.tracker.getXY());\r
-        var bottom = this.innerEl.getHeight()-pos.top;\r
+        var pos = this.innerEl.translatePoints(this.tracker.getXY()),\r
+            bottom = this.innerEl.getHeight()-pos.top;\r
         this.setValue(this.minValue + Ext.util.Format.round(bottom/this.getRatio(), this.decimalPrecision), false);\r
         this.fireEvent('drag', this, e);\r
     },\r
 \r
     onClickChange : function(local){\r
         if(local.left > this.clickRange[0] && local.left < this.clickRange[1]){\r
-            var bottom = this.innerEl.getHeight()-local.top;\r
+            var bottom = this.innerEl.getHeight() - local.top;\r
             this.setValue(this.minValue + Ext.util.Format.round(bottom/this.getRatio(), this.decimalPrecision), undefined, true);\r
         }\r
     }\r
@@ -25152,7 +26630,7 @@ Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {
         if(text){\r
             this.updateText(text);\r
         }\r
-        if(this.rendered){\r
+        if(this.rendered && !this.isDestroyed){\r
             var w = Math.floor(value*this.el.dom.firstChild.offsetWidth);\r
             this.progressBar.setWidth(w, animate === true || (animate !== false && this.animate));\r
             if(this.textTopEl){\r
@@ -25308,17 +26786,33 @@ myAction.on('complete', function(){
         if(this.textTopEl){\r
             this.textTopEl.addClass('x-hidden');\r
         }\r
+        this.clearTimer();\r
+        if(hide === true){\r
+            this.hide();\r
+        }\r
+        return this;\r
+    },\r
+    \r
+    // private\r
+    clearTimer : function(){\r
         if(this.waitTimer){\r
             this.waitTimer.onStop = null; //prevent recursion\r
             Ext.TaskMgr.stop(this.waitTimer);\r
             this.waitTimer = null;\r
         }\r
-        if(hide === true){\r
-            this.hide();\r
-        }\r
-        return this;\r
-    }\r
-});\r
+    },\r
+    \r
+    onDestroy: function(){\r
+        this.clearTimer();\r
+        if(this.rendered){\r
+            if(this.textEl.isComposite){\r
+                this.textEl.clear();\r
+            }\r
+            Ext.destroyMembers(this, 'textEl', 'progressBar', 'textTopEl');\r
+        }\r
+        Ext.ProgressBar.superclass.onDestroy.call(this);\r
+    }\r
+});\r
 Ext.reg('progress', Ext.ProgressBar);/*
  * These classes are derivatives of the similarly named classes in the YUI Library.
  * The original license:
@@ -25834,14 +27328,15 @@ Ext.dd.DragDrop.prototype = {
      * @param {Boolean} inContent (optional) Constrain the draggable in the content box of the element (inside padding and borders)
      */
     constrainTo : function(constrainTo, pad, inContent){
-        if(typeof pad == "number"){
+        if(Ext.isNumber(pad)){
             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;
+        var b = Ext.get(this.getEl()).getBox(),
+            ce = Ext.get(constrainTo),
+            s = ce.getScroll(),
+            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{
@@ -25850,8 +27345,8 @@ Ext.dd.DragDrop.prototype = {
         }
 
 
-        var topSpace = b.y - c.y;
-        var leftSpace = b.x - c.x;
+        var topSpace = b.y - c.y,
+            leftSpace = b.x - c.x;
 
         this.resetConstraints();
         this.setXConstraint(leftSpace - (pad.left||0), // left
@@ -26751,7 +28246,7 @@ Ext.dd.DragDropMgr = function() {
 
         /**
          * The number of milliseconds after the mousedown event to initiate the
-         * drag if we don't get a mouseup event. Default=1000
+         * drag if we don't get a mouseup event. Default=350
          * @property clickTimeThresh
          * @type int
          * @static
@@ -27582,7 +29077,7 @@ Ext.dd.DragDropMgr = function() {
 
         /**
          * Inner class for cached elements
-         * @class DragDropMgr.ElementWrapper
+         * @class Ext.dd.DragDropMgr.ElementWrapper
          * @for DragDropMgr
          * @private
          * @deprecated
@@ -28301,63 +29796,177 @@ Ext.dd.DDTarget = function(id, sGroup, config) {
 
 // Ext.dd.DDTarget.prototype = new Ext.dd.DragDrop();
 Ext.extend(Ext.dd.DDTarget, Ext.dd.DragDrop, {
+    /**
+     * @hide
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    getDragEl: Ext.emptyFn,
+    /**
+     * @hide
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    isValidHandleChild: Ext.emptyFn,
+    /**
+     * @hide
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    startDrag: Ext.emptyFn,
+    /**
+     * @hide
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    endDrag: Ext.emptyFn,
+    /**
+     * @hide
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    onDrag: Ext.emptyFn,
+    /**
+     * @hide
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    onDragDrop: Ext.emptyFn,
+    /**
+     * @hide
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    onDragEnter: Ext.emptyFn,
+    /**
+     * @hide
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    onDragOut: Ext.emptyFn,
+    /**
+     * @hide
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    onDragOver: Ext.emptyFn,
+    /**
+     * @hide
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    onInvalidDrop: Ext.emptyFn,
+    /**
+     * @hide
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    onMouseDown: Ext.emptyFn,
+    /**
+     * @hide
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    onMouseUp: Ext.emptyFn,
+    /**
+     * @hide
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    setXConstraint: Ext.emptyFn,
+    /**
+     * @hide
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    setYConstraint: Ext.emptyFn,
+    /**
+     * @hide
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    resetConstraints: Ext.emptyFn,
+    /**
+     * @hide
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    clearConstraints: Ext.emptyFn,
+    /**
+     * @hide
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    clearTicks: Ext.emptyFn,
+    /**
+     * @hide
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    setInitPosition: Ext.emptyFn,
+    /**
+     * @hide
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    setDragElId: Ext.emptyFn,
+    /**
+     * @hide
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    setHandleElId: Ext.emptyFn,
+    /**
+     * @hide
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    setOuterHandleElId: Ext.emptyFn,
+    /**
+     * @hide
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    addInvalidHandleClass: Ext.emptyFn,
+    /**
+     * @hide
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    addInvalidHandleId: Ext.emptyFn,
+    /**
+     * @hide
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    addInvalidHandleType: Ext.emptyFn,
+    /**
+     * @hide
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    removeInvalidHandleClass: Ext.emptyFn,
+    /**
+     * @hide
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    removeInvalidHandleId: Ext.emptyFn,
+    /**
+     * @hide
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    removeInvalidHandleType: Ext.emptyFn,
+
     toString: function() {
         return ("DDTarget " + this.id);
     }
-});
-/**\r
+});/**\r
  * @class Ext.dd.DragTracker\r
  * @extends Ext.util.Observable\r
  */\r
-Ext.dd.DragTracker = function(config){\r
-    Ext.apply(this, config);\r
-    this.addEvents(\r
-        /**\r
-         * @event mousedown\r
-         * @param {Object} this\r
-         * @param {Object} e event object\r
-         */\r
-        'mousedown',\r
-        /**\r
-         * @event mouseup\r
-         * @param {Object} this\r
-         * @param {Object} e event object\r
-         */\r
-        'mouseup',\r
-        /**\r
-         * @event mousemove\r
-         * @param {Object} this\r
-         * @param {Object} e event object\r
-         */\r
-        'mousemove',\r
-        /**\r
-         * @event dragstart\r
-         * @param {Object} this\r
-         * @param {Object} startXY the page coordinates of the event\r
-         */\r
-        'dragstart',\r
-        /**\r
-         * @event dragend\r
-         * @param {Object} this\r
-         * @param {Object} e event object\r
-         */\r
-        'dragend',\r
-        /**\r
-         * @event drag\r
-         * @param {Object} this\r
-         * @param {Object} e event object\r
-         */\r
-        'drag'\r
-    );\r
-\r
-    this.dragRegion = new Ext.lib.Region(0,0,0,0);\r
-\r
-    if(this.el){\r
-        this.initEl(this.el);\r
-    }\r
-}\r
-\r
-Ext.extend(Ext.dd.DragTracker, Ext.util.Observable,  {\r
+Ext.dd.DragTracker = Ext.extend(Ext.util.Observable,  {\r
     /**\r
      * @cfg {Boolean} active\r
         * Defaults to <tt>false</tt>.\r
@@ -28374,6 +29983,55 @@ Ext.extend(Ext.dd.DragTracker, Ext.util.Observable,  {
         * Specify a Number for the number of milliseconds to defer trigger start.\r
         */     \r
     autoStart: false,\r
+    \r
+    constructor : function(config){\r
+        Ext.apply(this, config);\r
+           this.addEvents(\r
+               /**\r
+                * @event mousedown\r
+                * @param {Object} this\r
+                * @param {Object} e event object\r
+                */\r
+               'mousedown',\r
+               /**\r
+                * @event mouseup\r
+                * @param {Object} this\r
+                * @param {Object} e event object\r
+                */\r
+               'mouseup',\r
+               /**\r
+                * @event mousemove\r
+                * @param {Object} this\r
+                * @param {Object} e event object\r
+                */\r
+               'mousemove',\r
+               /**\r
+                * @event dragstart\r
+                * @param {Object} this\r
+                * @param {Object} startXY the page coordinates of the event\r
+                */\r
+               'dragstart',\r
+               /**\r
+                * @event dragend\r
+                * @param {Object} this\r
+                * @param {Object} e event object\r
+                */\r
+               'dragend',\r
+               /**\r
+                * @event drag\r
+                * @param {Object} this\r
+                * @param {Object} e event object\r
+                */\r
+               'drag'\r
+           );\r
+       \r
+           this.dragRegion = new Ext.lib.Region(0,0,0,0);\r
+       \r
+           if(this.el){\r
+               this.initEl(this.el);\r
+           }\r
+        Ext.dd.DragTracker.superclass.constructor.call(this, config);\r
+    },\r
 \r
     initEl: function(el){\r
         this.el = Ext.get(el);\r
@@ -28962,8 +30620,8 @@ Ext.dd.StatusProxy.prototype = {
      * Causes the proxy to return to its position of origin via an animation.  Should be called after an\r
      * invalid drop operation by the item being dragged.\r
      * @param {Array} xy The XY position of the element ([x, y])\r
-     * @param {Function} callback The function to call after the repair is complete\r
-     * @param {Object} scope The scope in which to execute the callback\r
+     * @param {Function} callback The function to call after the repair is complete.\r
+     * @param {Object} scope The scope (<code>this</code> reference) in which the callback function is executed. Defaults to the browser window.\r
      */\r
     repair : function(xy, callback, scope){\r
         this.callback = callback;\r
@@ -28992,6 +30650,10 @@ Ext.dd.StatusProxy.prototype = {
         }\r
         this.callback = null;\r
         this.scope = null;\r
+    },\r
+    \r
+    destroy: function(){\r
+        Ext.destroy(this.ghost, this.el);    \r
     }\r
 };/**\r
  * @class Ext.dd.DragSource\r
@@ -29350,7 +31012,12 @@ Ext.extend(Ext.dd.DragSource, Ext.dd.DDProxy, {
     // private - pin to cursor\r
     autoOffset : function(x, y) {\r
         this.setDelta(-12, -20);\r
-    }    \r
+    },\r
+    \r
+    destroy: function(){\r
+        Ext.dd.DragSource.superclass.destroy.call(this);\r
+        Ext.destroy(this.proxy);\r
+    }\r
 });/**\r
  * @class Ext.dd.DropTarget\r
  * @extends Ext.dd.DDTarget\r
@@ -29476,8 +31143,8 @@ Ext.extend(Ext.dd.DropTarget, Ext.dd.DDTarget, {
  * by using the event's {@link Ext.EventObject#getTarget getTarget} method to identify a node based on a\r
  * {@link Ext.DomQuery} selector. For example, to make the nodes of a DataView draggable, use the following\r
  * technique. Knowledge of the use of the DataView is required:</p><pre><code>\r
-myDataView.on('render', function() {\r
-    myDataView.dragZone = new Ext.dd.DragZone(myDataView.getEl(), {\r
+myDataView.on('render', function(v) {\r
+    myDataView.dragZone = new Ext.dd.DragZone(v.getEl(), {\r
 \r
 //      On receipt of a mousedown event, see if it is within a DataView node.\r
 //      Return a drag data object if so.\r
@@ -29485,7 +31152,7 @@ myDataView.on('render', function() {
 \r
 //          Use the DataView's own itemSelector (a mandatory property) to\r
 //          test if the mousedown is within one of the DataView's nodes.\r
-            var sourceEl = e.getTarget(myDataView.itemSelector, 10);\r
+            var sourceEl = e.getTarget(v.itemSelector, 10);\r
 \r
 //          If the mousedown is within a DataView node, clone the node to produce\r
 //          a ddel element for use by the drag proxy. Also add application data\r
@@ -29497,8 +31164,8 @@ myDataView.on('render', function() {
                     ddel: d,\r
                     sourceEl: sourceEl,\r
                     repairXY: Ext.fly(sourceEl).getXY(),\r
-                    sourceStore: myDataView.store,\r
-                    draggedRecord: v.getRecord(sourceEl)\r
+                    sourceStore: v.store,\r
+                    draggedRecord: v.{@link Ext.DataView#getRecord getRecord}(sourceEl)\r
                 }\r
             }\r
         },\r
@@ -30044,7 +31711,8 @@ new Ext.data.HttpProxy({
                 proxy.api[action] = proxy.api[action] || proxy.url || proxy.directFn;
                 if (typeof(proxy.api[action]) == 'string') {
                     proxy.api[action] = {
-                        url: proxy.api[action]
+                        url: proxy.api[action],
+                        method: (proxy.restful === true) ? Ext.data.Api.restActions[action] : undefined
                     };
                 }
             }
@@ -30058,7 +31726,8 @@ new Ext.data.HttpProxy({
         restify : function(proxy) {
             proxy.restful = true;
             for (var verb in this.restActions) {
-                proxy.api[this.actions[verb]].method = this.restActions[verb];
+                proxy.api[this.actions[verb]].method ||
+                    (proxy.api[this.actions[verb]].method = this.restActions[verb]);
             }
             // TODO: perhaps move this interceptor elsewhere?  like into DataProxy, perhaps?  Placed here
             // to satisfy initial 3.0 final release of REST features.
@@ -30070,16 +31739,18 @@ new Ext.data.HttpProxy({
                 });
 
                 switch (response.status) {
-                    case 200:   // standard 200 response, send control back to HttpProxy#onWrite
+                    case 200:   // standard 200 response, send control back to HttpProxy#onWrite by returning true from this intercepted #onWrite
                         return true;
                         break;
                     case 201:   // entity created but no response returned
-                        //res[reader.meta.successProperty] = true;
-                        res.success = true;
+                        if (Ext.isEmpty(res.raw.responseText)) {
+                          res.success = true;
+                        } else {
+                          //if the response contains data, treat it like a 200
+                          return true;
+                        }
                         break;
                     case 204:  // no-content.  Create a fake response.
-                        //res[reader.meta.successProperty] = true;
-                        //res[reader.meta.root] = null;
                         res.success = true;
                         res.data = null;
                         break;
@@ -30087,13 +31758,6 @@ new Ext.data.HttpProxy({
                         return true;
                         break;
                 }
-                /*
-                if (res[reader.meta.successProperty] === true) {
-                    this.fireEvent("write", this, action, res[reader.meta.root], res, rs, o.request.arg);
-                } else {
-                    this.fireEvent('exception', this, 'remote', action, o, res, rs);
-                }
-                */
                 if (res.success === true) {
                     this.fireEvent("write", this, action, res.data, res, rs, o.request.arg);
                 } else {
@@ -30130,7 +31794,7 @@ Ext.data.Response.prototype = {
         return this.success;
     },
     getStatus : function() {
-        return this.status
+        return this.status;
     },
     getRoot : function() {
         return this.root;
@@ -30269,10 +31933,11 @@ Ext.data.SortTypes = {
  * @param {Object} data (Optional) An object, the properties of which provide values for the new Record's
  * fields. If not specified the <code>{@link Ext.data.Field#defaultValue defaultValue}</code>
  * for each field will be assigned.
- * @param {Object} id (Optional) The id of the Record. This id should be unique, and is used by the
- * {@link Ext.data.Store} object which owns the Record to index its collection of Records. If
- * an <code>id</code> is not specified a <b><code>{@link #phantom}</code></b> Record will be created
- * with an {@link #Record.id automatically generated id}.
+ * @param {Object} id (Optional) The id of the Record. The id is used by the
+ * {@link Ext.data.Store} object which owns the Record to index its collection
+ * of Records (therefore this id should be unique within each store). If an
+ * <code>id</code> is not specified a <b><code>{@link #phantom}</code></b>
+ * Record will be created with an {@link #Record.id automatically generated id}.
  */
 Ext.data.Record = function(data, id){
     // if no id, call the auto id method
@@ -30378,22 +32043,34 @@ Ext.data.Record.prototype = {
      * @property id
      * @type {Object}
      */
+    /**
+     * <p><b>Only present if this Record was created by an {@link Ext.data.XmlReader XmlReader}</b>.</p>
+     * <p>The XML element which was the source of the data for this Record.</p>
+     * @property node
+     * @type {XMLElement}
+     */
+    /**
+     * <p><b>Only present if this Record was created by an {@link Ext.data.ArrayReader ArrayReader} or a {@link Ext.data.JsonReader JsonReader}</b>.</p>
+     * <p>The Array or object which was the source of the data for this Record.</p>
+     * @property json
+     * @type {Array|Object}
+     */
     /**
      * Readonly flag - true if this Record has been modified.
      * @type Boolean
      */
     dirty : false,
     editing : false,
-    error: null,
+    error : null,
     /**
      * This object contains a key and value storing the original values of all modified
      * fields or is null if no fields have been modified.
      * @property modified
      * @type {Object}
      */
-    modified: null,
+    modified : null,
     /**
-     * <tt>false</tt> when the record does not yet exist in a server-side database (see
+     * <tt>true</tt> when the record does not yet exist in a server-side database (see
      * {@link #markDirty}).  Any record which has a real database pk set as its id property
      * is NOT a phantom -- it's real.
      * @property phantom
@@ -30431,7 +32108,7 @@ rec.{@link #commit}();
 
 // update the record in the store, bypass setting dirty flag,
 // and do not store the change in the {@link Ext.data.Store#getModifiedRecords modified records}
-rec.{@link #data}['firstname'] = 'Wilma'); // updates record, but not the view
+rec.{@link #data}['firstname'] = 'Wilma'; // updates record, but not the view
 rec.{@link #commit}(); // updates the view
      * </code></pre>
      * <b>Notes</b>:<div class="mdetail-params"><ul>
@@ -30443,20 +32120,18 @@ rec.{@link #commit}(); // updates the view
      * event fire.</li>
      * </ul></div>
      * @param {String} name The {@link Ext.data.Field#name name of the field} to set.
-     * @param {Object} value The value to set the field to.
+     * @param {String/Object/Array} value The value to set the field to.
      */
     set : function(name, value){
-        var isObj = (typeof value === 'object');
-        if(!isObj && String(this.data[name]) === String(value)){
-            return;
-        } else if (isObj && Ext.encode(this.data[name]) === Ext.encode(value)) {
+        var encode = Ext.isPrimitive(value) ? String : Ext.encode;
+        if(encode(this.data[name]) == encode(value)) {
             return;
-        }
+        }        
         this.dirty = true;
         if(!this.modified){
             this.modified = {};
         }
-        if(typeof this.modified[name] == 'undefined'){
+        if(this.modified[name] === undefined){
             this.modified[name] = this.data[name];
         }
         this.data[name] = value;
@@ -30466,21 +32141,21 @@ rec.{@link #commit}(); // updates the view
     },
 
     // private
-    afterEdit: function(){
+    afterEdit : function(){
         if(this.store){
             this.store.afterEdit(this);
         }
     },
 
     // private
-    afterReject: function(){
+    afterReject : function(){
         if(this.store){
             this.store.afterReject(this);
         }
     },
 
     // private
-    afterCommit: function(){
+    afterCommit : function(){
         if(this.store){
             this.store.afterCommit(this);
         }
@@ -30590,10 +32265,13 @@ rec.{@link #commit}(); // updates the view
     },
 
     /**
-     * Creates a copy of this Record.
-     * @param {String} id (optional) A new Record id, defaults to {@link #Record.id autogenerating an id}.
-     * Note: if an <code>id</code> is not specified the copy created will be a
-     * <code>{@link #phantom}</code> Record.
+     * Creates a copy (clone) of this Record.
+     * @param {String} id (optional) A new Record id, defaults to the id
+     * of the record being copied. See <code>{@link #id}</code>. 
+     * To generate a phantom record with a new id use:<pre><code>
+var rec = record.copy(); // clone the record
+Ext.data.Record.id(rec); // automatically generate a unique sequential id
+     * </code></pre>
      * @return {Record}
      */
     copy : function(newId) {
@@ -30640,7 +32318,8 @@ rec.{@link #commit}(); // updates the view
             this.modified[f.name] = this.data[f.name];
         },this);
     }
-};/**
+};
+/**
  * @class Ext.StoreMgr
  * @extends Ext.util.MixedCollection
  * The default global group of stores.
@@ -30777,282 +32456,7 @@ myStore.{@link #insert}(0, r); // insert a new record into the store (also see {
  * and read the data into Records.
  * @xtype store
  */
-Ext.data.Store = function(config){
-    this.data = new Ext.util.MixedCollection(false);
-    this.data.getKey = function(o){
-        return o.id;
-    };
-    /**
-     * See the <code>{@link #baseParams corresponding configuration option}</code>
-     * for a description of this property.
-     * To modify this property see <code>{@link #setBaseParam}</code>.
-     * @property
-     */
-    this.baseParams = {};
-
-    // temporary removed-records cache
-    this.removed = [];
-
-    if(config && config.data){
-        this.inlineData = config.data;
-        delete config.data;
-    }
-
-    Ext.apply(this, config);
-
-    this.paramNames = Ext.applyIf(this.paramNames || {}, this.defaultParamNames);
-
-    if(this.url && !this.proxy){
-        this.proxy = new Ext.data.HttpProxy({url: this.url});
-    }
-    // If Store is RESTful, so too is the DataProxy
-    if (this.restful === true && this.proxy) {
-        // 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);
-            this.reader.onMetaChange = this.reader.onMetaChange.createSequence(this.onMetaChange, this);
-        }
-        if (this.writer) { // writer passed
-            this.writer.meta = this.reader.meta;
-            this.pruneModifiedRecords = true;
-        }
-    }
-
-    /**
-     * The {@link Ext.data.Record Record} constructor as supplied to (or created by) the
-     * {@link Ext.data.DataReader Reader}. Read-only.
-     * <p>If the Reader was constructed by passing in an Array of {@link Ext.data.Field} definition objects,
-     * instead of a Record constructor, it will implicitly create a Record constructor from that Array (see
-     * {@link Ext.data.Record}.{@link Ext.data.Record#create create} for additional details).</p>
-     * <p>This property may be used to create new Records of the type held in this Store, for example:</p><pre><code>
-// create the data store
-var store = new Ext.data.ArrayStore({
-    autoDestroy: true,
-    fields: [
-       {name: 'company'},
-       {name: 'price', type: 'float'},
-       {name: 'change', type: 'float'},
-       {name: 'pctChange', type: 'float'},
-       {name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'}
-    ]
-});
-store.loadData(myData);
-
-// create the Grid
-var grid = new Ext.grid.EditorGridPanel({
-    store: store,
-    colModel: new Ext.grid.ColumnModel({
-        columns: [
-            {id:'company', header: 'Company', width: 160, dataIndex: 'company'},
-            {header: 'Price', renderer: 'usMoney', dataIndex: 'price'},
-            {header: 'Change', renderer: change, dataIndex: 'change'},
-            {header: '% Change', renderer: pctChange, dataIndex: 'pctChange'},
-            {header: 'Last Updated', width: 85,
-                renderer: Ext.util.Format.dateRenderer('m/d/Y'),
-                dataIndex: 'lastChange'}
-        ],
-        defaults: {
-            sortable: true,
-            width: 75
-        }
-    }),
-    autoExpandColumn: 'company', // match the id specified in the column model
-    height:350,
-    width:600,
-    title:'Array Grid',
-    tbar: [{
-        text: 'Add Record',
-        handler : function(){
-            var defaultData = {
-                change: 0,
-                company: 'New Company',
-                lastChange: (new Date()).clearTime(),
-                pctChange: 0,
-                price: 10
-            };
-            var recId = 3; // provide unique id
-            var p = new store.recordType(defaultData, recId); // create new record
-            grid.stopEditing();
-            store.{@link #insert}(0, p); // insert a new record into the store (also see {@link #add})
-            grid.startEditing(0, 0);
-        }
-    }]
-});
-     * </code></pre>
-     * @property recordType
-     * @type Function
-     */
-
-    if(this.recordType){
-        /**
-         * A {@link Ext.util.MixedCollection MixedCollection} containing the defined {@link Ext.data.Field Field}s
-         * for the {@link Ext.data.Record Records} stored in this Store. Read-only.
-         * @property fields
-         * @type Ext.util.MixedCollection
-         */
-        this.fields = this.recordType.prototype.fields;
-    }
-    this.modified = [];
-
-    this.addEvents(
-        /**
-         * @event datachanged
-         * Fires when the data cache has changed in a bulk manner (e.g., it has been sorted, filtered, etc.) and a
-         * widget that is using this Store as a Record cache should refresh its view.
-         * @param {Store} this
-         */
-        'datachanged',
-        /**
-         * @event metachange
-         * Fires when this store's reader provides new metadata (fields). This is currently only supported for JsonReaders.
-         * @param {Store} this
-         * @param {Object} meta The JSON metadata
-         */
-        'metachange',
-        /**
-         * @event add
-         * Fires when Records have been {@link #add}ed to the Store
-         * @param {Store} this
-         * @param {Ext.data.Record[]} records The array of Records added
-         * @param {Number} index The index at which the record(s) were added
-         */
-        'add',
-        /**
-         * @event remove
-         * Fires when a Record has been {@link #remove}d from the Store
-         * @param {Store} this
-         * @param {Ext.data.Record} record The Record that was removed
-         * @param {Number} index The index at which the record was removed
-         */
-        'remove',
-        /**
-         * @event update
-         * Fires when a Record has been updated
-         * @param {Store} this
-         * @param {Ext.data.Record} record The Record that was updated
-         * @param {String} operation The update operation being performed.  Value may be one of:
-         * <pre><code>
- Ext.data.Record.EDIT
- Ext.data.Record.REJECT
- Ext.data.Record.COMMIT
-         * </code></pre>
-         */
-        'update',
-        /**
-         * @event clear
-         * Fires when the data cache has been cleared.
-         * @param {Store} this
-         * @param {Record[]} The records that were cleared.
-         */
-        'clear',
-        /**
-         * @event exception
-         * <p>Fires if an exception occurs in the Proxy during a remote request.
-         * This event is relayed through the corresponding {@link Ext.data.DataProxy}.
-         * See {@link Ext.data.DataProxy}.{@link Ext.data.DataProxy#exception exception}
-         * for additional details.
-         * @param {misc} misc See {@link Ext.data.DataProxy}.{@link Ext.data.DataProxy#exception exception}
-         * for description.
-         */
-        'exception',
-        /**
-         * @event beforeload
-         * Fires before a request is made for a new data object.  If the beforeload handler returns
-         * <tt>false</tt> the {@link #load} action will be canceled.
-         * @param {Store} this
-         * @param {Object} options The loading options that were specified (see {@link #load} for details)
-         */
-        'beforeload',
-        /**
-         * @event load
-         * Fires after a new set of Records has been loaded.
-         * @param {Store} this
-         * @param {Ext.data.Record[]} records The Records that were loaded
-         * @param {Object} options The loading options that were specified (see {@link #load} for details)
-         */
-        'load',
-        /**
-         * @event loadexception
-         * <p>This event is <b>deprecated</b> in favor of the catch-all <b><code>{@link #exception}</code></b>
-         * event instead.</p>
-         * <p>This event is relayed through the corresponding {@link Ext.data.DataProxy}.
-         * See {@link Ext.data.DataProxy}.{@link Ext.data.DataProxy#loadexception loadexception}
-         * for additional details.
-         * @param {misc} misc See {@link Ext.data.DataProxy}.{@link Ext.data.DataProxy#loadexception loadexception}
-         * for description.
-         */
-        'loadexception',
-        /**
-         * @event beforewrite
-         * @param {Ext.data.Store} store
-         * @param {String} action [Ext.data.Api.actions.create|update|destroy]
-         * @param {Record/Array[Record]} rs
-         * @param {Object} options The loading options that were specified. Edit <code>options.params</code> to add Http parameters to the request.  (see {@link #save} for details)
-         * @param {Object} arg The callback's arg object passed to the {@link #request} function
-         */
-        'beforewrite',
-        /**
-         * @event write
-         * Fires if the server returns 200 after an Ext.data.Api.actions CRUD action.
-         * Success of the action is determined in the <code>result['successProperty']</code>property (<b>NOTE</b> for RESTful stores,
-         * a simple 20x response is sufficient for the actions "destroy" and "update".  The "create" action should should return 200 along with a database pk).
-         * @param {Ext.data.Store} store
-         * @param {String} action [Ext.data.Api.actions.create|update|destroy]
-         * @param {Object} result The 'data' picked-out out of the response for convenience.
-         * @param {Ext.Direct.Transaction} res
-         * @param {Record/Record[]} rs Store's records, the subject(s) of the write-action
-         */
-        'write'
-    );
-
-    if(this.proxy){
-        this.relayEvents(this.proxy,  ['loadexception', 'exception']);
-    }
-    // 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({
-            scope: this,
-            add: this.createRecords,
-            remove: this.destroyRecord,
-            update: this.updateRecord,
-            clear: this.onClear
-        });
-    }
-
-    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, {
+Ext.data.Store = Ext.extend(Ext.util.Observable, {
     /**
      * @cfg {String} storeId If passed, the id to use to register with the <b>{@link Ext.StoreMgr StoreMgr}</b>.
      * <p><b>Note</b>: if a (deprecated) <tt>{@link #id}</tt> is specified it will supersede the <tt>storeId</tt>
@@ -31234,6 +32638,334 @@ sortInfo: {
         dir : 'dir'
     },
 
+    // private
+    batchKey : '_ext_batch_',
+
+    constructor : function(config){
+        this.data = new Ext.util.MixedCollection(false);
+        this.data.getKey = function(o){
+            return o.id;
+        };
+
+
+        // temporary removed-records cache
+        this.removed = [];
+
+        if(config && config.data){
+            this.inlineData = config.data;
+            delete config.data;
+        }
+
+        Ext.apply(this, config);
+
+        /**
+         * See the <code>{@link #baseParams corresponding configuration option}</code>
+         * for a description of this property.
+         * To modify this property see <code>{@link #setBaseParam}</code>.
+         * @property
+         */
+        this.baseParams = Ext.isObject(this.baseParams) ? this.baseParams : {};
+
+        this.paramNames = Ext.applyIf(this.paramNames || {}, this.defaultParamNames);
+
+        if((this.url || this.api) && !this.proxy){
+            this.proxy = new Ext.data.HttpProxy({url: this.url, api: this.api});
+        }
+        // If Store is RESTful, so too is the DataProxy
+        if (this.restful === true && this.proxy) {
+            // When operating RESTfully, a unique transaction is generated for each record.
+            // TODO might want to allow implemention of faux REST where batch is possible using RESTful routes only.
+            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.reader.onMetaChange.createSequence(this.onMetaChange, this);
+            }
+            if (this.writer) { // writer passed
+                if (this.writer instanceof(Ext.data.DataWriter) === false) {    // <-- config-object instead of instance.
+                    this.writer = this.buildWriter(this.writer);
+                }
+                this.writer.meta = this.reader.meta;
+                this.pruneModifiedRecords = true;
+            }
+        }
+
+        /**
+         * The {@link Ext.data.Record Record} constructor as supplied to (or created by) the
+         * {@link Ext.data.DataReader Reader}. Read-only.
+         * <p>If the Reader was constructed by passing in an Array of {@link Ext.data.Field} definition objects,
+         * instead of a Record constructor, it will implicitly create a Record constructor from that Array (see
+         * {@link Ext.data.Record}.{@link Ext.data.Record#create create} for additional details).</p>
+         * <p>This property may be used to create new Records of the type held in this Store, for example:</p><pre><code>
+    // create the data store
+    var store = new Ext.data.ArrayStore({
+        autoDestroy: true,
+        fields: [
+           {name: 'company'},
+           {name: 'price', type: 'float'},
+           {name: 'change', type: 'float'},
+           {name: 'pctChange', type: 'float'},
+           {name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'}
+        ]
+    });
+    store.loadData(myData);
+
+    // create the Grid
+    var grid = new Ext.grid.EditorGridPanel({
+        store: store,
+        colModel: new Ext.grid.ColumnModel({
+            columns: [
+                {id:'company', header: 'Company', width: 160, dataIndex: 'company'},
+                {header: 'Price', renderer: 'usMoney', dataIndex: 'price'},
+                {header: 'Change', renderer: change, dataIndex: 'change'},
+                {header: '% Change', renderer: pctChange, dataIndex: 'pctChange'},
+                {header: 'Last Updated', width: 85,
+                    renderer: Ext.util.Format.dateRenderer('m/d/Y'),
+                    dataIndex: 'lastChange'}
+            ],
+            defaults: {
+                sortable: true,
+                width: 75
+            }
+        }),
+        autoExpandColumn: 'company', // match the id specified in the column model
+        height:350,
+        width:600,
+        title:'Array Grid',
+        tbar: [{
+            text: 'Add Record',
+            handler : function(){
+                var defaultData = {
+                    change: 0,
+                    company: 'New Company',
+                    lastChange: (new Date()).clearTime(),
+                    pctChange: 0,
+                    price: 10
+                };
+                var recId = 3; // provide unique id
+                var p = new store.recordType(defaultData, recId); // create new record
+                grid.stopEditing();
+                store.{@link #insert}(0, p); // insert a new record into the store (also see {@link #add})
+                grid.startEditing(0, 0);
+            }
+        }]
+    });
+         * </code></pre>
+         * @property recordType
+         * @type Function
+         */
+
+        if(this.recordType){
+            /**
+             * A {@link Ext.util.MixedCollection MixedCollection} containing the defined {@link Ext.data.Field Field}s
+             * for the {@link Ext.data.Record Records} stored in this Store. Read-only.
+             * @property fields
+             * @type Ext.util.MixedCollection
+             */
+            this.fields = this.recordType.prototype.fields;
+        }
+        this.modified = [];
+
+        this.addEvents(
+            /**
+             * @event datachanged
+             * Fires when the data cache has changed in a bulk manner (e.g., it has been sorted, filtered, etc.) and a
+             * widget that is using this Store as a Record cache should refresh its view.
+             * @param {Store} this
+             */
+            'datachanged',
+            /**
+             * @event metachange
+             * Fires when this store's reader provides new metadata (fields). This is currently only supported for JsonReaders.
+             * @param {Store} this
+             * @param {Object} meta The JSON metadata
+             */
+            'metachange',
+            /**
+             * @event add
+             * Fires when Records have been {@link #add}ed to the Store
+             * @param {Store} this
+             * @param {Ext.data.Record[]} records The array of Records added
+             * @param {Number} index The index at which the record(s) were added
+             */
+            'add',
+            /**
+             * @event remove
+             * Fires when a Record has been {@link #remove}d from the Store
+             * @param {Store} this
+             * @param {Ext.data.Record} record The Record that was removed
+             * @param {Number} index The index at which the record was removed
+             */
+            'remove',
+            /**
+             * @event update
+             * Fires when a Record has been updated
+             * @param {Store} this
+             * @param {Ext.data.Record} record The Record that was updated
+             * @param {String} operation The update operation being performed.  Value may be one of:
+             * <pre><code>
+     Ext.data.Record.EDIT
+     Ext.data.Record.REJECT
+     Ext.data.Record.COMMIT
+             * </code></pre>
+             */
+            'update',
+            /**
+             * @event clear
+             * Fires when the data cache has been cleared.
+             * @param {Store} this
+             * @param {Record[]} The records that were cleared.
+             */
+            'clear',
+            /**
+             * @event exception
+             * <p>Fires if an exception occurs in the Proxy during a remote request.
+             * This event is relayed through the corresponding {@link Ext.data.DataProxy}.
+             * See {@link Ext.data.DataProxy}.{@link Ext.data.DataProxy#exception exception}
+             * for additional details.
+             * @param {misc} misc See {@link Ext.data.DataProxy}.{@link Ext.data.DataProxy#exception exception}
+             * for description.
+             */
+            'exception',
+            /**
+             * @event beforeload
+             * Fires before a request is made for a new data object.  If the beforeload handler returns
+             * <tt>false</tt> the {@link #load} action will be canceled.
+             * @param {Store} this
+             * @param {Object} options The loading options that were specified (see {@link #load} for details)
+             */
+            'beforeload',
+            /**
+             * @event load
+             * Fires after a new set of Records has been loaded.
+             * @param {Store} this
+             * @param {Ext.data.Record[]} records The Records that were loaded
+             * @param {Object} options The loading options that were specified (see {@link #load} for details)
+             */
+            'load',
+            /**
+             * @event loadexception
+             * <p>This event is <b>deprecated</b> in favor of the catch-all <b><code>{@link #exception}</code></b>
+             * event instead.</p>
+             * <p>This event is relayed through the corresponding {@link Ext.data.DataProxy}.
+             * See {@link Ext.data.DataProxy}.{@link Ext.data.DataProxy#loadexception loadexception}
+             * for additional details.
+             * @param {misc} misc See {@link Ext.data.DataProxy}.{@link Ext.data.DataProxy#loadexception loadexception}
+             * for description.
+             */
+            'loadexception',
+            /**
+             * @event beforewrite
+             * @param {Ext.data.Store} store
+             * @param {String} action [Ext.data.Api.actions.create|update|destroy]
+             * @param {Record/Array[Record]} rs
+             * @param {Object} options The loading options that were specified. Edit <code>options.params</code> to add Http parameters to the request.  (see {@link #save} for details)
+             * @param {Object} arg The callback's arg object passed to the {@link #request} function
+             */
+            'beforewrite',
+            /**
+             * @event write
+             * Fires if the server returns 200 after an Ext.data.Api.actions CRUD action.
+             * Success of the action is determined in the <code>result['successProperty']</code>property (<b>NOTE</b> for RESTful stores,
+             * a simple 20x response is sufficient for the actions "destroy" and "update".  The "create" action should should return 200 along with a database pk).
+             * @param {Ext.data.Store} store
+             * @param {String} action [Ext.data.Api.actions.create|update|destroy]
+             * @param {Object} result The 'data' picked-out out of the response for convenience.
+             * @param {Ext.Direct.Transaction} res
+             * @param {Record/Record[]} rs Store's records, the subject(s) of the write-action
+             */
+            'write',
+            /**
+             * @event beforesave
+             * Fires before a save action is called. A save encompasses destroying records, updating records and creating records.
+             * @param {Ext.data.Store} store
+             * @param {Object} data An object containing the data that is to be saved. The object will contain a key for each appropriate action,
+             * with an array of records for each action.
+             */
+            'beforesave',
+            /**
+             * @event save
+             * Fires after a save is completed. A save encompasses destroying records, updating records and creating records.
+             * @param {Ext.data.Store} store
+             * @param {Number} batch The identifier for the batch that was saved.
+             * @param {Object} data An object containing the data that is to be saved. The object will contain a key for each appropriate action,
+             * with an array of records for each action.
+             */
+            'save'
+
+        );
+
+        if(this.proxy){
+            // TODO remove deprecated loadexception with ext-3.0.1
+            this.relayEvents(this.proxy,  ['loadexception', 'exception']);
+        }
+        // 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({
+                scope: this,
+                add: this.createRecords,
+                remove: this.destroyRecord,
+                update: this.updateRecord,
+                clear: this.onClear
+            });
+        }
+
+        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]);
+        }
+        // used internally to uniquely identify a batch
+        this.batchCounter = 0;
+        this.batches = {};
+    },
+
+    /**
+     * builds a DataWriter instance when Store constructor is provided with a writer config-object instead of an instace.
+     * @param {Object} config Writer configuration
+     * @return {Ext.data.DataWriter}
+     * @private
+     */
+    buildWriter : function(config) {
+        var klass = undefined,
+            type = (config.format || 'json').toLowerCase();
+        switch (type) {
+            case 'json':
+                klass = Ext.data.JsonWriter;
+                break;
+            case 'xml':
+                klass = Ext.data.XmlWriter;
+                break;
+            default:
+                klass = Ext.data.JsonWriter;
+        }
+        return new klass(config);
+    },
+
     /**
      * Destroys the store.
      */
@@ -31285,20 +33017,27 @@ sortInfo: {
     },
 
     /**
-     * Remove a Record from the Store and fires the {@link #remove} event.
-     * @param {Ext.data.Record} record The Ext.data.Record object to remove from the cache.
+     * Remove Records from the Store and fires the {@link #remove} event.
+     * @param {Ext.data.Record/Ext.data.Record[]} record The record object or array of records to remove from the cache.
      */
     remove : function(record){
+        if(Ext.isArray(record)){
+            Ext.each(record, function(r){
+                this.remove(r);
+            }, this);
+        }
         var index = this.data.indexOf(record);
         if(index > -1){
             record.join(null);
             this.data.removeAt(index);
-            if(this.pruneModifiedRecords){
-                this.modified.remove(record);
-            }
-            if(this.snapshot){
-                this.snapshot.remove(record);
-            }
+        }
+        if(this.pruneModifiedRecords){
+            this.modified.remove(record);
+        }
+        if(this.snapshot){
+            this.snapshot.remove(record);
+        }
+        if(index > -1){
             this.fireEvent('remove', this, record, index);
         }
     },
@@ -31313,8 +33052,9 @@ sortInfo: {
 
     /**
      * Remove all Records from the Store and fires the {@link #clear} event.
+     * @param {Boolean} silent [false] Defaults to <tt>false</tt>.  Set <tt>true</tt> to not fire clear event.
      */
-    removeAll : function(){
+    removeAll : function(silent){
         var items = [];
         this.each(function(rec){
             items.push(rec);
@@ -31326,7 +33066,9 @@ sortInfo: {
         if(this.pruneModifiedRecords){
             this.modified = [];
         }
-        this.fireEvent('clear', this, items);
+        if (silent !== true) {  // <-- prevents write-actions when we just want to clear a store.
+            this.fireEvent('clear', this, items);
+        }
     },
 
     // private
@@ -31348,6 +33090,9 @@ sortInfo: {
             this.data.insert(index, records[i]);
             records[i].join(this);
         }
+        if(this.snapshot){
+            this.snapshot.addAll(records);
+        }
         this.fireEvent('add', this, records, index);
     },
 
@@ -31375,7 +33120,7 @@ sortInfo: {
      * @return {Ext.data.Record} The Record with the passed id. Returns undefined if not found.
      */
     getById : function(id){
-        return this.data.key(id);
+        return (this.snapshot || this.data).key(id);
     },
 
     /**
@@ -31431,14 +33176,14 @@ sortInfo: {
      * parameters to a remote data source. <b>Note</b>: <code>params</code> will override any
      * <code>{@link #baseParams}</code> of the same name.</p>
      * <p>Parameters are encoded as standard HTTP parameters using {@link Ext#urlEncode}.</p></div></li>
-     * <li><b><tt>callback</tt></b> : Function<div class="sub-desc"><p>A function to be called after the Records
-     * have been loaded. The <tt>callback</tt> is called after the load event and is passed the following arguments:<ul>
-     * <li><tt>r</tt> : Ext.data.Record[]</li>
-     * <li><tt>options</tt>: Options object from the load call</li>
-     * <li><tt>success</tt>: Boolean success indicator</li></ul></p></div></li>
-     * <li><b><tt>scope</tt></b> : Object<div class="sub-desc"><p>Scope with which to call the callback (defaults
+     * <li><b>callback</b> : Function<div class="sub-desc"><p>A function to be called after the Records
+     * have been loaded. The callback is called after the load event is fired, and is passed the following arguments:<ul>
+     * <li>r : Ext.data.Record[] An Array of Records loaded.</li>
+     * <li>options : Options object from the load call.</li>
+     * <li>success : Boolean success indicator.</li></ul></p></div></li>
+     * <li><b>scope</b> : Object<div class="sub-desc"><p>Scope with which to call the callback (defaults
      * to the Store object)</p></div></li>
-     * <li><b><tt>add</tt></b> : Boolean<div class="sub-desc"><p>Indicator to append loaded records rather than
+     * <li><b>add</b> : Boolean<div class="sub-desc"><p>Indicator to append loaded records rather than
      * replace the current cache.  <b>Note</b>: see note for <tt>{@link #loadData}</tt></p></div></li>
      * </ul>
      * @return {Boolean} If the <i>developer</i> provided <tt>{@link #beforeload}</tt> event handler returns
@@ -31470,7 +33215,7 @@ sortInfo: {
      * @private
      */
     updateRecord : function(store, record, action) {
-        if (action == Ext.data.Record.EDIT && this.autoSave === true && (!record.phantom || (record.phantom && record.isValid))) {
+        if (action == Ext.data.Record.EDIT && this.autoSave === true && (!record.phantom || (record.phantom && record.isValid()))) {
             this.save();
         }
     },
@@ -31529,23 +33274,25 @@ sortInfo: {
      * @throws Error
      * @private
      */
-    execute : function(action, rs, options) {
+    execute : function(action, rs, options, /* private */ batch) {
         // 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
+        // make sure options has a fresh, new params hash
         options = Ext.applyIf(options||{}, {
             params: {}
         });
-
+        if(batch !== undefined){
+            this.addToBatch(batch);
+        }
         // 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 === 'read') {
-            Ext.applyIf(options.params, this.baseParams);
             doRequest = this.fireEvent('beforeload', this, options);
+            Ext.applyIf(options.params, this.baseParams);
         }
         else {
             // if Writer is configured as listful, force single-record rs to be [{}] instead of {}
@@ -31559,19 +33306,20 @@ sortInfo: {
             }
             // Write the action to options.params
             if ((doRequest = this.fireEvent('beforewrite', this, action, rs, options)) !== false) {
-                this.writer.write(action, options.params, rs);
+                this.writer.apply(options.params, this.baseParams, action, rs);
             }
         }
         if (doRequest !== false) {
             // Send request to proxy.
-            var params = Ext.apply({}, options.params, this.baseParams);
             if (this.writer && this.proxy.url && !this.proxy.restful && !Ext.data.Api.hasUniqueUrl(this.proxy, action)) {
-                params.xaction = action;    // <-- really old, probaby unecessary.
+                options.params.xaction = action;    // <-- really old, probaby unecessary.
             }
             // Note:  Up until this point we've been dealing with 'action' 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 user's configured DataProxy#api
-            this.proxy.request(Ext.data.Api.actions[action], rs, params, this.reader, this.createCallback(action, rs), this, options);
+            // TODO Refactor all Proxies to accept an instance of Ext.data.Request (not yet defined) instead of this looooooong list
+            // of params.  This method is an artifact from Ext2.
+            this.proxy.request(Ext.data.Api.actions[action], rs, options.params, this.reader, this.createCallback(action, rs, batch), this, options);
         }
         return doRequest;
     },
@@ -31588,68 +33336,125 @@ sortInfo: {
      * </pre>
      * @TODO:  Create extensions of Error class and send associated Record with thrown exceptions.
      * e.g.:  Ext.data.DataReader.Error or Ext.data.Error or Ext.data.DataProxy.Error, etc.
+     * @return {Number} batch Returns a number to uniquely identify the "batch" of saves occurring. -1 will be returned
+     * if there are no items to save or the save was cancelled.
      */
     save : function() {
         if (!this.writer) {
             throw new Ext.data.Store.Error('writer-undefined');
         }
 
+        var queue = [],
+            len,
+            trans,
+            batch,
+            data = {};
         // DESTROY:  First check for removed records.  Records in this.removed are guaranteed non-phantoms.  @see Store#remove
-        if (this.removed.length) {
-            this.doTransaction('destroy', this.removed);
+        if(this.removed.length){
+            queue.push(['destroy', this.removed]);
         }
 
         // Check for modified records. Use a copy so Store#rejectChanges will work if server returns error.
         var rs = [].concat(this.getModifiedRecords());
-        if (!rs.length) { // Bail-out if empty...
-            return true;
-        }
-
-        // CREATE:  Next check for phantoms within rs.  splice-off and execute create.
-        var phantoms = [];
-        for (var i = rs.length-1; i >= 0; i--) {
-            if (rs[i].phantom === true) {
-                var rec = rs.splice(i, 1).shift();
-                if (rec.isValid()) {
-                    phantoms.push(rec);
+        if(rs.length){
+            // CREATE:  Next check for phantoms within rs.  splice-off and execute create.
+            var phantoms = [];
+            for(var i = rs.length-1; i >= 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()){ // <-- while we're here, splice-off any !isValid real records
+                    rs.splice(i,1);
                 }
-            } else if (!rs[i].isValid()) { // <-- 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);
-        }
+            // If we have valid phantoms, create them...
+            if(phantoms.length){
+                queue.push(['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);
+            // UPDATE:  And finally, if we're still here after splicing-off phantoms and !isValid real records, update the rest...
+            if(rs.length){
+                queue.push(['update', rs]);
+            }
         }
-        return true;
+        len = queue.length;
+        if(len){
+            batch = ++this.batchCounter;
+            for(var i = 0; i < len; ++i){
+                trans = queue[i];
+                data[trans[0]] = trans[1];
+            }
+            if(this.fireEvent('beforesave', this, data) !== false){
+                for(var i = 0; i < len; ++i){
+                    trans = queue[i];
+                    this.doTransaction(trans[0], trans[1], batch);
+                }
+                return batch;
+            }
+        }
+        return -1;
     },
 
     // private.  Simply wraps call to Store#execute in try/catch.  Defers to Store#handleException on error.  Loops if batch: false
-    doTransaction : function(action, rs) {
+    doTransaction : function(action, rs, batch) {
         function transaction(records) {
-            try {
-                this.execute(action, records);
-            } catch (e) {
+            try{
+                this.execute(action, records, undefined, batch);
+            }catch (e){
                 this.handleException(e);
             }
         }
-        if (this.batch === false) {
-            for (var i = 0, len = rs.length; i < len; i++) {
+        if(this.batch === false){
+            for(var i = 0, len = rs.length; i < len; i++){
                 transaction.call(this, rs[i]);
             }
-        } else {
+        }else{
             transaction.call(this, rs);
         }
     },
 
+    // private
+    addToBatch : function(batch){
+        var b = this.batches,
+            key = this.batchKey + batch,
+            o = b[key];
+
+        if(!o){
+            b[key] = o = {
+                id: batch,
+                count: 0,
+                data: {}
+            }
+        }
+        ++o.count;
+    },
+
+    removeFromBatch : function(batch, action, data){
+        var b = this.batches,
+            key = this.batchKey + batch,
+            o = b[key],
+            data,
+            arr;
+
+
+        if(o){
+            arr = o.data[action] || [];
+            o.data[action] = arr.concat(data);
+            if(o.count === 1){
+                data = o.data;
+                delete b[key];
+                this.fireEvent('save', this, batch, data);
+            }else{
+                --o.count;
+            }
+        }
+    },
+
     // @private callback-handler for remote CRUD actions
     // Do not override -- override loadRecords, onCreateRecords, onDestroyRecords and onUpdateRecords instead.
-    createCallback : function(action, rs) {
+    createCallback : function(action, rs, batch) {
         var actions = Ext.data.Api.actions;
         return (action == 'read') ? this.loadRecords : function(data, response, success) {
             // calls: onCreateRecords | onUpdateRecords | onDestroyRecords
@@ -31658,6 +33463,7 @@ sortInfo: {
             if (success === true) {
                 this.fireEvent('write', this, action, data, response, rs);
             }
+            this.removeFromBatch(batch, action, data);
         };
     },
 
@@ -31744,12 +33550,22 @@ sortInfo: {
     },
 
     /**
-     * <p>Reloads the Record cache from the configured Proxy using the configured {@link Ext.data.Reader Reader} and
-     * the options from the last load operation performed.</p>
+     * <p>Reloads the Record cache from the configured Proxy using the configured
+     * {@link Ext.data.Reader Reader} and the options from the last load operation
+     * performed.</p>
      * <p><b>Note</b>: see the Important note in {@link #load}.</p>
-     * @param {Object} options (optional) An <tt>Object</tt> containing {@link #load loading options} which may
-     * override the options used in the last {@link #load} operation. See {@link #load} for details (defaults to
-     * <tt>null</tt>, in which case the {@link #lastOptions} are used).
+     * @param {Object} options <p>(optional) An <tt>Object</tt> containing
+     * {@link #load loading options} which may override the {@link #lastOptions options}
+     * used in the last {@link #load} operation. See {@link #load} for details
+     * (defaults to <tt>null</tt>, in which case the {@link #lastOptions} are
+     * used).</p>
+     * <br><p>To add new params to the existing params:</p><pre><code>
+lastOptions = myStore.lastOptions;
+Ext.apply(lastOptions.params, {
+    myNewParam: true
+});
+myStore.reload(lastOptions);
+     * </code></pre>
      */
     reload : function(options){
         this.load(Ext.applyIf(options||{}, this.lastOptions));
@@ -31758,6 +33574,9 @@ sortInfo: {
     // private
     // Called as a callback by the Reader during a load operation.
     loadRecords : function(o, options, success){
+        if (this.isDestroyed === true) {
+            return;
+        }
         if(!o || success === false){
             if(success !== false){
                 this.fireEvent('load', this, [], options);
@@ -31925,7 +33744,8 @@ sortInfo: {
      * Calls the specified function for each of the {@link Ext.data.Record Records} in the cache.
      * @param {Function} fn The function to call. The {@link Ext.data.Record Record} is passed as the first parameter.
      * Returning <tt>false</tt> aborts and exits the iteration.
-     * @param {Object} scope (optional) The scope in which to call the function (defaults to the {@link Ext.data.Record Record}).
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed.
+     * Defaults to the current {@link Ext.data.Record Record} in the iteration.
      */
     each : function(fn, scope){
         this.data.each(fn, scope);
@@ -31996,7 +33816,7 @@ sortInfo: {
      * to test for filtering. Access field values using {@link Ext.data.Record#get}.</p></li>
      * <li><b>id</b> : Object<p class="sub-desc">The ID of the Record passed.</p></li>
      * </ul>
-     * @param {Object} scope (optional) The scope of the function (defaults to this)
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to this Store.
      */
     filterBy : function(fn, scope){
         this.snapshot = this.snapshot || this.data;
@@ -32027,7 +33847,7 @@ sortInfo: {
      * to test for filtering. Access field values using {@link Ext.data.Record#get}.</p></li>
      * <li><b>id</b> : Object<p class="sub-desc">The ID of the Record passed.</p></li>
      * </ul>
-     * @param {Object} scope (optional) The scope of the function (defaults to this)
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to this Store.
      * @return {MixedCollection} Returns an Ext.util.MixedCollection of the matched records
      **/
     queryBy : function(fn, scope){
@@ -32036,10 +33856,10 @@ sortInfo: {
     },
 
     /**
-     * Finds the index of the first matching record in this store by a specific property/value.
-     * @param {String} property A property on your objects
-     * @param {String/RegExp} value Either a string that the property value
-     * should begin with, or a RegExp to test against the property.
+     * Finds the index of the first matching Record in this store by a specific field value.
+     * @param {String} fieldName The name of the Record field to test.
+     * @param {String/RegExp} value Either a string that the field value
+     * should begin with, or a RegExp to test against the field.
      * @param {Number} startIndex (optional) The index to start searching at
      * @param {Boolean} anyMatch (optional) True to match any part of the string, not just the beginning
      * @param {Boolean} caseSensitive (optional) True for case sensitive comparison
@@ -32051,9 +33871,9 @@ sortInfo: {
     },
 
     /**
-     * Finds the index of the first matching record in this store by a specific property/value.
-     * @param {String} property A property on your objects
-     * @param {String/RegExp} value The value to match against
+     * Finds the index of the first matching Record in this store by a specific field value.
+     * @param {String} fieldName The name of the Record field to test.
+     * @param {Mixed} value The value to match the field against.
      * @param {Number} startIndex (optional) The index to start searching at
      * @return {Number} The matched index or -1
      */
@@ -32071,7 +33891,7 @@ sortInfo: {
      * to test for filtering. Access field values using {@link Ext.data.Record#get}.</p></li>
      * <li><b>id</b> : Object<p class="sub-desc">The ID of the Record passed.</p></li>
      * </ul>
-     * @param {Object} scope (optional) The scope of the function (defaults to this)
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to this Store.
      * @param {Number} startIndex (optional) The index to start searching at
      * @return {Number} The matched index or -1
      */
@@ -32232,7 +34052,6 @@ Ext.apply(Ext.data.Store.Error.prototype, {
         'writer-undefined' : 'Attempted to execute a write-action without a DataWriter installed.'
     }
 });
-
 /**
  * @class Ext.data.Field
  * <p>This class encapsulates the field definition information specified in the field definition objects
@@ -32289,17 +34108,16 @@ Ext.data.Field = function(config){
             case "int":
                 cv = function(v){
                     return v !== undefined && v !== null && v !== '' ?
-                           parseInt(String(v).replace(stripRe, ""), 10) : '';
+                        parseInt(String(v).replace(stripRe, ""), 10) : '';
                     };
                 break;
             case "float":
                 cv = function(v){
                     return v !== undefined && v !== null && v !== '' ?
-                           parseFloat(String(v).replace(stripRe, ""), 10) : '';
+                        parseFloat(String(v).replace(stripRe, ""), 10) : '';
                     };
                 break;
             case "bool":
-            case "boolean":
                 cv = function(v){ return v === true || v === "true" || v == 1; };
                 break;
             case "date":
@@ -32322,7 +34140,10 @@ Ext.data.Field = function(config){
                     var parsed = Date.parse(v);
                     return parsed ? new Date(parsed) : null;
                 };
-             break;
+                break;
+            default:
+                cv = function(v){ return v; };
+                break;
 
         }
         this.convert = cv;
@@ -32383,7 +34204,7 @@ var store = new Ext.data.Store({
     reader: new Ext.data.JsonReader(
         {
             idProperty: 'key',
-            root: 'daRoot',  
+            root: 'daRoot',
             totalProperty: 'total'
         },
         Dude  // recordType
@@ -32468,13 +34289,13 @@ sortType: function(value) {
      * <tt>"ASC"</tt>.
      */
     sortDir : "ASC",
-       /**
-        * @cfg {Boolean} allowBlank 
-        * (Optional) Used for validating a {@link Ext.data.Record record}, defaults to <tt>true</tt>.
-        * An empty value here will cause {@link Ext.data.Record}.{@link Ext.data.Record#isValid isValid}
-        * to evaluate to <tt>false</tt>.
-        */
-       allowBlank : true
+    /**
+     * @cfg {Boolean} allowBlank
+     * (Optional) Used for validating a {@link Ext.data.Record record}, defaults to <tt>true</tt>.
+     * An empty value here will cause {@link Ext.data.Record}.{@link Ext.data.Record#isValid isValid}
+     * to evaluate to <tt>false</tt>.
+     */
+    allowBlank : true
 };/**\r
  * @class Ext.data.DataReader\r
  * Abstract base class for reading structured data from a data source and converting\r
@@ -32584,7 +34405,12 @@ Ext.data.DataReader.prototype = {
             rs.phantom = false; // <-- That's what it's all about\r
             rs._phid = rs.id;  // <-- copy phantom-id -> _phid, so we can remap in Store#onCreateRecords\r
             rs.id = this.getId(data);\r
-            rs.data = data;\r
+\r
+            rs.fields.each(function(f) {\r
+                if (data[f.name] !== f.defaultValue) {\r
+                    rs.data[f.name] = data[f.name];\r
+                }\r
+            });\r
             rs.commit();\r
         }\r
     },\r
@@ -32616,12 +34442,56 @@ Ext.data.DataReader.prototype = {
                 data = data.shift();\r
             }\r
             if (this.isData(data)) {\r
-                rs.data = Ext.apply(rs.data, data);\r
+                rs.fields.each(function(f) {\r
+                    if (data[f.name] !== f.defaultValue) {\r
+                        rs.data[f.name] = data[f.name];\r
+                    }\r
+                });\r
             }\r
             rs.commit();\r
         }\r
     },\r
 \r
+    /**\r
+     * returns extracted, type-cast rows of data.  Iterates to call #extractValues for each row\r
+     * @param {Object[]/Object} data-root from server response\r
+     * @param {Boolean} returnRecords [false] Set true to return instances of Ext.data.Record\r
+     * @private\r
+     */\r
+    extractData : function(root, returnRecords) {\r
+        // A bit ugly this, too bad the Record's raw data couldn't be saved in a common property named "raw" or something.\r
+        var rawName = (this instanceof Ext.data.JsonReader) ? 'json' : 'node';\r
+\r
+        var rs = [];\r
+\r
+        // Had to add Check for XmlReader, #isData returns true if root is an Xml-object.  Want to check in order to re-factor\r
+        // #extractData into DataReader base, since the implementations are almost identical for JsonReader, XmlReader\r
+        if (this.isData(root) && !(this instanceof Ext.data.XmlReader)) {\r
+            root = [root];\r
+        }\r
+        var f       = this.recordType.prototype.fields,\r
+            fi      = f.items,\r
+            fl      = f.length,\r
+            rs      = [];\r
+        if (returnRecords === true) {\r
+            var Record = this.recordType;\r
+            for (var i = 0; i < root.length; i++) {\r
+                var n = root[i];\r
+                var record = new Record(this.extractValues(n, fi, fl), this.getId(n));\r
+                record[rawName] = n;    // <-- There's implementation of ugly bit, setting the raw record-data.\r
+                rs.push(record);\r
+            }\r
+        }\r
+        else {\r
+            for (var i = 0; i < root.length; i++) {\r
+                var data = this.extractValues(root[i], fi, fl);\r
+                data[this.meta.idProperty] = this.getId(root[i]);\r
+                rs.push(data);\r
+            }\r
+        }\r
+        return rs;\r
+    },\r
+\r
     /**\r
      * Returns true if the supplied data-hash <b>looks</b> and quacks like data.  Checks to see if it has a key\r
      * corresponding to idProperty defined in your DataReader config containing non-empty pk.\r
@@ -32660,42 +34530,6 @@ Ext.apply(Ext.data.DataReader.Error.prototype, {
         'invalid-response': "#readResponse received an invalid response from the server."\r
     }\r
 });\r
-\r
-\r
-/**\r
- * Ext.data.Response\r
- * A generic response class to normalize response-handling internally to the framework.\r
- * TODO move to own file, add to jsb.\r
- */\r
-Ext.data.Response = function(params) {\r
-    Ext.apply(this, params);\r
-};\r
-Ext.data.Response.prototype = {\r
-    /**\r
-     * @property {String} action {@link Ext.data.Api#actions}\r
-     */\r
-    action: undefined,\r
-    /**\r
-     * @property {Boolean} success\r
-     */\r
-    success : undefined,\r
-    /**\r
-     * @property {String} message\r
-     */\r
-    message : undefined,\r
-    /**\r
-     * @property {Array/Object} data\r
-     */\r
-    data: undefined,\r
-    /**\r
-     * @property {Object} raw The raw response returned from server-code\r
-     */\r
-    raw: undefined,\r
-    /**\r
-     * @property {Ext.data.Record/Ext.data.Record[]} record(s) related to the Request action\r
-     */\r
-    records: undefined\r
-}\r
 /**
  * @class Ext.data.DataWriter
  * <p>Ext.data.DataWriter facilitates create, update, and destroy actions between
@@ -32706,34 +34540,72 @@ Ext.data.Response.prototype = {
  * {@link Ext.data.JsonWriter}.</p>
  * <p>Creating a writer is simple:</p>
  * <pre><code>
-var writer = new Ext.data.JsonWriter();
+var writer = new Ext.data.JsonWriter({
+    encode: false   // &lt;--- false causes data to be printed to jsonData config-property of Ext.Ajax#reqeust
+});
+ * </code></pre>
+ * * <p>Same old JsonReader as Ext-2.x:</p>
+ * <pre><code>
+var reader = new Ext.data.JsonReader({idProperty: 'id'}, [{name: 'first'}, {name: 'last'}, {name: 'email'}]);
  * </code></pre>
+ *
  * <p>The proxy for a writer enabled store can be configured with a simple <code>url</code>:</p>
  * <pre><code>
 // Create a standard HttpProxy instance.
 var proxy = new Ext.data.HttpProxy({
-    url: 'app.php/users'
+    url: 'app.php/users'    // &lt;--- Supports "provides"-type urls, such as '/users.json', '/products.xml' (Hello Rails/Merb)
 });
  * </code></pre>
- * <p>For finer grained control, the proxy may also be configured with an <code>api</code>:</p>
+ * <p>For finer grained control, the proxy may also be configured with an <code>API</code>:</p>
  * <pre><code>
-// Use the api specification
+// Maximum flexibility with the API-configuration
 var proxy = new Ext.data.HttpProxy({
     api: {
         read    : 'app.php/users/read',
         create  : 'app.php/users/create',
         update  : 'app.php/users/update',
-        destroy : 'app.php/users/destroy'
+        destroy : {  // &lt;--- Supports object-syntax as well
+            url: 'app.php/users/destroy',
+            method: "DELETE"
+        }
     }
 });
  * </code></pre>
- * <p>Creating a Writer enabled store:</p>
+ * <p>Pulling it all together into a Writer-enabled Store:</p>
  * <pre><code>
 var store = new Ext.data.Store({
     proxy: proxy,
     reader: reader,
-    writer: writer
+    writer: writer,
+    autoLoad: true,
+    autoSave: true  // -- Cell-level updates.
 });
+ * </code></pre>
+ * <p>Initiating write-actions <b>automatically</b>, using the existing Ext2.0 Store/Record API:</p>
+ * <pre><code>
+var rec = store.getAt(0);
+rec.set('email', 'foo@bar.com');  // &lt;--- Immediately initiates an UPDATE action through configured proxy.
+
+store.remove(rec);  // &lt;---- Immediately initiates a DESTROY action through configured proxy.
+ * </code></pre>
+ * <p>For <b>record/batch</b> updates, use the Store-configuration {@link Ext.data.Store#autoSave autoSave:false}</p>
+ * <pre><code>
+var store = new Ext.data.Store({
+    proxy: proxy,
+    reader: reader,
+    writer: writer,
+    autoLoad: true,
+    autoSave: false  // -- disable cell-updates
+});
+
+var urec = store.getAt(0);
+urec.set('email', 'foo@bar.com');
+
+var drec = store.getAt(1);
+store.remove(drec);
+
+// Push the button!
+store.save();
  * </code></pre>
  * @constructor Create a new DataWriter
  * @param {Object} meta Metadata configuration options (implementation-specific)
@@ -32761,13 +34633,14 @@ Ext.data.DataWriter.prototype = {
     listful : false,    // <-- listful is actually not used internally here in DataWriter.  @see Ext.data.Store#execute.
 
     /**
-     * Writes data in preparation for server-write action.  Simply proxies to DataWriter#update, DataWriter#create
-     * DataWriter#destroy.
-     * @param {String} action [CREATE|UPDATE|DESTROY]
-     * @param {Object} params The params-hash to write-to
-     * @param {Record/Record[]} rs The recordset write.
+     * Compiles a Store recordset into a data-format defined by an extension such as {@link Ext.data.JsonWriter} or {@link Ext.data.XmlWriter} in preparation for a {@link Ext.data.Api#actions server-write action}.  The first two params are similar similar in nature to {@link Ext#apply},
+     * Where the first parameter is the <i>receiver</i> of paramaters and the second, baseParams, <i>the source</i>.
+     * @param {Object} params The request-params receiver.
+     * @param {Object} baseParams as defined by {@link Ext.data.Store#baseParams}.  The baseParms must be encoded by the extending class, eg: {@link Ext.data.JsonWriter}, {@link Ext.data.XmlWriter}.
+     * @param {String} action [{@link Ext.data.Api#actions create|update|destroy}]
+     * @param {Record/Record[]} rs The recordset to write, the subject(s) of the write action.
      */
-    write : function(action, params, rs) {
+    apply : function(params, baseParams, action, rs) {
         var data    = [],
         renderer    = action + 'Record';
         // TODO implement @cfg listful here
@@ -32779,7 +34652,7 @@ Ext.data.DataWriter.prototype = {
         else if (rs instanceof Ext.data.Record) {
             data = this[renderer](rs);
         }
-        this.render(action, rs, params, data);
+        this.render(params, baseParams, data);
     },
 
     /**
@@ -32811,11 +34684,16 @@ Ext.data.DataWriter.prototype = {
     destroyRecord : Ext.emptyFn,
 
     /**
-     * Converts a Record to a hash.
-     * @param {Record}
-     * @private
+     * Converts a Record to a hash, taking into account the state of the Ext.data.Record along with configuration properties
+     * related to its rendering, such as {@link #writeAllFields}, {@link Ext.data.Record#phantom phantom}, {@link Ext.data.Record#getChanges getChanges} and
+     * {@link Ext.data.DataReader#idProperty idProperty}
+     * @param {Ext.data.Record}
+     * @param {Object} config <b>NOT YET IMPLEMENTED</b>.  Will implement an exlude/only configuration for fine-control over which fields do/don't get rendered.
+     * @return {Object}
+     * @protected
+     * TODO Implement excludes/only configuration with 2nd param?
      */
-    toHash : function(rec) {
+    toHash : function(rec, config) {
         var map = rec.fields.map,
             data = {},
             raw = (this.writeAllFields === false && rec.phantom === false) ? rec.getChanges() : rec.data,
@@ -32836,6 +34714,24 @@ Ext.data.DataWriter.prototype = {
             data[this.meta.idProperty] = rec.id
         }
         return data;
+    },
+
+    /**
+     * Converts a {@link Ext.data.DataWriter#toHash Hashed} {@link Ext.data.Record} to fields-array array suitable
+     * for encoding to xml via XTemplate, eg:
+<code><pre>&lt;tpl for=".">&lt;{name}>{value}&lt;/{name}&lt;/tpl></pre></code>
+     * eg, <b>non-phantom</b>:
+<code><pre>{id: 1, first: 'foo', last: 'bar'} --> [{name: 'id', value: 1}, {name: 'first', value: 'foo'}, {name: 'last', value: 'bar'}]</pre></code>
+     * {@link Ext.data.Record#phantom Phantom} records will have had their idProperty omitted in {@link #toHash} if determined to be auto-generated.
+     * Non AUTOINCREMENT pks should have been protected.
+     * @param {Hash} data Hashed by Ext.data.DataWriter#toHash
+     * @return {[Object]} Array of attribute-objects.
+     * @protected
+     */
+    toArray : function(data) {
+        var fields = [];
+        Ext.iterate(data, function(k, v) {fields.push({name: k, value: v});},this);
+        return fields;
     }
 };/**\r
  * @class Ext.data.DataProxy\r
@@ -32872,6 +34768,25 @@ proxy : new Ext.data.HttpProxy({
     }\r
 }),\r
  * </code></pre>\r
+ * <p>And <b>new in Ext version 3</b>, attach centralized event-listeners upon the DataProxy class itself!  This is a great place\r
+ * to implement a <i>messaging system</i> to centralize your application's user-feedback and error-handling.</p>\r
+ * <pre><code>\r
+// Listen to all "beforewrite" event fired by all proxies.\r
+Ext.data.DataProxy.on('beforewrite', function(proxy, action) {\r
+    console.log('beforewrite: ', action);\r
+});\r
+\r
+// Listen to "write" event fired by all proxies\r
+Ext.data.DataProxy.on('write', function(proxy, action, data, res, rs) {\r
+    console.info('write: ', action);\r
+});\r
+\r
+// Listen to "exception" event fired by all proxies\r
+Ext.data.DataProxy.on('exception', function(proxy, type, action) {\r
+    console.error(type + action + ' exception);\r
+});\r
+ * </code></pre>\r
+ * <b>Note:</b> These three events are all fired with the signature of the corresponding <i>DataProxy instance</i> event {@link #beforewrite beforewrite}, {@link #write write} and {@link #exception exception}.\r
  */\r
 Ext.data.DataProxy = function(conn){\r
     // make sure we have a config object here to support ux proxies.\r
@@ -33186,7 +35101,7 @@ proxy.setApi(Ext.data.Api.actions.read, '/users/new_load_url');
      * @param {Object} params\r
      * @param {Ext.data.DataReader} reader\r
      * @param {Function} callback\r
-     * @param {Object} scope Scope with which to call the callback (defaults to the Proxy object)\r
+     * @param {Object} scope The scope (<code>this</code> reference) in which the callback function is executed. Defaults to the Proxy object.\r
      * @param {Object} options Any options specified for the action (e.g. see {@link Ext.data.Store#load}.\r
      */\r
     request : function(action, rs, params, reader, callback, scope, options) {\r
@@ -33215,7 +35130,7 @@ proxy.setApi(Ext.data.Api.actions.read, '/users/new_load_url');
     load : null,\r
 \r
     /**\r
-     * @cfg {Function} doRequest Abstract method that should be implemented in all subclasses\r
+     * @cfg {Function} doRequest Abstract method that should be implemented in all subclasses.  <b>Note:</b> Should only be used by custom-proxy developers.\r
      * (e.g.: {@link Ext.data.HttpProxy#doRequest HttpProxy.doRequest},\r
      * {@link Ext.data.DirectProxy#doRequest DirectProxy.doRequest}).\r
      */\r
@@ -33226,6 +35141,27 @@ proxy.setApi(Ext.data.Api.actions.read, '/users/new_load_url');
         this.load(params, reader, callback, scope, options);\r
     },\r
 \r
+    /**\r
+     * @cfg {Function} onRead Abstract method that should be implemented in all subclasses.  <b>Note:</b> Should only be used by custom-proxy developers.  Callback for read {@link Ext.data.Api#actions action}.\r
+     * @param {String} action Action name as per {@link Ext.data.Api.actions#read}.\r
+     * @param {Object} o The request transaction object\r
+     * @param {Object} res The server response\r
+     * @fires loadexception (deprecated)\r
+     * @fires exception\r
+     * @fires load\r
+     * @protected\r
+     */\r
+    onRead : Ext.emptyFn,\r
+    /**\r
+     * @cfg {Function} onWrite Abstract method that should be implemented in all subclasses.  <b>Note:</b> Should only be used by custom-proxy developers.  Callback for <i>create, update and destroy</i> {@link Ext.data.Api#actions actions}.\r
+     * @param {String} action [Ext.data.Api.actions.create|read|update|destroy]\r
+     * @param {Object} trans The request transaction object\r
+     * @param {Object} res The server response\r
+     * @fires exception\r
+     * @fires write\r
+     * @protected\r
+     */\r
+    onWrite : Ext.emptyFn,\r
     /**\r
      * buildUrl\r
      * Sets the appropriate url based upon the action being executed.  If restful is true, and only a single record is being acted upon,\r
@@ -33238,30 +35174,32 @@ proxy.setApi(Ext.data.Api.actions.read, '/users/new_load_url');
      */\r
     buildUrl : function(action, record) {\r
         record = record || null;\r
-        var url = (this.api[action]) ? this.api[action].url : this.url;\r
+\r
+        // conn.url gets nullified after each request.  If it's NOT null here, that means the user must have intervened with a call\r
+        // to DataProxy#setUrl or DataProxy#setApi and changed it before the request was executed.  If that's the case, use conn.url,\r
+        // otherwise, build the url from the api or this.url.\r
+        var url = (this.conn && this.conn.url) ? this.conn.url : (this.api[action]) ? this.api[action].url : this.url;\r
         if (!url) {\r
             throw new Ext.data.Api.Error('invalid-url', action);\r
         }\r
 \r
-        // look for urls having "provides" suffix (from Rails/Merb and others...),\r
-        // e.g.: /users.json, /users.xml, etc\r
+        // look for urls having "provides" suffix used in some MVC frameworks like Rails/Merb and others.  The provides suffice informs\r
+        // the server what data-format the client is dealing with and returns data in the same format (eg: application/json, application/xml, etc)\r
+        // e.g.: /users.json, /users.xml, etc.\r
         // with restful routes, we need urls like:\r
         // PUT /users/1.json\r
         // DELETE /users/1.json\r
-        var format = null;\r
+        var provides = null;\r
         var m = url.match(/(.*)(\.json|\.xml|\.html)$/);\r
         if (m) {\r
-            format = m[2];  // eg ".json"\r
-            url = m[1];     // eg: "/users"\r
+            provides = m[2];    // eg ".json"\r
+            url      = m[1];    // eg: "/users"\r
         }\r
         // prettyUrls is deprectated in favor of restful-config\r
-        if ((this.prettyUrls === true || this.restful === true) && record instanceof Ext.data.Record && !record.phantom) {\r
+        if ((this.restful === true || this.prettyUrls === true) && record instanceof Ext.data.Record && !record.phantom) {\r
             url += '/' + record.id;\r
         }\r
-        if (format) {   // <-- append the request format if exists (ie: /users/update/69[.json])\r
-            url += format;\r
-        }\r
-        return url;\r
+        return (provides === null) ? url : url + provides;\r
     },\r
 \r
     /**\r
@@ -33300,6 +35238,74 @@ Ext.apply(Ext.data.DataProxy.Error.prototype, {
 });\r
 \r
 \r
+/**
+ * @class Ext.data.Request
+ * A simple Request class used internally to the data package to provide more generalized remote-requests
+ * to a DataProxy.
+ * TODO Not yet implemented.  Implement in Ext.data.Store#execute
+ */
+Ext.data.Request = function(params) {
+    Ext.apply(this, params);
+};
+Ext.data.Request.prototype = {
+    /**
+     * @cfg {String} action
+     */
+    action : undefined,
+    /**
+     * @cfg {Ext.data.Record[]/Ext.data.Record} rs The Store recordset associated with the request.
+     */
+    rs : undefined,
+    /**
+     * @cfg {Object} params HTTP request params
+     */
+    params: undefined,
+    /**
+     * @cfg {Function} callback The function to call when request is complete
+     */
+    callback : Ext.emptyFn,
+    /**
+     * @cfg {Object} scope The scope of the callback funtion
+     */
+    scope : undefined,
+    /**
+     * @cfg {Ext.data.DataReader} reader The DataReader instance which will parse the received response
+     */
+    reader : undefined
+};
+/**
+ * @class Ext.data.Response
+ * A generic response class to normalize response-handling internally to the framework.
+ */
+Ext.data.Response = function(params) {
+    Ext.apply(this, params);
+};
+Ext.data.Response.prototype = {
+    /**
+     * @cfg {String} action {@link Ext.data.Api#actions}
+     */
+    action: undefined,
+    /**
+     * @cfg {Boolean} success
+     */
+    success : undefined,
+    /**
+     * @cfg {String} message
+     */
+    message : undefined,
+    /**
+     * @cfg {Array/Object} data
+     */
+    data: undefined,
+    /**
+     * @cfg {Object} raw The raw response returned from server-code
+     */
+    raw: undefined,
+    /**
+     * @cfg {Ext.data.Record/Ext.data.Record[]} records related to the Request action
+     */
+    records: undefined
+};
 /**\r
  * @class Ext.data.ScriptTagProxy\r
  * @extends Ext.data.DataProxy\r
@@ -33334,6 +35340,32 @@ out.print(dataBlock.toJsonString());
 if (scriptTag) {\r
     out.write(");");\r
 }\r
+</code></pre>\r
+ * <p>Below is a PHP example to do the same thing:</p><pre><code>\r
+$callback = $_REQUEST['callback'];\r
+\r
+// Create the output object.\r
+$output = array('a' => 'Apple', 'b' => 'Banana');\r
+\r
+//start output\r
+if ($callback) {\r
+    header('Content-Type: text/javascript');\r
+    echo $callback . '(' . json_encode($output) . ');';\r
+} else {\r
+    header('Content-Type: application/x-json');\r
+    echo json_encode($output);\r
+}\r
+</code></pre>\r
+ * <p>Below is the ASP.Net code to do the same thing:</p><pre><code>\r
+String jsonString = "{success: true}";\r
+String cb = Request.Params.Get("callback");\r
+String responseString = "";\r
+if (!String.IsNullOrEmpty(cb)) {\r
+    responseString = cb + "(" + jsonString + ")";\r
+} else {\r
+    responseString = jsonString;\r
+}\r
+Response.Write(responseString);\r
 </code></pre>\r
  *\r
  * @constructor\r
@@ -33404,7 +35436,7 @@ Ext.extend(Ext.data.ScriptTagProxy, Ext.data.DataProxy, {
      * <li>The "arg" argument from the load function</li>\r
      * <li>A boolean success indicator</li>\r
      * </ul>\r
-     * @param {Object} scope The scope in which to call the callback\r
+     * @param {Object} scope The scope (<code>this</code> reference) in which the callback function is executed. Defaults to the browser window.\r
      * @param {Object} arg An optional argument which is passed to the callback as its second parameter.\r
      */\r
     doRequest : function(action, rs, params, reader, callback, scope, arg) {\r
@@ -33467,7 +35499,7 @@ Ext.extend(Ext.data.ScriptTagProxy, Ext.data.DataProxy, {
      * @param {String} action [Ext.data.Api.actions.create|read|update|destroy]\r
      * @param {Object} trans The request transaction object\r
      * @param {Object} res The server response\r
-     * @private\r
+     * @protected\r
      */\r
     onRead : function(action, trans, res) {\r
         var result;\r
@@ -33496,7 +35528,7 @@ Ext.extend(Ext.data.ScriptTagProxy, Ext.data.DataProxy, {
      * @param {String} action [Ext.data.Api.actions.create|read|update|destroy]\r
      * @param {Object} trans The request transaction object\r
      * @param {Object} res The server response\r
-     * @private\r
+     * @protected\r
      */\r
     onWrite : function(action, trans, response, rs) {\r
         var reader = trans.reader;\r
@@ -33585,7 +35617,7 @@ Ext.extend(Ext.data.ScriptTagProxy, Ext.data.DataProxy, {
  * @constructor\r
  * @param {Object} conn\r
  * An {@link Ext.data.Connection} object, or options parameter to {@link Ext.Ajax#request}.\r
- * <p>Note that if this HttpProxy is being used by a (@link Ext.data.Store Store}, then the\r
+ * <p>Note that if this HttpProxy is being used by a {@link Ext.data.Store Store}, then the\r
  * Store's call to {@link #load} will override any specified <tt>callback</tt> and <tt>params</tt>\r
  * options. In this case, use the Store's {@link Ext.data.Store#events events} to modify parameters,\r
  * or react to loading events. The Store's {@link Ext.data.Store#baseParams baseParams} may also be\r
@@ -33663,8 +35695,9 @@ Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {
      * <li><tt>r</tt> : Ext.data.Record[] The block of Ext.data.Records.</li>\r
      * <li><tt>options</tt>: Options object from the action request</li>\r
      * <li><tt>success</tt>: Boolean success indicator</li></ul></p></div>\r
-     * @param {Object} scope The scope in which to call the callback\r
+     * @param {Object} scope The scope (<code>this</code> reference) in which the callback function is executed. Defaults to the browser window.\r
      * @param {Object} arg An optional argument which is passed to the callback as its second parameter.\r
+     * @protected\r
      */\r
     doRequest : function(action, rs, params, reader, cb, scope, arg) {\r
         var  o = {\r
@@ -33681,7 +35714,6 @@ Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {
 \r
         // If possible, transmit data using jsonData || xmlData on Ext.Ajax.request (An installed DataWriter would have written it there.).\r
         // Use std HTTP params otherwise.\r
-        // TODO wrap into 1 Ext.apply now?\r
         if (params.jsonData) {\r
             o.jsonData = params.jsonData;\r
         } else if (params.xmlData) {\r
@@ -33690,14 +35722,10 @@ Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {
             o.params = params || {};\r
         }\r
         // Set the connection url.  If this.conn.url is not null here,\r
-        // the user may have overridden the url during a beforeaction event-handler.\r
+        // the user must have overridden the url during a beforewrite/beforeload event-handler.\r
         // this.conn.url is nullified after each request.\r
-        if (this.conn.url === null) {\r
-            this.conn.url = this.buildUrl(action, rs);\r
-        }\r
-        else if (this.restful === true && rs instanceof Ext.data.Record && !rs.phantom) { // <-- user must have intervened with #setApi or #setUrl\r
-            this.conn.url += '/' + rs.id;\r
-        }\r
+        this.conn.url = this.buildUrl(action, rs);\r
+\r
         if(this.useAjax){\r
 \r
             Ext.applyIf(o, this.conn);\r
@@ -33743,7 +35771,7 @@ Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {
             } else {\r
                 this.onWrite(action, o, response, rs);\r
             }\r
-        }\r
+        };\r
     },\r
 \r
     /**\r
@@ -33754,7 +35782,7 @@ Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {
      * @fires loadexception (deprecated)\r
      * @fires exception\r
      * @fires load\r
-     * @private\r
+     * @protected\r
      */\r
     onRead : function(action, o, response) {\r
         var result;\r
@@ -33793,7 +35821,7 @@ Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {
      * @param {Object} res The server response\r
      * @fires exception\r
      * @fires write\r
-     * @private\r
+     * @protected\r
      */\r
     onWrite : function(action, o, response, rs) {\r
         var reader = o.reader;\r
@@ -33805,10 +35833,10 @@ Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {
             o.request.callback.call(o.request.scope, null, o.request.arg, false);\r
             return;\r
         }\r
-        if (res.success === false) {\r
-            this.fireEvent('exception', this, 'remote', action, o, res, rs);\r
-        } else {\r
+        if (res.success === true) {\r
             this.fireEvent('write', this, action, res.data, res, rs, o.request.arg);\r
+        } else {\r
+            this.fireEvent('exception', this, 'remote', action, o, res, rs);\r
         }\r
         // TODO refactor onRead, onWrite to be more generalized now that we're dealing with Ext.data.Response instance\r
         // the calls to request.callback(...) in each will have to be made similar.\r
@@ -33873,7 +35901,7 @@ Ext.extend(Ext.data.MemoryProxy, Ext.data.DataProxy, {
      * <li>The "arg" argument from the load function</li>\r
      * <li>A boolean success indicator</li>\r
      * </ul>\r
-     * @param {Object} scope The scope in which to call the callback\r
+     * @param {Object} scope The scope (<code>this</code> reference) in which the callback function is executed. Defaults to the browser window.\r
      * @param {Object} arg An optional argument which is passed to the callback as its second parameter.\r
      */\r
     doRequest : function(action, rs, params, reader, callback, scope, arg) {\r
@@ -33897,20 +35925,7 @@ Ext.extend(Ext.data.MemoryProxy, Ext.data.DataProxy, {
  * @extends Ext.data.DataWriter
  * DataWriter extension for writing an array or single {@link Ext.data.Record} object(s) in preparation for executing a remote CRUD action.
  */
-Ext.data.JsonWriter = function(config) {
-    Ext.data.JsonWriter.superclass.constructor.call(this, config);
-
-    // careful to respect "returnJson", renamed to "encode"
-    // TODO: remove after v3 final release
-    if (this.returnJson != undefined) {
-        this.encode = this.returnJson;
-    }
-}
-Ext.extend(Ext.data.JsonWriter, Ext.data.DataWriter, {
-    /**
-     * @cfg {Boolean} returnJson <b>Deprecated</b>.  Use {@link Ext.data.JsonWriter#encode} instead.
-     */
-    returnJson : undefined,
+Ext.data.JsonWriter = Ext.extend(Ext.data.DataWriter, {
     /**
      * @cfg {Boolean} encode <tt>true</tt> to {@link Ext.util.JSON#encode encode} the
      * {@link Ext.data.DataWriter#toHash hashed data}. Defaults to <tt>true</tt>.  When using
@@ -33922,20 +35937,34 @@ Ext.extend(Ext.data.JsonWriter, Ext.data.DataWriter, {
      * let the lower-level connection object (eg: Ext.Ajax) do the encoding.
      */
     encode : true,
+    /**
+     * @cfg {Boolean} encodeDelete False to send only the id to the server on delete, true to encode it in an object
+     * literal, eg: <pre><code>
+{id: 1}
+ * </code></pre> Defaults to <tt>false</tt>
+     */
+    encodeDelete: false,
+    
+    constructor : function(config){
+        Ext.data.JsonWriter.superclass.constructor.call(this, config);    
+    },
 
     /**
      * Final action of a write event.  Apply the written data-object to params.
-     * @param {String} action [Ext.data.Api.actions.create|read|update|destroy]
-     * @param {Record[]} rs
-     * @param {Object} http params
-     * @param {Object} data object populated according to DataReader meta-data "root" and "idProperty"
+     * @param {Object} http params-object to write-to.
+     * @param {Object} baseParams as defined by {@link Ext.data.Store#baseParams}.  The baseParms must be encoded by the extending class, eg: {@link Ext.data.JsonWriter}, {@link Ext.data.XmlWriter}.
+     * @param {Object/Object[]} data Data-object representing compiled Store-recordset.
      */
-    render : function(action, rs, params, data) {
+    render : function(params, baseParams, data) {
         if (this.encode === true) {
+            // Encode here now.
+            Ext.apply(params, baseParams);
             params[this.meta.root] = Ext.encode(data);
         } else {
-            params.jsonData = {};
-            params.jsonData[this.meta.root] = data;
+            // defer encoding for some other layer, probably in {@link Ext.Ajax#request}.  Place everything into "jsonData" key.
+            var jdata = Ext.apply({}, baseParams);
+            jdata[this.meta.root] = data;
+            params.jsonData = jdata;
         }
     },
     /**
@@ -33963,8 +35992,14 @@ Ext.extend(Ext.data.JsonWriter, Ext.data.DataWriter, {
      * @param {Ext.data.Record} rec
      * @return {Object}
      */
-    destroyRecord : function(rec) {
-        return rec.id;
+    destroyRecord : function(rec){
+        if(this.encodeDelete){
+            var data = {};
+            data[this.meta.idProperty] = rec.id;
+            return data;
+        }else{
+            return rec.id;
+        }
     }
 });/**
  * @class Ext.data.JsonReader
@@ -34155,7 +36190,7 @@ Ext.extend(Ext.data.JsonReader, Ext.data.DataReader, {
         var res = new Ext.data.Response({
             action: action,
             success: this.getSuccess(o),
-            data: this.extractData(root),
+            data: (root) ? this.extractData(root, false) : [],
             message: this.getMessage(o),
             raw: o
         });
@@ -34260,50 +36295,22 @@ Ext.extend(Ext.data.JsonReader, Ext.data.DataReader, {
     createAccessor : function(){
         var re = /[\[\.]/;
         return function(expr) {
-            try {
-                return(re.test(expr)) ?
-                new Function('obj', 'return obj.' + expr) :
-                function(obj){
-                    return obj[expr];
-                };
-            } catch(e){}
-            return Ext.emptyFn;
-        };
-    }(),
-
-    /**
-     * returns extracted, type-cast rows of data.  Iterates to call #extractValues for each row
-     * @param {Object[]/Object} data-root from server response
-     * @param {Boolean} returnRecords [false] Set true to return instances of Ext.data.Record
-     * @private
-     */
-    extractData : function(root, returnRecords) {
-        var rs = undefined;
-        if (this.isData(root)) {
-            root = [root];
-        }
-        if (Ext.isArray(root)) {
-            var f       = this.recordType.prototype.fields,
-                fi      = f.items,
-                fl      = f.length,
-                rs      = [];
-            if (returnRecords === true) {
-                var Record = this.recordType;
-                for (var i = 0; i < root.length; i++) {
-                    var n = root[i];
-                    var record = new Record(this.extractValues(n, fi, fl), this.getId(n));
-                    record.json = n;
-                    rs.push(record);
-                }
+            if(Ext.isEmpty(expr)){
+                return Ext.emptyFn;
             }
-            else {
-                for (var i = 0; i < root.length; i++) {
-                    rs.push(this.extractValues(root[i], fi, fl));
-                }
+            if(Ext.isFunction(expr)){
+                return expr;
             }
-        }
-        return rs;
-    },
+            var i = String(expr).search(re);
+            if(i >= 0){
+                return new Function('obj', 'return obj' + (i > 0 ? '.' : '') + expr);
+            }
+            return function(obj){
+                return obj[expr];
+            };
+
+        };
+    }(),
 
     /**
      * type-casts a single row of raw-data from server
@@ -34394,18 +36401,12 @@ Ext.data.ArrayReader = Ext.extend(Ext.data.JsonReader, {
         this.arrayData = o;
         var s = this.meta,
             sid = s ? Ext.num(s.idIndex, s.id) : null,
-            recordType = this.recordType, 
+            recordType = this.recordType,
             fields = recordType.prototype.fields,
             records = [],
+            success = true,
             v;
 
-        if(!this.getRoot) {
-            this.getRoot = s.root ? this.getJsonAccessor(s.root) : function(p) {return p;};
-            if(s.totalProperty) {
-                this.getTotal = this.getJsonAccessor(s.totalProperty);
-            }
-        }
-
         var root = this.getRoot(o);
 
         for(var i = 0, len = root.length; i < len; i++) {
@@ -34432,8 +36433,15 @@ Ext.data.ArrayReader = Ext.extend(Ext.data.JsonReader, {
                 totalRecords = v;
             }
         }
+        if(s.successProperty){
+            v = this.getSuccess(o);
+            if(v === false || v === 'false'){
+                success = false;
+            }
+        }
 
         return {
+            success : success,
             records : records,
             totalRecords : totalRecords
         };
@@ -34547,14 +36555,31 @@ Ext.reg('jsonstore', Ext.data.JsonStore);/**
  * @class Ext.data.XmlWriter
  * @extends Ext.data.DataWriter
  * DataWriter extension for writing an array or single {@link Ext.data.Record} object(s) in preparation for executing a remote CRUD action via XML.
+ * XmlWriter uses an instance of {@link Ext.XTemplate} for maximum flexibility in defining your own custom XML schema if the default schema is not appropriate for your needs.
+ * See the {@link #tpl} configuration-property.
  */
 Ext.data.XmlWriter = function(params) {
     Ext.data.XmlWriter.superclass.constructor.apply(this, arguments);
-    this.tpl = new Ext.XTemplate(this.tpl).compile();
+    // compile the XTemplate for rendering XML documents.
+    this.tpl = (typeof(this.tpl) === 'string') ? new Ext.XTemplate(this.tpl).compile() : this.tpl.compile();
 };
 Ext.extend(Ext.data.XmlWriter, Ext.data.DataWriter, {
     /**
-     * @cfg {String} root [records] The name of the root element when writing <b>multiple</b> records to the server.  Each
+     * @cfg {String} documentRoot [xrequest] (Optional) The name of the XML document root-node.  <b>Note:</b>
+     * this parameter is required </b>only when</b> sending extra {@link Ext.data.Store#baseParams baseParams} to the server
+     * during a write-request -- if no baseParams are set, the {@link Ext.data.XmlReader#record} meta-property can
+     * suffice as the XML document root-node for write-actions involving just a <b>single record</b>.  For requests
+     * involving <b>multiple</b> records and <b>NO</b> baseParams, the {@link Ext.data.XmlWriter#root} property can
+     * act as the XML document root.
+     */
+    documentRoot: 'xrequest',
+    /**
+     * @cfg {Boolean} forceDocumentRoot [false] Set to <tt>true</tt> to force XML documents having a root-node as defined
+     * by {@link #documentRoot}, even with no baseParams defined.
+     */
+    forceDocumentRoot: false,
+    /**
+     * @cfg {String} root [records] The name of the containing element which will contain the nodes of an write-action involving <b>multiple</b> records.  Each
      * xml-record written to the server will be wrapped in an element named after {@link Ext.data.XmlReader#record} property.
      * eg:
 <code><pre>
@@ -34571,7 +36596,7 @@ Ext.extend(Ext.data.XmlWriter, Ext.data.DataWriter, {
         &lt;records>&lt;first>Barney&lt;/first>&lt;/user>
     &lt;/records>
 </code></pre>
-     * Defaults to <tt>records</tt>
+     * Defaults to <tt>records</tt>.  Do not confuse the nature of this property with that of {@link #documentRoot}
      */
     root: 'records',
     /**
@@ -34585,88 +36610,96 @@ Ext.extend(Ext.data.XmlWriter, Ext.data.DataWriter, {
      */
     xmlEncoding: 'ISO-8859-15',
     /**
-     * @cfg {String} tpl The xml template.  Defaults to
+     * @cfg {String/Ext.XTemplate} tpl The XML template used to render {@link Ext.data.Api#actions write-actions} to your server.
+     * <p>One can easily provide his/her own custom {@link Ext.XTemplate#constructor template-definition} if the default does not suffice.</p>
+     * <p>Defaults to:</p>
 <code><pre>
 &lt;?xml version="{version}" encoding="{encoding}"?>
-    &lt;tpl if="{[values.nodes.length>1]}">&lt;{root}}>',
+    &lt;tpl if="documentRoot">&lt;{documentRoot}>
+    &lt;tpl for="baseParams">
+        &lt;tpl for=".">
+            &lt;{name}>{value}&lt;/{name}>
+        &lt;/tpl>
+    &lt;/tpl>
+    &lt;tpl if="records.length &gt; 1">&lt;{root}>',
     &lt;tpl for="records">
         &lt;{parent.record}>
-        &lt;tpl for="fields">
+        &lt;tpl for=".">
             &lt;{name}>{value}&lt;/{name}>
         &lt;/tpl>
         &lt;/{parent.record}>
     &lt;/tpl>
-    &lt;tpl if="{[values.records.length>1]}">&lt;/{root}}>&lt;/tpl>
+    &lt;tpl if="records.length &gt; 1">&lt;/{root}>&lt;/tpl>
+    &lt;tpl if="documentRoot">&lt;/{documentRoot}>&lt;/tpl>
 </pre></code>
+     * <p>Templates will be called with the following API</p>
+     * <ul>
+     * <li>{String} version [1.0] The xml version.</li>
+     * <li>{String} encoding [ISO-8859-15] The xml encoding.</li>
+     * <li>{String/false} documentRoot The XML document root-node name or <tt>false</tt> if not required.  See {@link #documentRoot} and {@link #forceDocumentRoot}.</li>
+     * <li>{String} record The meta-data parameter defined on your {@link Ext.data.XmlReader#record} configuration represents the name of the xml-tag containing each record.</li>
+     * <li>{String} root The meta-data parameter defined by {@link Ext.data.XmlWriter#root} configuration-parameter.  Represents the name of the xml root-tag when sending <b>multiple</b> records to the server.</li>
+     * <li>{Array} records The records being sent to the server, ie: the subject of the write-action being performed.  The records parameter will be always be an array, even when only a single record is being acted upon.
+     *     Each item within the records array will contain an array of field objects having the following properties:
+     *     <ul>
+     *         <li>{String} name The field-name of the record as defined by your {@link Ext.data.Record#create Ext.data.Record definition}.  The "mapping" property will be used, otherwise it will match the "name" property.  Use this parameter to define the XML tag-name of the property.</li>
+     *         <li>{Mixed} value The record value of the field enclosed within XML tags specified by name property above.</li>
+     *     </ul></li>
+     * <li>{Array} baseParams.  The baseParams as defined upon {@link Ext.data.Store#baseParams}.  Note that the baseParams have been converted into an array of [{name : "foo", value: "bar"}, ...] pairs in the same manner as the <b>records</b> parameter above.  See {@link #documentRoot} and {@link #forceDocumentRoot}.</li>
+     * </ul>
      */
     // Break up encoding here in case it's being included by some kind of page that will parse it (eg. PHP)
     tpl: '<tpl for="."><' + '?xml version="{version}" encoding="{encoding}"?' + '><tpl if="documentRoot"><{documentRoot}><tpl for="baseParams"><tpl for="."><{name}>{value}</{name}</tpl></tpl></tpl><tpl if="records.length&gt;1"><{root}></tpl><tpl for="records"><{parent.record}><tpl for="."><{name}>{value}</{name}></tpl></{parent.record}></tpl><tpl if="records.length&gt;1"></{root}></tpl><tpl if="documentRoot"></{documentRoot}></tpl></tpl>',
 
     /**
-     * Final action of a write event.  Apply the written data-object to params.
-     * @param {String} action [Ext.data.Api.create|read|update|destroy]
-     * @param {Ext.data.Record/Ext.data.Record[]} rs
-     * @param {Object} http params
-     * @param {Object/Object[]} rendered data.
+     * XmlWriter implementation of the final stage of a write action.
+     * @param {Object} params Transport-proxy's (eg: {@link Ext.Ajax#request}) params-object to write-to.
+     * @param {Object} baseParams as defined by {@link Ext.data.Store#baseParams}.  The baseParms must be encoded by the extending class, eg: {@link Ext.data.JsonWriter}, {@link Ext.data.XmlWriter}.
+     * @param {Object/Object[]} data Data-object representing the compiled Store-recordset.
      */
-    render : function(action, rs, params, data) {
+    render : function(params, baseParams, data) {
+        baseParams = this.toArray(baseParams);
         params.xmlData = this.tpl.applyTemplate({
             version: this.xmlVersion,
             encoding: this.xmlEncoding,
+            documentRoot: (baseParams.length > 0 || this.forceDocumentRoot === true) ? this.documentRoot : false,
             record: this.meta.record,
             root: this.root,
-            records: (Ext.isArray(rs)) ? data : [data]
+            baseParams: baseParams,
+            records: (Ext.isArray(data[0])) ? data : [data]
         });
     },
 
-    /**
-     * Converts an Ext.data.Record to xml
-     * @param {Ext.data.Record} rec
-     * @return {String} rendered xml-element
-     * @private
-     */
-    toXml : function(data) {
-        var fields = [];
-        Ext.iterate(data, function(k, v) {
-            fields.push({
-                name: k,
-                value: v
-            });
-        },this);
-        return {
-            fields: fields
-        };
-    },
-
     /**
      * createRecord
+     * @protected
      * @param {Ext.data.Record} rec
-     * @return {String} xml element
-     * @private
+     * @return {Array} Array of <tt>name:value</tt> pairs for attributes of the {@link Ext.data.Record}.  See {@link Ext.data.DataWriter#toHash}.
      */
     createRecord : function(rec) {
-        return this.toXml(this.toHash(rec));
+        return this.toArray(this.toHash(rec));
     },
 
     /**
      * updateRecord
+     * @protected
      * @param {Ext.data.Record} rec
-     * @return {String} xml element
-     * @private
+     * @return {Array} Array of {name:value} pairs for attributes of the {@link Ext.data.Record}.  See {@link Ext.data.DataWriter#toHash}.
      */
     updateRecord : function(rec) {
-        return this.toXml(this.toHash(rec));
+        return this.toArray(this.toHash(rec));
 
     },
     /**
      * destroyRecord
+     * @protected
      * @param {Ext.data.Record} rec
-     * @return {String} xml element
+     * @return {Array} Array containing a attribute-object (name/value pair) representing the {@link Ext.data.DataReader#idProperty idProperty}.
      */
     destroyRecord : function(rec) {
         var data = {};
         data[this.meta.idProperty] = rec.id;
-        return this.toXml(data);
+        return this.toArray(data);
     }
 });
 
@@ -34725,8 +36758,11 @@ var myReader = new Ext.data.XmlReader({
 Ext.data.XmlReader = function(meta, recordType){
     meta = meta || {};
 
-    // backwards compat, convert idPath to idProperty
-    meta.idProperty = meta.idProperty || meta.idPath;
+    // backwards compat, convert idPath or id / success
+    Ext.applyIf(meta, {
+        idProperty: meta.idProperty || meta.idPath || meta.id,
+        successProperty: meta.successProperty || meta.success
+    });
 
     Ext.data.XmlReader.superclass.constructor.call(this, meta, recordType || meta.fields);
 };
@@ -34784,17 +36820,19 @@ Ext.extend(Ext.data.XmlReader, Ext.data.DataReader, {
     /**
      * Decode a json response from server.
      * @param {String} action [{@link Ext.data.Api#actions} create|read|update|destroy]
-     * @param {Ext.data.Response} response Returns an instance of {@link Ext.data.Response}
+     * @param {Object} response HTTP Response object from browser.
+     * @return {Ext.data.Response} response Returns an instance of {@link Ext.data.Response}
      */
     readResponse : function(action, response) {
         var q   = Ext.DomQuery,
         doc     = response.responseXML;
 
+        // create general Response instance.
         var res = new Ext.data.Response({
             action: action,
             success : this.getSuccess(doc),
             message: this.getMessage(doc),
-            data: this.extractData(q.select(this.meta.record, doc) || q.select(this.meta.root, doc)),
+            data: this.extractData(q.select(this.meta.record, doc) || q.select(this.meta.root, doc), false),
             raw: doc
         });
 
@@ -34802,6 +36840,7 @@ Ext.extend(Ext.data.XmlReader, Ext.data.DataReader, {
             throw new Ext.data.DataReader.Error('successProperty-response', this.meta.successProperty);
         }
 
+        // Create actions from a response having status 200 must return pk
         if (action === Ext.data.Api.actions.create) {
             var def = Ext.isDefined(res.data);
             if (def && Ext.isEmpty(res.data)) {
@@ -34895,36 +36934,6 @@ Ext.extend(Ext.data.XmlReader, Ext.data.DataReader, {
         };
     }(),
 
-    /**
-     * Extracts rows of record-data from server.  iterates and calls #extractValues
-     * TODO I don't care much for method-names of #extractData, #extractValues.
-     * @param {Array} root
-     * @param {Boolean} returnRecords When true, will return instances of Ext.data.Record; otherwise just hashes.
-     * @private
-     * @ignore
-     */
-    extractData : function(root, returnRecords) {
-        var Record  = this.recordType,
-        records     = [],
-        f           = Record.prototype.fields,
-        fi          = f.items,
-        fl          = f.length;
-        if (returnRecords === true) {
-            for (var i = 0, len = root.length; i < len; i++) {
-                var data = root[i],
-                    record = new Record(this.extractValues(data, fi, fl), this.getId(data));
-                    
-                record.node = data;
-                records.push(record);
-            }
-        } else {
-            for (var i = 0, len = root.length; i < len; i++) {
-                records.push(this.extractValues(root[i], fi, fl));
-            }
-        }
-        return records;
-    },
-
     /**
      * extracts values and type-casts a row of data from server, extracted by #extractData
      * @param {Hash} data
@@ -35023,13 +37032,13 @@ Ext.reg('xmlstore', Ext.data.XmlStore);/**
  * @xtype groupingstore\r
  */\r
 Ext.data.GroupingStore = Ext.extend(Ext.data.Store, {\r
-    \r
+\r
     //inherit docs\r
     constructor: function(config){\r
         Ext.data.GroupingStore.superclass.constructor.call(this, config);\r
         this.applyGroupField();\r
     },\r
-    \r
+\r
     /**\r
      * @cfg {String} groupField\r
      * The field name by which to sort the store's data (defaults to '').\r
@@ -35048,21 +37057,25 @@ Ext.data.GroupingStore = Ext.extend(Ext.data.Store, {
      */\r
     groupOnSort:false,\r
 \r
-       groupDir : 'ASC',\r
-       \r
+    groupDir : 'ASC',\r
+\r
     /**\r
      * Clears any existing grouping and refreshes the data using the default sort.\r
      */\r
     clearGrouping : function(){\r
         this.groupField = false;\r
+\r
         if(this.remoteGroup){\r
             if(this.baseParams){\r
                 delete this.baseParams.groupBy;\r
+                delete this.baseParams.groupDir;\r
             }\r
             var lo = this.lastOptions;\r
             if(lo && lo.params){\r
                 delete lo.params.groupBy;\r
+                delete lo.params.groupDir;\r
             }\r
+\r
             this.reload();\r
         }else{\r
             this.applySort();\r
@@ -35077,12 +37090,12 @@ Ext.data.GroupingStore = Ext.extend(Ext.data.Store, {
      * in is the same as the current grouping field, false to skip grouping on the same field (defaults to false)\r
      */\r
     groupBy : function(field, forceRegroup, direction){\r
-               direction = direction ? (String(direction).toUpperCase() == 'DESC' ? 'DESC' : 'ASC') : this.groupDir;\r
+        direction = direction ? (String(direction).toUpperCase() == 'DESC' ? 'DESC' : 'ASC') : this.groupDir;\r
         if(this.groupField == field && this.groupDir == direction && !forceRegroup){\r
             return; // already grouped by this field\r
         }\r
         this.groupField = field;\r
-               this.groupDir = direction;\r
+        this.groupDir = direction;\r
         this.applyGroupField();\r
         if(this.groupOnSort){\r
             this.sort(field, direction);\r
@@ -35092,7 +37105,7 @@ Ext.data.GroupingStore = Ext.extend(Ext.data.Store, {
             this.reload();\r
         }else{\r
             var si = this.sortInfo || {};\r
-            if(si.field != field || si.direction != direction){\r
+            if(forceRegroup || si.field != field || si.direction != direction){\r
                 this.applySort();\r
             }else{\r
                 this.sortData(field, direction);\r
@@ -35100,15 +37113,25 @@ Ext.data.GroupingStore = Ext.extend(Ext.data.Store, {
             this.fireEvent('datachanged', this);\r
         }\r
     },\r
-    \r
+\r
     // private\r
     applyGroupField: function(){\r
         if(this.remoteGroup){\r
             if(!this.baseParams){\r
                 this.baseParams = {};\r
             }\r
-            this.baseParams.groupBy = this.groupField;\r
-            this.baseParams.groupDir = this.groupDir;\r
+            Ext.apply(this.baseParams, {\r
+                groupBy : this.groupField,\r
+                groupDir : this.groupDir\r
+            });\r
+\r
+            var lo = this.lastOptions;\r
+            if(lo && lo.params){\r
+                Ext.apply(lo.params, {\r
+                    groupBy : this.groupField,\r
+                    groupDir : this.groupDir\r
+                });\r
+            }\r
         }\r
     },\r
 \r
@@ -35183,14 +37206,31 @@ paramOrder: 'param1|param2|param'
      */\r
     directFn : undefined,\r
 \r
-    // protected\r
+    /**\r
+     * DirectProxy implementation of {@link Ext.data.DataProxy#doRequest}\r
+     * @param {String} action The crud action type (create, read, update, destroy)\r
+     * @param {Ext.data.Record/Ext.data.Record[]} rs If action is load, rs will be null\r
+     * @param {Object} params An object containing properties which are to be used as HTTP parameters\r
+     * for the request to the remote server.\r
+     * @param {Ext.data.DataReader} reader The Reader object which converts the data\r
+     * object into a block of Ext.data.Records.\r
+     * @param {Function} callback\r
+     * <div class="sub-desc"><p>A function to be called after the request.\r
+     * The <tt>callback</tt> is passed the following arguments:<ul>\r
+     * <li><tt>r</tt> : Ext.data.Record[] The block of Ext.data.Records.</li>\r
+     * <li><tt>options</tt>: Options object from the action request</li>\r
+     * <li><tt>success</tt>: Boolean success indicator</li></ul></p></div>\r
+     * @param {Object} scope The scope (<code>this</code> reference) in which the callback function is executed. Defaults to the browser window.\r
+     * @param {Object} arg An optional argument which is passed to the callback as its second parameter.\r
+     * @protected\r
+     */\r
     doRequest : function(action, rs, params, reader, callback, scope, options) {\r
-        var args = [];\r
-        var directFn = this.api[action] || this.directFn;\r
+        var args = [],\r
+            directFn = this.api[action] || this.directFn;\r
 \r
         switch (action) {\r
             case Ext.data.Api.actions.create:\r
-                args.push(params.jsonData[reader.meta.root]);          // <-- create(Hash)\r
+                args.push(params.jsonData);            // <-- create(Hash)\r
                 break;\r
             case Ext.data.Api.actions.read:\r
                 // If the method has no parameters, ignore the paramOrder/paramsAsHash.\r
@@ -35205,10 +37245,10 @@ paramOrder: 'param1|param2|param'
                 }\r
                 break;\r
             case Ext.data.Api.actions.update:\r
-                args.push(params.jsonData[reader.meta.root]);        // <-- update(Hash/Hash[])\r
+                args.push(params.jsonData);        // <-- update(Hash/Hash[])\r
                 break;\r
             case Ext.data.Api.actions.destroy:\r
-                args.push(params.jsonData[reader.meta.root]);        // <-- destroy(Int/Int[])\r
+                args.push(params.jsonData);        // <-- destroy(Int/Int[])\r
                 break;\r
         }\r
 \r
@@ -35249,8 +37289,9 @@ paramOrder: 'param1|param2|param'
      * Callback for read actions\r
      * @param {String} action [Ext.data.Api.actions.create|read|update|destroy]\r
      * @param {Object} trans The request transaction object\r
+     * @param {Object} result Data object picked out of the server-response.\r
      * @param {Object} res The server response\r
-     * @private\r
+     * @protected\r
      */\r
     onRead : function(action, trans, result, res) {\r
         var records;\r
@@ -35270,13 +37311,15 @@ paramOrder: 'param1|param2|param'
     },\r
     /**\r
      * Callback for write actions\r
-     * @param {String} action [Ext.data.Api.actions.create|read|update|destroy]\r
+     * @param {String} action [{@link Ext.data.Api#actions create|read|update|destroy}]\r
      * @param {Object} trans The request transaction object\r
+     * @param {Object} result Data object picked out of the server-response.\r
      * @param {Object} res The server response\r
-     * @private\r
+     * @param {Ext.data.Record/[Ext.data.Record]} rs The Store resultset associated with the action.\r
+     * @protected\r
      */\r
     onWrite : function(action, trans, result, res, rs) {\r
-        var data = trans.reader.extractData(result);\r
+        var data = trans.reader.extractData(result, false);\r
         this.fireEvent("write", this, action, data, res, rs, trans.request.arg);\r
         trans.request.callback.call(trans.request.scope, data, res, true);\r
     }\r
@@ -35317,16 +37360,18 @@ paramOrder: 'param1|param2|param'
  * @constructor\r
  * @param {Object} config\r
  */\r
-Ext.data.DirectStore = function(c){\r
-    // each transaction upon a singe record will generatie a distinct Direct transaction since Direct queues them into one Ajax request.\r
-    c.batchTransactions = false;\r
-\r
-    Ext.data.DirectStore.superclass.constructor.call(this, Ext.apply(c, {\r
-        proxy: (typeof(c.proxy) == 'undefined') ? new Ext.data.DirectProxy(Ext.copyTo({}, c, 'paramOrder,paramsAsHash,directFn,api')) : c.proxy,\r
-        reader: (typeof(c.reader) == 'undefined' && typeof(c.fields) == 'object') ? new Ext.data.JsonReader(Ext.copyTo({}, c, 'totalProperty,root,idProperty'), c.fields) : c.reader\r
-    }));\r
-};\r
-Ext.extend(Ext.data.DirectStore, Ext.data.Store, {});\r
+Ext.data.DirectStore = Ext.extend(Ext.data.Store, {\r
+    constructor : function(config){\r
+        // each transaction upon a singe record will generate a distinct Direct transaction since Direct queues them into one Ajax request.\r
+        var c = Ext.apply({}, {\r
+            batchTransactions: false\r
+        }, config);\r
+        Ext.data.DirectStore.superclass.constructor.call(this, Ext.apply(c, {\r
+            proxy: Ext.isDefined(c.proxy) ? c.proxy : new Ext.data.DirectProxy(Ext.copyTo({}, c, 'paramOrder,paramsAsHash,directFn,api')),\r
+            reader: (!Ext.isDefined(c.reader) && c.fields) ? new Ext.data.JsonReader(Ext.copyTo({}, c, 'totalProperty,root,idProperty'), c.fields) : c.reader\r
+        }));\r
+    }\r
+});\r
 Ext.reg('directstore', Ext.data.DirectStore);
 /**\r
  * @class Ext.Direct\r
@@ -36266,7 +38311,13 @@ TestAction.multiply(
         }\r
     }\r
 });\r
-Ext.Direct.PROVIDERS['remoting'] = Ext.direct.RemotingProvider;/**\r
+Ext.Direct.PROVIDERS['remoting'] = Ext.direct.RemotingProvider;/*!\r
+ * Ext JS Library 3.1.1\r
+ * Copyright(c) 2006-2010 Ext JS, LLC\r
+ * licensing@extjs.com\r
+ * http://www.extjs.com/license\r
+ */\r
+/**\r
  * @class Ext.Resizable\r
  * @extends Ext.util.Observable\r
  * <p>Applies drag handles to an element to make it resizable. The drag handles are inserted into the element \r
@@ -36306,132 +38357,134 @@ resizer.on('resize', myHandler);
  * @param {Mixed} el The id or element to resize\r
  * @param {Object} config configuration options\r
   */\r
-Ext.Resizable = function(el, config){\r
-    this.el = Ext.get(el);\r
+Ext.Resizable = Ext.extend(Ext.util.Observable, {\r
     \r
-    if(config && config.wrap){\r
-        config.resizeChild = this.el;\r
-        this.el = this.el.wrap(typeof config.wrap == 'object' ? config.wrap : {cls:'xresizable-wrap'});\r
-        this.el.id = this.el.dom.id = config.resizeChild.id + '-rzwrap';\r
-        this.el.setStyle('overflow', 'hidden');\r
-        this.el.setPositioning(config.resizeChild.getPositioning());\r
-        config.resizeChild.clearPositioning();\r
-        if(!config.width || !config.height){\r
-            var csize = config.resizeChild.getSize();\r
-            this.el.setSize(csize.width, csize.height);\r
-        }\r
-        if(config.pinned && !config.adjustments){\r
-            config.adjustments = 'auto';\r
+    constructor: function(el, config){\r
+        this.el = Ext.get(el);\r
+        if(config && config.wrap){\r
+            config.resizeChild = this.el;\r
+            this.el = this.el.wrap(typeof config.wrap == 'object' ? config.wrap : {cls:'xresizable-wrap'});\r
+            this.el.id = this.el.dom.id = config.resizeChild.id + '-rzwrap';\r
+            this.el.setStyle('overflow', 'hidden');\r
+            this.el.setPositioning(config.resizeChild.getPositioning());\r
+            config.resizeChild.clearPositioning();\r
+            if(!config.width || !config.height){\r
+                var csize = config.resizeChild.getSize();\r
+                this.el.setSize(csize.width, csize.height);\r
+            }\r
+            if(config.pinned && !config.adjustments){\r
+                config.adjustments = 'auto';\r
+            }\r
         }\r
-    }\r
-\r
-    /**\r
-     * The proxy Element that is resized in place of the real Element during the resize operation.\r
-     * This may be queried using {@link Ext.Element#getBox} to provide the new area to resize to.\r
-     * Read only.\r
-     * @type Ext.Element.\r
-     * @property proxy\r
-     */\r
-    this.proxy = this.el.createProxy({tag: 'div', cls: 'x-resizable-proxy', id: this.el.id + '-rzproxy'}, Ext.getBody());\r
-    this.proxy.unselectable();\r
-    this.proxy.enableDisplayMode('block');\r
-\r
-    Ext.apply(this, config);\r
     \r
-    if(this.pinned){\r
-        this.disableTrackOver = true;\r
-        this.el.addClass('x-resizable-pinned');\r
-    }\r
-    // if the element isn't positioned, make it relative\r
-    var position = this.el.getStyle('position');\r
-    if(position != 'absolute' && position != 'fixed'){\r
-        this.el.setStyle('position', 'relative');\r
-    }\r
-    if(!this.handles){ // no handles passed, must be legacy style\r
-        this.handles = 's,e,se';\r
-        if(this.multiDirectional){\r
-            this.handles += ',n,w';\r
+        /**\r
+         * The proxy Element that is resized in place of the real Element during the resize operation.\r
+         * This may be queried using {@link Ext.Element#getBox} to provide the new area to resize to.\r
+         * Read only.\r
+         * @type Ext.Element.\r
+         * @property proxy\r
+         */\r
+        this.proxy = this.el.createProxy({tag: 'div', cls: 'x-resizable-proxy', id: this.el.id + '-rzproxy'}, Ext.getBody());\r
+        this.proxy.unselectable();\r
+        this.proxy.enableDisplayMode('block');\r
+    \r
+        Ext.apply(this, config);\r
+        \r
+        if(this.pinned){\r
+            this.disableTrackOver = true;\r
+            this.el.addClass('x-resizable-pinned');\r
         }\r
-    }\r
-    if(this.handles == 'all'){\r
-        this.handles = 'n s e w ne nw se sw';\r
-    }\r
-    var hs = this.handles.split(/\s*?[,;]\s*?| /);\r
-    var ps = Ext.Resizable.positions;\r
-    for(var i = 0, len = hs.length; i < len; i++){\r
-        if(hs[i] && ps[hs[i]]){\r
-            var pos = ps[hs[i]];\r
-            this[pos] = new Ext.Resizable.Handle(this, pos, this.disableTrackOver, this.transparent);\r
+        // if the element isn't positioned, make it relative\r
+        var position = this.el.getStyle('position');\r
+        if(position != 'absolute' && position != 'fixed'){\r
+            this.el.setStyle('position', 'relative');\r
         }\r
-    }\r
-    // legacy\r
-    this.corner = this.southeast;\r
-    \r
-    if(this.handles.indexOf('n') != -1 || this.handles.indexOf('w') != -1){\r
-        this.updateBox = true;\r
-    }   \r
-   \r
-    this.activeHandle = null;\r
-    \r
-    if(this.resizeChild){\r
-        if(typeof this.resizeChild == 'boolean'){\r
-            this.resizeChild = Ext.get(this.el.dom.firstChild, true);\r
+        if(!this.handles){ // no handles passed, must be legacy style\r
+            this.handles = 's,e,se';\r
+            if(this.multiDirectional){\r
+                this.handles += ',n,w';\r
+            }\r
+        }\r
+        if(this.handles == 'all'){\r
+            this.handles = 'n s e w ne nw se sw';\r
+        }\r
+        var hs = this.handles.split(/\s*?[,;]\s*?| /);\r
+        var ps = Ext.Resizable.positions;\r
+        for(var i = 0, len = hs.length; i < len; i++){\r
+            if(hs[i] && ps[hs[i]]){\r
+                var pos = ps[hs[i]];\r
+                this[pos] = new Ext.Resizable.Handle(this, pos, this.disableTrackOver, this.transparent, this.handleCls);\r
+            }\r
+        }\r
+        // legacy\r
+        this.corner = this.southeast;\r
+        \r
+        if(this.handles.indexOf('n') != -1 || this.handles.indexOf('w') != -1){\r
+            this.updateBox = true;\r
+        }   \r
+       \r
+        this.activeHandle = null;\r
+        \r
+        if(this.resizeChild){\r
+            if(typeof this.resizeChild == 'boolean'){\r
+                this.resizeChild = Ext.get(this.el.dom.firstChild, true);\r
+            }else{\r
+                this.resizeChild = Ext.get(this.resizeChild, true);\r
+            }\r
+        }\r
+        \r
+        if(this.adjustments == 'auto'){\r
+            var rc = this.resizeChild;\r
+            var hw = this.west, he = this.east, hn = this.north, hs = this.south;\r
+            if(rc && (hw || hn)){\r
+                rc.position('relative');\r
+                rc.setLeft(hw ? hw.el.getWidth() : 0);\r
+                rc.setTop(hn ? hn.el.getHeight() : 0);\r
+            }\r
+            this.adjustments = [\r
+                (he ? -he.el.getWidth() : 0) + (hw ? -hw.el.getWidth() : 0),\r
+                (hn ? -hn.el.getHeight() : 0) + (hs ? -hs.el.getHeight() : 0) -1 \r
+            ];\r
+        }\r
+        \r
+        if(this.draggable){\r
+            this.dd = this.dynamic ? \r
+                this.el.initDD(null) : this.el.initDDProxy(null, {dragElId: this.proxy.id});\r
+            this.dd.setHandleElId(this.resizeChild ? this.resizeChild.id : this.el.id);\r
+            if(this.constrainTo){\r
+                this.dd.constrainTo(this.constrainTo);\r
+            }\r
+        }\r
+        \r
+        this.addEvents(\r
+            /**\r
+             * @event beforeresize\r
+             * Fired before resize is allowed. Set {@link #enabled} to false to cancel resize.\r
+             * @param {Ext.Resizable} this\r
+             * @param {Ext.EventObject} e The mousedown event\r
+             */\r
+            'beforeresize',\r
+            /**\r
+             * @event resize\r
+             * Fired after a resize.\r
+             * @param {Ext.Resizable} this\r
+             * @param {Number} width The new width\r
+             * @param {Number} height The new height\r
+             * @param {Ext.EventObject} e The mouseup event\r
+             */\r
+            'resize'\r
+        );\r
+        \r
+        if(this.width !== null && this.height !== null){\r
+            this.resizeTo(this.width, this.height);\r
         }else{\r
-            this.resizeChild = Ext.get(this.resizeChild, true);\r
+            this.updateChildSize();\r
         }\r
-    }\r
-    \r
-    if(this.adjustments == 'auto'){\r
-        var rc = this.resizeChild;\r
-        var hw = this.west, he = this.east, hn = this.north, hs = this.south;\r
-        if(rc && (hw || hn)){\r
-            rc.position('relative');\r
-            rc.setLeft(hw ? hw.el.getWidth() : 0);\r
-            rc.setTop(hn ? hn.el.getHeight() : 0);\r
-        }\r
-        this.adjustments = [\r
-            (he ? -he.el.getWidth() : 0) + (hw ? -hw.el.getWidth() : 0),\r
-            (hn ? -hn.el.getHeight() : 0) + (hs ? -hs.el.getHeight() : 0) -1 \r
-        ];\r
-    }\r
-    \r
-    if(this.draggable){\r
-        this.dd = this.dynamic ? \r
-            this.el.initDD(null) : this.el.initDDProxy(null, {dragElId: this.proxy.id});\r
-        this.dd.setHandleElId(this.resizeChild ? this.resizeChild.id : this.el.id);\r
-    }\r
-    \r
-    this.addEvents(\r
-        /**\r
-         * @event beforeresize\r
-         * Fired before resize is allowed. Set {@link #enabled} to false to cancel resize.\r
-         * @param {Ext.Resizable} this\r
-         * @param {Ext.EventObject} e The mousedown event\r
-         */\r
-        'beforeresize',\r
-        /**\r
-         * @event resize\r
-         * Fired after a resize.\r
-         * @param {Ext.Resizable} this\r
-         * @param {Number} width The new width\r
-         * @param {Number} height The new height\r
-         * @param {Ext.EventObject} e The mouseup event\r
-         */\r
-        'resize'\r
-    );\r
-    \r
-    if(this.width !== null && this.height !== null){\r
-        this.resizeTo(this.width, this.height);\r
-    }else{\r
-        this.updateChildSize();\r
-    }\r
-    if(Ext.isIE){\r
-        this.el.dom.style.zoom = 1;\r
-    }\r
-    Ext.Resizable.superclass.constructor.call(this);\r
-};\r
-\r
-Ext.extend(Ext.Resizable, Ext.util.Observable, {\r
+        if(Ext.isIE){\r
+            this.el.dom.style.zoom = 1;\r
+        }\r
+        Ext.Resizable.superclass.constructor.call(this);    \r
+    },\r
 \r
     /**\r
      * @cfg {Array/String} adjustments String 'auto' or an array [width, height] with values to be <b>added</b> to the\r
@@ -36549,6 +38602,9 @@ Ext.extend(Ext.Resizable, Ext.util.Observable, {
      * @cfg {Boolean} wrap True to wrap an element with a div if needed (required for textareas and images, defaults to false)\r
      * in favor of the handles config option (defaults to false)\r
      */\r
+    /**\r
+     * @cfg {String} handleCls A css class to add to each handle. Defaults to <tt>''</tt>.\r
+     */\r
 \r
     \r
     /**\r
@@ -36719,6 +38775,10 @@ new Ext.Panel({
         if(!this.dynamic){\r
             this.proxy.hide();\r
         }\r
+        if(this.draggable && this.constrainTo){\r
+            this.dd.resetConstraints();\r
+            this.dd.constrainTo(this.constrainTo);\r
+        }\r
         return box;\r
     },\r
 \r
@@ -36969,35 +39029,36 @@ Ext.Resizable.positions = {
     n: 'north', s: 'south', e: 'east', w: 'west', se: 'southeast', sw: 'southwest', nw: 'northwest', ne: 'northeast'\r
 };\r
 \r
-// private\r
-Ext.Resizable.Handle = function(rz, pos, disableTrackOver, transparent){\r
-    if(!this.tpl){\r
-        // only initialize the template if resizable is used\r
-        var tpl = Ext.DomHelper.createTemplate(\r
-            {tag: 'div', cls: 'x-resizable-handle x-resizable-handle-{0}'}\r
-        );\r
-        tpl.compile();\r
-        Ext.Resizable.Handle.prototype.tpl = tpl;\r
-    }\r
-    this.position = pos;\r
-    this.rz = rz;\r
-    this.el = this.tpl.append(rz.el.dom, [this.position], true);\r
-    this.el.unselectable();\r
-    if(transparent){\r
-        this.el.setOpacity(0);\r
-    }\r
-    this.el.on('mousedown', this.onMouseDown, this);\r
-    if(!disableTrackOver){\r
-        this.el.on({\r
-            scope: this,\r
-            mouseover: this.onMouseOver,\r
-            mouseout: this.onMouseOut\r
-        });\r
-    }\r
-};\r
-\r
-// private\r
-Ext.Resizable.Handle.prototype = {\r
+Ext.Resizable.Handle = Ext.extend(Object, {\r
+    constructor : function(rz, pos, disableTrackOver, transparent, cls){\r
+       if(!this.tpl){\r
+            // only initialize the template if resizable is used\r
+            var tpl = Ext.DomHelper.createTemplate(\r
+                {tag: 'div', cls: 'x-resizable-handle x-resizable-handle-{0}'}\r
+            );\r
+            tpl.compile();\r
+            Ext.Resizable.Handle.prototype.tpl = tpl;\r
+        }\r
+        this.position = pos;\r
+        this.rz = rz;\r
+        this.el = this.tpl.append(rz.el.dom, [this.position], true);\r
+        this.el.unselectable();\r
+        if(transparent){\r
+            this.el.setOpacity(0);\r
+        }\r
+        if(!Ext.isEmpty(cls)){\r
+            this.el.addClass(cls);    \r
+        }\r
+        this.el.on('mousedown', this.onMouseDown, this);\r
+        if(!disableTrackOver){\r
+            this.el.on({\r
+                scope: this,\r
+                mouseover: this.onMouseOver,\r
+                mouseout: this.onMouseOut\r
+            });\r
+        }        \r
+    },\r
+    \r
     // private\r
     afterResize : function(rz){\r
         // do nothing    \r
@@ -37019,7 +39080,7 @@ Ext.Resizable.Handle.prototype = {
         Ext.destroy(this.el);\r
         this.el = null;\r
     }\r
-};\r
+});\r
 /**
  * @class Ext.Window
  * @extends Ext.Panel
@@ -37066,8 +39127,13 @@ Ext.Window = Ext.extend(Ext.Panel, {
      * A reference to the WindowGroup that should manage this window (defaults to {@link Ext.WindowMgr}).
      */
     /**
-    * @cfg {String/Number/Button} defaultButton
-    * The id / index of a button or a button instance to focus when this window received the focus.
+    * @cfg {String/Number/Component} defaultButton
+    * <p>Specifies a Component to receive focus when this Window is focussed.</p>
+    * <p>This may be one of:</p><div class="mdetail-params"><ul>
+    * <li>The index of a footer Button.</li>
+    * <li>The id of a Component.</li>
+    * <li>A Component.</li>
+    * </ul></div>
     */
     /**
     * @cfg {Function} onEsc
@@ -37199,19 +39265,13 @@ Ext.Window = Ext.extend(Ext.Panel, {
      * @deprecated
      */
     initHidden : undefined,
-    
+
     /**
      * @cfg {Boolean} hidden
      * Render this component hidden (default is <tt>true</tt>). If <tt>true</tt>, the
      * {@link #hide} method will be called internally.
      */
     hidden : true,
-    
-    /**
-    * @cfg {Boolean} monitorResize @hide
-    * This is automatically managed based on the value of constrain and constrainToHeader
-    */
-    monitorResize : true,
 
     // The following configs are set to provide the basic functionality of a window.
     // Changing them would require additional code to handle correctly and should
@@ -37322,7 +39382,8 @@ Ext.Window = Ext.extend(Ext.Panel, {
                 minHeight:this.minHeight,
                 handles: this.resizeHandles || 'all',
                 pinned: true,
-                resizeElement : this.resizerAction
+                resizeElement : this.resizerAction,
+                handleCls: 'x-window-handle'
             });
             this.resizer.window = this;
             this.mon(this.resizer, 'beforeresize', this.beforeResize, this);
@@ -37356,7 +39417,8 @@ Ext.Window = Ext.extend(Ext.Panel, {
     },
 
    // private
-    onEsc : function(){
+    onEsc : function(k, e){
+        e.stopEvent();
         this[this.closeAction]();
     },
 
@@ -37507,7 +39569,7 @@ Ext.Window = Ext.extend(Ext.Panel, {
      * @param {String/Element} animateTarget (optional) The target element or id from which the window should
      * animate while opening (defaults to null with no animation)
      * @param {Function} callback (optional) A callback function to call after the window is displayed
-     * @param {Object} scope (optional) The scope in which to execute the callback
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the callback is executed. Defaults to this Window.
      * @return {Ext.Window} this
      */
     show : function(animateTarget, cb, scope){
@@ -37539,13 +39601,16 @@ Ext.Window = Ext.extend(Ext.Panel, {
 
     // private
     afterShow : function(isAnim){
+        if (this.isDestroyed){
+            return false;
+        }
         this.proxy.hide();
         this.el.setStyle('display', 'block');
         this.el.show();
         if(this.maximized){
             this.fitContainer();
         }
-        if(Ext.isMac && Ext.isGecko){ // work around stupid FF 2.0/Mac scroll bar bug
+        if(Ext.isMac && Ext.isGecko2){ // work around stupid FF 2.0/Mac scroll bar bug
             this.cascade(this.setAutoScroll);
         }
 
@@ -37563,6 +39628,7 @@ Ext.Window = Ext.extend(Ext.Panel, {
             var sz = this.getSize();
             this.onResize(sz.width, sz.height);
         }
+        this.onShow();
         this.fireEvent('show', this);
     },
 
@@ -37587,7 +39653,7 @@ Ext.Window = Ext.extend(Ext.Panel, {
      * @param {String/Element} animateTarget (optional) The target element or id to which the window should
      * animate while hiding (defaults to null with no animation)
      * @param {Function} callback (optional) A callback function to call after the window is hidden
-     * @param {Object} scope (optional) The scope in which to execute the callback
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the callback is executed. Defaults to this Window.
      * @return {Ext.Window} this
      */
     hide : function(animateTarget, cb, scope){
@@ -37623,6 +39689,7 @@ Ext.Window = Ext.extend(Ext.Panel, {
         if(this.keyMap){
             this.keyMap.disable();
         }
+        this.onHide();
         this.fireEvent('hide', this);
     },
 
@@ -37642,6 +39709,18 @@ Ext.Window = Ext.extend(Ext.Panel, {
         }));
     },
 
+    /**
+     * Method that is called immediately before the <code>show</code> event is fired.
+     * Defaults to <code>Ext.emptyFn</code>.
+     */
+    onShow : Ext.emptyFn,
+
+    /**
+     * Method that is called immediately before the <code>hide</code> event is fired.
+     * Defaults to <code>Ext.emptyFn</code>.
+     */
+    onHide : Ext.emptyFn,
+
     // private
     onWindowResize : function(){
         if(this.maximized){
@@ -37699,7 +39778,7 @@ Ext.Window = Ext.extend(Ext.Panel, {
         if(show !== false){
             this.el.show();
             this.focus();
-            if(Ext.isMac && Ext.isGecko){ // work around stupid FF 2.0/Mac scroll bar bug
+            if(Ext.isMac && Ext.isGecko2){ // work around stupid FF 2.0/Mac scroll bar bug
                 this.cascade(this.setAutoScroll);
             }
         }
@@ -37739,7 +39818,7 @@ Ext.Window = Ext.extend(Ext.Panel, {
             }
         }
     },
-    
+
     // private
     doClose : function(){
         this.fireEvent('close', this);
@@ -37789,9 +39868,14 @@ Ext.Window = Ext.extend(Ext.Panel, {
      */
     restore : function(){
         if(this.maximized){
+            var t = this.tools;
             this.el.removeClass('x-window-maximized');
-            this.tools.restore.hide();
-            this.tools.maximize.show();
+            if(t.restore){
+                t.restore.hide();
+            }
+            if(t.maximize){
+                t.maximize.show();
+            }
             this.setPosition(this.restorePos[0], this.restorePos[1]);
             this.setSize(this.restoreSize.width, this.restoreSize.height);
             delete this.restorePos;
@@ -37802,8 +39886,8 @@ Ext.Window = Ext.extend(Ext.Panel, {
             if(this.dd){
                 this.dd.unlock();
             }
-            if(this.collapsible){
-                this.tools.toggle.show();
+            if(this.collapsible && t.toggle){
+                t.toggle.show();
             }
             this.container.removeClass('x-window-maximized-ct');
 
@@ -37824,7 +39908,7 @@ Ext.Window = Ext.extend(Ext.Panel, {
 
     // private
     fitContainer : function(){
-        var vs = this.container.getViewSize();
+        var vs = this.container.getViewSize(false);
         this.setSize(vs.width, vs.height);
     },
 
@@ -37847,7 +39931,7 @@ Ext.Window = Ext.extend(Ext.Panel, {
     /**
      * Aligns the window to the specified element
      * @param {Mixed} element The element to align to.
-     * @param {String} position The position to align to (see {@link Ext.Element#alignTo} for more details).
+     * @param {String} position (optional, defaults to "tl-bl?") The position to align to (see {@link Ext.Element#alignTo} for more details).
      * @param {Array} offsets (optional) Offset the positioning by [x, y]
      * @return {Ext.Window} this
      */
@@ -37881,7 +39965,6 @@ Ext.Window = Ext.extend(Ext.Panel, {
           Ext.EventManager.on(window, 'scroll', this.doAnchor, this,
               {buffer: tm == 'number' ? monitorScroll : 50});
       }
-      this.doAnchor();
       return this;
     },
 
@@ -37977,7 +40060,7 @@ Ext.extend(Ext.Window.DD, Ext.dd.DD, {
 });
 /**
  * @class Ext.WindowGroup
- * An object that represents a group of {@link Ext.Window} instances and provides z-order management
+ * An object that manages a group of {@link Ext.Window} instances and provides z-order management
  * and window activation behavior.
  * @constructor
  */
@@ -38034,20 +40117,42 @@ Ext.WindowGroup = function(){
 
     return {
         /**
-         * The starting z-index for windows (defaults to 9000)
+         * The starting z-index for windows in this WindowGroup (defaults to 9000)
          * @type Number The z-index value
          */
         zseed : 9000,
 
-        // private
+        /**
+         * <p>Registers a {@link Ext.Window Window} with this WindowManager. This should not
+         * need to be called under normal circumstances. Windows are automatically registered
+         * with a {@link Ext.Window#manager manager} at construction time.</p>
+         * <p>Where this may be useful is moving Windows between two WindowManagers. For example,
+         * to bring the Ext.MessageBox dialog under the same manager as the Desktop's
+         * WindowManager in the desktop sample app:</p><code><pre>
+var msgWin = Ext.MessageBox.getDialog();
+MyDesktop.getDesktop().getManager().register(msgWin);
+</pre></code>
+         * @param {Window} win The Window to register.
+         */
         register : function(win){
+            if(win.manager){
+                win.manager.unregister(win);
+            }
+            win.manager = this;
+
             list[win.id] = win;
             accessList.push(win);
             win.on('hide', activateLast);
         },
 
-        // private
+        /**
+         * <p>Unregisters a {@link Ext.Window Window} from this WindowManager. This should not
+         * need to be called. Windows are automatically unregistered upon destruction.
+         * See {@link #register}.</p>
+         * @param {Window} win The Window to unregister.
+         */
         unregister : function(win){
+            delete win.manager;
             delete list[win.id];
             win.un('hide', activateLast);
             accessList.remove(win);
@@ -38063,7 +40168,7 @@ Ext.WindowGroup = function(){
         },
 
         /**
-         * Brings the specified window to the front of any other active windows.
+         * Brings the specified window to the front of any other active windows in this WindowGroup.
          * @param {String/Object} win The id of the window or a {@link Ext.Window} instance
          * @return {Boolean} True if the dialog was brought to the front, else false
          * if it was already in front
@@ -38079,7 +40184,7 @@ Ext.WindowGroup = function(){
         },
 
         /**
-         * Sends the specified window to the back of other active windows.
+         * Sends the specified window to the back of other active windows in this WindowGroup.
          * @param {String/Object} win The id of the window or a {@link Ext.Window} instance
          * @return {Ext.Window} The window
          */
@@ -38091,7 +40196,7 @@ Ext.WindowGroup = function(){
         },
 
         /**
-         * Hides all windows in the group.
+         * Hides all windows in this WindowGroup.
          */
         hideAll : function(){
             for(var id in list){
@@ -38102,7 +40207,7 @@ Ext.WindowGroup = function(){
         },
 
         /**
-         * Gets the currently-active window in the group.
+         * Gets the currently-active window in this WindowGroup.
          * @return {Ext.Window} The active window
          */
         getActive : function(){
@@ -38110,11 +40215,11 @@ Ext.WindowGroup = function(){
         },
 
         /**
-         * Returns zero or more windows in the group using the custom search function passed to this method.
+         * Returns zero or more windows in this WindowGroup using the custom search function passed to this method.
          * The function should accept a single {@link Ext.Window} reference as its only argument and should
          * return true if the window matches the search criteria, otherwise it should return false.
          * @param {Function} fn The search function
-         * @param {Object} scope (optional) The scope in which to execute the function (defaults to the window
+         * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to the Window being tested.
          * that gets passed to the function if not specified)
          * @return {Array} An array of zero or more matching windows
          */
@@ -38130,10 +40235,10 @@ Ext.WindowGroup = function(){
         },
 
         /**
-         * Executes the specified function once for every window in the group, passing each
+         * Executes the specified function once for every window in this WindowGroup, passing each
          * window as the only parameter. Returning false from the function will stop the iteration.
          * @param {Function} fn The function to execute for each item
-         * @param {Object} scope (optional) The scope in which to execute the function
+         * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to the current Window in the iteration.
          */
         each : function(fn, scope){
             for(var id in list){
@@ -38189,10 +40294,12 @@ Ext.Msg.show({
 Ext.MessageBox = function(){\r
     var dlg, opt, mask, waitTimer,\r
         bodyEl, msgEl, textboxEl, textareaEl, progressBar, pp, iconEl, spacerEl,\r
-        buttons, activeTextEl, bwidth, bufferIcon = '', iconCls = '';\r
+        buttons, activeTextEl, bwidth, bufferIcon = '', iconCls = '',\r
+        buttonNames = ['ok', 'yes', 'no', 'cancel'];\r
 \r
     // private\r
     var handleButton = function(button){\r
+        buttons[button].blur();\r
         if(dlg.isVisible()){\r
             dlg.hide();\r
             handleHide();\r
@@ -38205,7 +40312,7 @@ Ext.MessageBox = function(){
         if(opt && opt.cls){\r
             dlg.el.removeClass(opt.cls);\r
         }\r
-        progressBar.reset();\r
+        progressBar.reset();        \r
     };\r
 \r
     // private\r
@@ -38221,26 +40328,25 @@ Ext.MessageBox = function(){
 \r
     // private\r
     var updateButtons = function(b){\r
-        var width = 0;\r
+        var width = 0,\r
+            cfg;\r
         if(!b){\r
-            buttons["ok"].hide();\r
-            buttons["cancel"].hide();\r
-            buttons["yes"].hide();\r
-            buttons["no"].hide();\r
+            Ext.each(buttonNames, function(name){\r
+                buttons[name].hide();\r
+            });\r
             return width;\r
         }\r
         dlg.footer.dom.style.display = '';\r
-        for(var k in buttons){\r
-            if(!Ext.isFunction(buttons[k])){\r
-                if(b[k]){\r
-                    buttons[k].show();\r
-                    buttons[k].setText(Ext.isString(b[k]) ? b[k] : Ext.MessageBox.buttonText[k]);\r
-                    width += buttons[k].el.getWidth()+15;\r
-                }else{\r
-                    buttons[k].hide();\r
-                }\r
+        Ext.iterate(buttons, function(name, btn){\r
+            cfg = b[name];\r
+            if(cfg){\r
+                btn.show();\r
+                btn.setText(Ext.isString(cfg) ? cfg : Ext.MessageBox.buttonText[name]);\r
+                width += btn.getEl().getWidth() + 15;\r
+            }else{\r
+                btn.hide();\r
             }\r
-        }\r
+        });\r
         return width;\r
     };\r
 \r
@@ -38251,6 +40357,16 @@ Ext.MessageBox = function(){
          */\r
         getDialog : function(titleText){\r
            if(!dlg){\r
+                var btns = [];\r
+                \r
+                buttons = {};\r
+                Ext.each(buttonNames, function(name){\r
+                    btns.push(buttons[name] = new Ext.Button({\r
+                        text: this.buttonText[name],\r
+                        handler: handleButton.createCallback(name),\r
+                        hideMode: 'offsets'\r
+                    }));\r
+                }, this);\r
                 dlg = new Ext.Window({\r
                     autoCreate : true,\r
                     title:titleText,\r
@@ -38275,16 +40391,12 @@ Ext.MessageBox = function(){
                         }else{\r
                             handleButton("cancel");\r
                         }\r
-                    }\r
+                    },\r
+                    fbar: new Ext.Toolbar({\r
+                        items: btns,\r
+                        enableOverflow: false\r
+                    })\r
                 });\r
-                buttons = {};\r
-                var bt = this.buttonText;\r
-                //TODO: refactor this block into a buttons config to pass into the Window constructor\r
-                buttons["ok"] = dlg.addButton(bt["ok"], handleButton.createCallback("ok"));\r
-                buttons["yes"] = dlg.addButton(bt["yes"], handleButton.createCallback("yes"));\r
-                buttons["no"] = dlg.addButton(bt["no"], handleButton.createCallback("no"));\r
-                buttons["cancel"] = dlg.addButton(bt["cancel"], handleButton.createCallback("cancel"));\r
-                buttons["ok"].hideMode = buttons["yes"].hideMode = buttons["no"].hideMode = buttons["cancel"].hideMode = 'offsets';\r
                 dlg.render(document.body);\r
                 dlg.getEl().addClass('x-window-dlg');\r
                 mask = dlg.mask;\r
@@ -38327,17 +40439,19 @@ Ext.MessageBox = function(){
             }\r
             msgEl.update(text || '&#160;');\r
 \r
-            var iw = iconCls != '' ? (iconEl.getWidth() + iconEl.getMargins('lr')) : 0;\r
-            var mw = msgEl.getWidth() + msgEl.getMargins('lr');\r
-            var fw = dlg.getFrameWidth('lr');\r
-            var bw = dlg.body.getFrameWidth('lr');\r
+            var iw = iconCls != '' ? (iconEl.getWidth() + iconEl.getMargins('lr')) : 0,\r
+                mw = msgEl.getWidth() + msgEl.getMargins('lr'),\r
+                fw = dlg.getFrameWidth('lr'),\r
+                bw = dlg.body.getFrameWidth('lr'),\r
+                w;\r
+                \r
             if (Ext.isIE && iw > 0){\r
                 //3 pixels get subtracted in the icon CSS for an IE margin issue,\r
                 //so we have to add it back here for the overall width to be consistent\r
                 iw += 3;\r
             }\r
-            var w = Math.max(Math.min(opt.width || iw+mw+fw+bw, this.maxWidth),\r
-                        Math.max(opt.minWidth || this.minWidth, bwidth || 0));\r
+            w = Math.max(Math.min(opt.width || iw+mw+fw+bw, opt.maxWidth || this.maxWidth),\r
+                    Math.max(opt.minWidth || this.minWidth, bwidth || 0));\r
 \r
             if(opt.prompt === true){\r
                 activeTextEl.setWidth(w-iw-fw-bw);\r
@@ -38524,18 +40638,16 @@ Ext.Msg.show({
                 // force it to the end of the z-index stack so it gets a cursor in FF\r
                 document.body.appendChild(dlg.el.dom);\r
                 d.setAnimateTarget(opt.animEl);\r
+                //workaround for window internally enabling keymap in afterShow\r
+                d.on('show', function(){\r
+                    if(allowClose === true){\r
+                        d.keyMap.enable();\r
+                    }else{\r
+                        d.keyMap.disable();\r
+                    }\r
+                }, this, {single:true});\r
                 d.show(opt.animEl);\r
             }\r
-\r
-            //workaround for window internally enabling keymap in afterShow\r
-            d.on('show', function(){\r
-                if(allowClose === true){\r
-                    d.keyMap.enable();\r
-                }else{\r
-                    d.keyMap.disable();\r
-                }\r
-            }, this, {single:true});\r
-\r
             if(opt.wait === true){\r
                 progressBar.wait(opt.waitConfig);\r
             }\r
@@ -38628,7 +40740,7 @@ Ext.MessageBox.ERROR
          * @param {String} title The title bar text\r
          * @param {String} msg The message box body text\r
          * @param {Function} fn (optional) The callback function invoked after the message box is closed\r
-         * @param {Object} scope (optional) The scope of the callback function\r
+         * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the callback is executed. Defaults to the browser wnidow.\r
          * @return {Ext.MessageBox} this\r
          */\r
         alert : function(title, msg, fn, scope){\r
@@ -38637,7 +40749,8 @@ Ext.MessageBox.ERROR
                 msg : msg,\r
                 buttons: this.OK,\r
                 fn: fn,\r
-                scope : scope\r
+                scope : scope,\r
+                minWidth: this.minWidth\r
             });\r
             return this;\r
         },\r
@@ -38650,7 +40763,7 @@ Ext.MessageBox.ERROR
          * @param {String} title The title bar text\r
          * @param {String} msg The message box body text\r
          * @param {Function} fn (optional) The callback function invoked after the message box is closed\r
-         * @param {Object} scope (optional) The scope of the callback function\r
+         * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the callback is executed. Defaults to the browser wnidow.\r
          * @return {Ext.MessageBox} this\r
          */\r
         confirm : function(title, msg, fn, scope){\r
@@ -38660,7 +40773,8 @@ Ext.MessageBox.ERROR
                 buttons: this.YESNO,\r
                 fn: fn,\r
                 scope : scope,\r
-                icon: this.QUESTION\r
+                icon: this.QUESTION,\r
+                minWidth: this.minWidth\r
             });\r
             return this;\r
         },\r
@@ -38673,7 +40787,7 @@ Ext.MessageBox.ERROR
          * @param {String} title The title bar text\r
          * @param {String} msg The message box body text\r
          * @param {Function} fn (optional) The callback function invoked after the message box is closed\r
-         * @param {Object} scope (optional) The scope of the callback function\r
+         * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the callback is executed. Defaults to the browser wnidow.\r
          * @param {Boolean/Number} multiline (optional) True to create a multiline textbox using the defaultTextHeight\r
          * property, or the height in pixels to create the textbox (defaults to false / single-line)\r
          * @param {String} value (optional) Default value of the text input element (defaults to '')\r
@@ -38685,7 +40799,7 @@ Ext.MessageBox.ERROR
                 msg : msg,\r
                 buttons: this.OKCANCEL,\r
                 fn: fn,\r
-                minWidth:250,\r
+                minWidth: this.minPromptWidth,\r
                 scope : scope,\r
                 prompt:true,\r
                 multiline: multiline,\r
@@ -38757,10 +40871,16 @@ Ext.MessageBox.ERROR
         minWidth : 100,\r
         /**\r
          * The minimum width in pixels of the message box if it is a progress-style dialog.  This is useful\r
-         * for setting a different minimum width than text-only dialogs may need (defaults to 250)\r
+         * for setting a different minimum width than text-only dialogs may need (defaults to 250).\r
          * @type Number\r
          */\r
         minProgressWidth : 250,\r
+        /**\r
+         * The minimum width in pixels of the message box if it is a prompt dialog.  This is useful\r
+         * for setting a different minimum width than text-only dialogs may need (defaults to 250).\r
+         * @type Number\r
+         */\r
+        minPromptWidth: 250,\r
         /**\r
          * An object containing the default button text strings that can be overriden for localized language support.\r
          * Supported properties are: ok, cancel, yes and no.  Generally you should include a locale-specific\r
@@ -39346,7 +41466,7 @@ Ext.DataView = Ext.extend(Ext.BoxComponent, {
             "click",
             /**
              * @event mouseenter
-             * Fires when the mouse enters a template node. trackOver:true or an overCls must be set to enable this event.
+             * Fires when the mouse enters a template node. trackOver:true or an overClass must be set to enable this event.
              * @param {Ext.DataView} this
              * @param {Number} index The index of the target node
              * @param {HTMLElement} node The target node
@@ -39355,7 +41475,7 @@ Ext.DataView = Ext.extend(Ext.BoxComponent, {
             "mouseenter",
             /**
              * @event mouseleave
-             * Fires when the mouse leaves a template node. trackOver:true or an overCls must be set to enable this event.
+             * Fires when the mouse leaves a template node. trackOver:true or an overClass must be set to enable this event.
              * @param {Ext.DataView} this
              * @param {Number} index The index of the target node
              * @param {HTMLElement} node The target node
@@ -39933,6 +42053,8 @@ Ext.DataView = Ext.extend(Ext.BoxComponent, {
     },
 
     onDestroy : function(){
+        this.all.clear();
+        this.selected.clear();
         Ext.DataView.superclass.onDestroy.call(this);
         this.bindStore(null);
     }
@@ -39944,10 +42066,11 @@ Ext.DataView = Ext.extend(Ext.BoxComponent, {
  */
 Ext.DataView.prototype.setStore = Ext.DataView.prototype.bindStore;
 
-Ext.reg('dataview', Ext.DataView);/**\r
- * @class Ext.ListView\r
+Ext.reg('dataview', Ext.DataView);
+/**\r
+ * @class Ext.list.ListView\r
  * @extends Ext.DataView\r
- * <p>Ext.ListView is a fast and light-weight implentation of a\r
+ * <p>Ext.list.ListView is a fast and light-weight implentation of a\r
  * {@link Ext.grid.GridPanel Grid} like view with the following characteristics:</p>\r
  * <div class="mdetail-params"><ul>\r
  * <li>resizable columns</li>\r
@@ -39988,7 +42111,7 @@ var store = new Ext.data.JsonStore({
 });\r
 store.load();\r
 \r
-var listView = new Ext.ListView({\r
+var listView = new Ext.list.ListView({\r
     store: store,\r
     multiSelect: true,\r
     emptyText: 'No images to display',\r
@@ -40033,7 +42156,7 @@ listView.on('selectionchange', function(view, nodes){
  * @param {Object} config\r
  * @xtype listview\r
  */\r
-Ext.ListView = Ext.extend(Ext.DataView, {\r
+Ext.list.ListView = Ext.extend(Ext.DataView, {\r
     /**\r
      * Set this property to <tt>true</tt> to disable the header click handler disabling sort\r
      * (defaults to <tt>false</tt>).\r
@@ -40084,7 +42207,7 @@ Ext.ListView = Ext.extend(Ext.DataView, {
     scrollOffset : undefined,\r
     /**\r
      * @cfg {Boolean/Object} columnResize\r
-     * Specify <tt>true</tt> or specify a configuration object for {@link Ext.ListView.ColumnResizer}\r
+     * Specify <tt>true</tt> or specify a configuration object for {@link Ext.list.ListView.ColumnResizer}\r
      * to enable the columns to be resizable (defaults to <tt>true</tt>).\r
      */\r
     columnResize: true,\r
@@ -40120,7 +42243,7 @@ Ext.ListView = Ext.extend(Ext.DataView, {
      */\r
     /**\r
      * @cfg {Boolean/Object} columnSort\r
-     * Specify <tt>true</tt> or specify a configuration object for {@link Ext.ListView.Sorter}\r
+     * Specify <tt>true</tt> or specify a configuration object for {@link Ext.list.ListView.Sorter}\r
      * to enable the columns to be sortable (defaults to <tt>true</tt>).\r
      */\r
     columnSort: true,\r
@@ -40136,18 +42259,18 @@ Ext.ListView = Ext.extend(Ext.DataView, {
     \r
     initComponent : function(){\r
         if(this.columnResize){\r
-            this.colResizer = new Ext.ListView.ColumnResizer(this.colResizer);\r
+            this.colResizer = new Ext.list.ColumnResizer(this.colResizer);\r
             this.colResizer.init(this);\r
         }\r
         if(this.columnSort){\r
-            this.colSorter = new Ext.ListView.Sorter(this.columnSort);\r
+            this.colSorter = new Ext.list.Sorter(this.columnSort);\r
             this.colSorter.init(this);\r
         }\r
         if(!this.internalTpl){\r
             this.internalTpl = new Ext.XTemplate(\r
                 '<div class="x-list-header"><div class="x-list-header-inner">',\r
                     '<tpl for="columns">',\r
-                    '<div style="width:{width}%;text-align:{align};"><em unselectable="on" id="',this.id, '-xlhd-{#}">',\r
+                    '<div style="width:{[values.width*100]}%;text-align:{align};"><em unselectable="on" id="',this.id, '-xlhd-{#}">',\r
                         '{header}',\r
                     '</em></div>',\r
                     '</tpl>',\r
@@ -40162,7 +42285,8 @@ Ext.ListView = Ext.extend(Ext.DataView, {
                 '<tpl for="rows">',\r
                     '<dl>',\r
                         '<tpl for="parent.columns">',\r
-                        '<dt style="width:{width}%;text-align:{align};"><em unselectable="on">',\r
+                        '<dt style="width:{[values.width*100]}%;text-align:{align};">',\r
+                        '<em unselectable="on"<tpl if="cls"> class="{cls}</tpl>">',\r
                             '{[values.tpl.apply(parent)]}',\r
                         '</em></dt>',\r
                         '</tpl>',\r
@@ -40171,48 +42295,49 @@ Ext.ListView = Ext.extend(Ext.DataView, {
                 '</tpl>'\r
             );\r
         };\r
+        \r
         var cs = this.columns, \r
             allocatedWidth = 0, \r
             colsWithWidth = 0, \r
             len = cs.length, \r
             columns = [];\r
+            \r
         for(var i = 0; i < len; i++){\r
-            var c = Ext.apply({}, cs[i]);\r
-            if(!c.tpl){\r
-                c.tpl = new Ext.XTemplate('{' + c.dataIndex + '}');\r
-            }else if(Ext.isString(c.tpl)){\r
-                c.tpl = new Ext.XTemplate(c.tpl);\r
+            var c = cs[i];\r
+            if(!c.isColumn) {\r
+                c.xtype = c.xtype ? (/^lv/.test(c.xtype) ? c.xtype : 'lv' + c.xtype) : 'lvcolumn';\r
+                c = Ext.create(c);\r
             }\r
-            c.align = c.align || 'left';\r
-            if(Ext.isNumber(c.width)){\r
-                c.width *= 100;\r
-                allocatedWidth += c.width;\r
+            if(c.width) {\r
+                allocatedWidth += c.width*100;\r
                 colsWithWidth++;\r
             }\r
             columns.push(c);\r
         }\r
+        \r
         cs = this.columns = columns;\r
+        \r
         // auto calculate missing column widths\r
         if(colsWithWidth < len){\r
             var remaining = len - colsWithWidth;\r
             if(allocatedWidth < this.maxWidth){\r
-                var perCol = ((this.maxWidth-allocatedWidth) / remaining);\r
+                var perCol = ((this.maxWidth-allocatedWidth) / remaining)/100;\r
                 for(var j = 0; j < len; j++){\r
                     var c = cs[j];\r
-                    if(!Ext.isNumber(c.width)){\r
+                    if(!c.width){\r
                         c.width = perCol;\r
                     }\r
                 }\r
             }\r
         }\r
-        Ext.ListView.superclass.initComponent.call(this);\r
+        Ext.list.ListView.superclass.initComponent.call(this);\r
     },\r
 \r
     onRender : function(){\r
         this.autoEl = {\r
             cls: 'x-list-wrap'  \r
         };\r
-        Ext.ListView.superclass.onRender.apply(this, arguments);\r
+        Ext.list.ListView.superclass.onRender.apply(this, arguments);\r
 \r
         this.internalTpl.overwrite(this.el, {columns: this.columns});\r
         \r
@@ -40243,7 +42368,7 @@ Ext.ListView = Ext.extend(Ext.DataView, {
      * XTemplate as described above.\r
      */\r
     collectData : function(){\r
-        var rs = Ext.ListView.superclass.collectData.apply(this, arguments);\r
+        var rs = Ext.list.ListView.superclass.collectData.apply(this, arguments);\r
         return {\r
             columns: this.columns,\r
             rows: rs\r
@@ -40286,7 +42411,7 @@ Ext.ListView = Ext.extend(Ext.DataView, {
     },\r
 \r
     updateIndexes : function(){\r
-        Ext.ListView.superclass.updateIndexes.apply(this, arguments);\r
+        Ext.list.ListView.superclass.updateIndexes.apply(this, arguments);\r
         this.verifyInternalSize();\r
     },\r
 \r
@@ -40304,19 +42429,173 @@ Ext.ListView = Ext.extend(Ext.DataView, {
     setHdWidths : function(){\r
         var els = this.innerHd.dom.getElementsByTagName('div');\r
         for(var i = 0, cs = this.columns, len = cs.length; i < len; i++){\r
-            els[i].style.width = cs[i].width + '%';\r
+            els[i].style.width = (cs[i].width*100) + '%';\r
         }\r
     }\r
 });\r
 \r
-Ext.reg('listview', Ext.ListView);/**\r
- * @class Ext.ListView.ColumnResizer\r
+Ext.reg('listview', Ext.list.ListView);\r
+\r
+// Backwards compatibility alias\r
+Ext.ListView = Ext.list.ListView;/**
+ * @class Ext.list.Column
+ * <p>This class encapsulates column configuration data to be used in the initialization of a
+ * {@link Ext.list.ListView ListView}.</p>
+ * <p>While subclasses are provided to render data in different ways, this class renders a passed
+ * data field unchanged and is usually used for textual columns.</p>
+ */
+Ext.list.Column = Ext.extend(Object, {
+    /**
+     * @private
+     * @cfg {Boolean} isColumn
+     * Used by ListView constructor method to avoid reprocessing a Column
+     * if <code>isColumn</code> is not set ListView will recreate a new Ext.list.Column
+     * Defaults to true.
+     */
+    isColumn: true,
+    
+    /**
+     * @cfg {String} align
+     * Set the CSS text-align property of the column. Defaults to <tt>'left'</tt>.
+     */        
+    align: 'left',
+    /**
+     * @cfg {String} header Optional. The header text to be used as innerHTML
+     * (html tags are accepted) to display in the ListView.  <b>Note</b>: to
+     * have a clickable header with no text displayed use <tt>'&#160;'</tt>.
+     */    
+    header: '',
+    
+    /**
+     * @cfg {Number} width Optional. Percentage of the container width
+     * this column should be allocated.  Columns that have no width specified will be
+     * allocated with an equal percentage to fill 100% of the container width.  To easily take
+     * advantage of the full container width, leave the width of at least one column undefined.
+     * Note that if you do not want to take up the full width of the container, the width of
+     * every column needs to be explicitly defined.
+     */    
+    width: null,
+
+    /**
+     * @cfg {String} cls Optional. This option can be used to add a CSS class to the cell of each
+     * row for this column.
+     */
+    cls: '',
+    
+    /**
+     * @cfg {String} tpl Optional. Specify a string to pass as the
+     * configuration string for {@link Ext.XTemplate}.  By default an {@link Ext.XTemplate}
+     * will be implicitly created using the <tt>dataIndex</tt>.
+     */
+
+    /**
+     * @cfg {String} dataIndex <p><b>Required</b>. The name of the field in the
+     * ListViews's {@link Ext.data.Store}'s {@link Ext.data.Record} definition from
+     * which to draw the column's value.</p>
+     */
+    
+    constructor : function(c){
+        if(!c.tpl){
+            c.tpl = new Ext.XTemplate('{' + c.dataIndex + '}');
+        }
+        else if(Ext.isString(c.tpl)){
+            c.tpl = new Ext.XTemplate(c.tpl);
+        }
+        
+        Ext.apply(this, c);
+    }
+});
+
+Ext.reg('lvcolumn', Ext.list.Column);
+
+/**
+ * @class Ext.list.NumberColumn
+ * @extends Ext.list.Column
+ * <p>A Column definition class which renders a numeric data field according to a {@link #format} string.  See the
+ * {@link Ext.list.Column#xtype xtype} config option of {@link Ext.list.Column} for more details.</p>
+ */
+Ext.list.NumberColumn = Ext.extend(Ext.list.Column, {
+    /**
+     * @cfg {String} format
+     * A formatting string as used by {@link Ext.util.Format#number} to format a numeric value for this Column
+     * (defaults to <tt>'0,000.00'</tt>).
+     */    
+    format: '0,000.00',
+    
+    constructor : function(c) {
+        c.tpl = c.tpl || new Ext.XTemplate('{' + c.dataIndex + ':number("' + (c.format || this.format) + '")}');       
+        Ext.list.NumberColumn.superclass.constructor.call(this, c);
+    }
+});
+
+Ext.reg('lvnumbercolumn', Ext.list.NumberColumn);
+
+/**
+ * @class Ext.list.DateColumn
+ * @extends Ext.list.Column
+ * <p>A Column definition class which renders a passed date according to the default locale, or a configured
+ * {@link #format}. See the {@link Ext.list.Column#xtype xtype} config option of {@link Ext.list.Column}
+ * for more details.</p>
+ */
+Ext.list.DateColumn = Ext.extend(Ext.list.Column, {
+    format: 'm/d/Y',
+    constructor : function(c) {
+        c.tpl = c.tpl || new Ext.XTemplate('{' + c.dataIndex + ':date("' + (c.format || this.format) + '")}');      
+        Ext.list.DateColumn.superclass.constructor.call(this, c);
+    }
+});
+Ext.reg('lvdatecolumn', Ext.list.DateColumn);
+
+/**
+ * @class Ext.list.BooleanColumn
+ * @extends Ext.list.Column
+ * <p>A Column definition class which renders boolean data fields.  See the {@link Ext.list.Column#xtype xtype}
+ * config option of {@link Ext.list.Column} for more details.</p>
+ */
+Ext.list.BooleanColumn = Ext.extend(Ext.list.Column, {
+    /**
+     * @cfg {String} trueText
+     * The string returned by the renderer when the column value is not falsey (defaults to <tt>'true'</tt>).
+     */
+    trueText: 'true',
+    /**
+     * @cfg {String} falseText
+     * The string returned by the renderer when the column value is falsey (but not undefined) (defaults to
+     * <tt>'false'</tt>).
+     */
+    falseText: 'false',
+    /**
+     * @cfg {String} undefinedText
+     * The string returned by the renderer when the column value is undefined (defaults to <tt>'&#160;'</tt>).
+     */
+    undefinedText: '&#160;',
+    
+    constructor : function(c) {
+        c.tpl = c.tpl || new Ext.XTemplate('{' + c.dataIndex + ':this.format}');
+        
+        var t = this.trueText, f = this.falseText, u = this.undefinedText;
+        c.tpl.format = function(v){
+            if(v === undefined){
+                return u;
+            }
+            if(!v || v === 'false'){
+                return f;
+            }
+            return t;
+        };
+        
+        Ext.list.DateColumn.superclass.constructor.call(this, c);
+    }
+});
+
+Ext.reg('lvbooleancolumn', Ext.list.BooleanColumn);/**\r
+ * @class Ext.list.ColumnResizer\r
  * @extends Ext.util.Observable\r
- * <p>Supporting Class for Ext.ListView.</p>\r
+ * <p>Supporting Class for Ext.list.ListView</p>\r
  * @constructor\r
  * @param {Object} config\r
  */\r
-Ext.ListView.ColumnResizer = Ext.extend(Ext.util.Observable, {\r
+Ext.list.ColumnResizer = Ext.extend(Ext.util.Observable, {\r
     /**\r
      * @cfg {Number} minPct The minimum percentage to allot for any column (defaults to <tt>.05</tt>)\r
      */\r
@@ -40324,7 +42603,7 @@ Ext.ListView.ColumnResizer = Ext.extend(Ext.util.Observable, {
 \r
     constructor: function(config){\r
         Ext.apply(this, config);\r
-        Ext.ListView.ColumnResizer.superclass.constructor.call(this);\r
+        Ext.list.ColumnResizer.superclass.constructor.call(this);\r
     },\r
     init : function(listView){\r
         this.view = listView;\r
@@ -40356,10 +42635,10 @@ Ext.ListView.ColumnResizer = Ext.extend(Ext.util.Observable, {
 \r
             if(x - r.left <= hw && pn != pn.parentNode.firstChild){\r
                 this.activeHd = Ext.get(pn.previousSibling.firstChild);\r
-                               ss.cursor = Ext.isWebKit ? 'e-resize' : 'col-resize';\r
+                ss.cursor = Ext.isWebKit ? 'e-resize' : 'col-resize';\r
             } else if(r.right - x <= hw && pn != pn.parentNode.lastChild.previousSibling){\r
                 this.activeHd = hd;\r
-                               ss.cursor = Ext.isWebKit ? 'w-resize' : 'col-resize';\r
+                ss.cursor = Ext.isWebKit ? 'w-resize' : 'col-resize';\r
             } else{\r
                 delete this.activeHd;\r
                 ss.cursor = '';\r
@@ -40396,30 +42675,31 @@ Ext.ListView.ColumnResizer = Ext.extend(Ext.util.Observable, {
     },\r
 \r
     onEnd: function(e){\r
+        /* calculate desired width by measuring proxy and then remove it */\r
         var nw = this.proxy.getWidth();\r
         this.proxy.remove();\r
 \r
         var index = this.hdIndex,\r
-            vw = this.view, \r
-            cs = vw.columns, \r
+            vw = this.view,\r
+            cs = vw.columns,\r
             len = cs.length,\r
-            w = this.view.innerHd.getWidth(), \r
-            minPct = this.minPct * 100;\r
+            w = this.view.innerHd.getWidth(),\r
+            minPct = this.minPct * 100,\r
             pct = Math.ceil((nw * vw.maxWidth) / w),\r
-            diff = cs[index].width - pct,\r
+            diff = (cs[index].width * 100) - pct,\r
             each = Math.floor(diff / (len-1-index)),\r
             mod = diff - (each * (len-1-index));\r
 \r
         for(var i = index+1; i < len; i++){\r
-            var cw = cs[i].width + each,\r
+            var cw = (cs[i].width * 100) + each,\r
                 ncw = Math.max(minPct, cw);\r
             if(cw != ncw){\r
                 mod += cw - ncw;\r
             }\r
-            cs[i].width = ncw;\r
+            cs[i].width = ncw / 100;\r
         }\r
-        cs[index].width = pct;\r
-        cs[index+1].width += mod;\r
+        cs[index].width = pct / 100;\r
+        cs[index+1].width += (mod / 100);\r
         delete this.dragHd;\r
         vw.setHdWidths();\r
         vw.refresh();\r
@@ -40427,14 +42707,17 @@ Ext.ListView.ColumnResizer = Ext.extend(Ext.util.Observable, {
             vw.disableHeaders = false;\r
         }, 100);\r
     }\r
-});/**\r
- * @class Ext.ListView.Sorter\r
+});\r
+\r
+// Backwards compatibility alias\r
+Ext.ListView.ColumnResizer = Ext.list.ColumnResizer;/**\r
+ * @class Ext.list.Sorter\r
  * @extends Ext.util.Observable\r
- * <p>Supporting Class for Ext.ListView.</p>\r
+ * <p>Supporting Class for Ext.list.ListView</p>\r
  * @constructor\r
  * @param {Object} config\r
  */\r
-Ext.ListView.Sorter = Ext.extend(Ext.util.Observable, {\r
+Ext.list.Sorter = Ext.extend(Ext.util.Observable, {\r
     /**\r
      * @cfg {Array} sortClasses\r
      * The CSS classes applied to a header when it is sorted. (defaults to <tt>["sort-asc", "sort-desc"]</tt>)\r
@@ -40443,7 +42726,7 @@ Ext.ListView.Sorter = Ext.extend(Ext.util.Observable, {
 \r
     constructor: function(config){\r
         Ext.apply(this, config);\r
-        Ext.ListView.Sorter.superclass.constructor.call(this);\r
+        Ext.list.Sorter.superclass.constructor.call(this);\r
     },\r
 \r
     init : function(listView){\r
@@ -40490,7 +42773,10 @@ Ext.ListView.Sorter = Ext.extend(Ext.util.Observable, {
             this.view.store.sort(this.view.columns[index].dataIndex);\r
         }\r
     }\r
-});/**
+});\r
+\r
+// Backwards compatibility alias\r
+Ext.ListView.Sorter = Ext.list.Sorter;/**
  * @class Ext.TabPanel
  * <p>A basic tab container. TabPanels can be used exactly like a standard {@link Ext.Panel}
  * for layout purposes, but also have special support for containing child Components
@@ -40519,6 +42805,9 @@ Ext.ListView.Sorter = Ext.extend(Ext.util.Observable, {
  * the active tab.</li>
  * <li><tt><b>{@link Ext.Panel#deactivate deactivate}</b></tt> : Fires when the Component that
  * was the active tab becomes deactivated.</li>
+ * <li><tt><b>{@link Ext.Panel#beforeclose beforeclose}</b></tt> : Fires when the user clicks on the close tool of a closeable tab.
+ * May be vetoed by returning <code>false</code> from a handler.</li>
+ * <li><tt><b>{@link Ext.Panel#close close}</b></tt> : Fires a closeable tab has been closed by the user.</li>
  * </ul></div>
  * <p><b><u>Creating TabPanels from Code</u></b></p>
  * <p>TabPanels can be created and rendered completely in code, as in this example:</p>
@@ -40588,11 +42877,6 @@ Ext.TabPanel = Ext.extend(Ext.Panel,  {
      * class name applied to the tab strip item representing the child Component, allowing special
      * styling to be applied.
      */
-    /**
-     * @cfg {Boolean} monitorResize True to automatically monitor window resize events and rerender the layout on
-     * browser resize (defaults to true).
-     */
-    monitorResize : true,
     /**
      * @cfg {Boolean} deferredRender
      * <p><tt>true</tt> by default to defer the rendering of child <tt>{@link Ext.Container#items items}</tt>
@@ -40705,9 +42989,9 @@ var tabs = new Ext.TabPanel({
     autoTabSelector : 'div.x-tab',
     /**
      * @cfg {String/Number} activeTab A string id or the numeric index of the tab that should be initially
-     * activated on render (defaults to none).
+     * activated on render (defaults to undefined).
      */
-    activeTab : null,
+    activeTab : undefined,
     /**
      * @cfg {Number} tabMargin The number of pixels of space to calculate into the sizing and scrolling of
      * tabs. If you change the margin in CSS, you will need to update this value so calculations are correct
@@ -40810,10 +43094,11 @@ var tabs = new Ext.TabPanel({
             tag:'ul', cls:'x-tab-strip x-tab-strip-'+this.tabPosition}});
 
         var beforeEl = (this.tabPosition=='bottom' ? this.stripWrap : null);
-        this.stripSpacer = st.createChild({cls:'x-tab-strip-spacer'}, beforeEl);
+        st.createChild({cls:'x-tab-strip-spacer'}, beforeEl);
         this.strip = new Ext.Element(this.stripWrap.dom.firstChild);
 
-        this.edge = this.strip.createChild({tag:'li', cls:'x-tab-edge'});
+        // create an empty span with class x-tab-strip-text to force the height of the header element when there's no tabs.
+        this.edge = this.strip.createChild({tag:'li', cls:'x-tab-edge', cn: [{tag: 'span', cls: 'x-tab-strip-text', cn: '&#160;'}]});
         this.strip.createChild({cls:'x-clear'});
 
         this.body.addClass('x-tab-panel-body-'+this.tabPosition);
@@ -40843,9 +43128,9 @@ new Ext.TabPanel({
     itemTpl: new Ext.XTemplate(
     '&lt;li class="{cls}" id="{id}" style="overflow:hidden">',
          '&lt;tpl if="closable">',
-            '&lt;a class="x-tab-strip-close" onclick="return false;">&lt;/a>',
+            '&lt;a class="x-tab-strip-close">&lt;/a>',
          '&lt;/tpl>',
-         '&lt;a class="x-tab-right" href="#" onclick="return false;" style="padding-left:6px">',
+         '&lt;a class="x-tab-right" href="#" style="padding-left:6px">',
             '&lt;em class="x-tab-left">',
                 '&lt;span class="x-tab-strip-inner">',
                     '&lt;img src="{src}" style="float:left;margin:3px 3px 0 0">',
@@ -40882,8 +43167,8 @@ new Ext.TabPanel({
          */
         if(!this.itemTpl){
             var tt = new Ext.Template(
-                 '<li class="{cls}" id="{id}"><a class="x-tab-strip-close" onclick="return false;"></a>',
-                 '<a class="x-tab-right" href="#" onclick="return false;"><em class="x-tab-left">',
+                 '<li class="{cls}" id="{id}"><a class="x-tab-strip-close"></a>',
+                 '<a class="x-tab-right" href="#"><em class="x-tab-left">',
                  '<span class="x-tab-strip-inner"><span class="x-tab-strip-text {iconCls}">{text}</span></span>',
                  '</em></a></li>'
             );
@@ -40923,8 +43208,9 @@ new Ext.TabPanel({
 
     // private
     findTargets : function(e){
-        var item = null;
-        var itemEl = e.getTarget('li', this.strip);
+        var item = null,
+            itemEl = e.getTarget('li:not(.x-tab-edge)', this.strip);
+
         if(itemEl){
             item = this.getComponent(itemEl.id.split(this.idDelimiter)[1]);
             if(item.disabled){
@@ -40952,7 +43238,6 @@ new Ext.TabPanel({
         if(t.close){
             if (t.item.fireEvent('beforeclose', t.item) !== false) {
                 t.item.fireEvent('close', t.item);
-                delete t.item.tabEl;
                 this.remove(t.item);
             }
             return;
@@ -40984,8 +43269,8 @@ new Ext.TabPanel({
         }
         var tabs = this.el.query(this.autoTabSelector);
         for(var i = 0, len = tabs.length; i < len; i++){
-            var tab = tabs[i];
-            var title = tab.getAttribute('title');
+            var tab = tabs[i],
+                title = tab.getAttribute('title');
             tab.removeAttribute('title');
             this.add({
                 title: title,
@@ -40996,26 +43281,46 @@ new Ext.TabPanel({
 
     // private
     initTab : function(item, index){
-        var before = this.strip.dom.childNodes[index];
-        var p = this.getTemplateArgs(item);
-        var el = before ?
+        var before = this.strip.dom.childNodes[index],
+            p = this.getTemplateArgs(item),
+            el = before ?
                  this.itemTpl.insertBefore(before, p) :
-                 this.itemTpl.append(this.strip, p);
+                 this.itemTpl.append(this.strip, p),
+            cls = 'x-tab-strip-over',
+            tabEl = Ext.get(el);
 
-        Ext.fly(el).addClassOnOver('x-tab-strip-over');
+        tabEl.hover(function(){
+            if(!item.disabled){
+                tabEl.addClass(cls);
+            }
+        }, function(){
+            tabEl.removeClass(cls);
+        });
 
         if(item.tabTip){
-            Ext.fly(el).child('span.x-tab-strip-text', true).qtip = item.tabTip;
+            tabEl.child('span.x-tab-strip-text', true).qtip = item.tabTip;
         }
         item.tabEl = el;
 
-        item.on('disable', this.onItemDisabled, this);
-        item.on('enable', this.onItemEnabled, this);
-        item.on('titlechange', this.onItemTitleChanged, this);
-        item.on('iconchange', this.onItemIconChanged, this);
-        item.on('beforeshow', this.onBeforeShowItem, this);
+        // Route *keyboard triggered* click events to the tab strip mouse handler.
+        tabEl.select('a').on('click', function(e){
+            if(!e.getPageX()){
+                this.onStripMouseDown(e);
+            }
+        }, this, {preventDefault: true});
+
+        item.on({
+            scope: this,
+            disable: this.onItemDisabled,
+            enable: this.onItemEnabled,
+            titlechange: this.onItemTitleChanged,
+            iconchange: this.onItemIconChanged,
+            beforeshow: this.onBeforeShowItem
+        });
     },
 
+
+
     /**
      * <p>Provides template arguments for rendering a tab selector item in the tab strip.</p>
      * <p>This method returns an object hash containing properties used by the TabPanel's <tt>{@link #itemTpl}</tt>
@@ -41077,9 +43382,15 @@ new Ext.TabPanel({
 
     // private
     onRemove : function(c){
+        var te = Ext.get(c.tabEl);
+        // check if the tabEl exists, it won't if the tab isn't rendered
+        if(te){
+            te.select('a').removeAllListeners();
+            Ext.destroy(te);
+        }
         Ext.TabPanel.superclass.onRemove.call(this, c);
-        Ext.destroy(Ext.get(this.getTabEl(c)));
         this.stack.remove(c);
+        delete c.tabEl;
         c.un('disable', this.onItemDisabled, this);
         c.un('enable', this.onItemEnabled, this);
         c.un('titlechange', this.onItemTitleChanged, this);
@@ -41092,10 +43403,12 @@ new Ext.TabPanel({
             }else if(this.items.getCount() > 0){
                 this.setActiveTab(0);
             }else{
-                this.activeTab = null;
+                this.setActiveTab(null);
             }
         }
-        this.delegateUpdates();
+        if(!this.destroying){
+            this.delegateUpdates();
+        }
     },
 
     // private
@@ -41148,7 +43461,8 @@ new Ext.TabPanel({
      * @return {HTMLElement} The DOM node
      */
     getTabEl : function(item){
-        return document.getElementById(this.id + this.idDelimiter + this.getComponent(item).getItemId());
+        var c = this.getComponent(item);
+        return c ? c.tabEl : null;
     },
 
     // private
@@ -41214,10 +43528,10 @@ new Ext.TabPanel({
 
     // private
     autoSizeTabs : function(){
-        var count = this.items.length;
-        var ce = this.tabPosition != 'bottom' ? 'header' : 'footer';
-        var ow = this[ce].dom.offsetWidth;
-        var aw = this[ce].dom.clientWidth;
+        var count = this.items.length,
+            ce = this.tabPosition != 'bottom' ? 'header' : 'footer',
+            ow = this[ce].dom.offsetWidth,
+            aw = this[ce].dom.clientWidth;
 
         if(!this.resizeTabs || count < 1 || !aw){ // !aw for display:none
             return;
@@ -41225,12 +43539,12 @@ new Ext.TabPanel({
 
         var each = Math.max(Math.min(Math.floor((aw-4) / count) - this.tabMargin, this.tabWidth), this.minTabWidth); // -4 for float errors in IE
         this.lastTabWidth = each;
-        var lis = this.strip.query("li:not([className^=x-tab-edge])");
+        var lis = this.strip.query('li:not(.x-tab-edge)');
         for(var i = 0, len = lis.length; i < len; i++) {
-            var li = lis[i];
-            var inner = Ext.fly(li).child('.x-tab-strip-inner', true);
-            var tw = li.offsetWidth;
-            var iw = inner.offsetWidth;
+            var li = lis[i],
+                inner = Ext.fly(li).child('.x-tab-strip-inner', true),
+                tw = li.offsetWidth,
+                iw = inner.offsetWidth;
             inner.style.width = (each - (tw-iw)) + 'px';
         }
     },
@@ -41261,7 +43575,7 @@ new Ext.TabPanel({
      */
     setActiveTab : function(item){
         item = this.getComponent(item);
-        if(!item || this.fireEvent('beforetabchange', this, item, this.activeTab) === false){
+        if(this.fireEvent('beforetabchange', this, item, this.activeTab) === false){
             return;
         }
         if(!this.rendered){
@@ -41274,26 +43588,27 @@ new Ext.TabPanel({
                 if(oldEl){
                     Ext.fly(oldEl).removeClass('x-tab-strip-active');
                 }
-                this.activeTab.fireEvent('deactivate', this.activeTab);
             }
-            var el = this.getTabEl(item);
-            Ext.fly(el).addClass('x-tab-strip-active');
-            this.activeTab = item;
-            this.stack.add(item);
-
-            this.layout.setActiveItem(item);
-            if(this.scrolling){
-                this.scrollToTab(item, this.animScroll);
+            if(item){
+                var el = this.getTabEl(item);
+                Ext.fly(el).addClass('x-tab-strip-active');
+                this.activeTab = item;
+                this.stack.add(item);
+
+                this.layout.setActiveItem(item);
+                if(this.scrolling){
+                    this.scrollToTab(item, this.animScroll);
+                }
             }
-
-            item.fireEvent('activate', item);
             this.fireEvent('tabchange', this, item);
         }
     },
 
     /**
-     * Gets the currently active tab.
-     * @return {Panel} The active tab
+     * Returns the Component which is the currently active tab. <b>Note that before the TabPanel
+     * first activates a child Component, this method will return whatever was configured in the
+     * {@link #activeTab} config option.</b>
+     * @return {BoxComponent} The currently active child Component if one <i>is</i> active, or the {@link #activeTab} config value.
      */
     getActiveTab : function(){
         return this.activeTab || null;
@@ -41311,15 +43626,14 @@ new Ext.TabPanel({
     // private
     autoScrollTabs : function(){
         this.pos = this.tabPosition=='bottom' ? this.footer : this.header;
-        var count = this.items.length;
-        var ow = this.pos.dom.offsetWidth;
-        var tw = this.pos.dom.clientWidth;
-
-        var wrap = this.stripWrap;
-        var wd = wrap.dom;
-        var cw = wd.offsetWidth;
-        var pos = this.getScrollPos();
-        var l = this.edge.getOffsetsTo(this.stripWrap)[0] + pos;
+        var count = this.items.length,
+            ow = this.pos.dom.offsetWidth,
+            tw = this.pos.dom.clientWidth,
+            wrap = this.stripWrap,
+            wd = wrap.dom,
+            cw = wd.offsetWidth,
+            pos = this.getScrollPos(),
+            l = this.edge.getOffsetsTo(this.stripWrap)[0] + pos;
 
         if(!this.enableTabScroll || count < 1 || cw < 20){ // 20 to prevent display:none issues
             return;
@@ -41431,11 +43745,14 @@ new Ext.TabPanel({
      */
 
     scrollToTab : function(item, animate){
-        if(!item){ return; }
-        var el = this.getTabEl(item);
-        var pos = this.getScrollPos(), area = this.getScrollArea();
-        var left = Ext.fly(el).getOffsetsTo(this.stripWrap)[0] + pos;
-        var right = left + el.offsetWidth;
+        if(!item){
+            return;
+        }
+        var el = this.getTabEl(item),
+            pos = this.getScrollPos(),
+            area = this.getScrollArea(),
+            left = Ext.fly(el).getOffsetsTo(this.stripWrap)[0] + pos,
+            right = left + el.offsetWidth;
         if(left < pos){
             this.scrollTo(left, animate);
         }else if(right > (pos + area)){
@@ -41455,9 +43772,9 @@ new Ext.TabPanel({
         var d = e.getWheelDelta()*this.wheelIncrement*-1;
         e.stopEvent();
 
-        var pos = this.getScrollPos();
-        var newpos = pos + d;
-        var sw = this.getScrollWidth()-this.getScrollArea();
+        var pos = this.getScrollPos(),
+            newpos = pos + d,
+            sw = this.getScrollWidth()-this.getScrollArea();
 
         var s = Math.max(0, Math.min(sw, newpos));
         if(s != pos){
@@ -41467,9 +43784,9 @@ new Ext.TabPanel({
 
     // private
     onScrollRight : function(){
-        var sw = this.getScrollWidth()-this.getScrollArea();
-        var pos = this.getScrollPos();
-        var s = Math.min(sw, pos + this.getScrollIncrement());
+        var sw = this.getScrollWidth()-this.getScrollArea(),
+            pos = this.getScrollPos(),
+            s = Math.min(sw, pos + this.getScrollIncrement());
         if(s != pos){
             this.scrollTo(s, this.animScroll);
         }
@@ -41477,8 +43794,8 @@ new Ext.TabPanel({
 
     // private
     onScrollLeft : function(){
-        var pos = this.getScrollPos();
-        var s = Math.max(0, pos - this.getScrollIncrement());
+        var pos = this.getScrollPos(),
+            s = Math.max(0, pos - this.getScrollIncrement());
         if(s != pos){
             this.scrollTo(s, this.animScroll);
         }
@@ -41493,17 +43810,9 @@ new Ext.TabPanel({
 
     // private
     beforeDestroy : function() {
-        if(this.items){
-            this.items.each(function(item){
-                if(item && item.tabEl){
-                    Ext.get(item.tabEl).removeAllListeners();
-                    item.tabEl = null;
-                }
-            }, this);
-        }
-        if(this.strip){
-            this.strip.removeAllListeners();
-        }
+        Ext.destroy(this.leftRepeater, this.rightRepeater);
+        this.deleteMembers('strip', 'edge', 'scrollLeft', 'scrollRight', 'stripWrap');
+        this.activeTab = null;
         Ext.TabPanel.superclass.beforeDestroy.apply(this);
     }
 
@@ -41592,768 +43901,824 @@ Ext.TabPanel.AccessStack = function(){
         }
     };
 };
-/**
- * @class Ext.Button
- * @extends Ext.BoxComponent
- * Simple Button class
- * @cfg {String} text The button text to be used as innerHTML (html tags are accepted)
- * @cfg {String} icon The path to an image to display in the button (the image will be set as the background-image
- * CSS property of the button by default, so if you want a mixed icon/text button, set cls:'x-btn-text-icon')
- * @cfg {Function} handler A function called when the button is clicked (can be used instead of click event).
- * The handler is passed the following parameters:<div class="mdetail-params"><ul>
- * <li><code>b</code> : Button<div class="sub-desc">This Button.</div></li>
- * <li><code>e</code> : EventObject<div class="sub-desc">The click event.</div></li>
- * </ul></div>
- * @cfg {Number} minWidth The minimum width for this button (used to give a set of buttons a common width).
- * See also {@link Ext.Panel}.<tt>{@link Ext.Panel#minButtonWidth minButtonWidth}</tt>.
- * @cfg {String/Object} tooltip The tooltip for the button - can be a string to be used as innerHTML (html tags are accepted) or QuickTips config object
- * @cfg {Boolean} hidden True to start hidden (defaults to false)
- * @cfg {Boolean} disabled True to start disabled (defaults to false)
- * @cfg {Boolean} pressed True to start pressed (only if enableToggle = true)
- * @cfg {String} toggleGroup The group this toggle button is a member of (only 1 per group can be pressed)
- * @cfg {Boolean/Object} repeat True to repeat fire the click event while the mouse is down. This can also be
- * a {@link Ext.util.ClickRepeater ClickRepeater} config object (defaults to false).
- * @constructor
- * Create a new button
- * @param {Object} config The config object
- * @xtype button
- */
-Ext.Button = Ext.extend(Ext.BoxComponent, {
-    /**
-     * Read-only. True if this button is hidden
-     * @type Boolean
-     */
-    hidden : false,
-    /**
-     * Read-only. True if this button is disabled
-     * @type Boolean
-     */
-    disabled : false,
-    /**
-     * Read-only. True if this button is pressed (only if enableToggle = true)
-     * @type Boolean
-     */
-    pressed : false,
-
-    /**
-     * @cfg {Number} tabIndex Set a DOM tabIndex for this button (defaults to undefined)
-     */
-
-    /**
-     * @cfg {Boolean} allowDepress
-     * False to not allow a pressed Button to be depressed (defaults to undefined). Only valid when {@link #enableToggle} is true.
-     */
-
-    /**
-     * @cfg {Boolean} enableToggle
-     * True to enable pressed/not pressed toggling (defaults to false)
-     */
-    enableToggle : false,
-    /**
-     * @cfg {Function} toggleHandler
-     * Function called when a Button with {@link #enableToggle} set to true is clicked. Two arguments are passed:<ul class="mdetail-params">
-     * <li><b>button</b> : Ext.Button<div class="sub-desc">this Button object</div></li>
-     * <li><b>state</b> : Boolean<div class="sub-desc">The next state if the Button, true means pressed.</div></li>
-     * </ul>
-     */
-    /**
-     * @cfg {Mixed} menu
-     * Standard menu attribute consisting of a reference to a menu object, a menu id or a menu config blob (defaults to undefined).
-     */
-    /**
-     * @cfg {String} menuAlign
-     * The position to align the menu to (see {@link Ext.Element#alignTo} for more details, defaults to 'tl-bl?').
-     */
-    menuAlign : 'tl-bl?',
-
-    /**
-     * @cfg {String} overflowText If used in a {@link Ext.Toolbar Toolbar}, the
-     * text to be used if this item is shown in the overflow menu. See also
-     * {@link Ext.Toolbar.Item}.<code>{@link Ext.Toolbar.Item#overflowText overflowText}</code>.
-     */
-    /**
-     * @cfg {String} iconCls
-     * A css class which sets a background image to be used as the icon for this button
-     */
-    /**
-     * @cfg {String} type
-     * submit, reset or button - defaults to 'button'
-     */
-    type : 'button',
-
-    // private
-    menuClassTarget : 'tr:nth(2)',
-
-    /**
-     * @cfg {String} clickEvent
-     * The DOM event that will fire the handler of the button. This can be any valid event name (dblclick, contextmenu). 
-     * Defaults to <tt>'click'</tt>.
-     */
-    clickEvent : 'click',
-
-    /**
-     * @cfg {Boolean} handleMouseEvents
-     * False to disable visual cues on mouseover, mouseout and mousedown (defaults to true)
-     */
-    handleMouseEvents : true,
-
-    /**
-     * @cfg {String} tooltipType
-     * The type of tooltip to use. Either 'qtip' (default) for QuickTips or 'title' for title attribute.
-     */
-    tooltipType : 'qtip',
-
-    /**
-     * @cfg {String} buttonSelector
-     * <p>(Optional) A {@link Ext.DomQuery DomQuery} selector which is used to extract the active, clickable element from the
-     * DOM structure created.</p>
-     * <p>When a custom {@link #template} is used, you  must ensure that this selector results in the selection of
-     * a focussable element.</p>
-     * <p>Defaults to <b><tt>'button:first-child'</tt></b>.</p>
-     */
-    buttonSelector : 'button:first-child',
-
-    /**
-     * @cfg {String} scale
-     * <p>(Optional) The size of the Button. Three values are allowed:</p>
-     * <ul class="mdetail-params">
-     * <li>'small'<div class="sub-desc">Results in the button element being 16px high.</div></li>
-     * <li>'medium'<div class="sub-desc">Results in the button element being 24px high.</div></li>
-     * <li>'large'<div class="sub-desc">Results in the button element being 32px high.</div></li>
-     * </ul>
-     * <p>Defaults to <b><tt>'small'</tt></b>.</p>
-     */
-    scale : 'small',
-
-    /**
-     * @cfg {Object} scope The scope (<tt><b>this</b></tt> reference) in which the
-     * <code>{@link #handler}</code> and <code>{@link #toggleHandler}</code> is
-     * executed. Defaults to this Button.
-     */
-
-    /**
-     * @cfg {String} iconAlign
-     * <p>(Optional) The side of the Button box to render the icon. Four values are allowed:</p>
-     * <ul class="mdetail-params">
-     * <li>'top'<div class="sub-desc"></div></li>
-     * <li>'right'<div class="sub-desc"></div></li>
-     * <li>'bottom'<div class="sub-desc"></div></li>
-     * <li>'left'<div class="sub-desc"></div></li>
-     * </ul>
-     * <p>Defaults to <b><tt>'left'</tt></b>.</p>
-     */
-    iconAlign : 'left',
-
-    /**
-     * @cfg {String} arrowAlign
-     * <p>(Optional) The side of the Button box to render the arrow if the button has an associated {@link #menu}.
-     * Two values are allowed:</p>
-     * <ul class="mdetail-params">
-     * <li>'right'<div class="sub-desc"></div></li>
-     * <li>'bottom'<div class="sub-desc"></div></li>
-     * </ul>
-     * <p>Defaults to <b><tt>'right'</tt></b>.</p>
-     */
-    arrowAlign : 'right',
-
-    /**
-     * @cfg {Ext.Template} template (Optional)
-     * <p>A {@link Ext.Template Template} used to create the Button's DOM structure.</p>
-     * Instances, or subclasses which need a different DOM structure may provide a different
-     * template layout in conjunction with an implementation of {@link #getTemplateArgs}.
-     * @type Ext.Template
-     * @property template
-     */
-    /**
-     * @cfg {String} cls
-     * A CSS class string to apply to the button's main element.
-     */
-    /**
-     * @property menu
-     * @type Menu
-     * The {@link Ext.menu.Menu Menu} object associated with this Button when configured with the {@link #menu} config option.
-     */
-
-    initComponent : function(){
-        Ext.Button.superclass.initComponent.call(this);
-
-        this.addEvents(
-            /**
-             * @event click
-             * Fires when this button is clicked
-             * @param {Button} this
-             * @param {EventObject} e The click event
-             */
-            'click',
-            /**
-             * @event toggle
-             * Fires when the 'pressed' state of this button changes (only if enableToggle = true)
-             * @param {Button} this
-             * @param {Boolean} pressed
-             */
-            'toggle',
-            /**
-             * @event mouseover
-             * Fires when the mouse hovers over the button
-             * @param {Button} this
-             * @param {Event} e The event object
-             */
-            'mouseover',
-            /**
-             * @event mouseout
-             * Fires when the mouse exits the button
-             * @param {Button} this
-             * @param {Event} e The event object
-             */
-            'mouseout',
-            /**
-             * @event menushow
-             * If this button has a menu, this event fires when it is shown
-             * @param {Button} this
-             * @param {Menu} menu
-             */
-            'menushow',
-            /**
-             * @event menuhide
-             * If this button has a menu, this event fires when it is hidden
-             * @param {Button} this
-             * @param {Menu} menu
-             */
-            'menuhide',
-            /**
-             * @event menutriggerover
-             * If this button has a menu, this event fires when the mouse enters the menu triggering element
-             * @param {Button} this
-             * @param {Menu} menu
-             * @param {EventObject} e
-             */
-            'menutriggerover',
-            /**
-             * @event menutriggerout
-             * If this button has a menu, this event fires when the mouse leaves the menu triggering element
-             * @param {Button} this
-             * @param {Menu} menu
-             * @param {EventObject} e
-             */
-            'menutriggerout'
-        );
-        if(this.menu){
-            this.menu = Ext.menu.MenuMgr.get(this.menu);
-        }
-        if(Ext.isString(this.toggleGroup)){
-            this.enableToggle = true;
-        }
-    },
-
-/**
-  * <p>This method returns an object which provides substitution parameters for the {@link #template Template} used
-  * to create this Button's DOM structure.</p>
-  * <p>Instances or subclasses which use a different Template to create a different DOM structure may need to provide their
-  * own implementation of this method.</p>
-  * <p>The default implementation which provides data for the default {@link #template} returns an Array containing the
-  * following items:</p><div class="mdetail-params"><ul>
-  * <li>The Button's {@link #text}</li>
-  * <li>The &lt;button&gt;'s {@link #type}</li>
-  * <li>The {@link iconCls} applied to the &lt;button&gt; {@link #btnEl element}</li>
-  * <li>The {@link #cls} applied to the Button's main {@link #getEl Element}</li>
-  * <li>A CSS class name controlling the Button's {@link #scale} and {@link #iconAlign icon alignment}</li>
-  * <li>A CSS class name which applies an arrow to the Button if configured with a {@link #menu}</li>
-  * </ul></div>
-  * @return {Object} Substitution data for a Template.
- */
-    getTemplateArgs : function(){
-        var cls = (this.cls || '');
-        cls += (this.iconCls || this.icon) ? (this.text ? ' x-btn-text-icon' : ' x-btn-icon') : ' x-btn-noicon';
-        if(this.pressed){
-            cls += ' x-btn-pressed';
-        }
-        return [this.text || '&#160;', this.type, this.iconCls || '', cls, 'x-btn-' + this.scale + ' x-btn-icon-' + this.scale + '-' + this.iconAlign, this.getMenuClass()];
-    },
-
-    // protected
-    getMenuClass : function(){
-        return this.menu ? (this.arrowAlign != 'bottom' ? 'x-btn-arrow' : 'x-btn-arrow-bottom') : '';
-    },
-
-    // private
-    onRender : function(ct, position){
-        if(!this.template){
-            if(!Ext.Button.buttonTemplate){
-                // hideous table template
-                Ext.Button.buttonTemplate = new Ext.Template(
-                    '<table cellspacing="0" class="x-btn {3}"><tbody class="{4}">',
-                    '<tr><td class="x-btn-tl"><i>&#160;</i></td><td class="x-btn-tc"></td><td class="x-btn-tr"><i>&#160;</i></td></tr>',
-                    '<tr><td class="x-btn-ml"><i>&#160;</i></td><td class="x-btn-mc"><em class="{5}" unselectable="on"><button class="x-btn-text {2}" type="{1}">{0}</button></em></td><td class="x-btn-mr"><i>&#160;</i></td></tr>',
-                    '<tr><td class="x-btn-bl"><i>&#160;</i></td><td class="x-btn-bc"></td><td class="x-btn-br"><i>&#160;</i></td></tr>',
-                    "</tbody></table>");
-                Ext.Button.buttonTemplate.compile();
-            }
-            this.template = Ext.Button.buttonTemplate;
-        }
-
-        var btn, targs = this.getTemplateArgs();
-
-        if(position){
-            btn = this.template.insertBefore(position, targs, true);
-        }else{
-            btn = this.template.append(ct, targs, true);
-        }
-        /**
-         * An {@link Ext.Element Element} encapsulating the Button's clickable element. By default,
-         * this references a <tt>&lt;button&gt;</tt> element. Read only.
-         * @type Ext.Element
-         * @property btnEl
-         */
-        this.btnEl = btn.child(this.buttonSelector);
-        this.mon(this.btnEl, {
-            scope: this,
-            focus: this.onFocus,
-            blur: this.onBlur
-        });
-
-        this.initButtonEl(btn, this.btnEl);
-
-        Ext.ButtonToggleMgr.register(this);
-    },
-
-    // private
-    initButtonEl : function(btn, btnEl){
-        this.el = btn;
-
-        if(this.id){
-            var d = this.el.dom,
-                c = Ext.Element.cache;
-                
-            delete c[d.id];
-            d.id = this.el.id = this.id;
-            c[d.id] = this.el;
-        }
-        if(this.icon){
-            btnEl.setStyle('background-image', 'url(' +this.icon +')');
-        }
-        if(this.tabIndex !== undefined){
-            btnEl.dom.tabIndex = this.tabIndex;
-        }
-        if(this.tooltip){
-            this.setTooltip(this.tooltip, true);
-        }
-
-        if(this.handleMouseEvents){
-            this.mon(btn, {
-                scope: this,
-                mouseover: this.onMouseOver,
-                mousedown: this.onMouseDown
-            });
-
-            // new functionality for monitoring on the document level
-            //this.mon(btn, 'mouseout', this.onMouseOut, this);
-        }
-
-        if(this.menu){
-            this.mon(this.menu, {
-                scope: this,
-                show: this.onMenuShow,
-                hide: this.onMenuHide
-            });
-        }
-
-        if(this.repeat){
-            var repeater = new Ext.util.ClickRepeater(btn, Ext.isObject(this.repeat) ? this.repeat : {});
-            this.mon(repeater, 'click', this.onClick, this);
-        }
-        this.mon(btn, this.clickEvent, this.onClick, this);
-    },
-
-    // private
-    afterRender : function(){
-        Ext.Button.superclass.afterRender.call(this);
-        this.doAutoWidth();
-    },
-
-    /**
-     * Sets the CSS class that provides a background image to use as the button's icon.  This method also changes
-     * the value of the {@link iconCls} config internally.
-     * @param {String} cls The CSS class providing the icon image
-     * @return {Ext.Button} this
-     */
-    setIconClass : function(cls){
-        if(this.el){
-            this.btnEl.replaceClass(this.iconCls, cls);
-        }
-        this.iconCls = cls;
-        return this;
-    },
-
-    /**
-     * Sets the tooltip for this Button.
-     * @param {String/Object} tooltip. This may be:<div class="mdesc-details"><ul>
-     * <li><b>String</b> : A string to be used as innerHTML (html tags are accepted) to show in a tooltip</li>
-     * <li><b>Object</b> : A configuration object for {@link Ext.QuickTips#register}.</li>
-     * </ul></div>
-     * @return {Ext.Button} this
-     */
-    setTooltip : function(tooltip, /* private */ initial){
-        if(this.rendered){
-            if(!initial){
-                this.clearTip();
-            }
-            if(Ext.isObject(tooltip)){
-                Ext.QuickTips.register(Ext.apply({
-                      target: this.btnEl.id
-                }, tooltip));
-                this.tooltip = tooltip;
-            }else{
-                this.btnEl.dom[this.tooltipType] = tooltip;
-            }
-        }else{
-            this.tooltip = tooltip;
-        }
-        return this;
-    },
-
-    // private
-    clearTip : function(){
-        if(Ext.isObject(this.tooltip)){
-            Ext.QuickTips.unregister(this.btnEl);
-        }
-    },
-
-    // private
-    beforeDestroy : function(){
-        if(this.rendered){
-            this.clearTip();
-        }
-        Ext.destroy(this.menu, this.repeater);
-    },
-
-    // private
-    onDestroy : function(){
-        var doc = Ext.getDoc();
-        doc.un('mouseover', this.monitorMouseOver, this);
-        doc.un('mouseup', this.onMouseUp, this);
-        if(this.rendered){
-            Ext.ButtonToggleMgr.unregister(this);
-        }
-    },
-
-    // private
-    doAutoWidth : function(){
-        if(this.el && this.text && this.width === undefined){
-            this.el.setWidth('auto');
-            if(Ext.isIE7 && Ext.isStrict){
-                var ib = this.btnEl;
-                if(ib && ib.getWidth() > 20){
-                    ib.clip();
-                    ib.setWidth(Ext.util.TextMetrics.measure(ib, this.text).width+ib.getFrameWidth('lr'));
-                }
-            }
-            if(this.minWidth){
-                if(this.el.getWidth() < this.minWidth){
-                    this.el.setWidth(this.minWidth);
-                }
-            }
-        }
-    },
-
-    /**
-     * Assigns this Button's click handler
-     * @param {Function} handler The function to call when the button is clicked
-     * @param {Object} scope (optional) Scope for the function passed in. Defaults to this Button.
-     * @return {Ext.Button} this
-     */
-    setHandler : function(handler, scope){
-        this.handler = handler;
-        this.scope = scope;
-        return this;
-    },
-
-    /**
-     * Sets this Button's text
-     * @param {String} text The button text
-     * @return {Ext.Button} this
-     */
-    setText : function(text){
-        this.text = text;
-        if(this.el){
-            this.el.child('td.x-btn-mc ' + this.buttonSelector).update(text);
-        }
-        this.doAutoWidth();
-        return this;
-    },
-
-    /**
-     * Gets the text for this Button
-     * @return {String} The button text
-     */
-    getText : function(){
-        return this.text;
-    },
-
-    /**
-     * If a state it passed, it becomes the pressed state otherwise the current state is toggled.
-     * @param {Boolean} state (optional) Force a particular state
-     * @param {Boolean} supressEvent (optional) True to stop events being fired when calling this method.
-     * @return {Ext.Button} this
-     */
-    toggle : function(state, suppressEvent){
-        state = state === undefined ? !this.pressed : !!state;
-        if(state != this.pressed){
-            if(this.rendered){
-                this.el[state ? 'addClass' : 'removeClass']('x-btn-pressed');
-            }
-            this.pressed = state;
-            if(!suppressEvent){
-                this.fireEvent('toggle', this, state);
-                if(this.toggleHandler){
-                    this.toggleHandler.call(this.scope || this, this, state);
-                }
-            }
-        }
-        return this;
-    },
-
-    /**
-     * Focus the button
-     */
-    focus : function(){
-        this.btnEl.focus();
-    },
-
-    // private
-    onDisable : function(){
-        this.onDisableChange(true);
-    },
-
-    // private
-    onEnable : function(){
-        this.onDisableChange(false);
-    },
-
-    onDisableChange : function(disabled){
-        if(this.el){
-            if(!Ext.isIE6 || !this.text){
-                this.el[disabled ? 'addClass' : 'removeClass'](this.disabledClass);
-            }
-            this.el.dom.disabled = disabled;
-        }
-        this.disabled = disabled;
-    },
-
-    /**
-     * Show this button's menu (if it has one)
-     */
-    showMenu : function(){
-        if(this.rendered && this.menu){
-            if(this.tooltip){
-                Ext.QuickTips.getQuickTip().cancelShow(this.btnEl);
-            }
-            this.menu.show(this.el, this.menuAlign);
-        }
-        return this;
-    },
-
-    /**
-     * Hide this button's menu (if it has one)
-     */
-    hideMenu : function(){
-        if(this.menu){
-            this.menu.hide();
-        }
-        return this;
-    },
-
-    /**
-     * Returns true if the button has a menu and it is visible
-     * @return {Boolean}
-     */
-    hasVisibleMenu : function(){
-        return this.menu && this.menu.isVisible();
-    },
-
-    // private
-    onClick : function(e){
-        if(e){
-            e.preventDefault();
-        }
-        if(e.button !== 0){
-            return;
-        }
-        if(!this.disabled){
-            if(this.enableToggle && (this.allowDepress !== false || !this.pressed)){
-                this.toggle();
-            }
-            if(this.menu && !this.menu.isVisible() && !this.ignoreNextClick){
-                this.showMenu();
-            }
-            this.fireEvent('click', this, e);
-            if(this.handler){
-                //this.el.removeClass('x-btn-over');
-                this.handler.call(this.scope || this, this, e);
-            }
-        }
-    },
-
-    // private
-    isMenuTriggerOver : function(e, internal){
-        return this.menu && !internal;
-    },
-
-    // private
-    isMenuTriggerOut : function(e, internal){
-        return this.menu && !internal;
-    },
-
-    // private
-    onMouseOver : function(e){
-        if(!this.disabled){
-            var internal = e.within(this.el,  true);
-            if(!internal){
-                this.el.addClass('x-btn-over');
-                if(!this.monitoringMouseOver){
-                    Ext.getDoc().on('mouseover', this.monitorMouseOver, this);
-                    this.monitoringMouseOver = true;
-                }
-                this.fireEvent('mouseover', this, e);
-            }
-            if(this.isMenuTriggerOver(e, internal)){
-                this.fireEvent('menutriggerover', this, this.menu, e);
-            }
-        }
-    },
-
-    // private
-    monitorMouseOver : function(e){
-        if(e.target != this.el.dom && !e.within(this.el)){
-            if(this.monitoringMouseOver){
-                Ext.getDoc().un('mouseover', this.monitorMouseOver, this);
-                this.monitoringMouseOver = false;
-            }
-            this.onMouseOut(e);
-        }
-    },
-
-    // private
-    onMouseOut : function(e){
-        var internal = e.within(this.el) && e.target != this.el.dom;
-        this.el.removeClass('x-btn-over');
-        this.fireEvent('mouseout', this, e);
-        if(this.isMenuTriggerOut(e, internal)){
-            this.fireEvent('menutriggerout', this, this.menu, e);
-        }
-    },
-    // private
-    onFocus : function(e){
-        if(!this.disabled){
-            this.el.addClass('x-btn-focus');
-        }
-    },
-    // private
-    onBlur : function(e){
-        this.el.removeClass('x-btn-focus');
-    },
-
-    // private
-    getClickEl : function(e, isUp){
-       return this.el;
-    },
-
-    // private
-    onMouseDown : function(e){
-        if(!this.disabled && e.button === 0){
-            this.getClickEl(e).addClass('x-btn-click');
-            Ext.getDoc().on('mouseup', this.onMouseUp, this);
-        }
-    },
-    // private
-    onMouseUp : function(e){
-        if(e.button === 0){
-            this.getClickEl(e, true).removeClass('x-btn-click');
-            Ext.getDoc().un('mouseup', this.onMouseUp, this);
-        }
-    },
-    // private
-    onMenuShow : function(e){
-        this.ignoreNextClick = 0;
-        this.el.addClass('x-btn-menu-active');
-        this.fireEvent('menushow', this, this.menu);
-    },
-    // private
-    onMenuHide : function(e){
-        this.el.removeClass('x-btn-menu-active');
-        this.ignoreNextClick = this.restoreClick.defer(250, this);
-        this.fireEvent('menuhide', this, this.menu);
-    },
-
-    // private
-    restoreClick : function(){
-        this.ignoreNextClick = 0;
-    }
-
-
-
-    /**
-     * @cfg {String} autoEl @hide
-     */
-});
-Ext.reg('button', Ext.Button);
-
-// Private utility class used by Button
-Ext.ButtonToggleMgr = function(){
-   var groups = {};
-
-   function toggleGroup(btn, state){
-       if(state){
-           var g = groups[btn.toggleGroup];
-           for(var i = 0, l = g.length; i < l; i++){
-               if(g[i] != btn){
-                   g[i].toggle(false);
-               }
-           }
-       }
-   }
-
-   return {
-       register : function(btn){
-           if(!btn.toggleGroup){
-               return;
-           }
-           var g = groups[btn.toggleGroup];
-           if(!g){
-               g = groups[btn.toggleGroup] = [];
-           }
-           g.push(btn);
-           btn.on('toggle', toggleGroup);
-       },
-
-       unregister : function(btn){
-           if(!btn.toggleGroup){
-               return;
-           }
-           var g = groups[btn.toggleGroup];
-           if(g){
-               g.remove(btn);
-               btn.un('toggle', toggleGroup);
-           }
-       },
-
-       /**
-        * Gets the pressed button in the passed group or null
-        * @param {String} group
-        * @return Button
-        */
-       getPressed : function(group){
-           var g = groups[group];
-           if(g){
-               for(var i = 0, len = g.length; i < len; i++){
-                   if(g[i].pressed === true){
-                       return g[i];
-                   }
-               }
-           }
-           return null;
-       }
-   };
-}();/**\r
+/**\r
+ * @class Ext.Button\r
+ * @extends Ext.BoxComponent\r
+ * Simple Button class\r
+ * @cfg {String} text The button text to be used as innerHTML (html tags are accepted)\r
+ * @cfg {String} icon The path to an image to display in the button (the image will be set as the background-image\r
+ * CSS property of the button by default, so if you want a mixed icon/text button, set cls:'x-btn-text-icon')\r
+ * @cfg {Function} handler A function called when the button is clicked (can be used instead of click event).\r
+ * The handler is passed the following parameters:<div class="mdetail-params"><ul>\r
+ * <li><code>b</code> : Button<div class="sub-desc">This Button.</div></li>\r
+ * <li><code>e</code> : EventObject<div class="sub-desc">The click event.</div></li>\r
+ * </ul></div>\r
+ * @cfg {Number} minWidth The minimum width for this button (used to give a set of buttons a common width).\r
+ * See also {@link Ext.Panel}.<tt>{@link Ext.Panel#minButtonWidth minButtonWidth}</tt>.\r
+ * @cfg {String/Object} tooltip The tooltip for the button - can be a string to be used as innerHTML (html tags are accepted) or QuickTips config object\r
+ * @cfg {Boolean} hidden True to start hidden (defaults to false)\r
+ * @cfg {Boolean} disabled True to start disabled (defaults to false)\r
+ * @cfg {Boolean} pressed True to start pressed (only if enableToggle = true)\r
+ * @cfg {String} toggleGroup The group this toggle button is a member of (only 1 per group can be pressed)\r
+ * @cfg {Boolean/Object} repeat True to repeat fire the click event while the mouse is down. This can also be\r
+ * a {@link Ext.util.ClickRepeater ClickRepeater} config object (defaults to false).\r
+ * @constructor\r
+ * Create a new button\r
+ * @param {Object} config The config object\r
+ * @xtype button\r
+ */\r
+Ext.Button = Ext.extend(Ext.BoxComponent, {\r
+    /**\r
+     * Read-only. True if this button is hidden\r
+     * @type Boolean\r
+     */\r
+    hidden : false,\r
+    /**\r
+     * Read-only. True if this button is disabled\r
+     * @type Boolean\r
+     */\r
+    disabled : false,\r
+    /**\r
+     * Read-only. True if this button is pressed (only if enableToggle = true)\r
+     * @type Boolean\r
+     */\r
+    pressed : false,\r
+\r
+    /**\r
+     * @cfg {Number} tabIndex Set a DOM tabIndex for this button (defaults to undefined)\r
+     */\r
+\r
+    /**\r
+     * @cfg {Boolean} allowDepress\r
+     * False to not allow a pressed Button to be depressed (defaults to undefined). Only valid when {@link #enableToggle} is true.\r
+     */\r
+\r
+    /**\r
+     * @cfg {Boolean} enableToggle\r
+     * True to enable pressed/not pressed toggling (defaults to false)\r
+     */\r
+    enableToggle : false,\r
+    /**\r
+     * @cfg {Function} toggleHandler\r
+     * Function called when a Button with {@link #enableToggle} set to true is clicked. Two arguments are passed:<ul class="mdetail-params">\r
+     * <li><b>button</b> : Ext.Button<div class="sub-desc">this Button object</div></li>\r
+     * <li><b>state</b> : Boolean<div class="sub-desc">The next state of the Button, true means pressed.</div></li>\r
+     * </ul>\r
+     */\r
+    /**\r
+     * @cfg {Mixed} menu\r
+     * Standard menu attribute consisting of a reference to a menu object, a menu id or a menu config blob (defaults to undefined).\r
+     */\r
+    /**\r
+     * @cfg {String} menuAlign\r
+     * The position to align the menu to (see {@link Ext.Element#alignTo} for more details, defaults to 'tl-bl?').\r
+     */\r
+    menuAlign : 'tl-bl?',\r
+\r
+    /**\r
+     * @cfg {String} overflowText If used in a {@link Ext.Toolbar Toolbar}, the\r
+     * text to be used if this item is shown in the overflow menu. See also\r
+     * {@link Ext.Toolbar.Item}.<code>{@link Ext.Toolbar.Item#overflowText overflowText}</code>.\r
+     */\r
+    /**\r
+     * @cfg {String} iconCls\r
+     * A css class which sets a background image to be used as the icon for this button\r
+     */\r
+    /**\r
+     * @cfg {String} type\r
+     * submit, reset or button - defaults to 'button'\r
+     */\r
+    type : 'button',\r
+\r
+    // private\r
+    menuClassTarget : 'tr:nth(2)',\r
+\r
+    /**\r
+     * @cfg {String} clickEvent\r
+     * The DOM event that will fire the handler of the button. This can be any valid event name (dblclick, contextmenu).\r
+     * Defaults to <tt>'click'</tt>.\r
+     */\r
+    clickEvent : 'click',\r
+\r
+    /**\r
+     * @cfg {Boolean} handleMouseEvents\r
+     * False to disable visual cues on mouseover, mouseout and mousedown (defaults to true)\r
+     */\r
+    handleMouseEvents : true,\r
+\r
+    /**\r
+     * @cfg {String} tooltipType\r
+     * The type of tooltip to use. Either 'qtip' (default) for QuickTips or 'title' for title attribute.\r
+     */\r
+    tooltipType : 'qtip',\r
+\r
+    /**\r
+     * @cfg {String} buttonSelector\r
+     * <p>(Optional) A {@link Ext.DomQuery DomQuery} selector which is used to extract the active, clickable element from the\r
+     * DOM structure created.</p>\r
+     * <p>When a custom {@link #template} is used, you  must ensure that this selector results in the selection of\r
+     * a focussable element.</p>\r
+     * <p>Defaults to <b><tt>'button:first-child'</tt></b>.</p>\r
+     */\r
+    buttonSelector : 'button:first-child',\r
+\r
+    /**\r
+     * @cfg {String} scale\r
+     * <p>(Optional) The size of the Button. Three values are allowed:</p>\r
+     * <ul class="mdetail-params">\r
+     * <li>'small'<div class="sub-desc">Results in the button element being 16px high.</div></li>\r
+     * <li>'medium'<div class="sub-desc">Results in the button element being 24px high.</div></li>\r
+     * <li>'large'<div class="sub-desc">Results in the button element being 32px high.</div></li>\r
+     * </ul>\r
+     * <p>Defaults to <b><tt>'small'</tt></b>.</p>\r
+     */\r
+    scale : 'small',\r
+\r
+    /**\r
+     * @cfg {Object} scope The scope (<tt><b>this</b></tt> reference) in which the\r
+     * <code>{@link #handler}</code> and <code>{@link #toggleHandler}</code> is\r
+     * executed. Defaults to this Button.\r
+     */\r
+\r
+    /**\r
+     * @cfg {String} iconAlign\r
+     * <p>(Optional) The side of the Button box to render the icon. Four values are allowed:</p>\r
+     * <ul class="mdetail-params">\r
+     * <li>'top'<div class="sub-desc"></div></li>\r
+     * <li>'right'<div class="sub-desc"></div></li>\r
+     * <li>'bottom'<div class="sub-desc"></div></li>\r
+     * <li>'left'<div class="sub-desc"></div></li>\r
+     * </ul>\r
+     * <p>Defaults to <b><tt>'left'</tt></b>.</p>\r
+     */\r
+    iconAlign : 'left',\r
+\r
+    /**\r
+     * @cfg {String} arrowAlign\r
+     * <p>(Optional) The side of the Button box to render the arrow if the button has an associated {@link #menu}.\r
+     * Two values are allowed:</p>\r
+     * <ul class="mdetail-params">\r
+     * <li>'right'<div class="sub-desc"></div></li>\r
+     * <li>'bottom'<div class="sub-desc"></div></li>\r
+     * </ul>\r
+     * <p>Defaults to <b><tt>'right'</tt></b>.</p>\r
+     */\r
+    arrowAlign : 'right',\r
+\r
+    /**\r
+     * @cfg {Ext.Template} template (Optional)\r
+     * <p>A {@link Ext.Template Template} used to create the Button's DOM structure.</p>\r
+     * Instances, or subclasses which need a different DOM structure may provide a different\r
+     * template layout in conjunction with an implementation of {@link #getTemplateArgs}.\r
+     * @type Ext.Template\r
+     * @property template\r
+     */\r
+    /**\r
+     * @cfg {String} cls\r
+     * A CSS class string to apply to the button's main element.\r
+     */\r
+    /**\r
+     * @property menu\r
+     * @type Menu\r
+     * The {@link Ext.menu.Menu Menu} object associated with this Button when configured with the {@link #menu} config option.\r
+     */\r
+\r
+    initComponent : function(){\r
+        Ext.Button.superclass.initComponent.call(this);\r
+\r
+        this.addEvents(\r
+            /**\r
+             * @event click\r
+             * Fires when this button is clicked\r
+             * @param {Button} this\r
+             * @param {EventObject} e The click event\r
+             */\r
+            'click',\r
+            /**\r
+             * @event toggle\r
+             * Fires when the 'pressed' state of this button changes (only if enableToggle = true)\r
+             * @param {Button} this\r
+             * @param {Boolean} pressed\r
+             */\r
+            'toggle',\r
+            /**\r
+             * @event mouseover\r
+             * Fires when the mouse hovers over the button\r
+             * @param {Button} this\r
+             * @param {Event} e The event object\r
+             */\r
+            'mouseover',\r
+            /**\r
+             * @event mouseout\r
+             * Fires when the mouse exits the button\r
+             * @param {Button} this\r
+             * @param {Event} e The event object\r
+             */\r
+            'mouseout',\r
+            /**\r
+             * @event menushow\r
+             * If this button has a menu, this event fires when it is shown\r
+             * @param {Button} this\r
+             * @param {Menu} menu\r
+             */\r
+            'menushow',\r
+            /**\r
+             * @event menuhide\r
+             * If this button has a menu, this event fires when it is hidden\r
+             * @param {Button} this\r
+             * @param {Menu} menu\r
+             */\r
+            'menuhide',\r
+            /**\r
+             * @event menutriggerover\r
+             * If this button has a menu, this event fires when the mouse enters the menu triggering element\r
+             * @param {Button} this\r
+             * @param {Menu} menu\r
+             * @param {EventObject} e\r
+             */\r
+            'menutriggerover',\r
+            /**\r
+             * @event menutriggerout\r
+             * If this button has a menu, this event fires when the mouse leaves the menu triggering element\r
+             * @param {Button} this\r
+             * @param {Menu} menu\r
+             * @param {EventObject} e\r
+             */\r
+            'menutriggerout'\r
+        );\r
+        if(this.menu){\r
+            this.menu = Ext.menu.MenuMgr.get(this.menu);\r
+        }\r
+        if(Ext.isString(this.toggleGroup)){\r
+            this.enableToggle = true;\r
+        }\r
+    },\r
+\r
+/**\r
+  * <p>This method returns an Array which provides substitution parameters for the {@link #template Template} used\r
+  * to create this Button's DOM structure.</p>\r
+  * <p>Instances or subclasses which use a different Template to create a different DOM structure may need to provide their\r
+  * own implementation of this method.</p>\r
+  * <p>The default implementation which provides data for the default {@link #template} returns an Array containing the\r
+  * following items:</p><div class="mdetail-params"><ul>\r
+  * <li>The &lt;button&gt;'s {@link #type}</li>\r
+  * <li>A CSS class name applied to the Button's main &lt;tbody&gt; element which determines the button's scale and icon alignment.</li>\r
+  * <li>A CSS class to determine the presence and position of an arrow icon. (<code>'x-btn-arrow'</code> or <code>'x-btn-arrow-bottom'</code> or <code>''</code>)</li>\r
+  * <li>The {@link #cls} CSS class name applied to the button's wrapping &lt;table&gt; element.</li>\r
+  * <li>The Component id which is applied to the button's wrapping &lt;table&gt; element.</li>\r
+  * </ul></div>\r
+  * @return {Array} Substitution data for a Template.\r
+ */\r
+    getTemplateArgs : function(){\r
+        return [this.type, 'x-btn-' + this.scale + ' x-btn-icon-' + this.scale + '-' + this.iconAlign, this.getMenuClass(), this.cls, this.id];\r
+    },\r
+\r
+    // private\r
+    setButtonClass : function(){\r
+        if(this.useSetClass){\r
+            if(!Ext.isEmpty(this.oldCls)){\r
+                this.el.removeClass([this.oldCls, 'x-btn-pressed']);\r
+            }\r
+            this.oldCls = (this.iconCls || this.icon) ? (this.text ? ' x-btn-text-icon' : ' x-btn-icon') : ' x-btn-noicon';\r
+            this.el.addClass([this.oldCls, this.pressed ? 'x-btn-pressed' : null]);\r
+        }\r
+    },\r
+\r
+    // protected\r
+    getMenuClass : function(){\r
+        return this.menu ? (this.arrowAlign != 'bottom' ? 'x-btn-arrow' : 'x-btn-arrow-bottom') : '';\r
+    },\r
+\r
+    // private\r
+    onRender : function(ct, position){\r
+        if(!this.template){\r
+            if(!Ext.Button.buttonTemplate){\r
+                // hideous table template\r
+                Ext.Button.buttonTemplate = new Ext.Template(\r
+                    '<table id="{4}" cellspacing="0" class="x-btn {3}"><tbody class="{1}">',\r
+                    '<tr><td class="x-btn-tl"><i>&#160;</i></td><td class="x-btn-tc"></td><td class="x-btn-tr"><i>&#160;</i></td></tr>',\r
+                    '<tr><td class="x-btn-ml"><i>&#160;</i></td><td class="x-btn-mc"><em class="{2}" unselectable="on"><button type="{0}"></button></em></td><td class="x-btn-mr"><i>&#160;</i></td></tr>',\r
+                    '<tr><td class="x-btn-bl"><i>&#160;</i></td><td class="x-btn-bc"></td><td class="x-btn-br"><i>&#160;</i></td></tr>',\r
+                    '</tbody></table>');\r
+                Ext.Button.buttonTemplate.compile();\r
+            }\r
+            this.template = Ext.Button.buttonTemplate;\r
+        }\r
+\r
+        var btn, targs = this.getTemplateArgs();\r
+\r
+        if(position){\r
+            btn = this.template.insertBefore(position, targs, true);\r
+        }else{\r
+            btn = this.template.append(ct, targs, true);\r
+        }\r
+        /**\r
+         * An {@link Ext.Element Element} encapsulating the Button's clickable element. By default,\r
+         * this references a <tt>&lt;button&gt;</tt> element. Read only.\r
+         * @type Ext.Element\r
+         * @property btnEl\r
+         */\r
+        this.btnEl = btn.child(this.buttonSelector);\r
+        this.mon(this.btnEl, {\r
+            scope: this,\r
+            focus: this.onFocus,\r
+            blur: this.onBlur\r
+        });\r
+\r
+        this.initButtonEl(btn, this.btnEl);\r
+\r
+        Ext.ButtonToggleMgr.register(this);\r
+    },\r
+\r
+    // private\r
+    initButtonEl : function(btn, btnEl){\r
+        this.el = btn;\r
+        this.setIcon(this.icon);\r
+        this.setText(this.text);\r
+        this.setIconClass(this.iconCls);\r
+        if(Ext.isDefined(this.tabIndex)){\r
+            btnEl.dom.tabIndex = this.tabIndex;\r
+        }\r
+        if(this.tooltip){\r
+            this.setTooltip(this.tooltip, true);\r
+        }\r
+\r
+        if(this.handleMouseEvents){\r
+            this.mon(btn, {\r
+                scope: this,\r
+                mouseover: this.onMouseOver,\r
+                mousedown: this.onMouseDown\r
+            });\r
+\r
+            // new functionality for monitoring on the document level\r
+            //this.mon(btn, 'mouseout', this.onMouseOut, this);\r
+        }\r
+\r
+        if(this.menu){\r
+            this.mon(this.menu, {\r
+                scope: this,\r
+                show: this.onMenuShow,\r
+                hide: this.onMenuHide\r
+            });\r
+        }\r
+\r
+        if(this.repeat){\r
+            var repeater = new Ext.util.ClickRepeater(btn, Ext.isObject(this.repeat) ? this.repeat : {});\r
+            this.mon(repeater, 'click', this.onClick, this);\r
+        }\r
+        this.mon(btn, this.clickEvent, this.onClick, this);\r
+    },\r
+\r
+    // private\r
+    afterRender : function(){\r
+        Ext.Button.superclass.afterRender.call(this);\r
+        this.useSetClass = true;\r
+        this.setButtonClass();\r
+        this.doc = Ext.getDoc();\r
+        this.doAutoWidth();\r
+    },\r
+\r
+    /**\r
+     * Sets the CSS class that provides a background image to use as the button's icon.  This method also changes\r
+     * the value of the {@link iconCls} config internally.\r
+     * @param {String} cls The CSS class providing the icon image\r
+     * @return {Ext.Button} this\r
+     */\r
+    setIconClass : function(cls){\r
+        this.iconCls = cls;\r
+        if(this.el){\r
+            this.btnEl.dom.className = '';\r
+            this.btnEl.addClass(['x-btn-text', cls || '']);\r
+            this.setButtonClass();\r
+        }\r
+        return this;\r
+    },\r
+\r
+    /**\r
+     * Sets the tooltip for this Button.\r
+     * @param {String/Object} tooltip. This may be:<div class="mdesc-details"><ul>\r
+     * <li><b>String</b> : A string to be used as innerHTML (html tags are accepted) to show in a tooltip</li>\r
+     * <li><b>Object</b> : A configuration object for {@link Ext.QuickTips#register}.</li>\r
+     * </ul></div>\r
+     * @return {Ext.Button} this\r
+     */\r
+    setTooltip : function(tooltip, /* private */ initial){\r
+        if(this.rendered){\r
+            if(!initial){\r
+                this.clearTip();\r
+            }\r
+            if(Ext.isObject(tooltip)){\r
+                Ext.QuickTips.register(Ext.apply({\r
+                      target: this.btnEl.id\r
+                }, tooltip));\r
+                this.tooltip = tooltip;\r
+            }else{\r
+                this.btnEl.dom[this.tooltipType] = tooltip;\r
+            }\r
+        }else{\r
+            this.tooltip = tooltip;\r
+        }\r
+        return this;\r
+    },\r
+\r
+    // private\r
+    clearTip : function(){\r
+        if(Ext.isObject(this.tooltip)){\r
+            Ext.QuickTips.unregister(this.btnEl);\r
+        }\r
+    },\r
+\r
+    // private\r
+    beforeDestroy : function(){\r
+        if(this.rendered){\r
+            this.clearTip();\r
+        }\r
+        if(this.menu && this.destroyMenu !== false) {\r
+            Ext.destroy(this.menu);\r
+        }\r
+        Ext.destroy(this.repeater);\r
+    },\r
+\r
+    // private\r
+    onDestroy : function(){\r
+        if(this.rendered){\r
+            this.doc.un('mouseover', this.monitorMouseOver, this);\r
+            this.doc.un('mouseup', this.onMouseUp, this);\r
+            delete this.doc;\r
+            delete this.btnEl;\r
+            Ext.ButtonToggleMgr.unregister(this);\r
+        }\r
+        Ext.Button.superclass.onDestroy.call(this);\r
+    },\r
+\r
+    // private\r
+    doAutoWidth : function(){\r
+        if(this.el && this.text && this.width === undefined){\r
+            this.el.setWidth('auto');\r
+            if(Ext.isIE7 && Ext.isStrict){\r
+                var ib = this.btnEl;\r
+                if(ib && ib.getWidth() > 20){\r
+                    ib.clip();\r
+                    ib.setWidth(Ext.util.TextMetrics.measure(ib, this.text).width+ib.getFrameWidth('lr'));\r
+                }\r
+            }\r
+            if(this.minWidth){\r
+                if(this.el.getWidth() < this.minWidth){\r
+                    this.el.setWidth(this.minWidth);\r
+                }\r
+            }\r
+        }\r
+    },\r
+\r
+    /**\r
+     * Assigns this Button's click handler\r
+     * @param {Function} handler The function to call when the button is clicked\r
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the handler function is executed.\r
+     * Defaults to this Button.\r
+     * @return {Ext.Button} this\r
+     */\r
+    setHandler : function(handler, scope){\r
+        this.handler = handler;\r
+        this.scope = scope;\r
+        return this;\r
+    },\r
+\r
+    /**\r
+     * Sets this Button's text\r
+     * @param {String} text The button text\r
+     * @return {Ext.Button} this\r
+     */\r
+    setText : function(text){\r
+        this.text = text;\r
+        if(this.el){\r
+            this.btnEl.update(text || '&#160;');\r
+            this.setButtonClass();\r
+        }\r
+        this.doAutoWidth();\r
+        return this;\r
+    },\r
+\r
+    /**\r
+     * Sets the background image (inline style) of the button.  This method also changes\r
+     * the value of the {@link icon} config internally.\r
+     * @param {String} icon The path to an image to display in the button\r
+     * @return {Ext.Button} this\r
+     */\r
+    setIcon : function(icon){\r
+        this.icon = icon;\r
+        if(this.el){\r
+            this.btnEl.setStyle('background-image', icon ? 'url(' + icon + ')' : '');\r
+            this.setButtonClass();\r
+        }\r
+        return this;\r
+    },\r
+\r
+    /**\r
+     * Gets the text for this Button\r
+     * @return {String} The button text\r
+     */\r
+    getText : function(){\r
+        return this.text;\r
+    },\r
+\r
+    /**\r
+     * If a state it passed, it becomes the pressed state otherwise the current state is toggled.\r
+     * @param {Boolean} state (optional) Force a particular state\r
+     * @param {Boolean} supressEvent (optional) True to stop events being fired when calling this method.\r
+     * @return {Ext.Button} this\r
+     */\r
+    toggle : function(state, suppressEvent){\r
+        state = state === undefined ? !this.pressed : !!state;\r
+        if(state != this.pressed){\r
+            if(this.rendered){\r
+                this.el[state ? 'addClass' : 'removeClass']('x-btn-pressed');\r
+            }\r
+            this.pressed = state;\r
+            if(!suppressEvent){\r
+                this.fireEvent('toggle', this, state);\r
+                if(this.toggleHandler){\r
+                    this.toggleHandler.call(this.scope || this, this, state);\r
+                }\r
+            }\r
+        }\r
+        return this;\r
+    },\r
+\r
+    /**\r
+     * Focus the button\r
+     */\r
+    focus : function(){\r
+        this.btnEl.focus();\r
+    },\r
+\r
+    // private\r
+    onDisable : function(){\r
+        this.onDisableChange(true);\r
+    },\r
+\r
+    // private\r
+    onEnable : function(){\r
+        this.onDisableChange(false);\r
+    },\r
+\r
+    onDisableChange : function(disabled){\r
+        if(this.el){\r
+            if(!Ext.isIE6 || !this.text){\r
+                this.el[disabled ? 'addClass' : 'removeClass'](this.disabledClass);\r
+            }\r
+            this.el.dom.disabled = disabled;\r
+        }\r
+        this.disabled = disabled;\r
+    },\r
+\r
+    /**\r
+     * Show this button's menu (if it has one)\r
+     */\r
+    showMenu : function(){\r
+        if(this.rendered && this.menu){\r
+            if(this.tooltip){\r
+                Ext.QuickTips.getQuickTip().cancelShow(this.btnEl);\r
+            }\r
+            if(this.menu.isVisible()){\r
+                this.menu.hide();\r
+            }\r
+            this.menu.ownerCt = this;\r
+            this.menu.show(this.el, this.menuAlign);\r
+        }\r
+        return this;\r
+    },\r
+\r
+    /**\r
+     * Hide this button's menu (if it has one)\r
+     */\r
+    hideMenu : function(){\r
+        if(this.hasVisibleMenu()){\r
+            this.menu.hide();\r
+        }\r
+        return this;\r
+    },\r
+\r
+    /**\r
+     * Returns true if the button has a menu and it is visible\r
+     * @return {Boolean}\r
+     */\r
+    hasVisibleMenu : function(){\r
+        return this.menu && this.menu.ownerCt == this && this.menu.isVisible();\r
+    },\r
+\r
+    // private\r
+    onClick : function(e){\r
+        if(e){\r
+            e.preventDefault();\r
+        }\r
+        if(e.button !== 0){\r
+            return;\r
+        }\r
+        if(!this.disabled){\r
+            if(this.enableToggle && (this.allowDepress !== false || !this.pressed)){\r
+                this.toggle();\r
+            }\r
+            if(this.menu && !this.hasVisibleMenu() && !this.ignoreNextClick){\r
+                this.showMenu();\r
+            }\r
+            this.fireEvent('click', this, e);\r
+            if(this.handler){\r
+                //this.el.removeClass('x-btn-over');\r
+                this.handler.call(this.scope || this, this, e);\r
+            }\r
+        }\r
+    },\r
+\r
+    // private\r
+    isMenuTriggerOver : function(e, internal){\r
+        return this.menu && !internal;\r
+    },\r
+\r
+    // private\r
+    isMenuTriggerOut : function(e, internal){\r
+        return this.menu && !internal;\r
+    },\r
+\r
+    // private\r
+    onMouseOver : function(e){\r
+        if(!this.disabled){\r
+            var internal = e.within(this.el,  true);\r
+            if(!internal){\r
+                this.el.addClass('x-btn-over');\r
+                if(!this.monitoringMouseOver){\r
+                    this.doc.on('mouseover', this.monitorMouseOver, this);\r
+                    this.monitoringMouseOver = true;\r
+                }\r
+                this.fireEvent('mouseover', this, e);\r
+            }\r
+            if(this.isMenuTriggerOver(e, internal)){\r
+                this.fireEvent('menutriggerover', this, this.menu, e);\r
+            }\r
+        }\r
+    },\r
+\r
+    // private\r
+    monitorMouseOver : function(e){\r
+        if(e.target != this.el.dom && !e.within(this.el)){\r
+            if(this.monitoringMouseOver){\r
+                this.doc.un('mouseover', this.monitorMouseOver, this);\r
+                this.monitoringMouseOver = false;\r
+            }\r
+            this.onMouseOut(e);\r
+        }\r
+    },\r
+\r
+    // private\r
+    onMouseOut : function(e){\r
+        var internal = e.within(this.el) && e.target != this.el.dom;\r
+        this.el.removeClass('x-btn-over');\r
+        this.fireEvent('mouseout', this, e);\r
+        if(this.isMenuTriggerOut(e, internal)){\r
+            this.fireEvent('menutriggerout', this, this.menu, e);\r
+        }\r
+    },\r
+\r
+    focus : function() {\r
+        this.btnEl.focus();\r
+    },\r
+\r
+    blur : function() {\r
+        this.btnEl.blur();\r
+    },\r
+\r
+    // private\r
+    onFocus : function(e){\r
+        if(!this.disabled){\r
+            this.el.addClass('x-btn-focus');\r
+        }\r
+    },\r
+    // private\r
+    onBlur : function(e){\r
+        this.el.removeClass('x-btn-focus');\r
+    },\r
+\r
+    // private\r
+    getClickEl : function(e, isUp){\r
+       return this.el;\r
+    },\r
+\r
+    // private\r
+    onMouseDown : function(e){\r
+        if(!this.disabled && e.button === 0){\r
+            this.getClickEl(e).addClass('x-btn-click');\r
+            this.doc.on('mouseup', this.onMouseUp, this);\r
+        }\r
+    },\r
+    // private\r
+    onMouseUp : function(e){\r
+        if(e.button === 0){\r
+            this.getClickEl(e, true).removeClass('x-btn-click');\r
+            this.doc.un('mouseup', this.onMouseUp, this);\r
+        }\r
+    },\r
+    // private\r
+    onMenuShow : function(e){\r
+        if(this.menu.ownerCt == this){\r
+            this.menu.ownerCt = this;\r
+            this.ignoreNextClick = 0;\r
+            this.el.addClass('x-btn-menu-active');\r
+            this.fireEvent('menushow', this, this.menu);\r
+        }\r
+    },\r
+    // private\r
+    onMenuHide : function(e){\r
+        if(this.menu.ownerCt == this){\r
+            this.el.removeClass('x-btn-menu-active');\r
+            this.ignoreNextClick = this.restoreClick.defer(250, this);\r
+            this.fireEvent('menuhide', this, this.menu);\r
+            delete this.menu.ownerCt;\r
+        }\r
+    },\r
+\r
+    // private\r
+    restoreClick : function(){\r
+        this.ignoreNextClick = 0;\r
+    }\r
+\r
+    /**\r
+     * @cfg {String} autoEl @hide\r
+     */\r
+    /**\r
+     * @cfg {String/Object} html @hide\r
+     */\r
+    /**\r
+     * @cfg {String} contentEl  @hide\r
+     */\r
+    /**\r
+     * @cfg {Mixed} data  @hide\r
+     */\r
+    /**\r
+     * @cfg {Mixed} tpl  @hide\r
+     */\r
+    /**\r
+     * @cfg {String} tplWriteMode  @hide\r
+     */\r
+});\r
+Ext.reg('button', Ext.Button);\r
+\r
+// Private utility class used by Button\r
+Ext.ButtonToggleMgr = function(){\r
+   var groups = {};\r
+\r
+   function toggleGroup(btn, state){\r
+       if(state){\r
+           var g = groups[btn.toggleGroup];\r
+           for(var i = 0, l = g.length; i < l; i++){\r
+               if(g[i] != btn){\r
+                   g[i].toggle(false);\r
+               }\r
+           }\r
+       }\r
+   }\r
+\r
+   return {\r
+       register : function(btn){\r
+           if(!btn.toggleGroup){\r
+               return;\r
+           }\r
+           var g = groups[btn.toggleGroup];\r
+           if(!g){\r
+               g = groups[btn.toggleGroup] = [];\r
+           }\r
+           g.push(btn);\r
+           btn.on('toggle', toggleGroup);\r
+       },\r
+\r
+       unregister : function(btn){\r
+           if(!btn.toggleGroup){\r
+               return;\r
+           }\r
+           var g = groups[btn.toggleGroup];\r
+           if(g){\r
+               g.remove(btn);\r
+               btn.un('toggle', toggleGroup);\r
+           }\r
+       },\r
+\r
+       /**\r
+        * Gets the pressed button in the passed group or null\r
+        * @param {String} group\r
+        * @return Button\r
+        */\r
+       getPressed : function(group){\r
+           var g = groups[group];\r
+           if(g){\r
+               for(var i = 0, len = g.length; i < len; i++){\r
+                   if(g[i].pressed === true){\r
+                       return g[i];\r
+                   }\r
+               }\r
+           }\r
+           return null;\r
+       }\r
+   };\r
+}();\r
+/**\r
  * @class Ext.SplitButton\r
  * @extends Ext.Button\r
  * A split button that provides a built-in dropdown arrow that can fire an event separately from the default\r
@@ -42430,9 +44795,13 @@ Ext.SplitButton = Ext.extend(Ext.Button, {
     },\r
 \r
     isClickOnArrow : function(e){\r
-        return this.arrowAlign != 'bottom' ?\r
-               e.getPageX() > this.el.child(this.buttonSelector).getRegion().right :\r
-               e.getPageY() > this.el.child(this.buttonSelector).getRegion().bottom;\r
+       if (this.arrowAlign != 'bottom') {\r
+           var visBtn = this.el.child('em.x-btn-split');\r
+           var right = visBtn.getRegion().right - visBtn.getPadding('r');\r
+           return e.getPageX() > right;\r
+       } else {\r
+           return e.getPageY() > this.btnEl.getRegion().bottom;\r
+       }\r
     },\r
 \r
     // private\r
@@ -42461,12 +44830,12 @@ Ext.SplitButton = Ext.extend(Ext.Button, {
 \r
     // private\r
     isMenuTriggerOver : function(e){\r
-        return this.menu && e.target.tagName == 'em';\r
+        return this.menu && e.target.tagName == this.arrowSelector;\r
     },\r
 \r
     // private\r
     isMenuTriggerOut : function(e, internal){\r
-        return this.menu && e.target.tagName != 'em';\r
+        return this.menu && e.target.tagName != this.arrowSelector;\r
     }\r
 });\r
 \r
@@ -42563,7 +44932,7 @@ Ext.CycleButton = Ext.extend(Ext.SplitButton, {
             }\r
             this.activeItem = item;\r
             if(!item.checked){\r
-                item.setChecked(true, true);\r
+                item.setChecked(true, false);\r
             }\r
             if(this.forceIcon){\r
                 this.setIconClass(this.forceIcon);\r
@@ -42604,7 +44973,7 @@ Ext.CycleButton = Ext.extend(Ext.SplitButton, {
         this.itemCount = this.items.length;\r
 \r
         this.menu = {cls:'x-cycle-menu', items:[]};\r
-        var checked;\r
+        var checked = 0;\r
         Ext.each(this.items, function(item, i){\r
             Ext.apply(item, {\r
                 group: item.group || this.id,\r
@@ -42615,13 +44984,12 @@ Ext.CycleButton = Ext.extend(Ext.SplitButton, {
             });\r
             this.menu.items.push(item);\r
             if(item.checked){\r
-                checked = item;\r
+                checked = i;\r
             }\r
         }, this);\r
-        this.setActiveItem(checked, true);\r
         Ext.CycleButton.superclass.initComponent.call(this);\r
-\r
         this.on('click', this.toggleSelected, this);\r
+        this.setActiveItem(checked, true);\r
     },\r
 \r
     // private\r
@@ -42657,809 +45025,582 @@ Ext.CycleButton = Ext.extend(Ext.SplitButton, {
         }\r
     }\r
 });\r
-Ext.reg('cycle', Ext.CycleButton);/**\r
- * @class Ext.layout.ToolbarLayout\r
- * @extends Ext.layout.ContainerLayout\r
- * Layout manager implicitly used by Ext.Toolbar.\r
- */\r
-Ext.layout.ToolbarLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
-    monitorResize : true,\r
-    triggerWidth : 18,\r
-    lastOverflow : false,\r
-\r
-    noItemsMenuText : '<div class="x-toolbar-no-items">(None)</div>',\r
-    // private\r
-    onLayout : function(ct, target){\r
-        if(!this.leftTr){\r
-            target.addClass('x-toolbar-layout-ct');\r
-            target.insertHtml('beforeEnd',\r
-                 '<table cellspacing="0" class="x-toolbar-ct"><tbody><tr><td class="x-toolbar-left" align="left"><table cellspacing="0"><tbody><tr class="x-toolbar-left-row"></tr></tbody></table></td><td class="x-toolbar-right" align="right"><table cellspacing="0" class="x-toolbar-right-ct"><tbody><tr><td><table cellspacing="0"><tbody><tr class="x-toolbar-right-row"></tr></tbody></table></td><td><table cellspacing="0"><tbody><tr class="x-toolbar-extras-row"></tr></tbody></table></td></tr></tbody></table></td></tr></tbody></table>');\r
-            this.leftTr = target.child('tr.x-toolbar-left-row', true);\r
-            this.rightTr = target.child('tr.x-toolbar-right-row', true);\r
-            this.extrasTr = target.child('tr.x-toolbar-extras-row', true);\r
-        }\r
-        var side = this.leftTr;\r
-        var pos = 0;\r
-\r
-        var items = ct.items.items;\r
-        for(var i = 0, len = items.length, c; i < len; i++, pos++) {\r
-            c = items[i];\r
-            if(c.isFill){\r
-                side = this.rightTr;\r
-                pos = -1;\r
-            }else if(!c.rendered){\r
-                c.render(this.insertCell(c, side, pos));\r
-            }else{\r
-                if(!c.xtbHidden && !this.isValidParent(c, side.childNodes[pos])){\r
-                    var td = this.insertCell(c, side, pos);\r
-                    td.appendChild(c.getDomPositionEl().dom);\r
-                    c.container = Ext.get(td);\r
-                }\r
-            }\r
-        }\r
-        //strip extra empty cells\r
-        this.cleanup(this.leftTr);\r
-        this.cleanup(this.rightTr);\r
-        this.cleanup(this.extrasTr);\r
-        this.fitToSize(target);\r
-    },\r
-\r
-    cleanup : function(row){\r
-        var cn = row.childNodes;\r
-        for(var i = cn.length-1, c; i >= 0 && (c = cn[i]); i--){\r
-            if(!c.firstChild){\r
-                row.removeChild(c);\r
-            }\r
-        }\r
-    },\r
-\r
-    insertCell : function(c, side, pos){\r
-        var td = document.createElement('td');\r
-        td.className='x-toolbar-cell';\r
-        side.insertBefore(td, side.childNodes[pos]||null);\r
-        return td;\r
-    },\r
-\r
-    hideItem : function(item){\r
-        var h = (this.hiddens = this.hiddens || []);\r
-        h.push(item);\r
-        item.xtbHidden = true;\r
-        item.xtbWidth = item.getDomPositionEl().dom.parentNode.offsetWidth;\r
-        item.hide();\r
-    },\r
-\r
-    unhideItem : function(item){\r
-        item.show();\r
-        item.xtbHidden = false;\r
-        this.hiddens.remove(item);\r
-        if(this.hiddens.length < 1){\r
-            delete this.hiddens;\r
-        }\r
-    },\r
-\r
-    getItemWidth : function(c){\r
-        return c.hidden ? (c.xtbWidth || 0) : c.getDomPositionEl().dom.parentNode.offsetWidth;\r
-    },\r
-\r
-    fitToSize : function(t){\r
-        if(this.container.enableOverflow === false){\r
-            return;\r
-        }\r
-        var w = t.dom.clientWidth;\r
-        var lw = this.lastWidth || 0;\r
-        this.lastWidth = w;\r
-        var iw = t.dom.firstChild.offsetWidth;\r
-\r
-        var clipWidth = w - this.triggerWidth;\r
-        var hideIndex = -1;\r
-\r
-        if(iw > w || (this.hiddens && w >= lw)){\r
-            var i, items = this.container.items.items, len = items.length, c;\r
-            var loopWidth = 0;\r
-            for(i = 0; i < len; i++) {\r
-                c = items[i];\r
-                if(!c.isFill){\r
-                    loopWidth += this.getItemWidth(c);\r
-                    if(loopWidth > clipWidth){\r
-                        if(!c.xtbHidden){\r
-                            this.hideItem(c);\r
-                        }\r
-                    }else{\r
-                        if(c.xtbHidden){\r
-                            this.unhideItem(c);\r
-                        }\r
-                    }\r
-                }\r
-            }\r
-        }\r
-        if(this.hiddens){\r
-            this.initMore();\r
-            if(!this.lastOverflow){\r
-                this.container.fireEvent('overflowchange', this.container, true);\r
-                this.lastOverflow = true;\r
-            }\r
-        }else if(this.more){\r
-            this.clearMenu();\r
-            this.more.destroy();\r
-            delete this.more;\r
-            if(this.lastOverflow){\r
-                this.container.fireEvent('overflowchange', this.container, false);\r
-                this.lastOverflow = false;\r
-            }\r
-        }\r
-    },\r
-\r
-    createMenuConfig : function(c, hideOnClick){\r
-        var cfg = Ext.apply({}, c.initialConfig),\r
-            group = c.toggleGroup;\r
-\r
-        Ext.apply(cfg, {\r
-            text: c.overflowText || c.text,\r
-            iconCls: c.iconCls,\r
-            icon: c.icon,\r
-            itemId: c.itemId,\r
-            disabled: c.disabled,\r
-            handler: c.handler,\r
-            scope: c.scope,\r
-            menu: c.menu,\r
-            hideOnClick: hideOnClick\r
-        });\r
-        if(group || c.enableToggle){\r
-            Ext.apply(cfg, {\r
-                group: group,\r
-                checked: c.pressed,\r
-                listeners: {\r
-                    checkchange: function(item, checked){\r
-                        c.toggle(checked);\r
-                    }\r
-                }\r
-            });\r
-        }\r
-        delete cfg.xtype;\r
-        delete cfg.id;\r
-        return cfg;\r
-    },\r
-\r
-    // private\r
-    addComponentToMenu : function(m, c){\r
-        if(c instanceof Ext.Toolbar.Separator){\r
-            m.add('-');\r
-        }else if(Ext.isFunction(c.isXType)){\r
-            if(c.isXType('splitbutton')){\r
-                m.add(this.createMenuConfig(c, true));\r
-            }else if(c.isXType('button')){\r
-                m.add(this.createMenuConfig(c, !c.menu));\r
-            }else if(c.isXType('buttongroup')){\r
-                c.items.each(function(item){\r
-                     this.addComponentToMenu(m, item);\r
-                }, this);\r
-            }\r
-        }\r
-    },\r
-\r
-    clearMenu : function(){\r
-        var m = this.moreMenu;\r
-        if(m && m.items){\r
-            m.items.each(function(item){\r
-                delete item.menu;\r
-            });\r
-        }\r
-    },\r
-\r
-    // private\r
-    beforeMoreShow : function(m){\r
-        var h = this.container.items.items,\r
-            len = h.length,\r
-            c,\r
-            prev,\r
-            needsSep = function(group, item){\r
-                return group.isXType('buttongroup') && !(item instanceof Ext.Toolbar.Separator);\r
-            };\r
-\r
-        this.clearMenu();\r
-        m.removeAll();\r
-        for(var i = 0; i < len; i++){\r
-            c = h[i];\r
-            if(c.xtbHidden){\r
-                if(prev && (needsSep(c, prev) || needsSep(prev, c))){\r
-                    m.add('-');\r
-                }\r
-                this.addComponentToMenu(m, c);\r
-                prev = c;\r
-            }\r
-        }\r
-        // put something so the menu isn't empty\r
-        // if no compatible items found\r
-        if(m.items.length < 1){\r
-            m.add(this.noItemsMenuText);\r
-        }\r
-    },\r
-\r
-    initMore : function(){\r
-        if(!this.more){\r
-            this.moreMenu = new Ext.menu.Menu({\r
-                listeners: {\r
-                    beforeshow: this.beforeMoreShow,\r
-                    scope: this\r
-                }\r
-            });\r
-            this.moreMenu.ownerCt = this.container;\r
-            this.more = new Ext.Button({\r
-                iconCls: 'x-toolbar-more-icon',\r
-                cls: 'x-toolbar-more',\r
-                menu: this.moreMenu\r
-            });\r
-            var td = this.insertCell(this.more, this.extrasTr, 100);\r
-            this.more.render(td);\r
-        }\r
-    },\r
-\r
-    destroy : function(){\r
-        Ext.destroy(this.more, this.moreMenu);\r
-        Ext.layout.ToolbarLayout.superclass.destroy.call(this);\r
-    }\r
-    /**\r
-     * @property activeItem\r
-     * @hide\r
-     */\r
-});\r
-\r
-Ext.Container.LAYOUTS.toolbar = Ext.layout.ToolbarLayout;\r
-\r
-/**\r
- * @class Ext.Toolbar\r
- * @extends Ext.Container\r
- * <p>Basic Toolbar class. Although the <tt>{@link Ext.Container#defaultType defaultType}</tt> for Toolbar\r
- * is <tt>{@link Ext.Button button}</tt>, Toolbar elements (child items for the Toolbar container) may\r
- * be virtually any type of Component. Toolbar elements can be created explicitly via their constructors,\r
- * or implicitly via their xtypes, and can be <tt>{@link #add}</tt>ed dynamically.</p>\r
- * <p>Some items have shortcut strings for creation:</p>\r
- * <pre>\r
-<u>Shortcut</u>  <u>xtype</u>          <u>Class</u>                  <u>Description</u>\r
-'->'      'tbfill'       {@link Ext.Toolbar.Fill}       begin using the right-justified button container\r
-'-'       'tbseparator'  {@link Ext.Toolbar.Separator}  add a vertical separator bar between toolbar items\r
-' '       'tbspacer'     {@link Ext.Toolbar.Spacer}     add horiztonal space between elements\r
- * </pre>\r
- *\r
- * Example usage of various elements:\r
- * <pre><code>\r
-var tb = new Ext.Toolbar({\r
-    renderTo: document.body,\r
-    width: 600,\r
-    height: 100,\r
-    items: [\r
-        {\r
-            // xtype: 'button', // default for Toolbars, same as 'tbbutton'\r
-            text: 'Button'\r
-        },\r
-        {\r
-            xtype: 'splitbutton', // same as 'tbsplitbutton'\r
-            text: 'Split Button'\r
-        },\r
-        // begin using the right-justified button container\r
-        '->', // same as {xtype: 'tbfill'}, // Ext.Toolbar.Fill\r
-        {\r
-            xtype: 'textfield',\r
-            name: 'field1',\r
-            emptyText: 'enter search term'\r
-        },\r
-        // add a vertical separator bar between toolbar items\r
-        '-', // same as {xtype: 'tbseparator'} to create Ext.Toolbar.Separator\r
-        'text 1', // same as {xtype: 'tbtext', text: 'text1'} to create Ext.Toolbar.TextItem\r
-        {xtype: 'tbspacer'},// same as ' ' to create Ext.Toolbar.Spacer\r
-        'text 2',\r
-        {xtype: 'tbspacer', width: 50}, // add a 50px space\r
-        'text 3'\r
-    ]\r
-});\r
- * </code></pre>\r
- * Example adding a ComboBox within a menu of a button:\r
- * <pre><code>\r
-// ComboBox creation\r
-var combo = new Ext.form.ComboBox({\r
-    store: new Ext.data.ArrayStore({\r
-        autoDestroy: true,\r
-        fields: ['initials', 'fullname'],\r
-        data : [\r
-            ['FF', 'Fred Flintstone'],\r
-            ['BR', 'Barney Rubble']\r
-        ]\r
-    }),\r
-    displayField: 'fullname',\r
-    typeAhead: true,\r
-    mode: 'local',\r
-    forceSelection: true,\r
-    triggerAction: 'all',\r
-    emptyText: 'Select a name...',\r
-    selectOnFocus: true,\r
-    width: 135,\r
-    getListParent: function() {\r
-        return this.el.up('.x-menu');\r
-    },\r
-    iconCls: 'no-icon' //use iconCls if placing within menu to shift to right side of menu\r
-});\r
-\r
-// put ComboBox in a Menu\r
-var menu = new Ext.menu.Menu({\r
-    id: 'mainMenu',\r
-    items: [\r
-        combo // A Field in a Menu\r
-    ]\r
-});\r
-\r
-// add a Button with the menu\r
-tb.add({\r
-        text:'Button w/ Menu',\r
-        menu: menu  // assign menu by instance\r
-    });\r
-tb.doLayout();\r
- * </code></pre>\r
- * @constructor\r
- * Creates a new Toolbar\r
- * @param {Object/Array} config A config object or an array of buttons to <tt>{@link #add}</tt>\r
- * @xtype toolbar\r
- */\r
-Ext.Toolbar = function(config){\r
-    if(Ext.isArray(config)){\r
-        config = {items: config, layout: 'toolbar'};\r
-    } else {\r
-        config = Ext.apply({\r
-            layout: 'toolbar'\r
-        }, config);\r
-        if(config.buttons) {\r
-            config.items = config.buttons;\r
-        }\r
-    }\r
-    Ext.Toolbar.superclass.constructor.call(this, config);\r
-};\r
-\r
-(function(){\r
-\r
-var T = Ext.Toolbar;\r
-\r
-Ext.extend(T, Ext.Container, {\r
-\r
-    defaultType: 'button',\r
-\r
-    /**\r
-     * @cfg {String/Object} layout\r
-     * This class assigns a default layout (<code>layout:'<b>toolbar</b>'</code>).\r
-     * Developers <i>may</i> override this configuration option if another layout\r
-     * is required (the constructor must be passed a configuration object in this\r
-     * case instead of an array).\r
-     * See {@link Ext.Container#layout} for additional information.\r
-     */\r
-\r
-    trackMenus : true,\r
-    internalDefaults: {removeMode: 'container', hideParent: true},\r
-    toolbarCls: 'x-toolbar',\r
-\r
-    initComponent : function(){\r
-        T.superclass.initComponent.call(this);\r
-\r
-        /**\r
-         * @event overflowchange\r
-         * Fires after the overflow state has changed.\r
-         * @param {Object} c The Container\r
-         * @param {Boolean} lastOverflow overflow state\r
-         */\r
-        this.addEvents('overflowchange');\r
-    },\r
-\r
-    // private\r
-    onRender : function(ct, position){\r
-        if(!this.el){\r
-            if(!this.autoCreate){\r
-                this.autoCreate = {\r
-                    cls: this.toolbarCls + ' x-small-editor'\r
-                };\r
-            }\r
-            this.el = ct.createChild(Ext.apply({ id: this.id },this.autoCreate), position);\r
-            Ext.Toolbar.superclass.onRender.apply(this, arguments);\r
-        }\r
-    },\r
-\r
-    /**\r
-     * <p>Adds element(s) to the toolbar -- this function takes a variable number of\r
-     * arguments of mixed type and adds them to the toolbar.</p>\r
-     * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>\r
-     * @param {Mixed} arg1 The following types of arguments are all valid:<br />\r
-     * <ul>\r
-     * <li>{@link Ext.Button} config: A valid button config object (equivalent to {@link #addButton})</li>\r
-     * <li>HtmlElement: Any standard HTML element (equivalent to {@link #addElement})</li>\r
-     * <li>Field: Any form field (equivalent to {@link #addField})</li>\r
-     * <li>Item: Any subclass of {@link Ext.Toolbar.Item} (equivalent to {@link #addItem})</li>\r
-     * <li>String: Any generic string (gets wrapped in a {@link Ext.Toolbar.TextItem}, equivalent to {@link #addText}).\r
-     * Note that there are a few special strings that are treated differently as explained next.</li>\r
-     * <li>'-': Creates a separator element (equivalent to {@link #addSeparator})</li>\r
-     * <li>' ': Creates a spacer element (equivalent to {@link #addSpacer})</li>\r
-     * <li>'->': Creates a fill element (equivalent to {@link #addFill})</li>\r
-     * </ul>\r
-     * @param {Mixed} arg2\r
-     * @param {Mixed} etc.\r
-     * @method add\r
-     */\r
-\r
-    // private\r
-    lookupComponent : function(c){\r
-        if(Ext.isString(c)){\r
-            if(c == '-'){\r
-                c = new T.Separator();\r
-            }else if(c == ' '){\r
-                c = new T.Spacer();\r
-            }else if(c == '->'){\r
-                c = new T.Fill();\r
-            }else{\r
-                c = new T.TextItem(c);\r
-            }\r
-            this.applyDefaults(c);\r
-        }else{\r
-            if(c.isFormField || c.render){ // some kind of form field, some kind of Toolbar.Item\r
-                c = this.constructItem(c);\r
-            }else if(c.tag){ // DomHelper spec\r
-                c = new T.Item({autoEl: c});\r
-            }else if(c.tagName){ // element\r
-                c = new T.Item({el:c});\r
-            }else if(Ext.isObject(c)){ // must be button config?\r
-                c = c.xtype ? this.constructItem(c) : this.constructButton(c);\r
-            }\r
-        }\r
-        return c;\r
-    },\r
-\r
-    // private\r
-    applyDefaults : function(c){\r
-        if(!Ext.isString(c)){\r
-            c = Ext.Toolbar.superclass.applyDefaults.call(this, c);\r
-            var d = this.internalDefaults;\r
-            if(c.events){\r
-                Ext.applyIf(c.initialConfig, d);\r
-                Ext.apply(c, d);\r
-            }else{\r
-                Ext.applyIf(c, d);\r
-            }\r
-        }\r
-        return c;\r
-    },\r
-\r
-    // private\r
-    constructItem : function(item, type){\r
-        return Ext.create(item, type || this.defaultType);\r
-    },\r
-\r
-    /**\r
-     * Adds a separator\r
-     * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>\r
-     * @return {Ext.Toolbar.Item} The separator {@link Ext.Toolbar.Item item}\r
-     */\r
-    addSeparator : function(){\r
-        return this.add(new T.Separator());\r
-    },\r
-\r
-    /**\r
-     * Adds a spacer element\r
-     * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>\r
-     * @return {Ext.Toolbar.Spacer} The spacer item\r
-     */\r
-    addSpacer : function(){\r
-        return this.add(new T.Spacer());\r
-    },\r
-\r
-    /**\r
-     * Forces subsequent additions into the float:right toolbar\r
-     * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>\r
-     */\r
-    addFill : function(){\r
-        this.add(new T.Fill());\r
-    },\r
-\r
-    /**\r
-     * Adds any standard HTML element to the toolbar\r
-     * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>\r
-     * @param {Mixed} el The element or id of the element to add\r
-     * @return {Ext.Toolbar.Item} The element's item\r
-     */\r
-    addElement : function(el){\r
-        return this.addItem(new T.Item({el:el}));\r
-    },\r
-\r
-    /**\r
-     * Adds any Toolbar.Item or subclass\r
-     * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>\r
-     * @param {Ext.Toolbar.Item} item\r
-     * @return {Ext.Toolbar.Item} The item\r
-     */\r
-    addItem : function(item){\r
-        return this.add.apply(this, arguments);\r
-    },\r
-\r
-    /**\r
-     * Adds a button (or buttons). See {@link Ext.Button} for more info on the config.\r
-     * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>\r
-     * @param {Object/Array} config A button config or array of configs\r
-     * @return {Ext.Button/Array}\r
-     */\r
-    addButton : function(config){\r
-        if(Ext.isArray(config)){\r
-            var buttons = [];\r
-            for(var i = 0, len = config.length; i < len; i++) {\r
-                buttons.push(this.addButton(config[i]));\r
-            }\r
-            return buttons;\r
-        }\r
-        return this.add(this.constructButton(config));\r
-    },\r
-\r
-    /**\r
-     * Adds text to the toolbar\r
-     * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>\r
-     * @param {String} text The text to add\r
-     * @return {Ext.Toolbar.Item} The element's item\r
-     */\r
-    addText : function(text){\r
-        return this.addItem(new T.TextItem(text));\r
-    },\r
-\r
-    /**\r
-     * Adds a new element to the toolbar from the passed {@link Ext.DomHelper} config\r
-     * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>\r
-     * @param {Object} config\r
-     * @return {Ext.Toolbar.Item} The element's item\r
-     */\r
-    addDom : function(config){\r
-        return this.add(new T.Item({autoEl: config}));\r
-    },\r
-\r
-    /**\r
-     * Adds a dynamically rendered Ext.form field (TextField, ComboBox, etc). Note: the field should not have\r
-     * been rendered yet. For a field that has already been rendered, use {@link #addElement}.\r
-     * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>\r
-     * @param {Ext.form.Field} field\r
-     * @return {Ext.Toolbar.Item}\r
-     */\r
-    addField : function(field){\r
-        return this.add(field);\r
-    },\r
-\r
-    /**\r
-     * Inserts any {@link Ext.Toolbar.Item}/{@link Ext.Button} at the specified index.\r
-     * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>\r
-     * @param {Number} index The index where the item is to be inserted\r
-     * @param {Object/Ext.Toolbar.Item/Ext.Button/Array} item The button, or button config object to be\r
-     * inserted, or an array of buttons/configs.\r
-     * @return {Ext.Button/Item}\r
-     */\r
-    insertButton : function(index, item){\r
-        if(Ext.isArray(item)){\r
-            var buttons = [];\r
-            for(var i = 0, len = item.length; i < len; i++) {\r
-               buttons.push(this.insertButton(index + i, item[i]));\r
-            }\r
-            return buttons;\r
-        }\r
-        return Ext.Toolbar.superclass.insert.call(this, index, item);\r
-    },\r
-\r
-    // private\r
-    initMenuTracking : function(item){\r
-        if(this.trackMenus && item.menu){\r
-            this.mon(item, {\r
-                'menutriggerover' : this.onButtonTriggerOver,\r
-                'menushow' : this.onButtonMenuShow,\r
-                'menuhide' : this.onButtonMenuHide,\r
-                scope: this\r
-            });\r
-        }\r
-    },\r
-\r
-    // private\r
-    constructButton : function(item){\r
-        var b = item.events ? item : this.constructItem(item, item.split ? 'splitbutton' : this.defaultType);\r
-        this.initMenuTracking(b);\r
-        return b;\r
-    },\r
-\r
-    // private\r
-    onDisable : function(){\r
-        this.items.each(function(item){\r
-             if(item.disable){\r
-                 item.disable();\r
-             }\r
-        });\r
-    },\r
-\r
-    // private\r
-    onEnable : function(){\r
-        this.items.each(function(item){\r
-             if(item.enable){\r
-                 item.enable();\r
-             }\r
-        });\r
-    },\r
-\r
-    // private\r
-    onButtonTriggerOver : function(btn){\r
-        if(this.activeMenuBtn && this.activeMenuBtn != btn){\r
-            this.activeMenuBtn.hideMenu();\r
-            btn.showMenu();\r
-            this.activeMenuBtn = btn;\r
-        }\r
-    },\r
-\r
-    // private\r
-    onButtonMenuShow : function(btn){\r
-        this.activeMenuBtn = btn;\r
-    },\r
-\r
-    // private\r
-    onButtonMenuHide : function(btn){\r
-        delete this.activeMenuBtn;\r
-    }\r
-});\r
-Ext.reg('toolbar', Ext.Toolbar);\r
-\r
-/**\r
- * @class Ext.Toolbar.Item\r
- * @extends Ext.BoxComponent\r
- * The base class that other non-interacting Toolbar Item classes should extend in order to\r
- * get some basic common toolbar item functionality.\r
- * @constructor\r
- * Creates a new Item\r
- * @param {HTMLElement} el\r
- * @xtype tbitem\r
- */\r
-T.Item = Ext.extend(Ext.BoxComponent, {\r
-    hideParent: true, //  Hiding a Toolbar.Item hides its containing TD\r
-    enable:Ext.emptyFn,\r
-    disable:Ext.emptyFn,\r
-    focus:Ext.emptyFn\r
-    /**\r
-     * @cfg {String} overflowText Text to be used for the menu if the item is overflowed.\r
-     */\r
-});\r
-Ext.reg('tbitem', T.Item);\r
-\r
-/**\r
- * @class Ext.Toolbar.Separator\r
- * @extends Ext.Toolbar.Item\r
- * A simple class that adds a vertical separator bar between toolbar items\r
- * (css class:<tt>'xtb-sep'</tt>). Example usage:\r
- * <pre><code>\r
-new Ext.Panel({\r
-    tbar : [\r
-        'Item 1',\r
-        {xtype: 'tbseparator'}, // or '-'\r
-        'Item 2'\r
-    ]\r
-});\r
-</code></pre>\r
- * @constructor\r
- * Creates a new Separator\r
- * @xtype tbseparator\r
- */\r
-T.Separator = Ext.extend(T.Item, {\r
-    onRender : function(ct, position){\r
-        this.el = ct.createChild({tag:'span', cls:'xtb-sep'}, position);\r
-    }\r
-});\r
-Ext.reg('tbseparator', T.Separator);\r
-\r
-/**\r
- * @class Ext.Toolbar.Spacer\r
- * @extends Ext.Toolbar.Item\r
- * A simple element that adds extra horizontal space between items in a toolbar.\r
- * By default a 2px wide space is added via css specification:<pre><code>\r
-.x-toolbar .xtb-spacer {\r
-    width:2px;\r
-}\r
- * </code></pre>\r
- * <p>Example usage:</p>\r
- * <pre><code>\r
-new Ext.Panel({\r
-    tbar : [\r
-        'Item 1',\r
-        {xtype: 'tbspacer'}, // or ' '\r
-        'Item 2',\r
-        // space width is also configurable via javascript\r
-        {xtype: 'tbspacer', width: 50}, // add a 50px space\r
-        'Item 3'\r
-    ]\r
-});\r
-</code></pre>\r
- * @constructor\r
- * Creates a new Spacer\r
- * @xtype tbspacer\r
- */\r
-T.Spacer = Ext.extend(T.Item, {\r
-    /**\r
-     * @cfg {Number} width\r
-     * The width of the spacer in pixels (defaults to 2px via css style <tt>.x-toolbar .xtb-spacer</tt>).\r
-     */\r
-\r
-    onRender : function(ct, position){\r
-        this.el = ct.createChild({tag:'div', cls:'xtb-spacer', style: this.width?'width:'+this.width+'px':''}, position);\r
-    }\r
-});\r
-Ext.reg('tbspacer', T.Spacer);\r
-\r
-/**\r
- * @class Ext.Toolbar.Fill\r
- * @extends Ext.Toolbar.Spacer\r
- * A non-rendering placeholder item which instructs the Toolbar's Layout to begin using\r
- * the right-justified button container.\r
- * <pre><code>\r
-new Ext.Panel({\r
-    tbar : [\r
-        'Item 1',\r
-        {xtype: 'tbfill'}, // or '->'\r
-        'Item 2'\r
-    ]\r
-});\r
-</code></pre>\r
- * @constructor\r
- * Creates a new Fill\r
- * @xtype tbfill\r
- */\r
-T.Fill = Ext.extend(T.Item, {\r
-    // private\r
-    render : Ext.emptyFn,\r
-    isFill : true\r
-});\r
-Ext.reg('tbfill', T.Fill);\r
-\r
-/**\r
- * @class Ext.Toolbar.TextItem\r
- * @extends Ext.Toolbar.Item\r
- * A simple class that renders text directly into a toolbar\r
- * (with css class:<tt>'xtb-text'</tt>). Example usage:\r
- * <pre><code>\r
-new Ext.Panel({\r
-    tbar : [\r
-        {xtype: 'tbtext', text: 'Item 1'} // or simply 'Item 1'\r
-    ]\r
-});\r
-</code></pre>\r
- * @constructor\r
- * Creates a new TextItem\r
- * @param {String/Object} text A text string, or a config object containing a <tt>text</tt> property\r
- * @xtype tbtext\r
- */\r
-T.TextItem = Ext.extend(T.Item, {\r
-    /**\r
-     * @cfg {String} text The text to be used as innerHTML (html tags are accepted)\r
-     */ \r
-\r
-    constructor: function(config){\r
-        T.TextItem.superclass.constructor.call(this, Ext.isString(config) ? {text: config} : config);\r
-    },\r
-    \r
-    // private\r
-    onRender : function(ct, position) {\r
-        this.autoEl = {cls: 'xtb-text', html: this.text || ''};\r
-        T.TextItem.superclass.onRender.call(this, ct, position);\r
-    },\r
-    \r
-    /**\r
-     * Updates this item's text, setting the text to be used as innerHTML.\r
-     * @param {String} t The text to display (html accepted).\r
-     */\r
-    setText : function(t) {\r
-        if(this.rendered){\r
-            this.el.update(t);\r
-        }else{\r
-            this.text = t;\r
-        }\r
-    }\r
-});\r
-Ext.reg('tbtext', T.TextItem);\r
-\r
-// backwards compat\r
-T.Button = Ext.extend(Ext.Button, {});\r
-T.SplitButton = Ext.extend(Ext.SplitButton, {});\r
-Ext.reg('tbbutton', T.Button);\r
-Ext.reg('tbsplit', T.SplitButton);\r
-\r
-})();\r
+Ext.reg('cycle', Ext.CycleButton);/**
+ * @class Ext.Toolbar
+ * @extends Ext.Container
+ * <p>Basic Toolbar class. Although the <tt>{@link Ext.Container#defaultType defaultType}</tt> for Toolbar
+ * is <tt>{@link Ext.Button button}</tt>, Toolbar elements (child items for the Toolbar container) may
+ * be virtually any type of Component. Toolbar elements can be created explicitly via their constructors,
+ * or implicitly via their xtypes, and can be <tt>{@link #add}</tt>ed dynamically.</p>
+ * <p>Some items have shortcut strings for creation:</p>
+ * <pre>
+<u>Shortcut</u>  <u>xtype</u>          <u>Class</u>                  <u>Description</u>
+'->'      'tbfill'       {@link Ext.Toolbar.Fill}       begin using the right-justified button container
+'-'       'tbseparator'  {@link Ext.Toolbar.Separator}  add a vertical separator bar between toolbar items
+' '       'tbspacer'     {@link Ext.Toolbar.Spacer}     add horiztonal space between elements
+ * </pre>
+ *
+ * Example usage of various elements:
+ * <pre><code>
+var tb = new Ext.Toolbar({
+    renderTo: document.body,
+    width: 600,
+    height: 100,
+    items: [
+        {
+            // xtype: 'button', // default for Toolbars, same as 'tbbutton'
+            text: 'Button'
+        },
+        {
+            xtype: 'splitbutton', // same as 'tbsplitbutton'
+            text: 'Split Button'
+        },
+        // begin using the right-justified button container
+        '->', // same as {xtype: 'tbfill'}, // Ext.Toolbar.Fill
+        {
+            xtype: 'textfield',
+            name: 'field1',
+            emptyText: 'enter search term'
+        },
+        // add a vertical separator bar between toolbar items
+        '-', // same as {xtype: 'tbseparator'} to create Ext.Toolbar.Separator
+        'text 1', // same as {xtype: 'tbtext', text: 'text1'} to create Ext.Toolbar.TextItem
+        {xtype: 'tbspacer'},// same as ' ' to create Ext.Toolbar.Spacer
+        'text 2',
+        {xtype: 'tbspacer', width: 50}, // add a 50px space
+        'text 3'
+    ]
+});
+ * </code></pre>
+ * Example adding a ComboBox within a menu of a button:
+ * <pre><code>
+// ComboBox creation
+var combo = new Ext.form.ComboBox({
+    store: new Ext.data.ArrayStore({
+        autoDestroy: true,
+        fields: ['initials', 'fullname'],
+        data : [
+            ['FF', 'Fred Flintstone'],
+            ['BR', 'Barney Rubble']
+        ]
+    }),
+    displayField: 'fullname',
+    typeAhead: true,
+    mode: 'local',
+    forceSelection: true,
+    triggerAction: 'all',
+    emptyText: 'Select a name...',
+    selectOnFocus: true,
+    width: 135,
+    getListParent: function() {
+        return this.el.up('.x-menu');
+    },
+    iconCls: 'no-icon' //use iconCls if placing within menu to shift to right side of menu
+});
+
+// put ComboBox in a Menu
+var menu = new Ext.menu.Menu({
+    id: 'mainMenu',
+    items: [
+        combo // A Field in a Menu
+    ]
+});
+
+// add a Button with the menu
+tb.add({
+        text:'Button w/ Menu',
+        menu: menu  // assign menu by instance
+    });
+tb.doLayout();
+ * </code></pre>
+ * @constructor
+ * Creates a new Toolbar
+ * @param {Object/Array} config A config object or an array of buttons to <tt>{@link #add}</tt>
+ * @xtype toolbar
+ */
+Ext.Toolbar = function(config){
+    if(Ext.isArray(config)){
+        config = {items: config, layout: 'toolbar'};
+    } else {
+        config = Ext.apply({
+            layout: 'toolbar'
+        }, config);
+        if(config.buttons) {
+            config.items = config.buttons;
+        }
+    }
+    Ext.Toolbar.superclass.constructor.call(this, config);
+};
+
+(function(){
+
+var T = Ext.Toolbar;
+
+Ext.extend(T, Ext.Container, {
+
+    defaultType: 'button',
+
+    /**
+     * @cfg {String/Object} layout
+     * This class assigns a default layout (<code>layout:'<b>toolbar</b>'</code>).
+     * Developers <i>may</i> override this configuration option if another layout
+     * is required (the constructor must be passed a configuration object in this
+     * case instead of an array).
+     * See {@link Ext.Container#layout} for additional information.
+     */
+
+    enableOverflow : false,
+
+    /**
+     * @cfg {Boolean} enableOverflow
+     * Defaults to false. Configure <code>true<code> to make the toolbar provide a button
+     * which activates a dropdown Menu to show items which overflow the Toolbar's width.
+     */
+    /**
+     * @cfg {String} buttonAlign
+     * <p>The default position at which to align child items. Defaults to <code>"left"</code></p>
+     * <p>May be specified as <code>"center"</code> to cause items added before a Fill (A <code>"->"</code>) item
+     * to be centered in the Toolbar. Items added after a Fill are still right-aligned.</p>
+     * <p>Specify as <code>"right"</code> to right align all child items.</p>
+     */
+
+    trackMenus : true,
+    internalDefaults: {removeMode: 'container', hideParent: true},
+    toolbarCls: 'x-toolbar',
+
+    initComponent : function(){
+        T.superclass.initComponent.call(this);
+
+        /**
+         * @event overflowchange
+         * Fires after the overflow state has changed.
+         * @param {Object} c The Container
+         * @param {Boolean} lastOverflow overflow state
+         */
+        this.addEvents('overflowchange');
+    },
+
+    // private
+    onRender : function(ct, position){
+        if(!this.el){
+            if(!this.autoCreate){
+                this.autoCreate = {
+                    cls: this.toolbarCls + ' x-small-editor'
+                };
+            }
+            this.el = ct.createChild(Ext.apply({ id: this.id },this.autoCreate), position);
+            Ext.Toolbar.superclass.onRender.apply(this, arguments);
+        }
+    },
+
+    /**
+     * <p>Adds element(s) to the toolbar -- this function takes a variable number of
+     * arguments of mixed type and adds them to the toolbar.</p>
+     * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>
+     * @param {Mixed} arg1 The following types of arguments are all valid:<br />
+     * <ul>
+     * <li>{@link Ext.Button} config: A valid button config object (equivalent to {@link #addButton})</li>
+     * <li>HtmlElement: Any standard HTML element (equivalent to {@link #addElement})</li>
+     * <li>Field: Any form field (equivalent to {@link #addField})</li>
+     * <li>Item: Any subclass of {@link Ext.Toolbar.Item} (equivalent to {@link #addItem})</li>
+     * <li>String: Any generic string (gets wrapped in a {@link Ext.Toolbar.TextItem}, equivalent to {@link #addText}).
+     * Note that there are a few special strings that are treated differently as explained next.</li>
+     * <li>'-': Creates a separator element (equivalent to {@link #addSeparator})</li>
+     * <li>' ': Creates a spacer element (equivalent to {@link #addSpacer})</li>
+     * <li>'->': Creates a fill element (equivalent to {@link #addFill})</li>
+     * </ul>
+     * @param {Mixed} arg2
+     * @param {Mixed} etc.
+     * @method add
+     */
+
+    // private
+    lookupComponent : function(c){
+        if(Ext.isString(c)){
+            if(c == '-'){
+                c = new T.Separator();
+            }else if(c == ' '){
+                c = new T.Spacer();
+            }else if(c == '->'){
+                c = new T.Fill();
+            }else{
+                c = new T.TextItem(c);
+            }
+            this.applyDefaults(c);
+        }else{
+            if(c.isFormField || c.render){ // some kind of form field, some kind of Toolbar.Item
+                c = this.createComponent(c);
+            }else if(c.tag){ // DomHelper spec
+                c = new T.Item({autoEl: c});
+            }else if(c.tagName){ // element
+                c = new T.Item({el:c});
+            }else if(Ext.isObject(c)){ // must be button config?
+                c = c.xtype ? this.createComponent(c) : this.constructButton(c);
+            }
+        }
+        return c;
+    },
+
+    // private
+    applyDefaults : function(c){
+        if(!Ext.isString(c)){
+            c = Ext.Toolbar.superclass.applyDefaults.call(this, c);
+            var d = this.internalDefaults;
+            if(c.events){
+                Ext.applyIf(c.initialConfig, d);
+                Ext.apply(c, d);
+            }else{
+                Ext.applyIf(c, d);
+            }
+        }
+        return c;
+    },
+
+    /**
+     * Adds a separator
+     * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>
+     * @return {Ext.Toolbar.Item} The separator {@link Ext.Toolbar.Item item}
+     */
+    addSeparator : function(){
+        return this.add(new T.Separator());
+    },
+
+    /**
+     * Adds a spacer element
+     * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>
+     * @return {Ext.Toolbar.Spacer} The spacer item
+     */
+    addSpacer : function(){
+        return this.add(new T.Spacer());
+    },
+
+    /**
+     * Forces subsequent additions into the float:right toolbar
+     * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>
+     */
+    addFill : function(){
+        this.add(new T.Fill());
+    },
+
+    /**
+     * Adds any standard HTML element to the toolbar
+     * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>
+     * @param {Mixed} el The element or id of the element to add
+     * @return {Ext.Toolbar.Item} The element's item
+     */
+    addElement : function(el){
+        return this.addItem(new T.Item({el:el}));
+    },
+
+    /**
+     * Adds any Toolbar.Item or subclass
+     * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>
+     * @param {Ext.Toolbar.Item} item
+     * @return {Ext.Toolbar.Item} The item
+     */
+    addItem : function(item){
+        return this.add.apply(this, arguments);
+    },
+
+    /**
+     * Adds a button (or buttons). See {@link Ext.Button} for more info on the config.
+     * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>
+     * @param {Object/Array} config A button config or array of configs
+     * @return {Ext.Button/Array}
+     */
+    addButton : function(config){
+        if(Ext.isArray(config)){
+            var buttons = [];
+            for(var i = 0, len = config.length; i < len; i++) {
+                buttons.push(this.addButton(config[i]));
+            }
+            return buttons;
+        }
+        return this.add(this.constructButton(config));
+    },
+
+    /**
+     * Adds text to the toolbar
+     * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>
+     * @param {String} text The text to add
+     * @return {Ext.Toolbar.Item} The element's item
+     */
+    addText : function(text){
+        return this.addItem(new T.TextItem(text));
+    },
+
+    /**
+     * Adds a new element to the toolbar from the passed {@link Ext.DomHelper} config
+     * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>
+     * @param {Object} config
+     * @return {Ext.Toolbar.Item} The element's item
+     */
+    addDom : function(config){
+        return this.add(new T.Item({autoEl: config}));
+    },
+
+    /**
+     * Adds a dynamically rendered Ext.form field (TextField, ComboBox, etc). Note: the field should not have
+     * been rendered yet. For a field that has already been rendered, use {@link #addElement}.
+     * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>
+     * @param {Ext.form.Field} field
+     * @return {Ext.Toolbar.Item}
+     */
+    addField : function(field){
+        return this.add(field);
+    },
+
+    /**
+     * Inserts any {@link Ext.Toolbar.Item}/{@link Ext.Button} at the specified index.
+     * <br><p><b>Note</b>: See the notes within {@link Ext.Container#add}.</p>
+     * @param {Number} index The index where the item is to be inserted
+     * @param {Object/Ext.Toolbar.Item/Ext.Button/Array} item The button, or button config object to be
+     * inserted, or an array of buttons/configs.
+     * @return {Ext.Button/Item}
+     */
+    insertButton : function(index, item){
+        if(Ext.isArray(item)){
+            var buttons = [];
+            for(var i = 0, len = item.length; i < len; i++) {
+               buttons.push(this.insertButton(index + i, item[i]));
+            }
+            return buttons;
+        }
+        return Ext.Toolbar.superclass.insert.call(this, index, item);
+    },
+
+    // private
+    trackMenu : function(item, remove){
+        if(this.trackMenus && item.menu){
+            var method = remove ? 'mun' : 'mon';
+            this[method](item, 'menutriggerover', this.onButtonTriggerOver, this);
+            this[method](item, 'menushow', this.onButtonMenuShow, this);
+            this[method](item, 'menuhide', this.onButtonMenuHide, this);
+        }
+    },
+
+    // private
+    constructButton : function(item){
+        var b = item.events ? item : this.createComponent(item, item.split ? 'splitbutton' : this.defaultType);
+        return b;
+    },
+
+    // private
+    onAdd : function(c){
+        Ext.Toolbar.superclass.onAdd.call(this);
+        this.trackMenu(c);
+        if(this.disabled){
+            c.disable();
+        }
+    },
+
+    // private
+    onRemove : function(c){
+        Ext.Toolbar.superclass.onRemove.call(this);
+        this.trackMenu(c, true);
+    },
+
+    // private
+    onDisable : function(){
+        this.items.each(function(item){
+             if(item.disable){
+                 item.disable();
+             }
+        });
+    },
+
+    // private
+    onEnable : function(){
+        this.items.each(function(item){
+             if(item.enable){
+                 item.enable();
+             }
+        });
+    },
+
+    // private
+    onButtonTriggerOver : function(btn){
+        if(this.activeMenuBtn && this.activeMenuBtn != btn){
+            this.activeMenuBtn.hideMenu();
+            btn.showMenu();
+            this.activeMenuBtn = btn;
+        }
+    },
+
+    // private
+    onButtonMenuShow : function(btn){
+        this.activeMenuBtn = btn;
+    },
+
+    // private
+    onButtonMenuHide : function(btn){
+        delete this.activeMenuBtn;
+    }
+});
+Ext.reg('toolbar', Ext.Toolbar);
+
+/**
+ * @class Ext.Toolbar.Item
+ * @extends Ext.BoxComponent
+ * The base class that other non-interacting Toolbar Item classes should extend in order to
+ * get some basic common toolbar item functionality.
+ * @constructor
+ * Creates a new Item
+ * @param {HTMLElement} el
+ * @xtype tbitem
+ */
+T.Item = Ext.extend(Ext.BoxComponent, {
+    hideParent: true, //  Hiding a Toolbar.Item hides its containing TD
+    enable:Ext.emptyFn,
+    disable:Ext.emptyFn,
+    focus:Ext.emptyFn
+    /**
+     * @cfg {String} overflowText Text to be used for the menu if the item is overflowed.
+     */
+});
+Ext.reg('tbitem', T.Item);
+
+/**
+ * @class Ext.Toolbar.Separator
+ * @extends Ext.Toolbar.Item
+ * A simple class that adds a vertical separator bar between toolbar items
+ * (css class:<tt>'xtb-sep'</tt>). Example usage:
+ * <pre><code>
+new Ext.Panel({
+    tbar : [
+        'Item 1',
+        {xtype: 'tbseparator'}, // or '-'
+        'Item 2'
+    ]
+});
+</code></pre>
+ * @constructor
+ * Creates a new Separator
+ * @xtype tbseparator
+ */
+T.Separator = Ext.extend(T.Item, {
+    onRender : function(ct, position){
+        this.el = ct.createChild({tag:'span', cls:'xtb-sep'}, position);
+    }
+});
+Ext.reg('tbseparator', T.Separator);
+
+/**
+ * @class Ext.Toolbar.Spacer
+ * @extends Ext.Toolbar.Item
+ * A simple element that adds extra horizontal space between items in a toolbar.
+ * By default a 2px wide space is added via css specification:<pre><code>
+.x-toolbar .xtb-spacer {
+    width:2px;
+}
+ * </code></pre>
+ * <p>Example usage:</p>
+ * <pre><code>
+new Ext.Panel({
+    tbar : [
+        'Item 1',
+        {xtype: 'tbspacer'}, // or ' '
+        'Item 2',
+        // space width is also configurable via javascript
+        {xtype: 'tbspacer', width: 50}, // add a 50px space
+        'Item 3'
+    ]
+});
+</code></pre>
+ * @constructor
+ * Creates a new Spacer
+ * @xtype tbspacer
+ */
+T.Spacer = Ext.extend(T.Item, {
+    /**
+     * @cfg {Number} width
+     * The width of the spacer in pixels (defaults to 2px via css style <tt>.x-toolbar .xtb-spacer</tt>).
+     */
+
+    onRender : function(ct, position){
+        this.el = ct.createChild({tag:'div', cls:'xtb-spacer', style: this.width?'width:'+this.width+'px':''}, position);
+    }
+});
+Ext.reg('tbspacer', T.Spacer);
+
+/**
+ * @class Ext.Toolbar.Fill
+ * @extends Ext.Toolbar.Spacer
+ * A non-rendering placeholder item which instructs the Toolbar's Layout to begin using
+ * the right-justified button container.
+ * <pre><code>
+new Ext.Panel({
+    tbar : [
+        'Item 1',
+        {xtype: 'tbfill'}, // or '->'
+        'Item 2'
+    ]
+});
+</code></pre>
+ * @constructor
+ * Creates a new Fill
+ * @xtype tbfill
+ */
+T.Fill = Ext.extend(T.Item, {
+    // private
+    render : Ext.emptyFn,
+    isFill : true
+});
+Ext.reg('tbfill', T.Fill);
+
+/**
+ * @class Ext.Toolbar.TextItem
+ * @extends Ext.Toolbar.Item
+ * A simple class that renders text directly into a toolbar
+ * (with css class:<tt>'xtb-text'</tt>). Example usage:
+ * <pre><code>
+new Ext.Panel({
+    tbar : [
+        {xtype: 'tbtext', text: 'Item 1'} // or simply 'Item 1'
+    ]
+});
+</code></pre>
+ * @constructor
+ * Creates a new TextItem
+ * @param {String/Object} text A text string, or a config object containing a <tt>text</tt> property
+ * @xtype tbtext
+ */
+T.TextItem = Ext.extend(T.Item, {
+    /**
+     * @cfg {String} text The text to be used as innerHTML (html tags are accepted)
+     */
+
+    constructor: function(config){
+        T.TextItem.superclass.constructor.call(this, Ext.isString(config) ? {text: config} : config);
+    },
+
+    // private
+    onRender : function(ct, position) {
+        this.autoEl = {cls: 'xtb-text', html: this.text || ''};
+        T.TextItem.superclass.onRender.call(this, ct, position);
+    },
+
+    /**
+     * Updates this item's text, setting the text to be used as innerHTML.
+     * @param {String} t The text to display (html accepted).
+     */
+    setText : function(t) {
+        if(this.rendered){
+            this.el.update(t);
+        }else{
+            this.text = t;
+        }
+    }
+});
+Ext.reg('tbtext', T.TextItem);
+
+// backwards compat
+T.Button = Ext.extend(Ext.Button, {});
+T.SplitButton = Ext.extend(Ext.SplitButton, {});
+Ext.reg('tbbutton', T.Button);
+Ext.reg('tbsplit', T.SplitButton);
+
+})();
 /**\r
  * @class Ext.ButtonGroup\r
  * @extends Ext.Panel\r
@@ -43500,6 +45641,9 @@ var p = new Ext.Panel({
     }]\r
 });\r
  * </code></pre>\r
+ * @constructor\r
+ * Create a new ButtonGroup.\r
+ * @param {Object} config The config object\r
  * @xtype buttongroup\r
  */\r
 Ext.ButtonGroup = Ext.extend(Ext.Panel, {\r
@@ -43772,6 +45916,7 @@ Ext.PagingToolbar = Ext.extend(Ext.Toolbar, {
             allowNegative: false,
             enableKeyEvents: true,
             selectOnFocus: true,
+            submitValue: false,
             listeners: {
                 scope: this,
                 keydown: this.onPagingKeyDown,
@@ -43972,12 +46117,6 @@ Ext.PagingToolbar = Ext.extend(Ext.Toolbar, {
         return this.paramNames || this.store.paramNames;
     },
 
-    // private
-    getParams : function(){
-        //retain backwards compat, allow params on the toolbar itself, if they exist.
-        return this.paramNames || this.store.paramNames;
-    },
-
     // private
     beforeLoad : function(){
         if(this.rendered && this.refresh){
@@ -44121,7 +46260,7 @@ Ext.History = (function () {
     }\r
 \r
     function updateIFrame (token) {\r
-        var html = ['<html><body><div id="state">',token,'</div></body></html>'].join('');\r
+        var html = ['<html><body><div id="state">',Ext.util.Format.htmlEncode(token),'</div></body></html>'].join('');\r
         try {\r
             var doc = iframe.contentWindow.document;\r
             doc.open();\r
@@ -44205,14 +46344,14 @@ Ext.History = (function () {
          * @property\r
          */\r
         iframeId: 'x-history-frame',\r
-        \r
+\r
         events:{},\r
 \r
         /**\r
          * Initialize the global History instance.\r
          * @param {Boolean} onReady (optional) A callback function that will be called once the history\r
          * component is fully initialized.\r
-         * @param {Object} scope (optional) The callback scope\r
+         * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the callback is executed. Defaults to the browser window.\r
          */\r
         init: function (onReady, scope) {\r
             if(ready) {\r
@@ -44229,7 +46368,20 @@ Ext.History = (function () {
             if (Ext.isIE) {\r
                 iframe = Ext.getDom(Ext.History.iframeId);\r
             }\r
-            this.addEvents('ready', 'change');\r
+            this.addEvents(\r
+                /**\r
+                 * @event ready\r
+                 * Fires when the Ext.History singleton has been initialized and is ready for use.\r
+                 * @param {Ext.History} The Ext.History singleton.\r
+                 */\r
+                'ready',\r
+                /**\r
+                 * @event change\r
+                 * Fires when navigation back or forwards within the local page's history occurs.\r
+                 * @param {String} token An identifier associated with the page state at that point in its history.\r
+                 */\r
+                'change'\r
+            );\r
             if(onReady){\r
                 this.on('ready', onReady, scope, {single:true});\r
             }\r
@@ -44378,12 +46530,13 @@ tip.showAt([50,100]);
     },\r
 \r
     // protected\r
-    doAutoWidth : function(){\r
+    doAutoWidth : function(adjust){\r
+        adjust = adjust || 0;\r
         var bw = this.body.getTextWidth();\r
         if(this.title){\r
             bw = Math.max(bw, this.header.child('span').getTextWidth(this.title));\r
         }\r
-        bw += this.getFrameWidth() + (this.closable ? 20 : 0) + this.body.getPadding("lr");\r
+        bw += this.getFrameWidth() + (this.closable ? 20 : 0) + this.body.getPadding("lr") + adjust;\r
         this.setWidth(bw.constrain(this.minWidth, this.maxWidth));\r
         \r
         // IE7 repaint bug on initial show\r
@@ -44626,18 +46779,17 @@ myGrid.on('render', function(grid) {
         }\r
         if(this.anchor){\r
             this.targetCounter++;\r
-            var offsets = this.getOffsets();\r
-            var xy = (this.anchorToTarget && !this.trackMouse) ?\r
-                this.el.getAlignToXY(this.anchorTarget, this.getAnchorAlign()) :\r
-                this.targetXY;\r
-\r
-            var dw = Ext.lib.Dom.getViewWidth()-5;\r
-            var dh = Ext.lib.Dom.getViewHeight()-5;\r
-            var scrollX = (document.documentElement.scrollLeft || document.body.scrollLeft || 0)+5;\r
-            var scrollY = (document.documentElement.scrollTop || document.body.scrollTop || 0)+5;\r
-\r
-            var axy = [xy[0] + offsets[0], xy[1] + offsets[1]];\r
-            var sz = this.getSize();\r
+            var offsets = this.getOffsets(),\r
+                xy = (this.anchorToTarget && !this.trackMouse) ? this.el.getAlignToXY(this.anchorTarget, this.getAnchorAlign()) : this.targetXY,\r
+                dw = Ext.lib.Dom.getViewWidth() - 5,\r
+                dh = Ext.lib.Dom.getViewHeight() - 5,\r
+                de = document.documentElement,\r
+                bd = document.body,\r
+                scrollX = (de.scrollLeft || bd.scrollLeft || 0) + 5,\r
+                scrollY = (de.scrollTop || bd.scrollTop || 0) + 5,\r
+                axy = [xy[0] + offsets[0], xy[1] + offsets[1]],\r
+                sz = this.getSize();\r
+                \r
             this.anchorEl.removeClass(this.anchorCls);\r
 \r
             if(this.targetCounter < 2){\r
@@ -44726,7 +46878,8 @@ myGrid.on('render', function(grid) {
 \r
     // private\r
     getOffsets : function(){\r
-        var offsets, ap = this.getAnchorPosition().charAt(0);\r
+        var offsets, \r
+            ap = this.getAnchorPosition().charAt(0);\r
         if(this.anchorToTarget && !this.trackMouse){\r
             switch(ap){\r
                 case 't':\r
@@ -44946,6 +47099,16 @@ myGrid.on('render', function(grid) {
         }\r
         return {x : x, y: y};\r
     },\r
+    \r
+    beforeDestroy : function(){\r
+        this.clearTimers();\r
+        Ext.destroy(this.anchorEl);\r
+        delete this.anchorEl;\r
+        delete this.target;\r
+        delete this.anchorTarget;\r
+        delete this.triggerElement;\r
+        Ext.ToolTip.superclass.beforeDestroy.call(this);    \r
+    },\r
 \r
     // private\r
     onDestroy : function(){\r
@@ -45046,13 +47209,12 @@ Ext.QuickTip = Ext.extend(Ext.ToolTip, {
             this.clearTimer('show');\r
         }\r
     },\r
-\r
-    // private\r
+    \r
     getTipCfg: function(e) {\r
         var t = e.getTarget(), \r
             ttp, \r
             cfg;\r
-        if(this.interceptTitles && t.title){\r
+        if(this.interceptTitles && t.title && Ext.isString(t.title)){\r
             ttp = t.title;\r
             t.qtip = ttp;\r
             t.removeAttribute("title");\r
@@ -45435,18 +47597,19 @@ new Ext.Viewport({
  */\r
 Ext.tree.TreePanel = Ext.extend(Ext.Panel, {\r
     rootVisible : true,\r
-    animate: Ext.enableFx,\r
+    animate : Ext.enableFx,\r
     lines : true,\r
     enableDD : false,\r
     hlDrop : Ext.enableFx,\r
-    pathSeparator: "/",\r
-    \r
+    pathSeparator : '/',\r
+\r
     /**\r
      * @cfg {Array} bubbleEvents\r
      * <p>An array of events that, when fired, should be bubbled to any parent container.\r
-     * Defaults to <tt>['add', 'remove']</tt>.\r
+     * See {@link Ext.util.Observable#enableBubble}.\r
+     * Defaults to <tt>[]</tt>.\r
      */\r
-    bubbleEvents: [],\r
+    bubbleEvents : [],\r
 \r
     initComponent : function(){\r
         Ext.tree.TreePanel.superclass.initComponent.call(this);\r
@@ -45462,7 +47625,7 @@ Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
                 dataUrl: this.dataUrl,\r
                 requestMethod: this.requestMethod\r
             });\r
-        }else if(typeof l == 'object' && !l.load){\r
+        }else if(Ext.isObject(l) && !l.load){\r
             l = new Ext.tree.TreeLoader(l);\r
         }\r
         this.loader = l;\r
@@ -45491,7 +47654,7 @@ Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
             * @param {Node} node The newly appended node\r
             * @param {Number} index The index of the newly appended node\r
             */\r
-           "append",\r
+           'append',\r
            /**\r
             * @event remove\r
             * Fires when a child node is removed from a node in this tree.\r
@@ -45499,7 +47662,7 @@ Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
             * @param {Node} parent The parent node\r
             * @param {Node} node The child node removed\r
             */\r
-           "remove",\r
+           'remove',\r
            /**\r
             * @event movenode\r
             * Fires when a node is moved to a new location in the tree\r
@@ -45509,7 +47672,7 @@ Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
             * @param {Node} newParent The new parent of this node\r
             * @param {Number} index The index it was moved to\r
             */\r
-           "movenode",\r
+           'movenode',\r
            /**\r
             * @event insert\r
             * Fires when a new child node is inserted in a node in this tree.\r
@@ -45518,7 +47681,7 @@ Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
             * @param {Node} node The child node inserted\r
             * @param {Node} refNode The child node the node was inserted before\r
             */\r
-           "insert",\r
+           'insert',\r
            /**\r
             * @event beforeappend\r
             * Fires before a new child is appended to a node in this tree, return false to cancel the append.\r
@@ -45526,7 +47689,7 @@ Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
             * @param {Node} parent The parent node\r
             * @param {Node} node The child node to be appended\r
             */\r
-           "beforeappend",\r
+           'beforeappend',\r
            /**\r
             * @event beforeremove\r
             * Fires before a child is removed from a node in this tree, return false to cancel the remove.\r
@@ -45534,7 +47697,7 @@ Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
             * @param {Node} parent The parent node\r
             * @param {Node} node The child node to be removed\r
             */\r
-           "beforeremove",\r
+           'beforeremove',\r
            /**\r
             * @event beforemovenode\r
             * Fires before a node is moved to a new location in the tree. Return false to cancel the move.\r
@@ -45544,7 +47707,7 @@ Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
             * @param {Node} newParent The new parent the node is moving to\r
             * @param {Number} index The index it is being moved to\r
             */\r
-           "beforemovenode",\r
+           'beforemovenode',\r
            /**\r
             * @event beforeinsert\r
             * Fires before a new child is inserted in a node in this tree, return false to cancel the insert.\r
@@ -45553,20 +47716,20 @@ Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
             * @param {Node} node The child node to be inserted\r
             * @param {Node} refNode The child node the node is being inserted before\r
             */\r
-            "beforeinsert",\r
+            'beforeinsert',\r
 \r
             /**\r
             * @event beforeload\r
             * Fires before a node is loaded, return false to cancel\r
             * @param {Node} node The node being loaded\r
             */\r
-            "beforeload",\r
+            'beforeload',\r
             /**\r
             * @event load\r
             * Fires when a node is loaded\r
             * @param {Node} node The node that was loaded\r
             */\r
-            "load",\r
+            'load',\r
             /**\r
             * @event textchange\r
             * Fires when the text for a node is changed\r
@@ -45574,7 +47737,7 @@ Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
             * @param {String} text The new text\r
             * @param {String} oldText The old text\r
             */\r
-            "textchange",\r
+            'textchange',\r
             /**\r
             * @event beforeexpandnode\r
             * Fires before a node is expanded, return false to cancel.\r
@@ -45582,7 +47745,7 @@ Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
             * @param {Boolean} deep\r
             * @param {Boolean} anim\r
             */\r
-            "beforeexpandnode",\r
+            'beforeexpandnode',\r
             /**\r
             * @event beforecollapsenode\r
             * Fires before a node is collapsed, return false to cancel.\r
@@ -45590,61 +47753,75 @@ Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
             * @param {Boolean} deep\r
             * @param {Boolean} anim\r
             */\r
-            "beforecollapsenode",\r
+            'beforecollapsenode',\r
             /**\r
             * @event expandnode\r
             * Fires when a node is expanded\r
             * @param {Node} node The node\r
             */\r
-            "expandnode",\r
+            'expandnode',\r
             /**\r
             * @event disabledchange\r
             * Fires when the disabled status of a node changes\r
             * @param {Node} node The node\r
             * @param {Boolean} disabled\r
             */\r
-            "disabledchange",\r
+            'disabledchange',\r
             /**\r
             * @event collapsenode\r
             * Fires when a node is collapsed\r
             * @param {Node} node The node\r
             */\r
-            "collapsenode",\r
+            'collapsenode',\r
             /**\r
             * @event beforeclick\r
             * Fires before click processing on a node. Return false to cancel the default action.\r
             * @param {Node} node The node\r
             * @param {Ext.EventObject} e The event object\r
             */\r
-            "beforeclick",\r
+            'beforeclick',\r
             /**\r
             * @event click\r
             * Fires when a node is clicked\r
             * @param {Node} node The node\r
             * @param {Ext.EventObject} e The event object\r
             */\r
-            "click",\r
+            'click',\r
+            /**\r
+            * @event containerclick\r
+            * Fires when the tree container is clicked\r
+            * @param {Tree} this\r
+            * @param {Ext.EventObject} e The event object\r
+            */\r
+            'containerclick',\r
             /**\r
             * @event checkchange\r
             * Fires when a node with a checkbox's checked property changes\r
             * @param {Node} this This node\r
             * @param {Boolean} checked\r
             */\r
-            "checkchange",\r
+            'checkchange',\r
             /**\r
             * @event beforedblclick\r
             * Fires before double click processing on a node. Return false to cancel the default action.\r
             * @param {Node} node The node\r
             * @param {Ext.EventObject} e The event object\r
             */\r
-            "beforedblclick",\r
+            'beforedblclick',\r
             /**\r
             * @event dblclick\r
             * Fires when a node is double clicked\r
             * @param {Node} node The node\r
             * @param {Ext.EventObject} e The event object\r
             */\r
-            "dblclick",\r
+            'dblclick',\r
+            /**\r
+            * @event containerdblclick\r
+            * Fires when the tree container is double clicked\r
+            * @param {Tree} this\r
+            * @param {Ext.EventObject} e The event object\r
+            */\r
+            'containerdblclick',\r
             /**\r
             * @event contextmenu\r
             * Fires when a node is right clicked. To display a context menu in response to this\r
@@ -45692,13 +47869,20 @@ new Ext.tree.TreePanel({
             * @param {Node} node The node\r
             * @param {Ext.EventObject} e The event object\r
             */\r
-            "contextmenu",\r
+            'contextmenu',\r
+            /**\r
+            * @event containercontextmenu\r
+            * Fires when the tree container is right clicked\r
+            * @param {Tree} this\r
+            * @param {Ext.EventObject} e The event object\r
+            */\r
+            'containercontextmenu',\r
             /**\r
             * @event beforechildrenrendered\r
             * Fires right before the child nodes for a node are rendered\r
             * @param {Node} node The node\r
             */\r
-            "beforechildrenrendered",\r
+            'beforechildrenrendered',\r
            /**\r
              * @event startdrag\r
              * Fires when a node starts being dragged\r
@@ -45706,7 +47890,7 @@ new Ext.tree.TreePanel({
              * @param {Ext.tree.TreeNode} node\r
              * @param {event} e The raw browser event\r
              */\r
-            "startdrag",\r
+            'startdrag',\r
             /**\r
              * @event enddrag\r
              * Fires when a drag operation is complete\r
@@ -45714,7 +47898,7 @@ new Ext.tree.TreePanel({
              * @param {Ext.tree.TreeNode} node\r
              * @param {event} e The raw browser event\r
              */\r
-            "enddrag",\r
+            'enddrag',\r
             /**\r
              * @event dragdrop\r
              * Fires when a dragged node is dropped on a valid DD target\r
@@ -45723,7 +47907,7 @@ new Ext.tree.TreePanel({
              * @param {DD} dd The dd it was dropped on\r
              * @param {event} e The raw browser event\r
              */\r
-            "dragdrop",\r
+            'dragdrop',\r
             /**\r
              * @event beforenodedrop\r
              * Fires when a DD object is dropped on a node in this tree for preprocessing. Return false to cancel the drop. The dropEvent\r
@@ -45739,11 +47923,11 @@ new Ext.tree.TreePanel({
              * to be inserted by setting them on this object.</li>\r
              * <li>cancel - Set this to true to cancel the drop.</li>\r
              * <li>dropStatus - If the default drop action is cancelled but the drop is valid, setting this to true\r
-             * will prevent the animated "repair" from appearing.</li>\r
+             * will prevent the animated 'repair' from appearing.</li>\r
              * </ul>\r
              * @param {Object} dropEvent\r
              */\r
-            "beforenodedrop",\r
+            'beforenodedrop',\r
             /**\r
              * @event nodedrop\r
              * Fires after a DD object is dropped on a node in this tree. The dropEvent\r
@@ -45759,7 +47943,7 @@ new Ext.tree.TreePanel({
              * </ul>\r
              * @param {Object} dropEvent\r
              */\r
-            "nodedrop",\r
+            'nodedrop',\r
              /**\r
              * @event nodedragover\r
              * Fires when a tree node is being targeted for a drag drop, return false to signal drop not allowed. The dragOverEvent\r
@@ -45776,10 +47960,10 @@ new Ext.tree.TreePanel({
              * </ul>\r
              * @param {Object} dragOverEvent\r
              */\r
-            "nodedragover"\r
+            'nodedragover'\r
         );\r
         if(this.singleExpand){\r
-            this.on("beforeexpandnode", this.restrictExpand, this);\r
+            this.on('beforeexpandnode', this.restrictExpand, this);\r
         }\r
     },\r
 \r
@@ -45820,12 +48004,24 @@ new Ext.tree.TreePanel({
             var uiP = node.attributes.uiProvider;\r
             node.ui = uiP ? new uiP(node) : new Ext.tree.RootTreeNodeUI(node);\r
         }\r
-        if (this.innerCt) {\r
-            this.innerCt.update('');\r
-            this.afterRender();\r
+        if(this.innerCt){\r
+            this.clearInnerCt();\r
+            this.renderRoot();\r
         }\r
         return node;\r
     },\r
+    \r
+    clearInnerCt : function(){\r
+        this.innerCt.update('');    \r
+    },\r
+    \r
+    // private\r
+    renderRoot : function(){\r
+        this.root.render();\r
+        if(!this.rootVisible){\r
+            this.root.renderChildren();\r
+        }\r
+    },\r
 \r
     /**\r
      * Gets a node in this tree by its id\r
@@ -45848,7 +48044,7 @@ new Ext.tree.TreePanel({
 \r
     // private\r
     toString : function(){\r
-        return "[Tree"+(this.id?" "+this.id:"")+"]";\r
+        return '[Tree'+(this.id?' '+this.id:'')+']';\r
     },\r
 \r
     // private\r
@@ -45863,7 +48059,7 @@ new Ext.tree.TreePanel({
     },\r
 \r
     /**\r
-     * Retrieve an array of checked nodes, or an array of a specific attribute of checked nodes (e.g. "id")\r
+     * Retrieve an array of checked nodes, or an array of a specific attribute of checked nodes (e.g. 'id')\r
      * @param {String} attribute (optional) Defaults to null (return the actual nodes)\r
      * @param {TreeNode} startNode (optional) The node to start from, defaults to the root\r
      * @return {Array}\r
@@ -45880,14 +48076,6 @@ new Ext.tree.TreePanel({
         return r;\r
     },\r
 \r
-    /**\r
-     * Returns the container element for this TreePanel.\r
-     * @return {Element} The container element for this TreePanel.\r
-     */\r
-    getEl : function(){\r
-        return this.el;\r
-    },\r
-\r
     /**\r
      * Returns the default {@link Ext.tree.TreeLoader} for this TreePanel.\r
      * @return {Ext.tree.TreeLoader} The TreeLoader for this TreePanel.\r
@@ -45929,7 +48117,7 @@ new Ext.tree.TreePanel({
      * (bSuccess, oLastNode) where bSuccess is if the expand was successful and oLastNode is the last node that was expanded.\r
      */\r
     expandPath : function(path, attr, callback){\r
-        attr = attr || "id";\r
+        attr = attr || 'id';\r
         var keys = path.split(this.pathSeparator);\r
         var curNode = this.root;\r
         if(curNode.attributes[attr] != keys[1]){ // invalid root\r
@@ -45967,7 +48155,7 @@ new Ext.tree.TreePanel({
      * (bSuccess, oSelNode) where bSuccess is if the selection was successful and oSelNode is the selected node.\r
      */\r
     selectPath : function(path, attr, callback){\r
-        attr = attr || "id";\r
+        attr = attr || 'id';\r
         var keys = path.split(this.pathSeparator),\r
             v = keys.pop();\r
         if(keys.length > 1){\r
@@ -46009,9 +48197,9 @@ new Ext.tree.TreePanel({
     onRender : function(ct, position){\r
         Ext.tree.TreePanel.superclass.onRender.call(this, ct, position);\r
         this.el.addClass('x-tree');\r
-        this.innerCt = this.body.createChild({tag:"ul",\r
-               cls:"x-tree-root-ct " +\r
-               (this.useArrows ? 'x-tree-arrows' : this.lines ? "x-tree-lines" : "x-tree-no-lines")});\r
+        this.innerCt = this.body.createChild({tag:'ul',\r
+               cls:'x-tree-root-ct ' +\r
+               (this.useArrows ? 'x-tree-arrows' : this.lines ? 'x-tree-lines' : 'x-tree-no-lines')});\r
     },\r
 \r
     // private\r
@@ -46028,7 +48216,7 @@ new Ext.tree.TreePanel({
             * @type Ext.tree.TreeDropZone\r
             */\r
              this.dropZone = new Ext.tree.TreeDropZone(this, this.dropConfig || {\r
-               ddGroup: this.ddGroup || "TreeDD", appendOnly: this.ddAppendOnly === true\r
+               ddGroup: this.ddGroup || 'TreeDD', appendOnly: this.ddAppendOnly === true\r
            });\r
         }\r
         if((this.enableDD || this.enableDrag) && !this.dragZone){\r
@@ -46038,7 +48226,7 @@ new Ext.tree.TreePanel({
             * @type Ext.tree.TreeDragZone\r
             */\r
             this.dragZone = new Ext.tree.TreeDragZone(this, this.dragConfig || {\r
-               ddGroup: this.ddGroup || "TreeDD",\r
+               ddGroup: this.ddGroup || 'TreeDD',\r
                scroll: this.ddScroll\r
            });\r
         }\r
@@ -46048,26 +48236,17 @@ new Ext.tree.TreePanel({
     // private\r
     afterRender : function(){\r
         Ext.tree.TreePanel.superclass.afterRender.call(this);\r
-        this.root.render();\r
-        if(!this.rootVisible){\r
-            this.root.renderChildren();\r
-        }\r
+        this.renderRoot();\r
     },\r
 \r
-    onDestroy : function(){\r
+    beforeDestroy : function(){\r
         if(this.rendered){\r
-            this.body.removeAllListeners();\r
             Ext.dd.ScrollManager.unregister(this.body);\r
-            if(this.dropZone){\r
-                this.dropZone.unreg();\r
-            }\r
-            if(this.dragZone){\r
-               this.dragZone.unreg();\r
-            }\r
+            Ext.destroy(this.dropZone, this.dragZone);\r
         }\r
-        this.root.destroy();\r
-        this.nodeHash = null;\r
-        Ext.tree.TreePanel.superclass.onDestroy.call(this);\r
+        Ext.destroy(this.root, this.loader);\r
+        this.nodeHash = this.root = this.loader = null;\r
+        Ext.tree.TreePanel.superclass.beforeDestroy.call(this);\r
     }\r
 \r
     /**\r
@@ -46209,6 +48388,15 @@ new Ext.tree.TreePanel({
     /**\r
      * @cfg {String} contentEl  @hide\r
      */\r
+    /**\r
+     * @cfg {Mixed} data  @hide\r
+     */\r
+    /**\r
+     * @cfg {Mixed} tpl  @hide\r
+     */\r
+    /**\r
+     * @cfg {String} tplWriteMode  @hide\r
+     */\r
     /**\r
      * @cfg {String} disabledClass  @hide\r
      */\r
@@ -46254,7 +48442,7 @@ Ext.reg('treepanel', Ext.tree.TreePanel);Ext.tree.TreeEventModel = function(tree
 Ext.tree.TreeEventModel.prototype = {\r
     initEvents : function(){\r
         var t = this.tree;\r
-            \r
+\r
         if(t.trackMouseOver !== false){\r
             t.mon(t.innerCt, {\r
                 scope: this,\r
@@ -46327,42 +48515,55 @@ Ext.tree.TreeEventModel.prototype = {
     },\r
 \r
     trackExit : function(e){\r
-        if(this.lastOverNode && !e.within(this.lastOverNode.ui.getEl())){\r
-            this.onNodeOut(e, this.lastOverNode);\r
+        if(this.lastOverNode){\r
+            if(this.lastOverNode.ui && !e.within(this.lastOverNode.ui.getEl())){\r
+                this.onNodeOut(e, this.lastOverNode);\r
+            }\r
             delete this.lastOverNode;\r
             Ext.getBody().un('mouseover', this.trackExit, this);\r
             this.trackingDoc = false;\r
         }\r
+\r
     },\r
 \r
     delegateClick : function(e, t){\r
-        if(!this.beforeEvent(e)){\r
-            return;\r
-        }\r
-\r
-        if(e.getTarget('input[type=checkbox]', 1)){\r
-            this.onCheckboxClick(e, this.getNode(e));\r
-        }\r
-        else if(e.getTarget('.x-tree-ec-icon', 1)){\r
-            this.onIconClick(e, this.getNode(e));\r
-        }\r
-        else if(this.getNodeTarget(e)){\r
-            this.onNodeClick(e, this.getNode(e));\r
+        if(this.beforeEvent(e)){\r
+            if(e.getTarget('input[type=checkbox]', 1)){\r
+                this.onCheckboxClick(e, this.getNode(e));\r
+            }else if(e.getTarget('.x-tree-ec-icon', 1)){\r
+                this.onIconClick(e, this.getNode(e));\r
+            }else if(this.getNodeTarget(e)){\r
+                this.onNodeClick(e, this.getNode(e));\r
+            }else{\r
+                this.onContainerEvent(e, 'click');\r
+            }\r
         }\r
     },\r
 \r
     delegateDblClick : function(e, t){\r
-        if(this.beforeEvent(e) && this.getNodeTarget(e)){\r
-            this.onNodeDblClick(e, this.getNode(e));\r
+        if(this.beforeEvent(e)){\r
+            if(this.getNodeTarget(e)){\r
+                this.onNodeDblClick(e, this.getNode(e));\r
+            }else{\r
+                this.onContainerEvent(e, 'dblclick');\r
+            }\r
         }\r
     },\r
 \r
     delegateContextMenu : function(e, t){\r
-        if(this.beforeEvent(e) && this.getNodeTarget(e)){\r
-            this.onNodeContextMenu(e, this.getNode(e));\r
+        if(this.beforeEvent(e)){\r
+            if(this.getNodeTarget(e)){\r
+                this.onNodeContextMenu(e, this.getNode(e));\r
+            }else{\r
+                this.onContainerEvent(e, 'contextmenu');\r
+            }\r
         }\r
     },\r
 \r
+    onContainerEvent: function(e, type){\r
+        this.tree.fireEvent('container' + type, this.tree, e);\r
+    },\r
+\r
     onNodeClick : function(e, node){\r
         node.ui.onClick(e);\r
     },\r
@@ -46401,7 +48602,8 @@ Ext.tree.TreeEventModel.prototype = {
     },\r
 \r
     beforeEvent : function(e){\r
-        if(this.disabled){\r
+        var node = this.getNode(e);\r
+        if(this.disabled || !node || !node.ui){\r
             e.stopEvent();\r
             return false;\r
         }\r
@@ -46430,7 +48632,7 @@ Ext.tree.DefaultSelectionModel = function(config){
         * @param {DefaultSelectionModel} this\r
         * @param {TreeNode} node the new selection\r
         */\r
-       "selectionchange",\r
+       'selectionchange',\r
 \r
        /**\r
         * @event beforeselect\r
@@ -46439,7 +48641,7 @@ Ext.tree.DefaultSelectionModel = function(config){
         * @param {TreeNode} node the new selection\r
         * @param {TreeNode} node the old selection\r
         */\r
-       "beforeselect"\r
+       'beforeselect'\r
    );\r
 \r
     Ext.apply(this, config);\r
@@ -46450,7 +48652,7 @@ Ext.extend(Ext.tree.DefaultSelectionModel, Ext.util.Observable, {
     init : function(tree){\r
         this.tree = tree;\r
         tree.mon(tree.getTreeEl(), 'keydown', this.onKeyDown, this);\r
-        tree.on("click", this.onNodeClick, this);\r
+        tree.on('click', this.onNodeClick, this);\r
     },\r
     \r
     onNodeClick : function(node, e){\r
@@ -46471,12 +48673,12 @@ Ext.extend(Ext.tree.DefaultSelectionModel, Ext.util.Observable, {
         if(node == last){\r
             node.ui.onSelectedChange(true);\r
         }else if(this.fireEvent('beforeselect', this, node, last) !== false){\r
-            if(last){\r
+            if(last && last.ui){\r
                 last.ui.onSelectedChange(false);\r
             }\r
             this.selNode = node;\r
             node.ui.onSelectedChange(true);\r
-            this.fireEvent("selectionchange", this, node, last);\r
+            this.fireEvent('selectionchange', this, node, last);\r
         }\r
         return node;\r
     },\r
@@ -46484,22 +48686,26 @@ Ext.extend(Ext.tree.DefaultSelectionModel, Ext.util.Observable, {
     /**\r
      * Deselect a node.\r
      * @param {TreeNode} node The node to unselect\r
+     * @param {Boolean} silent True to stop the selectionchange event from firing.\r
      */\r
-    unselect : function(node){\r
+    unselect : function(node, silent){\r
         if(this.selNode == node){\r
-            this.clearSelections();\r
+            this.clearSelections(silent);\r
         }    \r
     },\r
     \r
     /**\r
      * Clear all selections\r
+     * @param {Boolean} silent True to stop the selectionchange event from firing.\r
      */\r
-    clearSelections : function(){\r
+    clearSelections : function(silent){\r
         var n = this.selNode;\r
         if(n){\r
             n.ui.onSelectedChange(false);\r
             this.selNode = null;\r
-            this.fireEvent("selectionchange", this, null);\r
+            if(silent !== true){\r
+                this.fireEvent('selectionchange', this, null);\r
+            }\r
         }\r
         return n;\r
     },\r
@@ -46627,7 +48833,7 @@ Ext.tree.MultiSelectionModel = function(config){
         * @param {MultiSelectionModel} this\r
         * @param {Array} nodes Array of the selected nodes\r
         */\r
-       "selectionchange"\r
+       'selectionchange'\r
    );\r
     Ext.apply(this, config);\r
     Ext.tree.MultiSelectionModel.superclass.constructor.call(this);\r
@@ -46637,7 +48843,7 @@ Ext.extend(Ext.tree.MultiSelectionModel, Ext.util.Observable, {
     init : function(tree){\r
         this.tree = tree;\r
         tree.mon(tree.getTreeEl(), 'keydown', this.onKeyDown, this);\r
-        tree.on("click", this.onNodeClick, this);\r
+        tree.on('click', this.onNodeClick, this);\r
     },\r
     \r
     onNodeClick : function(node, e){\r
@@ -46667,7 +48873,7 @@ Ext.extend(Ext.tree.MultiSelectionModel, Ext.util.Observable, {
         this.selMap[node.id] = node;\r
         this.lastSelNode = node;\r
         node.ui.onSelectedChange(true);\r
-        this.fireEvent("selectionchange", this, this.selNodes);\r
+        this.fireEvent('selectionchange', this, this.selNodes);\r
         return node;\r
     },\r
     \r
@@ -46684,7 +48890,7 @@ Ext.extend(Ext.tree.MultiSelectionModel, Ext.util.Observable, {
                 this.selNodes.splice(index, 1);\r
             }\r
             delete this.selMap[node.id];\r
-            this.fireEvent("selectionchange", this, this.selNodes);\r
+            this.fireEvent('selectionchange', this, this.selNodes);\r
         }\r
     },\r
     \r
@@ -46700,7 +48906,7 @@ Ext.extend(Ext.tree.MultiSelectionModel, Ext.util.Observable, {
             this.selNodes = [];\r
             this.selMap = {};\r
             if(suppressEvent !== true){\r
-                this.fireEvent("selectionchange", this, this.selNodes);\r
+                this.fireEvent('selectionchange', this, this.selNodes);\r
             }\r
         }\r
     },\r
@@ -47140,9 +49346,10 @@ Ext.extend(Ext.data.Node, Ext.util.Observable, {
     /**\r
      * Removes a child node from this node.\r
      * @param {Node} node The node to remove\r
+     * @param {Boolean} destroy <tt>true</tt> to destroy the node upon removal. Defaults to <tt>false</tt>.\r
      * @return {Node} The removed node\r
      */\r
-    removeChild : function(node){\r
+    removeChild : function(node, destroy){\r
         var index = this.childNodes.indexOf(node);\r
         if(index == -1){\r
             return false;\r
@@ -47170,14 +49377,35 @@ Ext.extend(Ext.data.Node, Ext.util.Observable, {
             this.setLastChild(node.previousSibling);\r
         }\r
 \r
-        node.setOwnerTree(null);\r
-        // clear any references from the node\r
-        node.parentNode = null;\r
-        node.previousSibling = null;\r
-        node.nextSibling = null;\r
+        node.clear();\r
         this.fireEvent("remove", this.ownerTree, this, node);\r
+        if(destroy){\r
+            node.destroy();\r
+        }\r
         return node;\r
     },\r
+    \r
+    // private\r
+    clear : function(destroy){\r
+        // clear any references from the node\r
+        this.setOwnerTree(null, destroy);\r
+        this.parentNode = this.previousSibling = this.nextSibling = null\r
+        if(destroy){\r
+            this.firstChild = this.lastChild = null; \r
+        }\r
+    },\r
+    \r
+    /**\r
+     * Destroys the node.\r
+     */\r
+    destroy : function(){\r
+        this.purgeListeners();\r
+        this.clear(true);  \r
+        Ext.each(this.childNodes, function(n){\r
+            n.destroy();\r
+        });\r
+        this.childNodes = null;\r
+    },\r
 \r
     /**\r
      * Inserts the first node before the second node in this nodes childNodes collection.\r
@@ -47237,10 +49465,25 @@ Ext.extend(Ext.data.Node, Ext.util.Observable, {
 \r
     /**\r
      * Removes this node from its parent\r
+     * @param {Boolean} destroy <tt>true</tt> to destroy the node upon removal. Defaults to <tt>false</tt>.\r
      * @return {Node} this\r
      */\r
-    remove : function(){\r
-        this.parentNode.removeChild(this);\r
+    remove : function(destroy){\r
+        this.parentNode.removeChild(this, destroy);\r
+        return this;\r
+    },\r
+    \r
+    /**\r
+     * Removes all child nodes from this node.\r
+     * @param {Boolean} destroy <tt>true</tt> to destroy the node upon removal. Defaults to <tt>false</tt>.\r
+     * @return {Node} this\r
+     */\r
+    removeAll : function(destroy){\r
+        var cn = this.childNodes,\r
+            n;\r
+        while((n = cn[0])){\r
+            this.removeChild(n, destroy);\r
+        }\r
         return this;\r
     },\r
 \r
@@ -47309,16 +49552,18 @@ Ext.extend(Ext.data.Node, Ext.util.Observable, {
     },\r
 \r
     // private\r
-    setOwnerTree : function(tree){\r
+    setOwnerTree : function(tree, destroy){\r
         // if it is a move, we need to update everyone\r
         if(tree != this.ownerTree){\r
             if(this.ownerTree){\r
                 this.ownerTree.unregisterNode(this);\r
             }\r
             this.ownerTree = tree;\r
-            var cs = this.childNodes;\r
-            for(var i = 0, len = cs.length; i < len; i++) {\r
-               cs[i].setOwnerTree(tree);\r
+            // If we're destroying, we don't need to recurse since it will be called on each child node\r
+            if(destroy !== true){\r
+                Ext.each(this.childNodes, function(n){\r
+                    n.setOwnerTree(tree);\r
+                });\r
             }\r
             if(tree){\r
                 tree.registerNode(this);\r
@@ -47365,13 +49610,12 @@ Ext.extend(Ext.data.Node, Ext.util.Observable, {
     },\r
 \r
     /**\r
-     * Bubbles up the tree from this node, calling the specified function with each node. The scope (<i>this</i>) of\r
-     * function call will be the scope provided or the current node. The arguments to the function\r
+     * Bubbles up the tree from this node, calling the specified function with each node. The arguments to the function\r
      * will be the args provided or the current node. If the function returns false at any point,\r
      * the bubble is stopped.\r
      * @param {Function} fn The function to call\r
-     * @param {Object} scope (optional) The scope of the function (defaults to current node)\r
-     * @param {Array} args (optional) The args to call the function with (default to passing the current node)\r
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to the current Node.\r
+     * @param {Array} args (optional) The args to call the function with (default to passing the current Node)\r
      */\r
     bubble : function(fn, scope, args){\r
         var p = this;\r
@@ -47384,13 +49628,12 @@ Ext.extend(Ext.data.Node, Ext.util.Observable, {
     },\r
 \r
     /**\r
-     * Cascades down the tree from this node, calling the specified function with each node. The scope (<i>this</i>) of\r
-     * function call will be the scope provided or the current node. The arguments to the function\r
+     * Cascades down the tree from this node, calling the specified function with each node. The arguments to the function\r
      * will be the args provided or the current node. If the function returns false at any point,\r
      * the cascade is stopped on that branch.\r
      * @param {Function} fn The function to call\r
-     * @param {Object} scope (optional) The scope of the function (defaults to current node)\r
-     * @param {Array} args (optional) The args to call the function with (default to passing the current node)\r
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to the current Node.\r
+     * @param {Array} args (optional) The args to call the function with (default to passing the current Node)\r
      */\r
     cascade : function(fn, scope, args){\r
         if(fn.apply(scope || this, args || [this]) !== false){\r
@@ -47402,13 +49645,12 @@ Ext.extend(Ext.data.Node, Ext.util.Observable, {
     },\r
 \r
     /**\r
-     * Interates the child nodes of this node, calling the specified function with each node. The scope (<i>this</i>) of\r
-     * function call will be the scope provided or the current node. The arguments to the function\r
+     * Interates the child nodes of this node, calling the specified function with each node. The arguments to the function\r
      * will be the args provided or the current node. If the function returns false at any point,\r
      * the iteration stops.\r
      * @param {Function} fn The function to call\r
-     * @param {Object} scope (optional) The scope of the function (defaults to current node)\r
-     * @param {Array} args (optional) The args to call the function with (default to passing the current node)\r
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to the current Node in the iteration.\r
+     * @param {Array} args (optional) The args to call the function with (default to passing the current Node)\r
      */\r
     eachChild : function(fn, scope, args){\r
         var cs = this.childNodes;\r
@@ -47436,10 +49678,9 @@ Ext.extend(Ext.data.Node, Ext.util.Observable, {
     },\r
 \r
     /**\r
-     * Finds the first child by a custom function. The child matches if the function passed\r
-     * returns true.\r
-     * @param {Function} fn\r
-     * @param {Object} scope (optional)\r
+     * Finds the first child by a custom function. The child matches if the function passed returns <code>true</code>.\r
+     * @param {Function} fn A function which must return <code>true</code> if the passed Node is the required Node.\r
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to the Node being tested.\r
      * @return {Node} The found child or null if none was found\r
      */\r
     findChildBy : function(fn, scope){\r
@@ -47453,9 +49694,9 @@ Ext.extend(Ext.data.Node, Ext.util.Observable, {
     },\r
 \r
     /**\r
-     * Sorts this nodes children using the supplied sort function\r
-     * @param {Function} fn\r
-     * @param {Object} scope (optional)\r
+     * Sorts this nodes children using the supplied sort function.\r
+     * @param {Function} fn A function which, when passed two Nodes, returns -1, 0 or 1 depending upon required sort order.\r
+     * @param {Object} scope (optional)The scope (<code>this</code> reference) in which the function is executed. Defaults to the browser window.\r
      */\r
     sort : function(fn, scope){\r
         var cs = this.childNodes;\r
@@ -47505,649 +49746,668 @@ Ext.extend(Ext.data.Node, Ext.util.Observable, {
     toString : function(){\r
         return "[Node"+(this.id?" "+this.id:"")+"]";\r
     }\r
-});/**\r
- * @class Ext.tree.TreeNode\r
- * @extends Ext.data.Node\r
- * @cfg {String} text The text for this node\r
- * @cfg {Boolean} expanded true to start the node expanded\r
- * @cfg {Boolean} allowDrag False to make this node undraggable if {@link #draggable} = true (defaults to true)\r
- * @cfg {Boolean} allowDrop False if this node cannot have child nodes dropped on it (defaults to true)\r
- * @cfg {Boolean} disabled true to start the node disabled\r
- * @cfg {String} icon The path to an icon for the node. The preferred way to do this\r
- * is to use the cls or iconCls attributes and add the icon via a CSS background image.\r
- * @cfg {String} cls A css class to be added to the node\r
- * @cfg {String} iconCls A css class to be added to the nodes icon element for applying css background images\r
- * @cfg {String} href URL of the link used for the node (defaults to #)\r
- * @cfg {String} hrefTarget target frame for the link\r
- * @cfg {Boolean} hidden True to render hidden. (Defaults to false).\r
- * @cfg {String} qtip An Ext QuickTip for the node\r
- * @cfg {Boolean} expandable If set to true, the node will always show a plus/minus icon, even when empty\r
- * @cfg {String} qtipCfg An Ext QuickTip config for the node (used instead of qtip)\r
- * @cfg {Boolean} singleClickExpand True for single click expand on this node\r
- * @cfg {Function} uiProvider A UI <b>class</b> to use for this node (defaults to Ext.tree.TreeNodeUI)\r
- * @cfg {Boolean} checked True to render a checked checkbox for this node, false to render an unchecked checkbox\r
- * (defaults to undefined with no checkbox rendered)\r
- * @cfg {Boolean} draggable True to make this node draggable (defaults to false)\r
- * @cfg {Boolean} isTarget False to not allow this node to act as a drop target (defaults to true)\r
- * @cfg {Boolean} allowChildren False to not allow this node to have child nodes (defaults to true)\r
- * @cfg {Boolean} editable False to not allow this node to be edited by an (@link Ext.tree.TreeEditor} (defaults to true)\r
+});/**
+ * @class Ext.tree.TreeNode
+ * @extends Ext.data.Node
+ * @cfg {String} text The text for this node
+ * @cfg {Boolean} expanded true to start the node expanded
+ * @cfg {Boolean} allowDrag False to make this node undraggable if {@link #draggable} = true (defaults to true)
+ * @cfg {Boolean} allowDrop False if this node cannot have child nodes dropped on it (defaults to true)
+ * @cfg {Boolean} disabled true to start the node disabled
+ * @cfg {String} icon The path to an icon for the node. The preferred way to do this
+ * is to use the cls or iconCls attributes and add the icon via a CSS background image.
+ * @cfg {String} cls A css class to be added to the node
+ * @cfg {String} iconCls A css class to be added to the nodes icon element for applying css background images
+ * @cfg {String} href URL of the link used for the node (defaults to #)
+ * @cfg {String} hrefTarget target frame for the link
+ * @cfg {Boolean} hidden True to render hidden. (Defaults to false).
+ * @cfg {String} qtip An Ext QuickTip for the node
+ * @cfg {Boolean} expandable If set to true, the node will always show a plus/minus icon, even when empty
+ * @cfg {String} qtipCfg An Ext QuickTip config for the node (used instead of qtip)
+ * @cfg {Boolean} singleClickExpand True for single click expand on this node
+ * @cfg {Function} uiProvider A UI <b>class</b> to use for this node (defaults to Ext.tree.TreeNodeUI)
+ * @cfg {Boolean} checked True to render a checked checkbox for this node, false to render an unchecked checkbox
+ * (defaults to undefined with no checkbox rendered)
+ * @cfg {Boolean} draggable True to make this node draggable (defaults to false)
+ * @cfg {Boolean} isTarget False to not allow this node to act as a drop target (defaults to true)
+ * @cfg {Boolean} allowChildren False to not allow this node to have child nodes (defaults to true)
+ * @cfg {Boolean} editable False to not allow this node to be edited by an {@link Ext.tree.TreeEditor} (defaults to true)
+ * @constructor
+ * @param {Object/String} attributes The attributes/config for the node or just a string with the text for the node
+ */
+Ext.tree.TreeNode = function(attributes){
+    attributes = attributes || {};
+    if(Ext.isString(attributes)){
+        attributes = {text: attributes};
+    }
+    this.childrenRendered = false;
+    this.rendered = false;
+    Ext.tree.TreeNode.superclass.constructor.call(this, attributes);
+    this.expanded = attributes.expanded === true;
+    this.isTarget = attributes.isTarget !== false;
+    this.draggable = attributes.draggable !== false && attributes.allowDrag !== false;
+    this.allowChildren = attributes.allowChildren !== false && attributes.allowDrop !== false;
+
+    /**
+     * Read-only. The text for this node. To change it use <code>{@link #setText}</code>.
+     * @type String
+     */
+    this.text = attributes.text;
+    /**
+     * True if this node is disabled.
+     * @type Boolean
+     */
+    this.disabled = attributes.disabled === true;
+    /**
+     * True if this node is hidden.
+     * @type Boolean
+     */
+    this.hidden = attributes.hidden === true;
+
+    this.addEvents(
+        /**
+        * @event textchange
+        * Fires when the text for this node is changed
+        * @param {Node} this This node
+        * @param {String} text The new text
+        * @param {String} oldText The old text
+        */
+        'textchange',
+        /**
+        * @event beforeexpand
+        * Fires before this node is expanded, return false to cancel.
+        * @param {Node} this This node
+        * @param {Boolean} deep
+        * @param {Boolean} anim
+        */
+        'beforeexpand',
+        /**
+        * @event beforecollapse
+        * Fires before this node is collapsed, return false to cancel.
+        * @param {Node} this This node
+        * @param {Boolean} deep
+        * @param {Boolean} anim
+        */
+        'beforecollapse',
+        /**
+        * @event expand
+        * Fires when this node is expanded
+        * @param {Node} this This node
+        */
+        'expand',
+        /**
+        * @event disabledchange
+        * Fires when the disabled status of this node changes
+        * @param {Node} this This node
+        * @param {Boolean} disabled
+        */
+        'disabledchange',
+        /**
+        * @event collapse
+        * Fires when this node is collapsed
+        * @param {Node} this This node
+        */
+        'collapse',
+        /**
+        * @event beforeclick
+        * Fires before click processing. Return false to cancel the default action.
+        * @param {Node} this This node
+        * @param {Ext.EventObject} e The event object
+        */
+        'beforeclick',
+        /**
+        * @event click
+        * Fires when this node is clicked
+        * @param {Node} this This node
+        * @param {Ext.EventObject} e The event object
+        */
+        'click',
+        /**
+        * @event checkchange
+        * Fires when a node with a checkbox's checked property changes
+        * @param {Node} this This node
+        * @param {Boolean} checked
+        */
+        'checkchange',
+        /**
+        * @event beforedblclick
+        * Fires before double click processing. Return false to cancel the default action.
+        * @param {Node} this This node
+        * @param {Ext.EventObject} e The event object
+        */
+        'beforedblclick',
+        /**
+        * @event dblclick
+        * Fires when this node is double clicked
+        * @param {Node} this This node
+        * @param {Ext.EventObject} e The event object
+        */
+        'dblclick',
+        /**
+        * @event contextmenu
+        * Fires when this node is right clicked
+        * @param {Node} this This node
+        * @param {Ext.EventObject} e The event object
+        */
+        'contextmenu',
+        /**
+        * @event beforechildrenrendered
+        * Fires right before the child nodes for this node are rendered
+        * @param {Node} this This node
+        */
+        'beforechildrenrendered'
+    );
+
+    var uiClass = this.attributes.uiProvider || this.defaultUI || Ext.tree.TreeNodeUI;
+
+    /**
+     * Read-only. The UI for this node
+     * @type TreeNodeUI
+     */
+    this.ui = new uiClass(this);
+};
+Ext.extend(Ext.tree.TreeNode, Ext.data.Node, {
+    preventHScroll : true,
+    /**
+     * Returns true if this node is expanded
+     * @return {Boolean}
+     */
+    isExpanded : function(){
+        return this.expanded;
+    },
+
+/**
+ * Returns the UI object for this node.
+ * @return {TreeNodeUI} The object which is providing the user interface for this tree
+ * node. Unless otherwise specified in the {@link #uiProvider}, this will be an instance
+ * of {@link Ext.tree.TreeNodeUI}
+ */
+    getUI : function(){
+        return this.ui;
+    },
+
+    getLoader : function(){
+        var owner;
+        return this.loader || ((owner = this.getOwnerTree()) && owner.loader ? owner.loader : (this.loader = new Ext.tree.TreeLoader()));
+    },
+
+    // private override
+    setFirstChild : function(node){
+        var of = this.firstChild;
+        Ext.tree.TreeNode.superclass.setFirstChild.call(this, node);
+        if(this.childrenRendered && of && node != of){
+            of.renderIndent(true, true);
+        }
+        if(this.rendered){
+            this.renderIndent(true, true);
+        }
+    },
+
+    // private override
+    setLastChild : function(node){
+        var ol = this.lastChild;
+        Ext.tree.TreeNode.superclass.setLastChild.call(this, node);
+        if(this.childrenRendered && ol && node != ol){
+            ol.renderIndent(true, true);
+        }
+        if(this.rendered){
+            this.renderIndent(true, true);
+        }
+    },
+
+    // these methods are overridden to provide lazy rendering support
+    // private override
+    appendChild : function(n){
+        var node, exists;
+        if(!n.render && !Ext.isArray(n)){
+            n = this.getLoader().createNode(n);
+        }else{
+            exists = !n.parentNode;
+        }
+        node = Ext.tree.TreeNode.superclass.appendChild.call(this, n);
+        if(node){
+            this.afterAdd(node, exists);
+        }
+        this.ui.updateExpandIcon();
+        return node;
+    },
+
+    // private override
+    removeChild : function(node, destroy){
+        this.ownerTree.getSelectionModel().unselect(node);
+        Ext.tree.TreeNode.superclass.removeChild.apply(this, arguments);
+        // if it's been rendered remove dom node
+        if(node.ui.rendered){
+            node.ui.remove();
+        }
+        if(this.childNodes.length < 1){
+            this.collapse(false, false);
+        }else{
+            this.ui.updateExpandIcon();
+        }
+        if(!this.firstChild && !this.isHiddenRoot()) {
+            this.childrenRendered = false;
+        }
+        return node;
+    },
+
+    // private override
+    insertBefore : function(node, refNode){
+        var newNode, exists;
+        if(!node.render){
+            node = this.getLoader().createNode(node);
+        } else {
+            exists = Ext.isObject(node.parentNode);
+        }
+        newNode = Ext.tree.TreeNode.superclass.insertBefore.call(this, node, refNode);
+        if(newNode && refNode){
+            this.afterAdd(newNode, exists);
+        }
+        this.ui.updateExpandIcon();
+        return newNode;
+    },
+    
+    // private
+    afterAdd : function(node, exists){
+        if(this.childrenRendered){
+            // bulk render if the node already exists
+            node.render(exists);
+        }else if(exists){
+            // make sure we update the indent
+            node.renderIndent(true, true);
+        }
+    },
+
+    /**
+     * Sets the text for this node
+     * @param {String} text
+     */
+    setText : function(text){
+        var oldText = this.text;
+        this.text = this.attributes.text = text;
+        if(this.rendered){ // event without subscribing
+            this.ui.onTextChange(this, text, oldText);
+        }
+        this.fireEvent('textchange', this, text, oldText);
+    },
+
+    /**
+     * Triggers selection of this node
+     */
+    select : function(){
+        var t = this.getOwnerTree();
+        if(t){
+            t.getSelectionModel().select(this);
+        }
+    },
+
+    /**
+     * Triggers deselection of this node
+     * @param {Boolean} silent (optional) True to stop selection change events from firing.
+     */
+    unselect : function(silent){
+        var t = this.getOwnerTree();
+        if(t){
+            t.getSelectionModel().unselect(this, silent);
+        }
+    },
+
+    /**
+     * Returns true if this node is selected
+     * @return {Boolean}
+     */
+    isSelected : function(){
+        var t = this.getOwnerTree();
+        return t ? t.getSelectionModel().isSelected(this) : false;
+    },
+
+    /**
+     * Expand this node.
+     * @param {Boolean} deep (optional) True to expand all children as well
+     * @param {Boolean} anim (optional) false to cancel the default animation
+     * @param {Function} callback (optional) A callback to be called when
+     * expanding this node completes (does not wait for deep expand to complete).
+     * Called with 1 parameter, this node.
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the callback is executed. Defaults to this TreeNode.
+     */
+    expand : function(deep, anim, callback, scope){
+        if(!this.expanded){
+            if(this.fireEvent('beforeexpand', this, deep, anim) === false){
+                return;
+            }
+            if(!this.childrenRendered){
+                this.renderChildren();
+            }
+            this.expanded = true;
+            if(!this.isHiddenRoot() && (this.getOwnerTree().animate && anim !== false) || anim){
+                this.ui.animExpand(function(){
+                    this.fireEvent('expand', this);
+                    this.runCallback(callback, scope || this, [this]);
+                    if(deep === true){
+                        this.expandChildNodes(true);
+                    }
+                }.createDelegate(this));
+                return;
+            }else{
+                this.ui.expand();
+                this.fireEvent('expand', this);
+                this.runCallback(callback, scope || this, [this]);
+            }
+        }else{
+           this.runCallback(callback, scope || this, [this]);
+        }
+        if(deep === true){
+            this.expandChildNodes(true);
+        }
+    },
+
+    runCallback : function(cb, scope, args){
+        if(Ext.isFunction(cb)){
+            cb.apply(scope, args);
+        }
+    },
+
+    isHiddenRoot : function(){
+        return this.isRoot && !this.getOwnerTree().rootVisible;
+    },
+
+    /**
+     * Collapse this node.
+     * @param {Boolean} deep (optional) True to collapse all children as well
+     * @param {Boolean} anim (optional) false to cancel the default animation
+     * @param {Function} callback (optional) A callback to be called when
+     * expanding this node completes (does not wait for deep expand to complete).
+     * Called with 1 parameter, this node.
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the callback is executed. Defaults to this TreeNode.
+     */
+    collapse : function(deep, anim, callback, scope){
+        if(this.expanded && !this.isHiddenRoot()){
+            if(this.fireEvent('beforecollapse', this, deep, anim) === false){
+                return;
+            }
+            this.expanded = false;
+            if((this.getOwnerTree().animate && anim !== false) || anim){
+                this.ui.animCollapse(function(){
+                    this.fireEvent('collapse', this);
+                    this.runCallback(callback, scope || this, [this]);
+                    if(deep === true){
+                        this.collapseChildNodes(true);
+                    }
+                }.createDelegate(this));
+                return;
+            }else{
+                this.ui.collapse();
+                this.fireEvent('collapse', this);
+                this.runCallback(callback, scope || this, [this]);
+            }
+        }else if(!this.expanded){
+            this.runCallback(callback, scope || this, [this]);
+        }
+        if(deep === true){
+            var cs = this.childNodes;
+            for(var i = 0, len = cs.length; i < len; i++) {
+               cs[i].collapse(true, false);
+            }
+        }
+    },
+
+    // private
+    delayedExpand : function(delay){
+        if(!this.expandProcId){
+            this.expandProcId = this.expand.defer(delay, this);
+        }
+    },
+
+    // private
+    cancelExpand : function(){
+        if(this.expandProcId){
+            clearTimeout(this.expandProcId);
+        }
+        this.expandProcId = false;
+    },
+
+    /**
+     * Toggles expanded/collapsed state of the node
+     */
+    toggle : function(){
+        if(this.expanded){
+            this.collapse();
+        }else{
+            this.expand();
+        }
+    },
+
+    /**
+     * Ensures all parent nodes are expanded, and if necessary, scrolls
+     * the node into view.
+     * @param {Function} callback (optional) A function to call when the node has been made visible.
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the callback is executed. Defaults to this TreeNode.
+     */
+    ensureVisible : function(callback, scope){
+        var tree = this.getOwnerTree();
+        tree.expandPath(this.parentNode ? this.parentNode.getPath() : this.getPath(), false, function(){
+            var node = tree.getNodeById(this.id);  // Somehow if we don't do this, we lose changes that happened to node in the meantime
+            tree.getTreeEl().scrollChildIntoView(node.ui.anchor);
+            this.runCallback(callback, scope || this, [this]);
+        }.createDelegate(this));
+    },
+
+    /**
+     * Expand all child nodes
+     * @param {Boolean} deep (optional) true if the child nodes should also expand their child nodes
+     */
+    expandChildNodes : function(deep){
+        var cs = this.childNodes;
+        for(var i = 0, len = cs.length; i < len; i++) {
+               cs[i].expand(deep);
+        }
+    },
+
+    /**
+     * Collapse all child nodes
+     * @param {Boolean} deep (optional) true if the child nodes should also collapse their child nodes
+     */
+    collapseChildNodes : function(deep){
+        var cs = this.childNodes;
+        for(var i = 0, len = cs.length; i < len; i++) {
+               cs[i].collapse(deep);
+        }
+    },
+
+    /**
+     * Disables this node
+     */
+    disable : function(){
+        this.disabled = true;
+        this.unselect();
+        if(this.rendered && this.ui.onDisableChange){ // event without subscribing
+            this.ui.onDisableChange(this, true);
+        }
+        this.fireEvent('disabledchange', this, true);
+    },
+
+    /**
+     * Enables this node
+     */
+    enable : function(){
+        this.disabled = false;
+        if(this.rendered && this.ui.onDisableChange){ // event without subscribing
+            this.ui.onDisableChange(this, false);
+        }
+        this.fireEvent('disabledchange', this, false);
+    },
+
+    // private
+    renderChildren : function(suppressEvent){
+        if(suppressEvent !== false){
+            this.fireEvent('beforechildrenrendered', this);
+        }
+        var cs = this.childNodes;
+        for(var i = 0, len = cs.length; i < len; i++){
+            cs[i].render(true);
+        }
+        this.childrenRendered = true;
+    },
+
+    // private
+    sort : function(fn, scope){
+        Ext.tree.TreeNode.superclass.sort.apply(this, arguments);
+        if(this.childrenRendered){
+            var cs = this.childNodes;
+            for(var i = 0, len = cs.length; i < len; i++){
+                cs[i].render(true);
+            }
+        }
+    },
+
+    // private
+    render : function(bulkRender){
+        this.ui.render(bulkRender);
+        if(!this.rendered){
+            // make sure it is registered
+            this.getOwnerTree().registerNode(this);
+            this.rendered = true;
+            if(this.expanded){
+                this.expanded = false;
+                this.expand(false, false);
+            }
+        }
+    },
+
+    // private
+    renderIndent : function(deep, refresh){
+        if(refresh){
+            this.ui.childIndent = null;
+        }
+        this.ui.renderIndent();
+        if(deep === true && this.childrenRendered){
+            var cs = this.childNodes;
+            for(var i = 0, len = cs.length; i < len; i++){
+                cs[i].renderIndent(true, refresh);
+            }
+        }
+    },
+
+    beginUpdate : function(){
+        this.childrenRendered = false;
+    },
+
+    endUpdate : function(){
+        if(this.expanded && this.rendered){
+            this.renderChildren();
+        }
+    },
+
+    destroy : function(){
+        this.unselect(true);
+        Ext.tree.TreeNode.superclass.destroy.call(this);
+        Ext.destroy(this.ui, this.loader);
+        this.ui = this.loader = null;
+    },
+
+    // private
+    onIdChange : function(id){
+        this.ui.onIdChange(id);
+    }
+});
+
+Ext.tree.TreePanel.nodeTypes.node = Ext.tree.TreeNode;/**\r
+ * @class Ext.tree.AsyncTreeNode\r
+ * @extends Ext.tree.TreeNode\r
+ * @cfg {TreeLoader} loader A TreeLoader to be used by this node (defaults to the loader defined on the tree)\r
  * @constructor\r
- * @param {Object/String} attributes The attributes/config for the node or just a string with the text for the node\r
+ * @param {Object/String} attributes The attributes/config for the node or just a string with the text for the node \r
  */\r
-Ext.tree.TreeNode = function(attributes){\r
-    attributes = attributes || {};\r
-    if(typeof attributes == 'string'){\r
-        attributes = {text: attributes};\r
-    }\r
-    this.childrenRendered = false;\r
-    this.rendered = false;\r
-    Ext.tree.TreeNode.superclass.constructor.call(this, attributes);\r
-    this.expanded = attributes.expanded === true;\r
-    this.isTarget = attributes.isTarget !== false;\r
-    this.draggable = attributes.draggable !== false && attributes.allowDrag !== false;\r
-    this.allowChildren = attributes.allowChildren !== false && attributes.allowDrop !== false;\r
-\r
-    /**\r
-     * Read-only. The text for this node. To change it use <code>{@link #setText}</code>.\r
-     * @type String\r
-     */\r
-    this.text = attributes.text;\r
+ Ext.tree.AsyncTreeNode = function(config){\r
+    this.loaded = config && config.loaded === true;\r
+    this.loading = false;\r
+    Ext.tree.AsyncTreeNode.superclass.constructor.apply(this, arguments);\r
     /**\r
-     * True if this node is disabled.\r
-     * @type Boolean\r
-     */\r
-    this.disabled = attributes.disabled === true;\r
+    * @event beforeload\r
+    * Fires before this node is loaded, return false to cancel\r
+    * @param {Node} this This node\r
+    */\r
+    this.addEvents('beforeload', 'load');\r
     /**\r
-     * True if this node is hidden.\r
-     * @type Boolean\r
-     */\r
-    this.hidden = attributes.hidden === true;\r
-\r
-    this.addEvents(\r
-        /**\r
-        * @event textchange\r
-        * Fires when the text for this node is changed\r
-        * @param {Node} this This node\r
-        * @param {String} text The new text\r
-        * @param {String} oldText The old text\r
-        */\r
-        'textchange',\r
-        /**\r
-        * @event beforeexpand\r
-        * Fires before this node is expanded, return false to cancel.\r
-        * @param {Node} this This node\r
-        * @param {Boolean} deep\r
-        * @param {Boolean} anim\r
-        */\r
-        'beforeexpand',\r
-        /**\r
-        * @event beforecollapse\r
-        * Fires before this node is collapsed, return false to cancel.\r
-        * @param {Node} this This node\r
-        * @param {Boolean} deep\r
-        * @param {Boolean} anim\r
-        */\r
-        'beforecollapse',\r
-        /**\r
-        * @event expand\r
-        * Fires when this node is expanded\r
-        * @param {Node} this This node\r
-        */\r
-        'expand',\r
-        /**\r
-        * @event disabledchange\r
-        * Fires when the disabled status of this node changes\r
-        * @param {Node} this This node\r
-        * @param {Boolean} disabled\r
-        */\r
-        'disabledchange',\r
-        /**\r
-        * @event collapse\r
-        * Fires when this node is collapsed\r
-        * @param {Node} this This node\r
-        */\r
-        'collapse',\r
-        /**\r
-        * @event beforeclick\r
-        * Fires before click processing. Return false to cancel the default action.\r
-        * @param {Node} this This node\r
-        * @param {Ext.EventObject} e The event object\r
-        */\r
-        'beforeclick',\r
-        /**\r
-        * @event click\r
-        * Fires when this node is clicked\r
-        * @param {Node} this This node\r
-        * @param {Ext.EventObject} e The event object\r
-        */\r
-        'click',\r
-        /**\r
-        * @event checkchange\r
-        * Fires when a node with a checkbox's checked property changes\r
-        * @param {Node} this This node\r
-        * @param {Boolean} checked\r
-        */\r
-        'checkchange',\r
-        /**\r
-        * @event beforedblclick\r
-        * Fires before double click processing. Return false to cancel the default action.\r
-        * @param {Node} this This node\r
-        * @param {Ext.EventObject} e The event object\r
-        */\r
-        'beforedblclick',\r
-        /**\r
-        * @event dblclick\r
-        * Fires when this node is double clicked\r
-        * @param {Node} this This node\r
-        * @param {Ext.EventObject} e The event object\r
-        */\r
-        'dblclick',\r
-        /**\r
-        * @event contextmenu\r
-        * Fires when this node is right clicked\r
-        * @param {Node} this This node\r
-        * @param {Ext.EventObject} e The event object\r
-        */\r
-        'contextmenu',\r
-        /**\r
-        * @event beforechildrenrendered\r
-        * Fires right before the child nodes for this node are rendered\r
-        * @param {Node} this This node\r
-        */\r
-        'beforechildrenrendered'\r
-    );\r
-\r
-    var uiClass = this.attributes.uiProvider || this.defaultUI || Ext.tree.TreeNodeUI;\r
-\r
+    * @event load\r
+    * Fires when this node is loaded\r
+    * @param {Node} this This node\r
+    */\r
     /**\r
-     * Read-only. The UI for this node\r
-     * @type TreeNodeUI\r
+     * The loader used by this node (defaults to using the tree's defined loader)\r
+     * @type TreeLoader\r
+     * @property loader\r
      */\r
-    this.ui = new uiClass(this);\r
 };\r
-Ext.extend(Ext.tree.TreeNode, Ext.data.Node, {\r
-    preventHScroll : true,\r
+Ext.extend(Ext.tree.AsyncTreeNode, Ext.tree.TreeNode, {\r
+    expand : function(deep, anim, callback, scope){\r
+        if(this.loading){ // if an async load is already running, waiting til it's done\r
+            var timer;\r
+            var f = function(){\r
+                if(!this.loading){ // done loading\r
+                    clearInterval(timer);\r
+                    this.expand(deep, anim, callback, scope);\r
+                }\r
+            }.createDelegate(this);\r
+            timer = setInterval(f, 200);\r
+            return;\r
+        }\r
+        if(!this.loaded){\r
+            if(this.fireEvent("beforeload", this) === false){\r
+                return;\r
+            }\r
+            this.loading = true;\r
+            this.ui.beforeLoad(this);\r
+            var loader = this.loader || this.attributes.loader || this.getOwnerTree().getLoader();\r
+            if(loader){\r
+                loader.load(this, this.loadComplete.createDelegate(this, [deep, anim, callback, scope]), this);\r
+                return;\r
+            }\r
+        }\r
+        Ext.tree.AsyncTreeNode.superclass.expand.call(this, deep, anim, callback, scope);\r
+    },\r
+    \r
     /**\r
-     * Returns true if this node is expanded\r
+     * Returns true if this node is currently loading\r
      * @return {Boolean}\r
      */\r
-    isExpanded : function(){\r
-        return this.expanded;\r
-    },\r
-\r
-/**\r
- * Returns the UI object for this node.\r
- * @return {TreeNodeUI} The object which is providing the user interface for this tree\r
- * node. Unless otherwise specified in the {@link #uiProvider}, this will be an instance\r
- * of {@link Ext.tree.TreeNodeUI}\r
- */\r
-    getUI : function(){\r
-        return this.ui;\r
-    },\r
-\r
-    getLoader : function(){\r
-        var owner;\r
-        return this.loader || ((owner = this.getOwnerTree()) && owner.loader ? owner.loader : new Ext.tree.TreeLoader());\r
-    },\r
-\r
-    // private override\r
-    setFirstChild : function(node){\r
-        var of = this.firstChild;\r
-        Ext.tree.TreeNode.superclass.setFirstChild.call(this, node);\r
-        if(this.childrenRendered && of && node != of){\r
-            of.renderIndent(true, true);\r
-        }\r
-        if(this.rendered){\r
-            this.renderIndent(true, true);\r
-        }\r
+    isLoading : function(){\r
+        return this.loading;  \r
     },\r
-\r
-    // private override\r
-    setLastChild : function(node){\r
-        var ol = this.lastChild;\r
-        Ext.tree.TreeNode.superclass.setLastChild.call(this, node);\r
-        if(this.childrenRendered && ol && node != ol){\r
-            ol.renderIndent(true, true);\r
-        }\r
-        if(this.rendered){\r
-            this.renderIndent(true, true);\r
-        }\r
+    \r
+    loadComplete : function(deep, anim, callback, scope){\r
+        this.loading = false;\r
+        this.loaded = true;\r
+        this.ui.afterLoad(this);\r
+        this.fireEvent("load", this);\r
+        this.expand(deep, anim, callback, scope);\r
     },\r
-\r
-    // these methods are overridden to provide lazy rendering support\r
-    // private override\r
-    appendChild : function(n){\r
-        if(!n.render && !Ext.isArray(n)){\r
-            n = this.getLoader().createNode(n);\r
-        }\r
-        var node = Ext.tree.TreeNode.superclass.appendChild.call(this, n);\r
-        if(node && this.childrenRendered){\r
-            node.render();\r
-        }\r
-        this.ui.updateExpandIcon();\r
-        return node;\r
+    \r
+    /**\r
+     * Returns true if this node has been loaded\r
+     * @return {Boolean}\r
+     */\r
+    isLoaded : function(){\r
+        return this.loaded;\r
     },\r
-\r
-    // private override\r
-    removeChild : function(node){\r
-        this.ownerTree.getSelectionModel().unselect(node);\r
-        Ext.tree.TreeNode.superclass.removeChild.apply(this, arguments);\r
-        // if it's been rendered remove dom node\r
-        if(this.childrenRendered){\r
-            node.ui.remove();\r
-        }\r
-        if(this.childNodes.length < 1){\r
-            this.collapse(false, false);\r
+    \r
+    hasChildNodes : function(){\r
+        if(!this.isLeaf() && !this.loaded){\r
+            return true;\r
         }else{\r
-            this.ui.updateExpandIcon();\r
-        }\r
-        if(!this.firstChild && !this.isHiddenRoot()) {\r
-            this.childrenRendered = false;\r
-        }\r
-        return node;\r
-    },\r
-\r
-    // private override\r
-    insertBefore : function(node, refNode){\r
-        if(!node.render){\r
-            node = this.getLoader().createNode(node);\r
-        }\r
-        var newNode = Ext.tree.TreeNode.superclass.insertBefore.call(this, node, refNode);\r
-        if(newNode && refNode && this.childrenRendered){\r
-            node.render();\r
+            return Ext.tree.AsyncTreeNode.superclass.hasChildNodes.call(this);\r
         }\r
-        this.ui.updateExpandIcon();\r
-        return newNode;\r
     },\r
 \r
     /**\r
-     * Sets the text for this node\r
-     * @param {String} text\r
+     * Trigger a reload for this node\r
+     * @param {Function} callback\r
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the callback is executed. Defaults to this Node.\r
      */\r
-    setText : function(text){\r
-        var oldText = this.text;\r
-        this.text = text;\r
-        this.attributes.text = text;\r
-        if(this.rendered){ // event without subscribing\r
-            this.ui.onTextChange(this, text, oldText);\r
-        }\r
-        this.fireEvent('textchange', this, text, oldText);\r
-    },\r
-\r
-    /**\r
-     * Triggers selection of this node\r
-     */\r
-    select : function(){\r
-        this.getOwnerTree().getSelectionModel().select(this);\r
-    },\r
-\r
-    /**\r
-     * Triggers deselection of this node\r
-     */\r
-    unselect : function(){\r
-        this.getOwnerTree().getSelectionModel().unselect(this);\r
-    },\r
-\r
-    /**\r
-     * Returns true if this node is selected\r
-     * @return {Boolean}\r
-     */\r
-    isSelected : function(){\r
-        return this.getOwnerTree().getSelectionModel().isSelected(this);\r
-    },\r
-\r
-    /**\r
-     * Expand this node.\r
-     * @param {Boolean} deep (optional) True to expand all children as well\r
-     * @param {Boolean} anim (optional) false to cancel the default animation\r
-     * @param {Function} callback (optional) A callback to be called when\r
-     * expanding this node completes (does not wait for deep expand to complete).\r
-     * Called with 1 parameter, this node.\r
-     * @param {Object} scope (optional) The scope in which to execute the callback.\r
-     */\r
-    expand : function(deep, anim, callback, scope){\r
-        if(!this.expanded){\r
-            if(this.fireEvent('beforeexpand', this, deep, anim) === false){\r
-                return;\r
-            }\r
-            if(!this.childrenRendered){\r
-                this.renderChildren();\r
-            }\r
-            this.expanded = true;\r
-            if(!this.isHiddenRoot() && (this.getOwnerTree().animate && anim !== false) || anim){\r
-                this.ui.animExpand(function(){\r
-                    this.fireEvent('expand', this);\r
-                    this.runCallback(callback, scope || this, [this]);\r
-                    if(deep === true){\r
-                        this.expandChildNodes(true);\r
-                    }\r
-                }.createDelegate(this));\r
-                return;\r
-            }else{\r
-                this.ui.expand();\r
-                this.fireEvent('expand', this);\r
-                this.runCallback(callback, scope || this, [this]);\r
-            }\r
-        }else{\r
-           this.runCallback(callback, scope || this, [this]);\r
-        }\r
-        if(deep === true){\r
-            this.expandChildNodes(true);\r
-        }\r
-    },\r
-\r
-    runCallback : function(cb, scope, args){\r
-        if(Ext.isFunction(cb)){\r
-            cb.apply(scope, args);\r
-        }\r
-    },\r
-\r
-    isHiddenRoot : function(){\r
-        return this.isRoot && !this.getOwnerTree().rootVisible;\r
-    },\r
-\r
-    /**\r
-     * Collapse this node.\r
-     * @param {Boolean} deep (optional) True to collapse all children as well\r
-     * @param {Boolean} anim (optional) false to cancel the default animation\r
-     * @param {Function} callback (optional) A callback to be called when\r
-     * expanding this node completes (does not wait for deep expand to complete).\r
-     * Called with 1 parameter, this node.\r
-     * @param {Object} scope (optional) The scope in which to execute the callback.\r
-     */\r
-    collapse : function(deep, anim, callback, scope){\r
-        if(this.expanded && !this.isHiddenRoot()){\r
-            if(this.fireEvent('beforecollapse', this, deep, anim) === false){\r
-                return;\r
-            }\r
-            this.expanded = false;\r
-            if((this.getOwnerTree().animate && anim !== false) || anim){\r
-                this.ui.animCollapse(function(){\r
-                    this.fireEvent('collapse', this);\r
-                    this.runCallback(callback, scope || this, [this]);\r
-                    if(deep === true){\r
-                        this.collapseChildNodes(true);\r
-                    }\r
-                }.createDelegate(this));\r
-                return;\r
-            }else{\r
-                this.ui.collapse();\r
-                this.fireEvent('collapse', this);\r
-                this.runCallback(callback, scope || this, [this]);\r
-            }\r
-        }else if(!this.expanded){\r
-            this.runCallback(callback, scope || this, [this]);\r
-        }\r
-        if(deep === true){\r
-            var cs = this.childNodes;\r
-            for(var i = 0, len = cs.length; i < len; i++) {\r
-               cs[i].collapse(true, false);\r
-            }\r
-        }\r
-    },\r
-\r
-    // private\r
-    delayedExpand : function(delay){\r
-        if(!this.expandProcId){\r
-            this.expandProcId = this.expand.defer(delay, this);\r
-        }\r
-    },\r
-\r
-    // private\r
-    cancelExpand : function(){\r
-        if(this.expandProcId){\r
-            clearTimeout(this.expandProcId);\r
-        }\r
-        this.expandProcId = false;\r
-    },\r
-\r
-    /**\r
-     * Toggles expanded/collapsed state of the node\r
-     */\r
-    toggle : function(){\r
-        if(this.expanded){\r
-            this.collapse();\r
-        }else{\r
-            this.expand();\r
-        }\r
-    },\r
-\r
-    /**\r
-     * Ensures all parent nodes are expanded, and if necessary, scrolls\r
-     * the node into view.\r
-     * @param {Function} callback (optional) A function to call when the node has been made visible.\r
-     * @param {Object} scope (optional) The scope in which to execute the callback.\r
-     */\r
-    ensureVisible : function(callback, scope){\r
-        var tree = this.getOwnerTree();\r
-        tree.expandPath(this.parentNode ? this.parentNode.getPath() : this.getPath(), false, function(){\r
-            var node = tree.getNodeById(this.id);  // Somehow if we don't do this, we lose changes that happened to node in the meantime\r
-            tree.getTreeEl().scrollChildIntoView(node.ui.anchor);\r
-            this.runCallback(callback, scope || this, [this]);\r
-        }.createDelegate(this));\r
-    },\r
-\r
-    /**\r
-     * Expand all child nodes\r
-     * @param {Boolean} deep (optional) true if the child nodes should also expand their child nodes\r
-     */\r
-    expandChildNodes : function(deep){\r
-        var cs = this.childNodes;\r
-        for(var i = 0, len = cs.length; i < len; i++) {\r
-               cs[i].expand(deep);\r
-        }\r
-    },\r
-\r
-    /**\r
-     * Collapse all child nodes\r
-     * @param {Boolean} deep (optional) true if the child nodes should also collapse their child nodes\r
-     */\r
-    collapseChildNodes : function(deep){\r
-        var cs = this.childNodes;\r
-        for(var i = 0, len = cs.length; i < len; i++) {\r
-               cs[i].collapse(deep);\r
-        }\r
-    },\r
-\r
-    /**\r
-     * Disables this node\r
-     */\r
-    disable : function(){\r
-        this.disabled = true;\r
-        this.unselect();\r
-        if(this.rendered && this.ui.onDisableChange){ // event without subscribing\r
-            this.ui.onDisableChange(this, true);\r
-        }\r
-        this.fireEvent('disabledchange', this, true);\r
-    },\r
-\r
-    /**\r
-     * Enables this node\r
-     */\r
-    enable : function(){\r
-        this.disabled = false;\r
-        if(this.rendered && this.ui.onDisableChange){ // event without subscribing\r
-            this.ui.onDisableChange(this, false);\r
-        }\r
-        this.fireEvent('disabledchange', this, false);\r
-    },\r
-\r
-    // private\r
-    renderChildren : function(suppressEvent){\r
-        if(suppressEvent !== false){\r
-            this.fireEvent('beforechildrenrendered', this);\r
-        }\r
-        var cs = this.childNodes;\r
-        for(var i = 0, len = cs.length; i < len; i++){\r
-            cs[i].render(true);\r
-        }\r
-        this.childrenRendered = true;\r
-    },\r
-\r
-    // private\r
-    sort : function(fn, scope){\r
-        Ext.tree.TreeNode.superclass.sort.apply(this, arguments);\r
-        if(this.childrenRendered){\r
-            var cs = this.childNodes;\r
-            for(var i = 0, len = cs.length; i < len; i++){\r
-                cs[i].render(true);\r
-            }\r
-        }\r
-    },\r
-\r
-    // private\r
-    render : function(bulkRender){\r
-        this.ui.render(bulkRender);\r
-        if(!this.rendered){\r
-            // make sure it is registered\r
-            this.getOwnerTree().registerNode(this);\r
-            this.rendered = true;\r
-            if(this.expanded){\r
-                this.expanded = false;\r
-                this.expand(false, false);\r
-            }\r
-        }\r
-    },\r
-\r
-    // private\r
-    renderIndent : function(deep, refresh){\r
-        if(refresh){\r
-            this.ui.childIndent = null;\r
-        }\r
-        this.ui.renderIndent();\r
-        if(deep === true && this.childrenRendered){\r
-            var cs = this.childNodes;\r
-            for(var i = 0, len = cs.length; i < len; i++){\r
-                cs[i].renderIndent(true, refresh);\r
-            }\r
-        }\r
-    },\r
-\r
-    beginUpdate : function(){\r
-        this.childrenRendered = false;\r
-    },\r
-\r
-    endUpdate : function(){\r
-        if(this.expanded && this.rendered){\r
-            this.renderChildren();\r
-        }\r
-    },\r
-\r
-    destroy : function(){\r
-        if(this.childNodes){\r
-            for(var i = 0,l = this.childNodes.length; i < l; i++){\r
-                this.childNodes[i].destroy();\r
-            }\r
-            this.childNodes = null;\r
-        }\r
-        if(this.ui.destroy){\r
-            this.ui.destroy();\r
-        }\r
-    },\r
-\r
-    // private\r
-    onIdChange : function(id){\r
-        this.ui.onIdChange(id);\r
-    }\r
-});\r
-\r
-Ext.tree.TreePanel.nodeTypes.node = Ext.tree.TreeNode;/**\r
- * @class Ext.tree.AsyncTreeNode\r
- * @extends Ext.tree.TreeNode\r
- * @cfg {TreeLoader} loader A TreeLoader to be used by this node (defaults to the loader defined on the tree)\r
- * @constructor\r
- * @param {Object/String} attributes The attributes/config for the node or just a string with the text for the node \r
- */\r
- Ext.tree.AsyncTreeNode = function(config){\r
-    this.loaded = config && config.loaded === true;\r
-    this.loading = false;\r
-    Ext.tree.AsyncTreeNode.superclass.constructor.apply(this, arguments);\r
-    /**\r
-    * @event beforeload\r
-    * Fires before this node is loaded, return false to cancel\r
-    * @param {Node} this This node\r
-    */\r
-    this.addEvents('beforeload', 'load');\r
-    /**\r
-    * @event load\r
-    * Fires when this node is loaded\r
-    * @param {Node} this This node\r
-    */\r
-    /**\r
-     * The loader used by this node (defaults to using the tree's defined loader)\r
-     * @type TreeLoader\r
-     * @property loader\r
-     */\r
-};\r
-Ext.extend(Ext.tree.AsyncTreeNode, Ext.tree.TreeNode, {\r
-    expand : function(deep, anim, callback, scope){\r
-        if(this.loading){ // if an async load is already running, waiting til it's done\r
-            var timer;\r
-            var f = function(){\r
-                if(!this.loading){ // done loading\r
-                    clearInterval(timer);\r
-                    this.expand(deep, anim, callback, scope);\r
-                }\r
-            }.createDelegate(this);\r
-            timer = setInterval(f, 200);\r
-            return;\r
-        }\r
-        if(!this.loaded){\r
-            if(this.fireEvent("beforeload", this) === false){\r
-                return;\r
-            }\r
-            this.loading = true;\r
-            this.ui.beforeLoad(this);\r
-            var loader = this.loader || this.attributes.loader || this.getOwnerTree().getLoader();\r
-            if(loader){\r
-                loader.load(this, this.loadComplete.createDelegate(this, [deep, anim, callback, scope]), this);\r
-                return;\r
-            }\r
-        }\r
-        Ext.tree.AsyncTreeNode.superclass.expand.call(this, deep, anim, callback, scope);\r
-    },\r
-    \r
-    /**\r
-     * Returns true if this node is currently loading\r
-     * @return {Boolean}\r
-     */\r
-    isLoading : function(){\r
-        return this.loading;  \r
-    },\r
-    \r
-    loadComplete : function(deep, anim, callback, scope){\r
-        this.loading = false;\r
-        this.loaded = true;\r
-        this.ui.afterLoad(this);\r
-        this.fireEvent("load", this);\r
-        this.expand(deep, anim, callback, scope);\r
-    },\r
-    \r
-    /**\r
-     * Returns true if this node has been loaded\r
-     * @return {Boolean}\r
-     */\r
-    isLoaded : function(){\r
-        return this.loaded;\r
-    },\r
-    \r
-    hasChildNodes : function(){\r
-        if(!this.isLeaf() && !this.loaded){\r
-            return true;\r
-        }else{\r
-            return Ext.tree.AsyncTreeNode.superclass.hasChildNodes.call(this);\r
-        }\r
-    },\r
-\r
-    /**\r
-     * Trigger a reload for this node\r
-     * @param {Function} callback\r
-     * @param {Object} scope (optional) The scope in which to execute the callback.\r
-     */\r
-    reload : function(callback, scope){\r
-        this.collapse(false, false);\r
-        while(this.firstChild){\r
-            this.removeChild(this.firstChild).destroy();\r
+    reload : function(callback, scope){\r
+        this.collapse(false, false);\r
+        while(this.firstChild){\r
+            this.removeChild(this.firstChild).destroy();\r
         }\r
         this.childrenRendered = false;\r
         this.loaded = false;\r
@@ -48185,7 +50445,7 @@ Ext.tree.TreeNodeUI.prototype = {
     removeChild : function(node){\r
         if(this.rendered){\r
             this.ctNode.removeChild(node.ui.getEl());\r
-        } \r
+        }\r
     },\r
 \r
     // private\r
@@ -48208,14 +50468,14 @@ Ext.tree.TreeNodeUI.prototype = {
     // private\r
     onDisableChange : function(node, state){\r
         this.disabled = state;\r
-               if (this.checkbox) {\r
-                       this.checkbox.disabled = state;\r
-               }        \r
+        if (this.checkbox) {\r
+            this.checkbox.disabled = state;\r
+        }\r
         if(state){\r
             this.addClass("x-tree-node-disabled");\r
         }else{\r
             this.removeClass("x-tree-node-disabled");\r
-        } \r
+        }\r
     },\r
 \r
     // private\r
@@ -48266,7 +50526,7 @@ Ext.tree.TreeNodeUI.prototype = {
  */\r
     removeClass : function(cls){\r
         if(this.elNode){\r
-            Ext.fly(this.elNode).removeClass(cls);  \r
+            Ext.fly(this.elNode).removeClass(cls);\r
         }\r
     },\r
 \r
@@ -48275,12 +50535,12 @@ Ext.tree.TreeNodeUI.prototype = {
         if(this.rendered){\r
             this.holder = document.createElement("div");\r
             this.holder.appendChild(this.wrap);\r
-        }  \r
+        }\r
     },\r
 \r
     // private\r
     fireEvent : function(){\r
-        return this.node.fireEvent.apply(this.node, arguments);  \r
+        return this.node.fireEvent.apply(this.node, arguments);\r
     },\r
 \r
     // private\r
@@ -48288,7 +50548,7 @@ Ext.tree.TreeNodeUI.prototype = {
         this.node.on("move", this.onMove, this);\r
 \r
         if(this.node.disabled){\r
-            this.onDisableChange(this.node, true);            \r
+            this.onDisableChange(this.node, true);\r
         }\r
         if(this.node.hidden){\r
             this.hide();\r
@@ -48326,7 +50586,7 @@ Ext.tree.TreeNodeUI.prototype = {
         this.node.hidden = false;\r
         if(this.wrap){\r
             this.wrap.style.display = "";\r
-        } \r
+        }\r
     },\r
 \r
     // private\r
@@ -48395,8 +50655,8 @@ Ext.tree.TreeNodeUI.prototype = {
     // private\r
     onCheckChange : function(){\r
         var checked = this.checkbox.checked;\r
-               // fix for IE6\r
-               this.checkbox.defaultChecked = checked;         \r
+        // fix for IE6\r
+        this.checkbox.defaultChecked = checked;\r
         this.node.attributes.checked = checked;\r
         this.fireEvent('checkchange', this.node, checked);\r
     },\r
@@ -48412,12 +50672,12 @@ Ext.tree.TreeNodeUI.prototype = {
     startDrop : function(){\r
         this.dropping = true;\r
     },\r
-    \r
+\r
     // delayed drop so the click event doesn't get fired on a drop\r
-    endDrop : function(){ \r
+    endDrop : function(){\r
        setTimeout(function(){\r
            this.dropping = false;\r
-       }.createDelegate(this), 50); \r
+       }.createDelegate(this), 50);\r
     },\r
 \r
     // private\r
@@ -48458,7 +50718,7 @@ Ext.tree.TreeNodeUI.prototype = {
     blur : function(){\r
         try{\r
             this.anchor.blur();\r
-        }catch(e){} \r
+        }catch(e){}\r
     },\r
 \r
     // private\r
@@ -48473,7 +50733,7 @@ Ext.tree.TreeNodeUI.prototype = {
         }\r
         this.animating = true;\r
         this.updateExpandIcon();\r
-        \r
+\r
         ct.slideIn('t', {\r
            callback : function(){\r
                this.animating = false;\r
@@ -48520,12 +50780,15 @@ Ext.tree.TreeNodeUI.prototype = {
 \r
     // private\r
     getContainer : function(){\r
-        return this.ctNode;  \r
+        return this.ctNode;\r
     },\r
 \r
-    // private\r
+/**\r
+ * Returns the element which encapsulates this node.\r
+ * @return {HtmlElement} The DOM element. The default implementation uses a <code>&lt;li></code>.\r
+ */\r
     getEl : function(){\r
-        return this.wrap;  \r
+        return this.wrap;\r
     },\r
 \r
     // private\r
@@ -48540,15 +50803,15 @@ Ext.tree.TreeNodeUI.prototype = {
 \r
     // private\r
     onRender : function(){\r
-        this.render();    \r
+        this.render();\r
     },\r
 \r
     // private\r
     render : function(bulkRender){\r
         var n = this.node, a = n.attributes;\r
-        var targetNode = n.parentNode ? \r
+        var targetNode = n.parentNode ?\r
               n.parentNode.ui.getContainer() : n.ownerTree.innerCt.dom;\r
-        \r
+\r
         if(!this.rendered){\r
             this.rendered = true;\r
 \r
@@ -48565,7 +50828,7 @@ Ext.tree.TreeNodeUI.prototype = {
                    if(a.qtipTitle){\r
                        this.textNode.setAttribute("ext:qtitle", a.qtipTitle);\r
                    }\r
-               } \r
+               }\r
             }else if(a.qtipCfg){\r
                 a.qtipCfg.target = Ext.id(this.textNode);\r
                 Ext.QuickTips.register(a.qtipCfg);\r
@@ -48586,10 +50849,10 @@ Ext.tree.TreeNodeUI.prototype = {
         // add some indent caching, this helps performance when rendering a large tree\r
         this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';\r
 \r
-        var cb = typeof a.checked == 'boolean';\r
-\r
-        var href = a.href ? a.href : Ext.isGecko ? "" : "#";\r
-        var buf = ['<li class="x-tree-node"><div ext:tree-node-id="',n.id,'" class="x-tree-node-el x-tree-node-leaf x-unselectable ', a.cls,'" unselectable="on">',\r
+        var cb = Ext.isBoolean(a.checked),\r
+            nel,\r
+            href = a.href ? a.href : Ext.isGecko ? "" : "#",\r
+            buf = ['<li class="x-tree-node"><div ext:tree-node-id="',n.id,'" class="x-tree-node-el x-tree-node-leaf x-unselectable ', a.cls,'" unselectable="on">',\r
             '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",\r
             '<img src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow" />',\r
             '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on" />',\r
@@ -48599,13 +50862,12 @@ Ext.tree.TreeNodeUI.prototype = {
             '<ul class="x-tree-node-ct" style="display:none;"></ul>',\r
             "</li>"].join('');\r
 \r
-        var nel;\r
         if(bulkRender !== true && n.nextSibling && (nel = n.nextSibling.ui.getEl())){\r
             this.wrap = Ext.DomHelper.insertHtml("beforeBegin", nel, buf);\r
         }else{\r
             this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf);\r
         }\r
-        \r
+\r
         this.elNode = this.wrap.childNodes[0];\r
         this.ctNode = this.wrap.childNodes[1];\r
         var cs = this.elNode.childNodes;\r
@@ -48615,8 +50877,8 @@ Ext.tree.TreeNodeUI.prototype = {
         var index = 3;\r
         if(cb){\r
             this.checkbox = cs[3];\r
-                       // fix for IE6\r
-                       this.checkbox.defaultChecked = this.checkbox.checked;                                           \r
+            // fix for IE6\r
+            this.checkbox.defaultChecked = this.checkbox.checked;\r
             index++;\r
         }\r
         this.anchor = cs[index];\r
@@ -48630,7 +50892,7 @@ Ext.tree.TreeNodeUI.prototype = {
     getAnchor : function(){\r
         return this.anchor;\r
     },\r
-    \r
+\r
 /**\r
  * Returns the text node.\r
  * @return {HtmlNode} The DOM text node.\r
@@ -48638,7 +50900,7 @@ Ext.tree.TreeNodeUI.prototype = {
     getTextEl : function(){\r
         return this.textNode;\r
     },\r
-    \r
+\r
 /**\r
  * Returns the icon &lt;img> element.\r
  * @return {HtmlElement} The DOM image element.\r
@@ -48653,15 +50915,17 @@ Ext.tree.TreeNodeUI.prototype = {
  * @return {Boolean} The checked flag.\r
  */\r
     isChecked : function(){\r
-        return this.checkbox ? this.checkbox.checked : false; \r
+        return this.checkbox ? this.checkbox.checked : false;\r
     },\r
 \r
     // private\r
     updateExpandIcon : function(){\r
         if(this.rendered){\r
-            var n = this.node, c1, c2;\r
-            var cls = n.isLast() ? "x-tree-elbow-end" : "x-tree-elbow";\r
-            var hasChild = n.hasChildNodes();\r
+            var n = this.node,\r
+                c1,\r
+                c2,\r
+                cls = n.isLast() ? "x-tree-elbow-end" : "x-tree-elbow",\r
+                hasChild = n.hasChildNodes();\r
             if(hasChild || n.attributes.expandable){\r
                 if(n.expanded){\r
                     cls += "-minus";\r
@@ -48682,7 +50946,7 @@ Ext.tree.TreeNodeUI.prototype = {
                 }\r
             }else{\r
                 if(!this.wasLeaf){\r
-                    Ext.fly(this.elNode).replaceClass("x-tree-node-expanded", "x-tree-node-leaf");\r
+                    Ext.fly(this.elNode).replaceClass("x-tree-node-expanded", "x-tree-node-collapsed");\r
                     delete this.c1;\r
                     delete this.c2;\r
                     this.wasLeaf = true;\r
@@ -48695,7 +50959,7 @@ Ext.tree.TreeNodeUI.prototype = {
             }\r
         }\r
     },\r
-    \r
+\r
     // private\r
     onIdChange: function(id){\r
         if(this.rendered){\r
@@ -48706,8 +50970,8 @@ Ext.tree.TreeNodeUI.prototype = {
     // private\r
     getChildIndent : function(){\r
         if(!this.childIndent){\r
-            var buf = [];\r
-            var p = this.node;\r
+            var buf = [],\r
+                p = this.node;\r
             while(p){\r
                 if(!p.isRoot || (p.isRoot && p.ownerTree.rootVisible)){\r
                     if(!p.isLast()) {\r
@@ -48726,8 +50990,8 @@ Ext.tree.TreeNodeUI.prototype = {
     // private\r
     renderIndent : function(){\r
         if(this.rendered){\r
-            var indent = "";\r
-            var p = this.node.parentNode;\r
+            var indent = "",\r
+                p = this.node.parentNode;\r
             if(p){\r
                 indent = p.ui.getChildIndent();\r
             }\r
@@ -48743,23 +51007,14 @@ Ext.tree.TreeNodeUI.prototype = {
         if(this.elNode){\r
             Ext.dd.Registry.unregister(this.elNode.id);\r
         }\r
-        delete this.elNode;\r
-        delete this.ctNode;\r
-        delete this.indentNode;\r
-        delete this.ecNode;\r
-        delete this.iconNode;\r
-        delete this.checkbox;\r
-        delete this.anchor;\r
-        delete this.textNode;\r
-        \r
-        if (this.holder){\r
-             delete this.wrap;\r
-             Ext.removeNode(this.holder);\r
-             delete this.holder;\r
-        }else{\r
-            Ext.removeNode(this.wrap);\r
-            delete this.wrap;\r
-        }\r
+\r
+        Ext.each(['textnode', 'anchor', 'checkbox', 'indentNode', 'ecNode', 'iconNode', 'elNode', 'ctNode', 'wrap', 'holder'], function(el){\r
+            if(this[el]){\r
+                Ext.fly(this[el]).remove();\r
+                delete this[el];\r
+            }\r
+        }, this);\r
+        delete this.node;\r
     }\r
 };\r
 \r
@@ -48853,7 +51108,7 @@ Ext.tree.TreeLoader = function(config){
         "loadexception"\r
     );\r
     Ext.tree.TreeLoader.superclass.constructor.call(this);\r
-    if(typeof this.paramOrder == 'string'){\r
+    if(Ext.isString(this.paramOrder)){\r
         this.paramOrder = this.paramOrder.split(/[\s,|]/);\r
     }\r
 };\r
@@ -48899,15 +51154,15 @@ Ext.extend(Ext.tree.TreeLoader, Ext.util.Observable, {
 \r
     /**\r
      * @cfg {Array/String} paramOrder Defaults to <tt>undefined</tt>. Only used when using directFn.\r
-     * A list of params to be executed\r
-     * server side.  Specify the params in the order in which they must be executed on the server-side\r
+     * Specifies the params in the order in which they must be passed to the server-side Direct method\r
      * as either (1) an Array of String values, or (2) a String of params delimited by either whitespace,\r
      * comma, or pipe. For example,\r
      * any of the following would be acceptable:<pre><code>\r
+nodeParameter: 'node',\r
 paramOrder: ['param1','param2','param3']\r
-paramOrder: 'param1 param2 param3'\r
-paramOrder: 'param1,param2,param3'\r
-paramOrder: 'param1|param2|param'\r
+paramOrder: 'node param1 param2 param3'\r
+paramOrder: 'param1,node,param2,param3'\r
+paramOrder: 'param1|param2|param|node'\r
      </code></pre>\r
      */\r
     paramOrder: undefined,\r
@@ -48919,6 +51174,12 @@ paramOrder: 'param1|param2|param'
      */\r
     paramsAsHash: false,\r
 \r
+    /**\r
+     * @cfg {String} nodeParameter The name of the parameter sent to the server which contains\r
+     * the identifier of the node. Defaults to <tt>'node'</tt>.\r
+     */\r
+    nodeParameter: 'node',\r
+\r
     /**\r
      * @cfg {Function} directFn\r
      * Function to call when executing a request.\r
@@ -48930,8 +51191,10 @@ paramOrder: 'param1|param2|param'
      * This is called automatically when a node is expanded, but may be used to reload\r
      * a node (or append new children if the {@link #clearOnLoad} option is false.)\r
      * @param {Ext.tree.TreeNode} node\r
-     * @param {Function} callback\r
-     * @param (Object) scope\r
+     * @param {Function} callback Function to call after the node has been loaded. The\r
+     * function is passed the TreeNode which was requested to be loaded.\r
+     * @param (Object) scope The cope (<code>this</code> reference) in which the callback is executed.\r
+     * defaults to the loaded TreeNode.\r
      */\r
     load : function(node, callback, scope){\r
         if(this.clearOnLoad){\r
@@ -48965,27 +51228,29 @@ paramOrder: 'param1|param2|param'
     },\r
 \r
     getParams: function(node){\r
-        var buf = [], bp = this.baseParams;\r
+        var bp = Ext.apply({}, this.baseParams),\r
+            np = this.nodeParameter,\r
+            po = this.paramOrder;\r
+\r
+        np && (bp[ np ] = node.id);\r
+\r
         if(this.directFn){\r
-            buf.push(node.id);\r
-            if(bp){\r
-                if(this.paramOrder){\r
-                    for(var i = 0, len = this.paramOrder.length; i < len; i++){\r
-                        buf.push(bp[this.paramOrder[i]]);\r
-                    }\r
-                }else if(this.paramsAsHash){\r
-                    buf.push(bp);\r
+            var buf = [node.id];\r
+            if(po){\r
+                // reset 'buf' if the nodeParameter was included in paramOrder\r
+                if(np && po.indexOf(np) > -1){\r
+                    buf = [];\r
+                }\r
+\r
+                for(var i = 0, len = po.length; i < len; i++){\r
+                    buf.push(bp[ po[i] ]);\r
                 }\r
+            }else if(this.paramsAsHash){\r
+                buf = [bp];\r
             }\r
             return buf;\r
         }else{\r
-            for(var key in bp){\r
-                if(!Ext.isFunction(bp[key])){\r
-                    buf.push(encodeURIComponent(key), "=", encodeURIComponent(bp[key]), "&");\r
-                }\r
-            }\r
-            buf.push("node=", encodeURIComponent(node.id));\r
-            return buf.join("");\r
+            return bp;\r
         }\r
     },\r
 \r
@@ -49075,7 +51340,7 @@ new Ext.tree.TreePanel({
         if(this.applyLoader !== false && !attr.loader){\r
             attr.loader = this;\r
         }\r
-        if(typeof attr.uiProvider == 'string'){\r
+        if(Ext.isString(attr.uiProvider)){\r
            attr.uiProvider = this.uiProviders[attr.uiProvider] || eval(attr.uiProvider);\r
         }\r
         if(attr.nodeType){\r
@@ -49117,6 +51382,11 @@ new Ext.tree.TreePanel({
         var a = response.argument;\r
         this.fireEvent("loadexception", this, a.node, response);\r
         this.runCallback(a.callback, a.scope || a.node, [a.node]);\r
+    },\r
+\r
+    destroy : function(){\r
+        this.abort();\r
+        this.purgeListeners();\r
     }\r
 });/**
  * @class Ext.tree.TreeFilter
@@ -49172,7 +51442,7 @@ Ext.tree.TreeFilter.prototype = {
      * node in the tree (or from the startNode). If the function returns true, the node is kept
      * otherwise it is filtered. If a node is filtered, its children are also filtered.
      * @param {Function} fn The filter function
-     * @param {Object} scope (optional) The scope of the function (defaults to the current node)
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to the current Node.
      */
     filterBy : function(fn, scope, startNode){
         startNode = startNode || this.tree.root;
@@ -49228,7 +51498,7 @@ Ext.tree.TreeFilter.prototype = {
 };
 /**\r
  * @class Ext.tree.TreeSorter\r
- * Provides sorting of nodes in a {@link Ext.tree.TreePanel}.  The TreeSorter automatically monitors events on the \r
+ * Provides sorting of nodes in a {@link Ext.tree.TreePanel}.  The TreeSorter automatically monitors events on the\r
  * associated TreePanel that might affect the tree's sort order (beforechildrenrendered, append, insert and textchange).\r
  * Example usage:<br />\r
  * <pre><code>\r
@@ -49249,33 +51519,33 @@ Ext.tree.TreeSorter = function(tree, config){
     /**\r
      * @cfg {Boolean} folderSort True to sort leaf nodes under non-leaf nodes (defaults to false)\r
      */\r
-    /** \r
-     * @cfg {String} property The named attribute on the node to sort by (defaults to "text").  Note that this \r
+    /**\r
+     * @cfg {String} property The named attribute on the node to sort by (defaults to "text").  Note that this\r
      * property is only used if no {@link #sortType} function is specified, otherwise it is ignored.\r
      */\r
-    /** \r
+    /**\r
      * @cfg {String} dir The direction to sort ("asc" or "desc," case-insensitive, defaults to "asc")\r
      */\r
-    /** \r
+    /**\r
      * @cfg {String} leafAttr The attribute used to determine leaf nodes when {@link #folderSort} = true (defaults to "leaf")\r
      */\r
-    /** \r
+    /**\r
      * @cfg {Boolean} caseSensitive true for case-sensitive sort (defaults to false)\r
      */\r
-    /** \r
+    /**\r
      * @cfg {Function} sortType A custom "casting" function used to convert node values before sorting.  The function\r
      * will be called with a single parameter (the {@link Ext.tree.TreeNode} being evaluated) and is expected to return\r
      * the node's sort value cast to the specific data type required for sorting.  This could be used, for example, when\r
-     * a node's text (or other attribute) should be sorted as a date or numeric value.  See the class description for \r
+     * a node's text (or other attribute) should be sorted as a date or numeric value.  See the class description for\r
      * example usage.  Note that if a sortType is specified, any {@link #property} config will be ignored.\r
      */\r
-    \r
+\r
     Ext.apply(this, config);\r
     tree.on("beforechildrenrendered", this.doSort, this);\r
     tree.on("append", this.updateSort, this);\r
     tree.on("insert", this.updateSort, this);\r
     tree.on("textchange", this.updateSortParent, this);\r
-    \r
+\r
     var dsc = this.dir && this.dir.toLowerCase() == "desc";\r
     var p = this.property || "text";\r
     var sortType = this.sortType;\r
@@ -49292,14 +51562,14 @@ Ext.tree.TreeSorter = function(tree, config){
                 return -1;\r
             }\r
         }\r
-       var v1 = sortType ? sortType(n1) : (cs ? n1.attributes[p] : n1.attributes[p].toUpperCase());\r
-       var v2 = sortType ? sortType(n2) : (cs ? n2.attributes[p] : n2.attributes[p].toUpperCase());\r
-       if(v1 < v2){\r
-                       return dsc ? +1 : -1;\r
-               }else if(v1 > v2){\r
-                       return dsc ? -1 : +1;\r
+        var v1 = sortType ? sortType(n1) : (cs ? n1.attributes[p] : n1.attributes[p].toUpperCase());\r
+        var v2 = sortType ? sortType(n2) : (cs ? n2.attributes[p] : n2.attributes[p].toUpperCase());\r
+        if(v1 < v2){\r
+            return dsc ? +1 : -1;\r
+        }else if(v1 > v2){\r
+            return dsc ? -1 : +1;\r
         }else{\r
-               return 0;\r
+            return 0;\r
         }\r
     };\r
 };\r
@@ -49308,20 +51578,20 @@ Ext.tree.TreeSorter.prototype = {
     doSort : function(node){\r
         node.sort(this.sortFn);\r
     },\r
-    \r
+\r
     compareNodes : function(n1, n2){\r
         return (n1.text.toUpperCase() > n2.text.toUpperCase() ? 1 : -1);\r
     },\r
-    \r
+\r
     updateSort : function(tree, node){\r
         if(node.childrenRendered){\r
             this.doSort.defer(1, this, [node]);\r
         }\r
     },\r
-    \r
+\r
     updateSortParent : function(node){\r
-               var p = node.parentNode;\r
-               if(p && p.childrenRendered){\r
+        var p = node.parentNode;\r
+        if(p && p.childrenRendered){\r
             this.doSort.defer(1, this, [p]);\r
         }\r
     }\r
@@ -49728,6 +51998,7 @@ Ext.extend(Ext.tree.TreeDragZone, Ext.dd.DragZone, {
 Ext.tree.TreeEditor = function(tree, fc, config){
     fc = fc || {};
     var field = fc.events ? fc : new Ext.form.TextField(fc);
+    
     Ext.tree.TreeEditor.superclass.constructor.call(this, field, config);
 
     this.tree = tree;
@@ -49779,12 +52050,20 @@ Ext.extend(Ext.tree.TreeEditor, Ext.Editor, {
     editDelay : 350,
 
     initEditor : function(tree){
-        tree.on('beforeclick', this.beforeNodeClick, this);
-        tree.on('dblclick', this.onNodeDblClick, this);
-        this.on('complete', this.updateNode, this);
-        this.on('beforestartedit', this.fitToTree, this);
+        tree.on({
+            scope      : this,
+            beforeclick: this.beforeNodeClick,
+            dblclick   : this.onNodeDblClick
+        });
+        
+        this.on({
+            scope          : this,
+            complete       : this.updateNode,
+            beforestartedit: this.fitToTree,
+            specialkey     : this.onSpecialKey
+        });
+        
         this.on('startedit', this.bindScroll, this, {delay:10});
-        this.on('specialkey', this.onSpecialKey, this);
     },
 
     // private
@@ -49866,6 +52145,14 @@ Ext.extend(Ext.tree.TreeEditor, Ext.Editor, {
             e.stopEvent();
             this.completeEdit();
         }
+    },
+    
+    onDestroy : function(){
+        clearTimeout(this.autoEditTimer);
+        Ext.tree.TreeEditor.superclass.onDestroy.call(this);
+        var tree = this.tree;
+        tree.un('beforeclick', this.beforeNodeClick, this);
+        tree.un('dblclick', this.onNodeDblClick, this);
     }
 });/*! SWFObject v2.2 <http://code.google.com/p/swfobject/> \r
     is released under the MIT License <http://www.opensource.org/licenses/mit-license.php> \r
@@ -50655,7 +52942,7 @@ Ext.FlashComponent = Ext.extend(Ext.BoxComponent, {
      * @cfg {String} flashVersion
      * Indicates the version the flash content was published for. Defaults to <tt>'9.0.45'</tt>.
      */
-    flashVersion : '9.0.45',
+    flashVersion : '9.0.115',
 
     /**
      * @cfg {String} backgroundColor
@@ -50701,7 +52988,14 @@ Ext.FlashComponent = Ext.extend(Ext.BoxComponent, {
     initComponent : function(){
         Ext.FlashComponent.superclass.initComponent.call(this);
 
-        this.addEvents('initialize');
+        this.addEvents(
+            /**
+             * @event initialize
+             * 
+             * @param {Chart} this
+             */
+            'initialize'
+        );
     },
 
     onRender : function(){
@@ -50785,17 +53079,23 @@ Ext.FlashEventProxy = {
  * @extends Ext.FlashComponent\r
  * The Ext.chart package provides the capability to visualize data with flash based charting.\r
  * Each chart binds directly to an Ext.data.Store enabling automatic updates of the chart.\r
+ * To change the look and feel of a chart, see the {@link #chartStyle} and {@link #extraStyle} config options.\r
  * @constructor\r
  * @xtype chart\r
  */\r
  \r
  Ext.chart.Chart = Ext.extend(Ext.FlashComponent, {\r
     refreshBuffer: 100,\r
+    \r
+    /**\r
+     * @cfg {String} backgroundColor\r
+     * @hide\r
+     */\r
 \r
     /**\r
      * @cfg {Object} chartStyle\r
-     * Sets styles for this chart. Contains a number of default values. Modifying this property will override\r
-     * the base styles on the chart.\r
+     * Sets styles for this chart. This contains default styling, so modifying this property will <b>override</b>\r
+     * the built in styles of the chart. Use {@link #extraStyle} to add customizations to the default styling. \r
      */\r
     chartStyle: {\r
         padding: 10,\r
@@ -50833,9 +53133,75 @@ Ext.FlashEventProxy = {
     /**\r
      * @cfg {Object} extraStyle\r
      * Contains extra styles that will be added or overwritten to the default chartStyle. Defaults to <tt>null</tt>.\r
+     * For a detailed list of the options available, visit the YUI Charts site \r
+     * at <a href="http://developer.yahoo.com/yui/charts/#basicstyles">http://developer.yahoo.com/yui/charts/#basicstyles</a><br/>\r
+     * Some of the options availabe:<br />\r
+     * <ul style="padding:5px;padding-left:16px;list-style-type:inherit;">\r
+     * <li><b>padding</b> - The space around the edge of the chart's contents. Padding does not increase the size of the chart.</li>\r
+     * <li><b>animationEnabled</b> - A Boolean value that specifies whether marker animations are enabled or not. Enabled by default.</li>\r
+     * <li><b>font</b> - An Object defining the font style to be used in the chart. Defaults to <tt>{ name: 'Tahoma', color: 0x444444, size: 11 }</tt><br/>\r
+     *  <ul style="padding:5px;padding-left:26px;list-style-type:circle;">\r
+     *      <li><b>name</b> - font name</li>\r
+     *      <li><b>color</b> - font color (hex code, ie: "#ff0000", "ff0000" or 0xff0000)</li>\r
+     *      <li><b>size</b> - font size in points (numeric portion only, ie: 11)</li>\r
+     *      <li><b>bold</b> - boolean</li>\r
+     *      <li><b>italic</b> - boolean</li>\r
+     *      <li><b>underline</b> - boolean</li>\r
+     *  </ul>\r
+     * </li>\r
+     * <li><b>border</b> - An object defining the border style around the chart. The chart itself will decrease in dimensions to accomodate the border.<br/>\r
+     *  <ul style="padding:5px;padding-left:26px;list-style-type:circle;">\r
+     *      <li><b>color</b> - border color (hex code, ie: "#ff0000", "ff0000" or 0xff0000)</li>\r
+     *      <li><b>size</b> - border size in pixels (numeric portion only, ie: 1)</li>\r
+     *  </ul>\r
+     * </li>\r
+     * <li><b>background</b> - An object defining the background style of the chart.<br/>\r
+     *  <ul style="padding:5px;padding-left:26px;list-style-type:circle;">\r
+     *      <li><b>color</b> - border color (hex code, ie: "#ff0000", "ff0000" or 0xff0000)</li>\r
+     *      <li><b>image</b> - an image URL. May be relative to the current document or absolute.</li>\r
+     *  </ul>\r
+     * </li>\r
+     * <li><b>legend</b> - An object defining the legend style<br/>\r
+     *  <ul style="padding:5px;padding-left:26px;list-style-type:circle;">\r
+     *      <li><b>display</b> - location of the legend. Possible values are "none", "left", "right", "top", and "bottom".</li>\r
+     *      <li><b>spacing</b> - an image URL. May be relative to the current document or absolute.</li>\r
+     *      <li><b>padding, border, background, font</b> - same options as described above.</li>\r
+     *  </ul></li>\r
+     * <li><b>dataTip</b> - An object defining the style of the data tip (tooltip).<br/>\r
+     *  <ul style="padding:5px;padding-left:26px;list-style-type:circle;">\r
+     *      <li><b>padding, border, background, font</b> - same options as described above.</li>\r
+     *  </ul></li>\r
+     * <li><b>xAxis and yAxis</b> - An object defining the style of the style of either axis.<br/>\r
+     *  <ul style="padding:5px;padding-left:26px;list-style-type:circle;">\r
+     *      <li><b>color</b> - same option as described above.</li>\r
+     *      <li><b>size</b> - same option as described above.</li>\r
+     *      <li><b>showLabels</b> - boolean</li>\r
+     *      <li><b>labelRotation</b> - a value in degrees from -90 through 90. Default is zero.</li>\r
+     *  </ul></li>\r
+     * <li><b>majorGridLines and minorGridLines</b> - An object defining the style of the style of the grid lines.<br/>\r
+     *  <ul style="padding:5px;padding-left:26px;list-style-type:circle;">\r
+     *      <li><b>color, size</b> - same options as described above.</li>\r
+     *  </ul></li></li>\r
+     * <li><b>zeroGridLine</b> - An object defining the style of the style of the zero grid line.<br/>\r
+     *  <ul style="padding:5px;padding-left:26px;list-style-type:circle;">\r
+     *      <li><b>color, size</b> - same options as described above.</li>\r
+     *  </ul></li></li>\r
+     * <li><b>majorTicks and minorTicks</b> - An object defining the style of the style of ticks in the chart.<br/>\r
+     *  <ul style="padding:5px;padding-left:26px;list-style-type:circle;">\r
+     *      <li><b>color, size</b> - same options as described above.</li>\r
+     *      <li><b>length</b> - the length of each tick in pixels extending from the axis.</li>\r
+     *      <li><b>display</b> - how the ticks are drawn. Possible values are "none", "inside", "outside", and "cross".</li>\r
+     *  </ul></li></li>\r
+     * </ul>\r
      */\r
     extraStyle: null,\r
     \r
+    /**\r
+     * @cfg {Object} seriesStyles\r
+     * Contains styles to apply to the series after a refresh. Defaults to <tt>null</tt>.\r
+     */\r
+    seriesStyles: null,\r
+    \r
     /**\r
      * @cfg {Boolean} disableCaching\r
      * True to add a "cache buster" to the end of the chart url. Defaults to true for Opera and IE.\r
@@ -50858,7 +53224,20 @@ Ext.FlashEventProxy = {
             'itemdoubleclick',\r
             'itemdragstart',\r
             'itemdrag',\r
-            'itemdragend'\r
+            'itemdragend',\r
+            /**\r
+             * @event beforerefresh\r
+             * Fires before a refresh to the chart data is called.  If the beforerefresh handler returns\r
+             * <tt>false</tt> the {@link #refresh} action will be cancelled.\r
+             * @param {Chart} this\r
+             */\r
+            'beforerefresh',\r
+            /**\r
+             * @event refresh\r
+             * Fires after the chart data has been refreshed.\r
+             * @param {Chart} this\r
+             */\r
+            'refresh'\r
         );\r
         this.store = Ext.StoreMgr.lookup(this.store);\r
     },\r
@@ -50888,6 +53267,7 @@ Ext.FlashEventProxy = {
      * @param styles {Array} Initializer for all Chart series styles.\r
      */\r
     setSeriesStyles: function(styles){\r
+        this.seriesStyles = styles;\r
         var s = [];\r
         Ext.each(styles, function(style){\r
             s.push(Ext.encode(style));\r
@@ -50975,51 +53355,57 @@ Ext.FlashEventProxy = {
     },\r
 \r
     refresh : function(){\r
-        var styleChanged = false;\r
-        // convert the store data into something YUI charts can understand\r
-        var data = [], rs = this.store.data.items;\r
-        for(var j = 0, len = rs.length; j < len; j++){\r
-            data[j] = rs[j].data;\r
-        }\r
-        //make a copy of the series definitions so that we aren't\r
-        //editing them directly.\r
-        var dataProvider = [];\r
-        var seriesCount = 0;\r
-        var currentSeries = null;\r
-        var i = 0;\r
-        if(this.series){\r
-            seriesCount = this.series.length;\r
-            for(i = 0; i < seriesCount; i++){\r
-                currentSeries = this.series[i];\r
-                var clonedSeries = {};\r
-                for(var prop in currentSeries){\r
-                    if(prop == "style" && currentSeries.style !== null){\r
-                        clonedSeries.style = Ext.encode(currentSeries.style);\r
-                        styleChanged = true;\r
-                        //we don't want to modify the styles again next time\r
-                        //so null out the style property.\r
-                        // this causes issues\r
-                        // currentSeries.style = null;\r
-                    } else{\r
-                        clonedSeries[prop] = currentSeries[prop];\r
-                    }\r
-                }\r
-                dataProvider.push(clonedSeries);\r
-            }\r
-        }\r
-\r
-        if(seriesCount > 0){\r
-            for(i = 0; i < seriesCount; i++){\r
-                currentSeries = dataProvider[i];\r
-                if(!currentSeries.type){\r
-                    currentSeries.type = this.type;\r
-                }\r
-                currentSeries.dataProvider = data;\r
-            }\r
-        } else{\r
-            dataProvider.push({type: this.type, dataProvider: data});\r
+        if(this.fireEvent('beforerefresh', this) !== false){\r
+               var styleChanged = false;\r
+               // convert the store data into something YUI charts can understand\r
+               var data = [], rs = this.store.data.items;\r
+               for(var j = 0, len = rs.length; j < len; j++){\r
+                   data[j] = rs[j].data;\r
+               }\r
+               //make a copy of the series definitions so that we aren't\r
+               //editing them directly.\r
+               var dataProvider = [];\r
+               var seriesCount = 0;\r
+               var currentSeries = null;\r
+               var i = 0;\r
+               if(this.series){\r
+                   seriesCount = this.series.length;\r
+                   for(i = 0; i < seriesCount; i++){\r
+                       currentSeries = this.series[i];\r
+                       var clonedSeries = {};\r
+                       for(var prop in currentSeries){\r
+                           if(prop == "style" && currentSeries.style !== null){\r
+                               clonedSeries.style = Ext.encode(currentSeries.style);\r
+                               styleChanged = true;\r
+                               //we don't want to modify the styles again next time\r
+                               //so null out the style property.\r
+                               // this causes issues\r
+                               // currentSeries.style = null;\r
+                           } else{\r
+                               clonedSeries[prop] = currentSeries[prop];\r
+                           }\r
+                       }\r
+                       dataProvider.push(clonedSeries);\r
+                   }\r
+               }\r
+       \r
+               if(seriesCount > 0){\r
+                   for(i = 0; i < seriesCount; i++){\r
+                       currentSeries = dataProvider[i];\r
+                       if(!currentSeries.type){\r
+                           currentSeries.type = this.type;\r
+                       }\r
+                       currentSeries.dataProvider = data;\r
+                   }\r
+               } else{\r
+                   dataProvider.push({type: this.type, dataProvider: data});\r
+               }\r
+               this.swf.setDataProvider(dataProvider);\r
+               if(this.seriesStyles){\r
+                   this.setSeriesStyles(this.seriesStyles);\r
+               }\r
+            this.fireEvent('refresh', this);\r
         }\r
-        this.swf.setDataProvider(dataProvider);\r
     },\r
 \r
     createFnProxy : function(fn, old){\r
@@ -51499,833 +53885,776 @@ Ext.chart.PieSeries = Ext.extend(Ext.chart.Series, {
     type: "pie",\r
     dataField: null,\r
     categoryField: null\r
-});/**\r
- * @class Ext.layout.MenuLayout\r
- * @extends Ext.layout.ContainerLayout\r
- * <p>Layout manager used by {@link Ext.menu.Menu}. Generally this class should not need to be used directly.</p>\r
- */\r
- Ext.layout.MenuLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
-    monitorResize : true,\r
-\r
-    setContainer : function(ct){\r
-        this.monitorResize = !ct.floating;\r
-        // This event is only fired by the menu in IE, used so we don't couple\r
-        // the menu with the layout.\r
-        ct.on('autosize', this.doAutoSize, this);\r
-        Ext.layout.MenuLayout.superclass.setContainer.call(this, ct);\r
-    },\r
-\r
-    renderItem : function(c, position, target){\r
-        if (!this.itemTpl) {\r
-            this.itemTpl = Ext.layout.MenuLayout.prototype.itemTpl = new Ext.XTemplate(\r
-                '<li id="{itemId}" class="{itemCls}">',\r
-                    '<tpl if="needsIcon">',\r
-                        '<img src="{icon}" class="{iconCls}"/>',\r
-                    '</tpl>',\r
-                '</li>'\r
-            );\r
-        }\r
-\r
-        if(c && !c.rendered){\r
-            if(Ext.isNumber(position)){\r
-                position = target.dom.childNodes[position];\r
-            }\r
-            var a = this.getItemArgs(c);\r
-\r
-//          The Component's positionEl is the <li> it is rendered into\r
-            c.render(c.positionEl = position ?\r
-                this.itemTpl.insertBefore(position, a, true) :\r
-                this.itemTpl.append(target, a, true));\r
-\r
-//          Link the containing <li> to the item.\r
-            c.positionEl.menuItemId = c.getItemId();\r
-\r
-//          If rendering a regular Component, and it needs an icon,\r
-//          move the Component rightwards.\r
-            if (!a.isMenuItem && a.needsIcon) {\r
-                c.positionEl.addClass('x-menu-list-item-indent');\r
-            }\r
-            this.configureItem(c, position);\r
-        }else if(c && !this.isValidParent(c, target)){\r
-            if(Ext.isNumber(position)){\r
-                position = target.dom.childNodes[position];\r
-            }\r
-            target.dom.insertBefore(c.getActionEl().dom, position || null);\r
-        }\r
-    },\r
-\r
-    getItemArgs : function(c) {\r
-        var isMenuItem = c instanceof Ext.menu.Item;\r
-        return {\r
-            isMenuItem: isMenuItem,\r
-            needsIcon: !isMenuItem && (c.icon || c.iconCls),\r
-            icon: c.icon || Ext.BLANK_IMAGE_URL,\r
-            iconCls: 'x-menu-item-icon ' + (c.iconCls || ''),\r
-            itemId: 'x-menu-el-' + c.id,\r
-            itemCls: 'x-menu-list-item '\r
-        };\r
-    },\r
-\r
-//  Valid if the Component is in a <li> which is part of our target <ul>\r
-    isValidParent : function(c, target) {\r
-        return c.el.up('li.x-menu-list-item', 5).dom.parentNode === (target.dom || target);\r
-    },\r
-\r
-    onLayout : function(ct, target){\r
-        this.renderAll(ct, target);\r
-        this.doAutoSize();\r
-    },\r
-\r
-    doAutoSize : function(){\r
-        var ct = this.container, w = ct.width;\r
-        if(ct.floating){\r
-            if(w){\r
-                ct.setWidth(w);\r
-            }else if(Ext.isIE){\r
-                ct.setWidth(Ext.isStrict && (Ext.isIE7 || Ext.isIE8) ? 'auto' : ct.minWidth);\r
-                var el = ct.getEl(), t = el.dom.offsetWidth; // force recalc\r
-                ct.setWidth(ct.getLayoutTarget().getWidth() + el.getFrameWidth('lr'));\r
-            }\r
-        }\r
-    }\r
-});\r
-Ext.Container.LAYOUTS['menu'] = Ext.layout.MenuLayout;\r
-\r
-/**\r
- * @class Ext.menu.Menu\r
- * @extends Ext.Container\r
- * <p>A menu object.  This is the container to which you may add menu items.  Menu can also serve as a base class\r
- * when you want a specialized menu based off of another component (like {@link Ext.menu.DateMenu} for example).</p>\r
- * <p>Menus may contain either {@link Ext.menu.Item menu items}, or general {@link Ext.Component Component}s.</p>\r
- * <p>To make a contained general {@link Ext.Component Component} line up with other {@link Ext.menu.Item menu items}\r
- * specify <tt>iconCls: 'no-icon'</tt>.  This reserves a space for an icon, and indents the Component in line\r
- * with the other menu items.  See {@link Ext.form.ComboBox}.{@link Ext.form.ComboBox#getListParent getListParent}\r
- * for an example.</p>\r
- * <p>By default, Menus are absolutely positioned, floating Components. By configuring a Menu with\r
- * <b><tt>{@link #floating}:false</tt></b>, a Menu may be used as child of a Container.</p>\r
- *\r
- * @xtype menu\r
- */\r
-Ext.menu.Menu = Ext.extend(Ext.Container, {\r
-    /**\r
-     * @cfg {Object} defaults\r
-     * A config object that will be applied to all items added to this container either via the {@link #items}\r
-     * config or via the {@link #add} method.  The defaults config can contain any number of\r
-     * name/value property pairs to be added to each item, and should be valid for the types of items\r
-     * being added to the menu.\r
-     */\r
-    /**\r
-     * @cfg {Mixed} items\r
-     * An array of items to be added to this menu. Menus may contain either {@link Ext.menu.Item menu items},\r
-     * or general {@link Ext.Component Component}s.\r
-     */\r
-    /**\r
-     * @cfg {Number} minWidth The minimum width of the menu in pixels (defaults to 120)\r
-     */\r
-    minWidth : 120,\r
-    /**\r
-     * @cfg {Boolean/String} shadow True or 'sides' for the default effect, 'frame' for 4-way shadow, and 'drop'\r
-     * for bottom-right shadow (defaults to 'sides')\r
-     */\r
-    shadow : 'sides',\r
-    /**\r
-     * @cfg {String} subMenuAlign The {@link Ext.Element#alignTo} anchor position value to use for submenus of\r
-     * this menu (defaults to 'tl-tr?')\r
-     */\r
-    subMenuAlign : 'tl-tr?',\r
-    /**\r
-     * @cfg {String} defaultAlign The default {@link Ext.Element#alignTo} anchor position value for this menu\r
-     * relative to its element of origin (defaults to 'tl-bl?')\r
-     */\r
-    defaultAlign : 'tl-bl?',\r
-    /**\r
-     * @cfg {Boolean} allowOtherMenus True to allow multiple menus to be displayed at the same time (defaults to false)\r
-     */\r
-    allowOtherMenus : false,\r
-    /**\r
-     * @cfg {Boolean} ignoreParentClicks True to ignore clicks on any item in this menu that is a parent item (displays\r
-     * a submenu) so that the submenu is not dismissed when clicking the parent item (defaults to false).\r
-     */\r
-    ignoreParentClicks : false,\r
-    /**\r
-     * @cfg {Boolean} enableScrolling True to allow the menu container to have scroller controls if the menu is too long (defaults to true).\r
-     */\r
-    enableScrolling : true,\r
-    /**\r
-     * @cfg {Number} maxHeight The maximum height of the menu. Only applies when enableScrolling is set to True (defaults to null).\r
-     */\r
-    maxHeight : null,\r
-    /**\r
-     * @cfg {Number} scrollIncrement The amount to scroll the menu. Only applies when enableScrolling is set to True (defaults to 24).\r
-     */\r
-    scrollIncrement : 24,\r
-    /**\r
-     * @cfg {Boolean} showSeparator True to show the icon separator. (defaults to true).\r
-     */\r
-    showSeparator : true,\r
-    /**\r
-     * @cfg {Array} defaultOffsets An array specifying the [x, y] offset in pixels by which to\r
-     * change the default Menu popup position after aligning according to the {@link #defaultAlign}\r
-     * configuration. Defaults to <tt>[0, 0]</tt>.\r
-     */\r
-    defaultOffsets : [0, 0],\r
-    \r
-    /**\r
-     * @cfg {Boolean} plain\r
-     * True to remove the incised line down the left side of the menu. Defaults to <tt>false</tt>.\r
-     */\r
-    plain : false,\r
-\r
-    /**\r
-     * @cfg {Boolean} floating\r
-     * <p>By default, a Menu configured as <b><code>floating:true</code></b>\r
-     * will be rendered as an {@link Ext.Layer} (an absolutely positioned,\r
-     * floating Component with zindex=15000).\r
-     * If configured as <b><code>floating:false</code></b>, the Menu may be\r
-     * used as child item of another Container instead of a free-floating\r
-     * {@link Ext.Layer Layer}.\r
-     */\r
-    floating : true,\r
-\r
-    // private\r
-    hidden : true,\r
-\r
-    /**\r
-     * @cfg {String/Object} layout\r
-     * This class assigns a default layout (<code>layout:'<b>menu</b>'</code>).\r
-     * Developers <i>may</i> override this configuration option if another layout is required.\r
-     * See {@link Ext.Container#layout} for additional information.\r
-     */\r
-    layout : 'menu',\r
-    hideMode : 'offsets',    // Important for laying out Components\r
-    scrollerHeight : 8,\r
-    autoLayout : true,       // Provided for backwards compat\r
-    defaultType : 'menuitem',\r
-\r
-    initComponent : function(){\r
-        if(Ext.isArray(this.initialConfig)){\r
-            Ext.apply(this, {items:this.initialConfig});\r
-        }\r
-        this.addEvents(\r
-            /**\r
-             * @event click\r
-             * Fires when this menu is clicked (or when the enter key is pressed while it is active)\r
-             * @param {Ext.menu.Menu} this\r
-            * @param {Ext.menu.Item} menuItem The menu item that was clicked\r
-             * @param {Ext.EventObject} e\r
-             */\r
-            'click',\r
-            /**\r
-             * @event mouseover\r
-             * Fires when the mouse is hovering over this menu\r
-             * @param {Ext.menu.Menu} this\r
-             * @param {Ext.EventObject} e\r
-             * @param {Ext.menu.Item} menuItem The menu item that was clicked\r
-             */\r
-            'mouseover',\r
-            /**\r
-             * @event mouseout\r
-             * Fires when the mouse exits this menu\r
-             * @param {Ext.menu.Menu} this\r
-             * @param {Ext.EventObject} e\r
-             * @param {Ext.menu.Item} menuItem The menu item that was clicked\r
-             */\r
-            'mouseout',\r
-            /**\r
-             * @event itemclick\r
-             * Fires when a menu item contained in this menu is clicked\r
-             * @param {Ext.menu.BaseItem} baseItem The BaseItem that was clicked\r
-             * @param {Ext.EventObject} e\r
-             */\r
-            'itemclick'\r
-        );\r
-        Ext.menu.MenuMgr.register(this);\r
-        if(this.floating){\r
-            Ext.EventManager.onWindowResize(this.hide, this);\r
-        }else{\r
-            if(this.initialConfig.hidden !== false){\r
-                this.hidden = false;\r
-            }\r
-            this.internalDefaults = {hideOnClick: false};\r
-        }\r
-        Ext.menu.Menu.superclass.initComponent.call(this);\r
-        if(this.autoLayout){\r
-            this.on({\r
-                add: this.doLayout,\r
-                remove: this.doLayout,\r
-                scope: this\r
-            });\r
-        }\r
-    },\r
-\r
-    //private\r
-    getLayoutTarget : function() {\r
-        return this.ul;\r
-    },\r
-\r
-    // private\r
-    onRender : function(ct, position){\r
-        if(!ct){\r
-            ct = Ext.getBody();\r
-        }\r
-\r
-        var dh = {\r
-            id: this.getId(),\r
-            cls: 'x-menu ' + ((this.floating) ? 'x-menu-floating x-layer ' : '') + (this.cls || '') + (this.plain ? ' x-menu-plain' : '') + (this.showSeparator ? '' : ' x-menu-nosep'),\r
-            style: this.style,\r
-            cn: [\r
-                {tag: 'a', cls: 'x-menu-focus', href: '#', onclick: 'return false;', tabIndex: '-1'},\r
-                {tag: 'ul', cls: 'x-menu-list'}\r
-            ]\r
-        };\r
-        if(this.floating){\r
-            this.el = new Ext.Layer({\r
-                shadow: this.shadow,\r
-                dh: dh,\r
-                constrain: false,\r
-                parentEl: ct,\r
-                zindex:15000\r
-            });\r
-        }else{\r
-            this.el = ct.createChild(dh);\r
-        }\r
-        Ext.menu.Menu.superclass.onRender.call(this, ct, position);\r
-\r
-        if(!this.keyNav){\r
-            this.keyNav = new Ext.menu.MenuNav(this);\r
-        }\r
-        // generic focus element\r
-        this.focusEl = this.el.child('a.x-menu-focus');\r
-        this.ul = this.el.child('ul.x-menu-list');\r
-        this.mon(this.ul, {\r
-            scope: this,\r
-            click: this.onClick,\r
-            mouseover: this.onMouseOver,\r
-            mouseout: this.onMouseOut\r
-        });\r
-        if(this.enableScrolling){\r
-            this.mon(this.el, {\r
-                scope: this,\r
-                delegate: '.x-menu-scroller',\r
-                click: this.onScroll,\r
-                mouseover: this.deactivateActive\r
-            });\r
-        }\r
-    },\r
-\r
-    // private\r
-    findTargetItem : function(e){\r
-        var t = e.getTarget('.x-menu-list-item', this.ul, true);\r
-        if(t && t.menuItemId){\r
-            return this.items.get(t.menuItemId);\r
-        }\r
-    },\r
-\r
-    // private\r
-    onClick : function(e){\r
-        var t = this.findTargetItem(e);\r
-        if(t){\r
-            if(t.isFormField){\r
-                this.setActiveItem(t);\r
-            }else if(t instanceof Ext.menu.BaseItem){\r
-                if(t.menu && this.ignoreParentClicks){\r
-                    t.expandMenu();\r
-                    e.preventDefault();\r
-                }else if(t.onClick){\r
-                    t.onClick(e);\r
-                    this.fireEvent('click', this, t, e);\r
-                }\r
-            }\r
-        }\r
-    },\r
-\r
-    // private\r
-    setActiveItem : function(item, autoExpand){\r
-        if(item != this.activeItem){\r
-            this.deactivateActive();\r
-            if((this.activeItem = item).isFormField){\r
-                item.focus();\r
-            }else{\r
-                item.activate(autoExpand);\r
-            }\r
-        }else if(autoExpand){\r
-            item.expandMenu();\r
-        }\r
-    },\r
-\r
-    deactivateActive : function(){\r
-        var a = this.activeItem;\r
-        if(a){\r
-            if(a.isFormField){\r
-                //Fields cannot deactivate, but Combos must collapse\r
-                if(a.collapse){\r
-                    a.collapse();\r
-                }\r
-            }else{\r
-                a.deactivate();\r
-            }\r
-            delete this.activeItem;\r
-        }\r
-    },\r
-\r
-    // private\r
-    tryActivate : function(start, step){\r
-        var items = this.items;\r
-        for(var i = start, len = items.length; i >= 0 && i < len; i+= step){\r
-            var item = items.get(i);\r
-            if(!item.disabled && (item.canActivate || item.isFormField)){\r
-                this.setActiveItem(item, false);\r
-                return item;\r
-            }\r
-        }\r
-        return false;\r
-    },\r
-\r
-    // private\r
-    onMouseOver : function(e){\r
-        var t = this.findTargetItem(e);\r
-        if(t){\r
-            if(t.canActivate && !t.disabled){\r
-                this.setActiveItem(t, true);\r
-            }\r
-        }\r
-        this.over = true;\r
-        this.fireEvent('mouseover', this, e, t);\r
-    },\r
-\r
-    // private\r
-    onMouseOut : function(e){\r
-        var t = this.findTargetItem(e);\r
-        if(t){\r
-            if(t == this.activeItem && t.shouldDeactivate && t.shouldDeactivate(e)){\r
-                this.activeItem.deactivate();\r
-                delete this.activeItem;\r
-            }\r
-        }\r
-        this.over = false;\r
-        this.fireEvent('mouseout', this, e, t);\r
-    },\r
-\r
-    // private\r
-    onScroll : function(e, t){\r
-        if(e){\r
-            e.stopEvent();\r
-        }\r
-        var ul = this.ul.dom, top = Ext.fly(t).is('.x-menu-scroller-top');\r
-        ul.scrollTop += this.scrollIncrement * (top ? -1 : 1);\r
-        if(top ? ul.scrollTop <= 0 : ul.scrollTop + this.activeMax >= ul.scrollHeight){\r
-           this.onScrollerOut(null, t);\r
-        }\r
-    },\r
-\r
-    // private\r
-    onScrollerIn : function(e, t){\r
-        var ul = this.ul.dom, top = Ext.fly(t).is('.x-menu-scroller-top');\r
-        if(top ? ul.scrollTop > 0 : ul.scrollTop + this.activeMax < ul.scrollHeight){\r
-            Ext.fly(t).addClass(['x-menu-item-active', 'x-menu-scroller-active']);\r
-        }\r
-    },\r
-\r
-    // private\r
-    onScrollerOut : function(e, t){\r
-        Ext.fly(t).removeClass(['x-menu-item-active', 'x-menu-scroller-active']);\r
-    },\r
-\r
-    /**\r
-     * If <code>{@link #floating}=true</code>, shows this menu relative to\r
-     * another element using {@link #showat}, otherwise uses {@link Ext.Component#show}.\r
-     * @param {Mixed} element The element to align to\r
-     * @param {String} position (optional) The {@link Ext.Element#alignTo} anchor position to use in aligning to\r
-     * the element (defaults to this.defaultAlign)\r
-     * @param {Ext.menu.Menu} parentMenu (optional) This menu's parent menu, if applicable (defaults to undefined)\r
-     */\r
-    show : function(el, pos, parentMenu){\r
-        if(this.floating){\r
-            this.parentMenu = parentMenu;\r
-            if(!this.el){\r
-                this.render();\r
-                this.doLayout(false, true);\r
-            }\r
-            this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign, this.defaultOffsets), parentMenu);\r
-        }else{\r
-            Ext.menu.Menu.superclass.show.call(this);\r
-        }\r
-    },\r
-\r
-    /**\r
-     * Displays this menu at a specific xy position and fires the 'show' event if a\r
-     * handler for the 'beforeshow' event does not return false cancelling the operation.\r
-     * @param {Array} xyPosition Contains X & Y [x, y] values for the position at which to show the menu (coordinates are page-based)\r
-     * @param {Ext.menu.Menu} parentMenu (optional) This menu's parent menu, if applicable (defaults to undefined)\r
-     */\r
-    showAt : function(xy, parentMenu){\r
-        if(this.fireEvent('beforeshow', this) !== false){\r
-            this.parentMenu = parentMenu;\r
-            if(!this.el){\r
-                this.render();\r
-            }\r
-            if(this.enableScrolling){\r
-                // set the position so we can figure out the constrain value.\r
-                this.el.setXY(xy);\r
-                //constrain the value, keep the y coordinate the same\r
-                this.constrainScroll(xy[1]);\r
-                xy = [this.el.adjustForConstraints(xy)[0], xy[1]];\r
-            }else{\r
-                //constrain to the viewport.\r
-                xy = this.el.adjustForConstraints(xy);\r
-            }\r
-            this.el.setXY(xy);\r
-            this.el.show();\r
-            Ext.menu.Menu.superclass.onShow.call(this);\r
-            if(Ext.isIE){\r
-                // internal event, used so we don't couple the layout to the menu\r
-                this.fireEvent('autosize', this);\r
-                if(!Ext.isIE8){\r
-                    this.el.repaint();\r
-                }\r
-            }\r
-            this.hidden = false;\r
-            this.focus();\r
-            this.fireEvent('show', this);\r
-        }\r
-    },\r
-\r
-    constrainScroll : function(y){\r
-        var max, full = this.ul.setHeight('auto').getHeight();\r
-        if(this.floating){\r
-            max = this.maxHeight ? this.maxHeight : Ext.fly(this.el.dom.parentNode).getViewSize().height - y;\r
-        }else{\r
-            max = this.getHeight();\r
-        }\r
-        if(full > max && max > 0){\r
-            this.activeMax = max - this.scrollerHeight * 2 - this.el.getFrameWidth('tb') - Ext.num(this.el.shadowOffset, 0);\r
-            this.ul.setHeight(this.activeMax);\r
-            this.createScrollers();\r
-            this.el.select('.x-menu-scroller').setDisplayed('');\r
-        }else{\r
-            this.ul.setHeight(full);\r
-            this.el.select('.x-menu-scroller').setDisplayed('none');\r
-        }\r
-        this.ul.dom.scrollTop = 0;\r
-    },\r
-\r
-    createScrollers : function(){\r
-        if(!this.scroller){\r
-            this.scroller = {\r
-                pos: 0,\r
-                top: this.el.insertFirst({\r
-                    tag: 'div',\r
-                    cls: 'x-menu-scroller x-menu-scroller-top',\r
-                    html: '&#160;'\r
-                }),\r
-                bottom: this.el.createChild({\r
-                    tag: 'div',\r
-                    cls: 'x-menu-scroller x-menu-scroller-bottom',\r
-                    html: '&#160;'\r
-                })\r
-            };\r
-            this.scroller.top.hover(this.onScrollerIn, this.onScrollerOut, this);\r
-            this.scroller.topRepeater = new Ext.util.ClickRepeater(this.scroller.top, {\r
-                listeners: {\r
-                    click: this.onScroll.createDelegate(this, [null, this.scroller.top], false)\r
-                }\r
-            });\r
-            this.scroller.bottom.hover(this.onScrollerIn, this.onScrollerOut, this);\r
-            this.scroller.bottomRepeater = new Ext.util.ClickRepeater(this.scroller.bottom, {\r
-                listeners: {\r
-                    click: this.onScroll.createDelegate(this, [null, this.scroller.bottom], false)\r
-                }\r
-            });\r
-        }\r
-    },\r
-\r
-    onLayout : function(){\r
-        if(this.isVisible()){\r
-            if(this.enableScrolling){\r
-                this.constrainScroll(this.el.getTop());\r
-            }\r
-            if(this.floating){\r
-                this.el.sync();\r
-            }\r
-        }\r
-    },\r
-\r
-    focus : function(){\r
-        if(!this.hidden){\r
-            this.doFocus.defer(50, this);\r
-        }\r
-    },\r
-\r
-    doFocus : function(){\r
-        if(!this.hidden){\r
-            this.focusEl.focus();\r
-        }\r
-    },\r
-\r
-    /**\r
-     * Hides this menu and optionally all parent menus\r
-     * @param {Boolean} deep (optional) True to hide all parent menus recursively, if any (defaults to false)\r
-     */\r
-    hide : function(deep){\r
-        this.deepHide = deep;\r
-        Ext.menu.Menu.superclass.hide.call(this);\r
-        delete this.deepHide;\r
-    },\r
-\r
-    // private\r
-    onHide : function(){\r
-        Ext.menu.Menu.superclass.onHide.call(this);\r
-        this.deactivateActive();\r
-        if(this.el && this.floating){\r
-            this.el.hide();\r
-        }\r
-        var pm = this.parentMenu;\r
-        if(this.deepHide === true && pm){\r
-            if(pm.floating){\r
-                pm.hide(true);\r
-            }else{\r
-                pm.deactivateActive();\r
-            }\r
-        }\r
-    },\r
-\r
-    // private\r
-    lookupComponent : function(c){\r
-         if(Ext.isString(c)){\r
-            c = (c == 'separator' || c == '-') ? new Ext.menu.Separator() : new Ext.menu.TextItem(c);\r
-             this.applyDefaults(c);\r
-         }else{\r
-            if(Ext.isObject(c)){\r
-                c = this.getMenuItem(c);\r
-            }else if(c.tagName || c.el){ // element. Wrap it.\r
-                c = new Ext.BoxComponent({\r
-                    el: c\r
-                });\r
-            }\r
-         }\r
-         return c;\r
-    },\r
-\r
-    applyDefaults : function(c){\r
-        if(!Ext.isString(c)){\r
-            c = Ext.menu.Menu.superclass.applyDefaults.call(this, c);\r
-            var d = this.internalDefaults;\r
-            if(d){\r
-                if(c.events){\r
-                    Ext.applyIf(c.initialConfig, d);\r
-                    Ext.apply(c, d);\r
-                }else{\r
-                    Ext.applyIf(c, d);\r
-                }\r
-            }\r
-        }\r
-        return c;\r
-    },\r
-\r
-    // private\r
-    getMenuItem : function(config){\r
-       if(!config.isXType){\r
-            if(!config.xtype && Ext.isBoolean(config.checked)){\r
-                return new Ext.menu.CheckItem(config)\r
-            }\r
-            return Ext.create(config, this.defaultType);\r
-        }\r
-        return config;\r
-    },\r
-\r
-    /**\r
-     * Adds a separator bar to the menu\r
-     * @return {Ext.menu.Item} The menu item that was added\r
-     */\r
-    addSeparator : function(){\r
-        return this.add(new Ext.menu.Separator());\r
-    },\r
-\r
-    /**\r
-     * Adds an {@link Ext.Element} object to the menu\r
-     * @param {Mixed} el The element or DOM node to add, or its id\r
-     * @return {Ext.menu.Item} The menu item that was added\r
-     */\r
-    addElement : function(el){\r
-        return this.add(new Ext.menu.BaseItem(el));\r
-    },\r
-\r
-    /**\r
-     * Adds an existing object based on {@link Ext.menu.BaseItem} to the menu\r
-     * @param {Ext.menu.Item} item The menu item to add\r
-     * @return {Ext.menu.Item} The menu item that was added\r
-     */\r
-    addItem : function(item){\r
-        return this.add(item);\r
-    },\r
-\r
-    /**\r
-     * Creates a new {@link Ext.menu.Item} based an the supplied config object and adds it to the menu\r
-     * @param {Object} config A MenuItem config object\r
-     * @return {Ext.menu.Item} The menu item that was added\r
-     */\r
-    addMenuItem : function(config){\r
-        return this.add(this.getMenuItem(config));\r
-    },\r
-\r
-    /**\r
-     * Creates a new {@link Ext.menu.TextItem} with the supplied text and adds it to the menu\r
-     * @param {String} text The text to display in the menu item\r
-     * @return {Ext.menu.Item} The menu item that was added\r
-     */\r
-    addText : function(text){\r
-        return this.add(new Ext.menu.TextItem(text));\r
-    },\r
-\r
-    //private\r
-    onDestroy : function(){\r
-        Ext.menu.Menu.superclass.onDestroy.call(this);\r
-        Ext.menu.MenuMgr.unregister(this);\r
-        Ext.EventManager.removeResizeListener(this.hide, this);\r
-        if(this.keyNav) {\r
-            this.keyNav.disable();\r
-        }\r
-        var s = this.scroller;\r
-        if(s){\r
-            Ext.destroy(s.topRepeater, s.bottomRepeater, s.top, s.bottom);\r
-        }\r
-        Ext.destroy(\r
-            this.el,\r
-            this.focusEl,\r
-            this.ul\r
-        );\r
-    }\r
-});\r
-\r
-Ext.reg('menu', Ext.menu.Menu);\r
-\r
-// MenuNav is a private utility class used internally by the Menu\r
-Ext.menu.MenuNav = Ext.extend(Ext.KeyNav, function(){\r
-    function up(e, m){\r
-        if(!m.tryActivate(m.items.indexOf(m.activeItem)-1, -1)){\r
-            m.tryActivate(m.items.length-1, -1);\r
-        }\r
-    }\r
-    function down(e, m){\r
-        if(!m.tryActivate(m.items.indexOf(m.activeItem)+1, 1)){\r
-            m.tryActivate(0, 1);\r
-        }\r
-    }\r
-    return {\r
-        constructor : function(menu){\r
-            Ext.menu.MenuNav.superclass.constructor.call(this, menu.el);\r
-            this.scope = this.menu = menu;\r
-        },\r
-\r
-        doRelay : function(e, h){\r
-            var k = e.getKey();\r
-//          Keystrokes within a form Field (e.g.: down in a Combo) do not navigate. Allow only TAB\r
-            if (this.menu.activeItem && this.menu.activeItem.isFormField && k != e.TAB) {\r
-                return false;\r
-            }\r
-            if(!this.menu.activeItem && e.isNavKeyPress() && k != e.SPACE && k != e.RETURN){\r
-                this.menu.tryActivate(0, 1);\r
-                return false;\r
-            }\r
-            return h.call(this.scope || this, e, this.menu);\r
-        },\r
-\r
-        tab: function(e, m) {\r
-            e.stopEvent();\r
-            if (e.shiftKey) {\r
-                up(e, m);\r
-            } else {\r
-                down(e, m);\r
-            }\r
-        },\r
-\r
-        up : up,\r
-\r
-        down : down,\r
-\r
-        right : function(e, m){\r
-            if(m.activeItem){\r
-                m.activeItem.expandMenu(true);\r
-            }\r
-        },\r
-\r
-        left : function(e, m){\r
-            m.hide();\r
-            if(m.parentMenu && m.parentMenu.activeItem){\r
-                m.parentMenu.activeItem.activate();\r
-            }\r
-        },\r
-\r
-        enter : function(e, m){\r
-            if(m.activeItem){\r
-                e.stopPropagation();\r
-                m.activeItem.onClick(e);\r
-                m.fireEvent('click', this, m.activeItem);\r
-                return true;\r
-            }\r
-        }\r
-    };\r
-}());\r
-/**
- * @class Ext.menu.MenuMgr
- * Provides a common registry of all menu items on a page so that they can be easily accessed by id.
- * @singleton
+});/**
+ * @class Ext.menu.Menu
+ * @extends Ext.Container
+ * <p>A menu object.  This is the container to which you may add menu items.  Menu can also serve as a base class
+ * when you want a specialized menu based off of another component (like {@link Ext.menu.DateMenu} for example).</p>
+ * <p>Menus may contain either {@link Ext.menu.Item menu items}, or general {@link Ext.Component Component}s.</p>
+ * <p>To make a contained general {@link Ext.Component Component} line up with other {@link Ext.menu.Item menu items}
+ * specify <tt>iconCls: 'no-icon'</tt>.  This reserves a space for an icon, and indents the Component in line
+ * with the other menu items.  See {@link Ext.form.ComboBox}.{@link Ext.form.ComboBox#getListParent getListParent}
+ * for an example.</p>
+ * <p>By default, Menus are absolutely positioned, floating Components. By configuring a Menu with
+ * <b><tt>{@link #floating}:false</tt></b>, a Menu may be used as child of a Container.</p>
+ *
+ * @xtype menu
  */
-Ext.menu.MenuMgr = function(){
-   var menus, active, groups = {}, attached = false, lastShow = new Date();
+Ext.menu.Menu = Ext.extend(Ext.Container, {
+    /**
+     * @cfg {Object} defaults
+     * A config object that will be applied to all items added to this container either via the {@link #items}
+     * config or via the {@link #add} method.  The defaults config can contain any number of
+     * name/value property pairs to be added to each item, and should be valid for the types of items
+     * being added to the menu.
+     */
+    /**
+     * @cfg {Mixed} items
+     * An array of items to be added to this menu. Menus may contain either {@link Ext.menu.Item menu items},
+     * or general {@link Ext.Component Component}s.
+     */
+    /**
+     * @cfg {Number} minWidth The minimum width of the menu in pixels (defaults to 120)
+     */
+    minWidth : 120,
+    /**
+     * @cfg {Boolean/String} shadow True or 'sides' for the default effect, 'frame' for 4-way shadow, and 'drop'
+     * for bottom-right shadow (defaults to 'sides')
+     */
+    shadow : 'sides',
+    /**
+     * @cfg {String} subMenuAlign The {@link Ext.Element#alignTo} anchor position value to use for submenus of
+     * this menu (defaults to 'tl-tr?')
+     */
+    subMenuAlign : 'tl-tr?',
+    /**
+     * @cfg {String} defaultAlign The default {@link Ext.Element#alignTo} anchor position value for this menu
+     * relative to its element of origin (defaults to 'tl-bl?')
+     */
+    defaultAlign : 'tl-bl?',
+    /**
+     * @cfg {Boolean} allowOtherMenus True to allow multiple menus to be displayed at the same time (defaults to false)
+     */
+    allowOtherMenus : false,
+    /**
+     * @cfg {Boolean} ignoreParentClicks True to ignore clicks on any item in this menu that is a parent item (displays
+     * a submenu) so that the submenu is not dismissed when clicking the parent item (defaults to false).
+     */
+    ignoreParentClicks : false,
+    /**
+     * @cfg {Boolean} enableScrolling True to allow the menu container to have scroller controls if the menu is too long (defaults to true).
+     */
+    enableScrolling : true,
+    /**
+     * @cfg {Number} maxHeight The maximum height of the menu. Only applies when enableScrolling is set to True (defaults to null).
+     */
+    maxHeight : null,
+    /**
+     * @cfg {Number} scrollIncrement The amount to scroll the menu. Only applies when enableScrolling is set to True (defaults to 24).
+     */
+    scrollIncrement : 24,
+    /**
+     * @cfg {Boolean} showSeparator True to show the icon separator. (defaults to true).
+     */
+    showSeparator : true,
+    /**
+     * @cfg {Array} defaultOffsets An array specifying the [x, y] offset in pixels by which to
+     * change the default Menu popup position after aligning according to the {@link #defaultAlign}
+     * configuration. Defaults to <tt>[0, 0]</tt>.
+     */
+    defaultOffsets : [0, 0],
 
-   // private - called when first menu is created
-   function init(){
-       menus = {};
-       active = new Ext.util.MixedCollection();
-       Ext.getDoc().addKeyListener(27, function(){
-           if(active.length > 0){
-               hideAll();
-           }
-       });
-   }
+    /**
+     * @cfg {Boolean} plain
+     * True to remove the incised line down the left side of the menu. Defaults to <tt>false</tt>.
+     */
+    plain : false,
 
-   // private
-   function hideAll(){
-       if(active && active.length > 0){
-           var c = active.clone();
-           c.each(function(m){
-               m.hide();
-           });
-       }
-   }
+    /**
+     * @cfg {Boolean} floating
+     * <p>By default, a Menu configured as <b><code>floating:true</code></b>
+     * will be rendered as an {@link Ext.Layer} (an absolutely positioned,
+     * floating Component with zindex=15000).
+     * If configured as <b><code>floating:false</code></b>, the Menu may be
+     * used as child item of another Container instead of a free-floating
+     * {@link Ext.Layer Layer}.
+     */
+    floating : true,
 
-   // private
-   function onHide(m){
-       active.remove(m);
-       if(active.length < 1){
-           Ext.getDoc().un("mousedown", onMouseDown);
-           attached = false;
-       }
-   }
 
-   // private
-   function onShow(m){
-       var last = active.last();
-       lastShow = new Date();
-       active.add(m);
-       if(!attached){
-           Ext.getDoc().on("mousedown", onMouseDown);
-           attached = true;
-       }
-       if(m.parentMenu){
-          m.getEl().setZIndex(parseInt(m.parentMenu.getEl().getStyle("z-index"), 10) + 3);
-          m.parentMenu.activeChild = m;
-       }else if(last && last.isVisible()){
-          m.getEl().setZIndex(parseInt(last.getEl().getStyle("z-index"), 10) + 3);
-       }
-   }
+    /**
+     * @cfg {Number} zIndex
+     * zIndex to use when the menu is floating.
+     */
+    zIndex: 15000,
 
-   // private
-   function onBeforeHide(m){
-       if(m.activeChild){
-           m.activeChild.hide();
-       }
+    // private
+    hidden : true,
+
+    /**
+     * @cfg {String/Object} layout
+     * This class assigns a default layout (<code>layout:'<b>menu</b>'</code>).
+     * Developers <i>may</i> override this configuration option if another layout is required.
+     * See {@link Ext.Container#layout} for additional information.
+     */
+    layout : 'menu',
+    hideMode : 'offsets',    // Important for laying out Components
+    scrollerHeight : 8,
+    autoLayout : true,       // Provided for backwards compat
+    defaultType : 'menuitem',
+    bufferResize : false,
+
+    initComponent : function(){
+        if(Ext.isArray(this.initialConfig)){
+            Ext.apply(this, {items:this.initialConfig});
+        }
+        this.addEvents(
+            /**
+             * @event click
+             * Fires when this menu is clicked (or when the enter key is pressed while it is active)
+             * @param {Ext.menu.Menu} this
+            * @param {Ext.menu.Item} menuItem The menu item that was clicked
+             * @param {Ext.EventObject} e
+             */
+            'click',
+            /**
+             * @event mouseover
+             * Fires when the mouse is hovering over this menu
+             * @param {Ext.menu.Menu} this
+             * @param {Ext.EventObject} e
+             * @param {Ext.menu.Item} menuItem The menu item that was clicked
+             */
+            'mouseover',
+            /**
+             * @event mouseout
+             * Fires when the mouse exits this menu
+             * @param {Ext.menu.Menu} this
+             * @param {Ext.EventObject} e
+             * @param {Ext.menu.Item} menuItem The menu item that was clicked
+             */
+            'mouseout',
+            /**
+             * @event itemclick
+             * Fires when a menu item contained in this menu is clicked
+             * @param {Ext.menu.BaseItem} baseItem The BaseItem that was clicked
+             * @param {Ext.EventObject} e
+             */
+            'itemclick'
+        );
+        Ext.menu.MenuMgr.register(this);
+        if(this.floating){
+            Ext.EventManager.onWindowResize(this.hide, this);
+        }else{
+            if(this.initialConfig.hidden !== false){
+                this.hidden = false;
+            }
+            this.internalDefaults = {hideOnClick: false};
+        }
+        Ext.menu.Menu.superclass.initComponent.call(this);
+        if(this.autoLayout){
+            var fn = this.doLayout.createDelegate(this, []);
+            this.on({
+                add: fn,
+                remove: fn
+            });
+        }
+    },
+
+    //private
+    getLayoutTarget : function() {
+        return this.ul;
+    },
+
+    // private
+    onRender : function(ct, position){
+        if(!ct){
+            ct = Ext.getBody();
+        }
+
+        var dh = {
+            id: this.getId(),
+            cls: 'x-menu ' + ((this.floating) ? 'x-menu-floating x-layer ' : '') + (this.cls || '') + (this.plain ? ' x-menu-plain' : '') + (this.showSeparator ? '' : ' x-menu-nosep'),
+            style: this.style,
+            cn: [
+                {tag: 'a', cls: 'x-menu-focus', href: '#', onclick: 'return false;', tabIndex: '-1'},
+                {tag: 'ul', cls: 'x-menu-list'}
+            ]
+        };
+        if(this.floating){
+            this.el = new Ext.Layer({
+                shadow: this.shadow,
+                dh: dh,
+                constrain: false,
+                parentEl: ct,
+                zindex: this.zIndex
+            });
+        }else{
+            this.el = ct.createChild(dh);
+        }
+        Ext.menu.Menu.superclass.onRender.call(this, ct, position);
+
+        if(!this.keyNav){
+            this.keyNav = new Ext.menu.MenuNav(this);
+        }
+        // generic focus element
+        this.focusEl = this.el.child('a.x-menu-focus');
+        this.ul = this.el.child('ul.x-menu-list');
+        this.mon(this.ul, {
+            scope: this,
+            click: this.onClick,
+            mouseover: this.onMouseOver,
+            mouseout: this.onMouseOut
+        });
+        if(this.enableScrolling){
+            this.mon(this.el, {
+                scope: this,
+                delegate: '.x-menu-scroller',
+                click: this.onScroll,
+                mouseover: this.deactivateActive
+            });
+        }
+    },
+
+    // private
+    findTargetItem : function(e){
+        var t = e.getTarget('.x-menu-list-item', this.ul, true);
+        if(t && t.menuItemId){
+            return this.items.get(t.menuItemId);
+        }
+    },
+
+    // private
+    onClick : function(e){
+        var t = this.findTargetItem(e);
+        if(t){
+            if(t.isFormField){
+                this.setActiveItem(t);
+            }else if(t instanceof Ext.menu.BaseItem){
+                if(t.menu && this.ignoreParentClicks){
+                    t.expandMenu();
+                    e.preventDefault();
+                }else if(t.onClick){
+                    t.onClick(e);
+                    this.fireEvent('click', this, t, e);
+                }
+            }
+        }
+    },
+
+    // private
+    setActiveItem : function(item, autoExpand){
+        if(item != this.activeItem){
+            this.deactivateActive();
+            if((this.activeItem = item).isFormField){
+                item.focus();
+            }else{
+                item.activate(autoExpand);
+            }
+        }else if(autoExpand){
+            item.expandMenu();
+        }
+    },
+
+    deactivateActive : function(){
+        var a = this.activeItem;
+        if(a){
+            if(a.isFormField){
+                //Fields cannot deactivate, but Combos must collapse
+                if(a.collapse){
+                    a.collapse();
+                }
+            }else{
+                a.deactivate();
+            }
+            delete this.activeItem;
+        }
+    },
+
+    // private
+    tryActivate : function(start, step){
+        var items = this.items;
+        for(var i = start, len = items.length; i >= 0 && i < len; i+= step){
+            var item = items.get(i);
+            if(!item.disabled && (item.canActivate || item.isFormField)){
+                this.setActiveItem(item, false);
+                return item;
+            }
+        }
+        return false;
+    },
+
+    // private
+    onMouseOver : function(e){
+        var t = this.findTargetItem(e);
+        if(t){
+            if(t.canActivate && !t.disabled){
+                this.setActiveItem(t, true);
+            }
+        }
+        this.over = true;
+        this.fireEvent('mouseover', this, e, t);
+    },
+
+    // private
+    onMouseOut : function(e){
+        var t = this.findTargetItem(e);
+        if(t){
+            if(t == this.activeItem && t.shouldDeactivate && t.shouldDeactivate(e)){
+                this.activeItem.deactivate();
+                delete this.activeItem;
+            }
+        }
+        this.over = false;
+        this.fireEvent('mouseout', this, e, t);
+    },
+
+    // private
+    onScroll : function(e, t){
+        if(e){
+            e.stopEvent();
+        }
+        var ul = this.ul.dom, top = Ext.fly(t).is('.x-menu-scroller-top');
+        ul.scrollTop += this.scrollIncrement * (top ? -1 : 1);
+        if(top ? ul.scrollTop <= 0 : ul.scrollTop + this.activeMax >= ul.scrollHeight){
+           this.onScrollerOut(null, t);
+        }
+    },
+
+    // private
+    onScrollerIn : function(e, t){
+        var ul = this.ul.dom, top = Ext.fly(t).is('.x-menu-scroller-top');
+        if(top ? ul.scrollTop > 0 : ul.scrollTop + this.activeMax < ul.scrollHeight){
+            Ext.fly(t).addClass(['x-menu-item-active', 'x-menu-scroller-active']);
+        }
+    },
+
+    // private
+    onScrollerOut : function(e, t){
+        Ext.fly(t).removeClass(['x-menu-item-active', 'x-menu-scroller-active']);
+    },
+
+    /**
+     * If <code>{@link #floating}=true</code>, shows this menu relative to
+     * another element using {@link #showat}, otherwise uses {@link Ext.Component#show}.
+     * @param {Mixed} element The element to align to
+     * @param {String} position (optional) The {@link Ext.Element#alignTo} anchor position to use in aligning to
+     * the element (defaults to this.defaultAlign)
+     * @param {Ext.menu.Menu} parentMenu (optional) This menu's parent menu, if applicable (defaults to undefined)
+     */
+    show : function(el, pos, parentMenu){
+        if(this.floating){
+            this.parentMenu = parentMenu;
+            if(!this.el){
+                this.render();
+                this.doLayout(false, true);
+            }
+            this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign, this.defaultOffsets), parentMenu);
+        }else{
+            Ext.menu.Menu.superclass.show.call(this);
+        }
+    },
+
+    /**
+     * Displays this menu at a specific xy position and fires the 'show' event if a
+     * handler for the 'beforeshow' event does not return false cancelling the operation.
+     * @param {Array} xyPosition Contains X & Y [x, y] values for the position at which to show the menu (coordinates are page-based)
+     * @param {Ext.menu.Menu} parentMenu (optional) This menu's parent menu, if applicable (defaults to undefined)
+     */
+    showAt : function(xy, parentMenu){
+        if(this.fireEvent('beforeshow', this) !== false){
+            this.parentMenu = parentMenu;
+            if(!this.el){
+                this.render();
+            }
+            if(this.enableScrolling){
+                // set the position so we can figure out the constrain value.
+                this.el.setXY(xy);
+                //constrain the value, keep the y coordinate the same
+                xy[1] = this.constrainScroll(xy[1]);
+                xy = [this.el.adjustForConstraints(xy)[0], xy[1]];
+            }else{
+                //constrain to the viewport.
+                xy = this.el.adjustForConstraints(xy);
+            }
+            this.el.setXY(xy);
+            this.el.show();
+            Ext.menu.Menu.superclass.onShow.call(this);
+            if(Ext.isIE){
+                // internal event, used so we don't couple the layout to the menu
+                this.fireEvent('autosize', this);
+                if(!Ext.isIE8){
+                    this.el.repaint();
+                }
+            }
+            this.hidden = false;
+            this.focus();
+            this.fireEvent('show', this);
+        }
+    },
+
+    constrainScroll : function(y){
+        var max, full = this.ul.setHeight('auto').getHeight(),
+            returnY = y, normalY, parentEl, scrollTop, viewHeight;
+        if(this.floating){
+            parentEl = Ext.fly(this.el.dom.parentNode);
+            scrollTop = parentEl.getScroll().top;
+            viewHeight = parentEl.getViewSize().height;
+            //Normalize y by the scroll position for the parent element.  Need to move it into the coordinate space
+            //of the view.
+            normalY = y - scrollTop;
+            max = this.maxHeight ? this.maxHeight : viewHeight - normalY;
+            if(full > viewHeight) {
+                max = viewHeight;
+                //Set returnY equal to (0,0) in view space by reducing y by the value of normalY
+                returnY = y - normalY;
+            } else if(max < full) {
+                returnY = y - (full - max);
+                max = full;
+            }
+        }else{
+            max = this.getHeight();
+        }
+        if(full > max && max > 0){
+            this.activeMax = max - this.scrollerHeight * 2 - this.el.getFrameWidth('tb') - Ext.num(this.el.shadowOffset, 0);
+            this.ul.setHeight(this.activeMax);
+            this.createScrollers();
+            this.el.select('.x-menu-scroller').setDisplayed('');
+        }else{
+            this.ul.setHeight(full);
+            this.el.select('.x-menu-scroller').setDisplayed('none');
+        }
+        this.ul.dom.scrollTop = 0;
+        return returnY;
+    },
+
+    createScrollers : function(){
+        if(!this.scroller){
+            this.scroller = {
+                pos: 0,
+                top: this.el.insertFirst({
+                    tag: 'div',
+                    cls: 'x-menu-scroller x-menu-scroller-top',
+                    html: '&#160;'
+                }),
+                bottom: this.el.createChild({
+                    tag: 'div',
+                    cls: 'x-menu-scroller x-menu-scroller-bottom',
+                    html: '&#160;'
+                })
+            };
+            this.scroller.top.hover(this.onScrollerIn, this.onScrollerOut, this);
+            this.scroller.topRepeater = new Ext.util.ClickRepeater(this.scroller.top, {
+                listeners: {
+                    click: this.onScroll.createDelegate(this, [null, this.scroller.top], false)
+                }
+            });
+            this.scroller.bottom.hover(this.onScrollerIn, this.onScrollerOut, this);
+            this.scroller.bottomRepeater = new Ext.util.ClickRepeater(this.scroller.bottom, {
+                listeners: {
+                    click: this.onScroll.createDelegate(this, [null, this.scroller.bottom], false)
+                }
+            });
+        }
+    },
+
+    onLayout : function(){
+        if(this.isVisible()){
+            if(this.enableScrolling){
+                this.constrainScroll(this.el.getTop());
+            }
+            if(this.floating){
+                this.el.sync();
+            }
+        }
+    },
+
+    focus : function(){
+        if(!this.hidden){
+            this.doFocus.defer(50, this);
+        }
+    },
+
+    doFocus : function(){
+        if(!this.hidden){
+            this.focusEl.focus();
+        }
+    },
+
+    /**
+     * Hides this menu and optionally all parent menus
+     * @param {Boolean} deep (optional) True to hide all parent menus recursively, if any (defaults to false)
+     */
+    hide : function(deep){
+        if (!this.isDestroyed) {
+            this.deepHide = deep;
+            Ext.menu.Menu.superclass.hide.call(this);
+            delete this.deepHide;
+        }
+    },
+
+    // private
+    onHide : function(){
+        Ext.menu.Menu.superclass.onHide.call(this);
+        this.deactivateActive();
+        if(this.el && this.floating){
+            this.el.hide();
+        }
+        var pm = this.parentMenu;
+        if(this.deepHide === true && pm){
+            if(pm.floating){
+                pm.hide(true);
+            }else{
+                pm.deactivateActive();
+            }
+        }
+    },
+
+    // private
+    lookupComponent : function(c){
+         if(Ext.isString(c)){
+            c = (c == 'separator' || c == '-') ? new Ext.menu.Separator() : new Ext.menu.TextItem(c);
+             this.applyDefaults(c);
+         }else{
+            if(Ext.isObject(c)){
+                c = this.getMenuItem(c);
+            }else if(c.tagName || c.el){ // element. Wrap it.
+                c = new Ext.BoxComponent({
+                    el: c
+                });
+            }
+         }
+         return c;
+    },
+
+    applyDefaults : function(c){
+        if(!Ext.isString(c)){
+            c = Ext.menu.Menu.superclass.applyDefaults.call(this, c);
+            var d = this.internalDefaults;
+            if(d){
+                if(c.events){
+                    Ext.applyIf(c.initialConfig, d);
+                    Ext.apply(c, d);
+                }else{
+                    Ext.applyIf(c, d);
+                }
+            }
+        }
+        return c;
+    },
+
+    // private
+    getMenuItem : function(config){
+       if(!config.isXType){
+            if(!config.xtype && Ext.isBoolean(config.checked)){
+                return new Ext.menu.CheckItem(config)
+            }
+            return Ext.create(config, this.defaultType);
+        }
+        return config;
+    },
+
+    /**
+     * Adds a separator bar to the menu
+     * @return {Ext.menu.Item} The menu item that was added
+     */
+    addSeparator : function(){
+        return this.add(new Ext.menu.Separator());
+    },
+
+    /**
+     * Adds an {@link Ext.Element} object to the menu
+     * @param {Mixed} el The element or DOM node to add, or its id
+     * @return {Ext.menu.Item} The menu item that was added
+     */
+    addElement : function(el){
+        return this.add(new Ext.menu.BaseItem({
+            el: el
+        }));
+    },
+
+    /**
+     * Adds an existing object based on {@link Ext.menu.BaseItem} to the menu
+     * @param {Ext.menu.Item} item The menu item to add
+     * @return {Ext.menu.Item} The menu item that was added
+     */
+    addItem : function(item){
+        return this.add(item);
+    },
+
+    /**
+     * Creates a new {@link Ext.menu.Item} based an the supplied config object and adds it to the menu
+     * @param {Object} config A MenuItem config object
+     * @return {Ext.menu.Item} The menu item that was added
+     */
+    addMenuItem : function(config){
+        return this.add(this.getMenuItem(config));
+    },
+
+    /**
+     * Creates a new {@link Ext.menu.TextItem} with the supplied text and adds it to the menu
+     * @param {String} text The text to display in the menu item
+     * @return {Ext.menu.Item} The menu item that was added
+     */
+    addText : function(text){
+        return this.add(new Ext.menu.TextItem(text));
+    },
+
+    //private
+    onDestroy : function(){
+        Ext.EventManager.removeResizeListener(this.hide, this);
+        var pm = this.parentMenu;
+        if(pm && pm.activeChild == this){
+            delete pm.activeChild;
+        }
+        delete this.parentMenu;
+        Ext.menu.Menu.superclass.onDestroy.call(this);
+        Ext.menu.MenuMgr.unregister(this);
+        if(this.keyNav) {
+            this.keyNav.disable();
+        }
+        var s = this.scroller;
+        if(s){
+            Ext.destroy(s.topRepeater, s.bottomRepeater, s.top, s.bottom);
+        }
+        Ext.destroy(
+            this.el,
+            this.focusEl,
+            this.ul
+        );
+    }
+});
+
+Ext.reg('menu', Ext.menu.Menu);
+
+// MenuNav is a private utility class used internally by the Menu
+Ext.menu.MenuNav = Ext.extend(Ext.KeyNav, function(){
+    function up(e, m){
+        if(!m.tryActivate(m.items.indexOf(m.activeItem)-1, -1)){
+            m.tryActivate(m.items.length-1, -1);
+        }
+    }
+    function down(e, m){
+        if(!m.tryActivate(m.items.indexOf(m.activeItem)+1, 1)){
+            m.tryActivate(0, 1);
+        }
+    }
+    return {
+        constructor : function(menu){
+            Ext.menu.MenuNav.superclass.constructor.call(this, menu.el);
+            this.scope = this.menu = menu;
+        },
+
+        doRelay : function(e, h){
+            var k = e.getKey();
+//          Keystrokes within a form Field (e.g.: down in a Combo) do not navigate. Allow only TAB
+            if (this.menu.activeItem && this.menu.activeItem.isFormField && k != e.TAB) {
+                return false;
+            }
+            if(!this.menu.activeItem && e.isNavKeyPress() && k != e.SPACE && k != e.RETURN){
+                this.menu.tryActivate(0, 1);
+                return false;
+            }
+            return h.call(this.scope || this, e, this.menu);
+        },
+
+        tab: function(e, m) {
+            e.stopEvent();
+            if (e.shiftKey) {
+                up(e, m);
+            } else {
+                down(e, m);
+            }
+        },
+
+        up : up,
+
+        down : down,
+
+        right : function(e, m){
+            if(m.activeItem){
+                m.activeItem.expandMenu(true);
+            }
+        },
+
+        left : function(e, m){
+            m.hide();
+            if(m.parentMenu && m.parentMenu.activeItem){
+                m.parentMenu.activeItem.activate();
+            }
+        },
+
+        enter : function(e, m){
+            if(m.activeItem){
+                e.stopPropagation();
+                m.activeItem.onClick(e);
+                m.fireEvent('click', this, m.activeItem);
+                return true;
+            }
+        }
+    };
+}());
+/**
+ * @class Ext.menu.MenuMgr
+ * Provides a common registry of all menu items on a page so that they can be easily accessed by id.
+ * @singleton
+ */
+Ext.menu.MenuMgr = function(){
+   var menus, active, groups = {}, attached = false, lastShow = new Date();
+
+   // private - called when first menu is created
+   function init(){
+       menus = {};
+       active = new Ext.util.MixedCollection();
+       Ext.getDoc().addKeyListener(27, function(){
+           if(active.length > 0){
+               hideAll();
+           }
+       });
+   }
+
+   // private
+   function hideAll(){
+       if(active && active.length > 0){
+           var c = active.clone();
+           c.each(function(m){
+               m.hide();
+           });
+           return true;
+       }
+       return false;
+   }
+
+   // private
+   function onHide(m){
+       active.remove(m);
+       if(active.length < 1){
+           Ext.getDoc().un("mousedown", onMouseDown);
+           attached = false;
+       }
+   }
+
+   // private
+   function onShow(m){
+       var last = active.last();
+       lastShow = new Date();
+       active.add(m);
+       if(!attached){
+           Ext.getDoc().on("mousedown", onMouseDown);
+           attached = true;
+       }
+       if(m.parentMenu){
+          m.getEl().setZIndex(parseInt(m.parentMenu.getEl().getStyle("z-index"), 10) + 3);
+          m.parentMenu.activeChild = m;
+       }else if(last && !last.isDestroyed && last.isVisible()){
+          m.getEl().setZIndex(parseInt(last.getEl().getStyle("z-index"), 10) + 3);
+       }
+   }
+
+   // private
+   function onBeforeHide(m){
+       if(m.activeChild){
+           m.activeChild.hide();
+       }
        if(m.autoHideTimer){
            clearTimeout(m.autoHideTimer);
            delete m.autoHideTimer;
@@ -52365,9 +54694,10 @@ Ext.menu.MenuMgr = function(){
 
        /**
         * Hides all menus that are currently visible
+        * @return {Boolean} success True if any active menus were hidden.
         */
        hideAll : function(){
-            hideAll();  
+            return hideAll();
        },
 
        // private
@@ -52376,18 +54706,12 @@ Ext.menu.MenuMgr = function(){
                init();
            }
            menus[menu.id] = menu;
-           menu.on("beforehide", onBeforeHide);
-           menu.on("hide", onHide);
-           menu.on("beforeshow", onBeforeShow);
-           menu.on("show", onShow);
-           var g = menu.group;
-           if(g && menu.events["checkchange"]){
-               if(!groups[g]){
-                   groups[g] = [];
-               }
-               groups[g].push(menu);
-               menu.on("checkchange", onCheck);
-           }
+           menu.on({
+               beforehide: onBeforeHide,
+               hide: onHide,
+               beforeshow: onBeforeShow,
+               show: onShow
+           });
        },
 
         /**
@@ -52418,11 +54742,6 @@ Ext.menu.MenuMgr = function(){
            menu.un("hide", onHide);
            menu.un("beforeshow", onBeforeShow);
            menu.un("show", onShow);
-           var g = menu.group;
-           if(g && menu.events["checkchange"]){
-               groups[g].remove(menu);
-               menu.un("checkchange", onCheck);
-           }
        },
 
        // private
@@ -52481,37 +54800,7 @@ Ext.menu.MenuMgr = function(){
  * @param {Object} config Configuration options
  * @xtype menubaseitem
  */
-Ext.menu.BaseItem = function(config){
-    Ext.menu.BaseItem.superclass.constructor.call(this, config);
-
-    this.addEvents(
-        /**
-         * @event click
-         * Fires when this item is clicked
-         * @param {Ext.menu.BaseItem} this
-         * @param {Ext.EventObject} e
-         */
-        'click',
-        /**
-         * @event activate
-         * Fires when this item is activated
-         * @param {Ext.menu.BaseItem} this
-         */
-        'activate',
-        /**
-         * @event deactivate
-         * Fires when this item is deactivated
-         * @param {Ext.menu.BaseItem} this
-         */
-        'deactivate'
-    );
-
-    if(this.handler){
-        this.on("click", this.handler, this.scope);
-    }
-};
-
-Ext.extend(Ext.menu.BaseItem, Ext.Component, {
+Ext.menu.BaseItem = Ext.extend(Ext.Component, {
     /**
      * @property parentMenu
      * @type Ext.menu.Menu
@@ -52551,6 +54840,34 @@ Ext.extend(Ext.menu.BaseItem, Ext.Component, {
 
     // private
     actionMode : "container",
+    
+    initComponent : function(){
+        Ext.menu.BaseItem.superclass.initComponent.call(this);
+        this.addEvents(
+               /**
+                * @event click
+                * Fires when this item is clicked
+                * @param {Ext.menu.BaseItem} this
+                * @param {Ext.EventObject} e
+                */
+               'click',
+               /**
+                * @event activate
+                * Fires when this item is activated
+                * @param {Ext.menu.BaseItem} this
+                */
+               'activate',
+               /**
+                * @event deactivate
+                * Fires when this item is deactivated
+                * @param {Ext.menu.BaseItem} this
+                */
+               'deactivate'
+           );
+           if(this.handler){
+               this.on("click", this.handler, this.scope);
+           }
+    },
 
     // private
     onRender : function(container, position){
@@ -52559,9 +54876,12 @@ Ext.extend(Ext.menu.BaseItem, Ext.Component, {
             this.parentMenu = this.ownerCt;
         }else{
             this.container.addClass('x-menu-list-item');
-            this.mon(this.el, 'click', this.onClick, this);
-            this.mon(this.el, 'mouseenter', this.activate, this);
-            this.mon(this.el, 'mouseleave', this.deactivate, this);
+            this.mon(this.el, {
+                scope: this,
+                click: this.onClick,
+                mouseenter: this.activate,
+                mouseleave: this.deactivate
+            });
         }
     },
 
@@ -52569,7 +54889,7 @@ Ext.extend(Ext.menu.BaseItem, Ext.Component, {
      * Sets the function that will handle click events for this item (equivalent to passing in the {@link #handler}
      * config property).  If an existing handler is already registered, it will be unregistered for you.
      * @param {Function} handler The function that should be called on click
-     * @param {Object} scope The scope that should be passed to the handler
+     * @param {Object} scope The scope (<code>this</code> reference) in which the handler function is executed. Defaults to this menu item.
      */
     setHandler : function(handler, scope){
         if(this.handler){
@@ -52639,14 +54959,7 @@ Ext.reg('menubaseitem', Ext.menu.BaseItem);/**
  * is applied as a config object (and should contain a <tt>text</tt> property).
  * @xtype menutextitem
  */
-Ext.menu.TextItem = function(cfg){
-    if(typeof cfg == 'string'){
-        cfg = {text: cfg}
-    }
-    Ext.menu.TextItem.superclass.constructor.call(this, cfg);
-};
-
-Ext.extend(Ext.menu.TextItem, Ext.menu.BaseItem, {
+Ext.menu.TextItem = Ext.extend(Ext.menu.BaseItem, {
     /**
      * @cfg {String} text The text to display for this item (defaults to '')
      */
@@ -52658,6 +54971,13 @@ Ext.extend(Ext.menu.TextItem, Ext.menu.BaseItem, {
      * @cfg {String} itemCls The default CSS class to use for text items (defaults to "x-menu-text")
      */
     itemCls : "x-menu-text",
+    
+    constructor : function(config){
+        if(typeof config == 'string'){
+            config = {text: config}
+        }
+        Ext.menu.TextItem.superclass.constructor.call(this, config);
+    },
 
     // private
     onRender : function(){
@@ -52677,11 +54997,7 @@ Ext.reg('menutextitem', Ext.menu.TextItem);/**
  * @param {Object} config Configuration options
  * @xtype menuseparator
  */
-Ext.menu.Separator = function(config){
-    Ext.menu.Separator.superclass.constructor.call(this, config);
-};
-
-Ext.extend(Ext.menu.Separator, Ext.menu.BaseItem, {
+Ext.menu.Separator = Ext.extend(Ext.menu.BaseItem, {
     /**
      * @cfg {String} itemCls The default CSS class to use for separators (defaults to "x-menu-sep")
      */
@@ -52718,13 +55034,7 @@ Ext.reg('menuseparator', Ext.menu.Separator);/**
  * @param {Object} config Configuration options\r
  * @xtype menuitem\r
  */\r
-Ext.menu.Item = function(config){\r
-    Ext.menu.Item.superclass.constructor.call(this, config);\r
-    if(this.menu){\r
-        this.menu = Ext.menu.MenuMgr.get(this.menu);\r
-    }\r
-};\r
-Ext.extend(Ext.menu.Item, Ext.menu.BaseItem, {\r
+Ext.menu.Item = Ext.extend(Ext.menu.BaseItem, {\r
     /**\r
      * @property menu\r
      * @type Ext.menu.Menu\r
@@ -52769,6 +55079,14 @@ Ext.extend(Ext.menu.Item, Ext.menu.BaseItem, {
     // private\r
     ctype: 'Ext.menu.Item',\r
 \r
+    initComponent : function(){\r
+        Ext.menu.Item.superclass.initComponent.call(this);\r
+        if(this.menu){\r
+            this.menu = Ext.menu.MenuMgr.get(this.menu);\r
+            this.menu.ownerCt = this;\r
+        }\r
+    },\r
+\r
     // private\r
     onRender : function(container, position){\r
         if (!this.itemTpl) {\r
@@ -52787,6 +55105,9 @@ Ext.extend(Ext.menu.Item, Ext.menu.BaseItem, {
         this.el = position ? this.itemTpl.insertBefore(position, a, true) : this.itemTpl.append(container, a, true);\r
         this.iconEl = this.el.child('img.x-menu-item-icon');\r
         this.textEl = this.el.child('.x-menu-item-text');\r
+        if(!this.href) { // if no link defined, prevent the default anchor event\r
+            this.mon(this.el, 'click', Ext.emptyFn, null, { preventDefault: true });\r
+        }\r
         Ext.menu.Item.superclass.onRender.call(this, container, position);\r
     },\r
 \r
@@ -52825,10 +55146,11 @@ Ext.extend(Ext.menu.Item, Ext.menu.BaseItem, {
             this.iconEl.replaceClass(oldCls, this.iconCls);\r
         }\r
     },\r
-    \r
+\r
     //private\r
     beforeDestroy: function(){\r
         if (this.menu){\r
+            delete this.menu.ownerCt;\r
             this.menu.destroy();\r
         }\r
         Ext.menu.Item.superclass.beforeDestroy.call(this);\r
@@ -52920,37 +55242,7 @@ Ext.reg('menuitem', Ext.menu.Item);/**
  * @param {Object} config Configuration options
  * @xtype menucheckitem
  */
-Ext.menu.CheckItem = function(config){
-    Ext.menu.CheckItem.superclass.constructor.call(this, config);
-    this.addEvents(
-        /**
-         * @event beforecheckchange
-         * Fires before the checked value is set, providing an opportunity to cancel if needed
-         * @param {Ext.menu.CheckItem} this
-         * @param {Boolean} checked The new checked value that will be set
-         */
-        "beforecheckchange" ,
-        /**
-         * @event checkchange
-         * Fires after the checked value has been set
-         * @param {Ext.menu.CheckItem} this
-         * @param {Boolean} checked The checked value that was set
-         */
-        "checkchange"
-    );
-    /**
-     * A function that handles the checkchange event.  The function is undefined by default, but if an implementation
-     * is provided, it will be called automatically when the checkchange event fires.
-     * @param {Ext.menu.CheckItem} this
-     * @param {Boolean} checked The checked value that was set
-     * @method checkHandler
-     */
-    if(this.checkHandler){
-        this.on('checkchange', this.checkHandler, this.scope);
-    }
-    Ext.menu.MenuMgr.registerCheckable(this);
-};
-Ext.extend(Ext.menu.CheckItem, Ext.menu.Item, {
+Ext.menu.CheckItem = Ext.extend(Ext.menu.Item, {
     /**
      * @cfg {String} group
      * All check items with the same group name will automatically be grouped into a single-select
@@ -52974,6 +55266,37 @@ Ext.extend(Ext.menu.CheckItem, Ext.menu.Item, {
 
     // private
     ctype: "Ext.menu.CheckItem",
+    
+    initComponent : function(){
+        Ext.menu.CheckItem.superclass.initComponent.call(this);
+           this.addEvents(
+               /**
+                * @event beforecheckchange
+                * Fires before the checked value is set, providing an opportunity to cancel if needed
+                * @param {Ext.menu.CheckItem} this
+                * @param {Boolean} checked The new checked value that will be set
+                */
+               "beforecheckchange" ,
+               /**
+                * @event checkchange
+                * Fires after the checked value has been set
+                * @param {Ext.menu.CheckItem} this
+                * @param {Boolean} checked The checked value that was set
+                */
+               "checkchange"
+           );
+           /**
+            * A function that handles the checkchange event.  The function is undefined by default, but if an implementation
+            * is provided, it will be called automatically when the checkchange event fires.
+            * @param {Ext.menu.CheckItem} this
+            * @param {Boolean} checked The checked value that was set
+            * @method checkHandler
+            */
+           if(this.checkHandler){
+               this.on('checkchange', this.checkHandler, this.scope);
+           }
+           Ext.menu.MenuMgr.registerCheckable(this);
+    },
 
     // private
     onRender : function(c){
@@ -52999,12 +55322,13 @@ Ext.extend(Ext.menu.CheckItem, Ext.menu.Item, {
      * @param {Boolean} suppressEvent (optional) True to prevent the checkchange event from firing (defaults to false)
      */
     setChecked : function(state, suppressEvent){
-        if(this.checked != state && this.fireEvent("beforecheckchange", this, state) !== false){
+        var suppress = suppressEvent === true;
+        if(this.checked != state && (suppress || this.fireEvent("beforecheckchange", this, state) !== false)){
             if(this.container){
                 this.container[state ? "addClass" : "removeClass"]("x-menu-item-checked");
             }
             this.checked = state;
-            if(suppressEvent !== true){
+            if(!suppress){
                 this.fireEvent("checkchange", this, state);
             }
         }
@@ -53111,6 +55435,7 @@ Ext.reg('menucheckitem', Ext.menu.CheckItem);/**
          * @param {Date} date The selected date\r
          */\r
         this.relayEvents(this.picker, ['select']);\r
+        this.on('show', this.picker.focus, this.picker);\r
         this.on('select', this.menuHide, this);\r
         if(this.handler){\r
             this.on('select', this.handler, this.scope || this);\r
@@ -53222,7 +55547,7 @@ Ext.reg('menucheckitem', Ext.menu.CheckItem);/**
          * @event select\r
          * Fires when a color is selected from the {@link #palette Ext.ColorPalette}\r
          * @param {Ext.ColorPalette} palette The {@link #palette Ext.ColorPalette}\r
-         * @param {String} color The 6-digit color hex code (without the # symbol)\r
+            * @param {String} color The 6-digit color hex code (without the # symbol)\r
          */\r
         this.relayEvents(this.palette, ['select']);\r
         this.on('select', this.menuHide, this);\r
@@ -53248,6 +55573,12 @@ Ext.reg('colormenu', Ext.menu.ColorMenu);
  * @xtype field
  */
 Ext.form.Field = Ext.extend(Ext.BoxComponent,  {
+    /**
+     * <p>The label Element associated with this Field. <b>Only available after this Field has been rendered by a
+     * {@link form Ext.layout.FormLayout} layout manager.</b></p>
+     * @type Ext.Element
+     * @property label
+     */
     /**
      * @cfg {String} inputType The type attribute for input fields -- e.g. radio, text, password, file (defaults
      * to 'text'). The types 'file' and 'password' must be used to render those field types currently -- there are
@@ -53314,17 +55645,16 @@ Ext.form.Field = Ext.extend(Ext.BoxComponent,  {
      */
     fieldClass : 'x-form-field',
     /**
-     * @cfg {String} msgTarget The location where error text should display.  Should be one of the following values
-     * (defaults to 'qtip'):
-     *<pre>
-Value         Description
------------   ----------------------------------------------------------------------
-qtip          Display a quick tip when the user hovers over the field
-title         Display a default browser title attribute popup
-under         Add a block div beneath the field containing the error text
-side          Add an error icon to the right of the field with a popup on hover
-[element id]  Add the error text directly to the innerHTML of the specified element
-</pre>
+     * @cfg {String} msgTarget<p>The location where the message text set through {@link #markInvalid} should display.
+     * Must be one of the following values:</p>
+     * <div class="mdetail-params"><ul>
+     * <li><code>qtip</code> Display a quick tip containing the message when the user hovers over the field. This is the default.
+     * <div class="subdesc"><b>{@link Ext.QuickTips#init Ext.QuickTips.init} must have been called for this setting to work.</b></div</li>
+     * <li><code>title</code> Display the message in a default browser title attribute popup.</li>
+     * <li><code>under</code> Add a block div beneath the field containing the error message.</li>
+     * <li><code>side</code> Add an error icon to the right of the field, displaying the message in a popup on hover.</li>
+     * <li><code>[element id]</code> Add the error message directly to the innerHTML of the specified element.</li>
+     * </ul></div>
      */
     msgTarget : 'qtip',
     /**
@@ -53348,6 +55678,11 @@ side          Add an error icon to the right of the field with a popup on hover
      * disabled Fields will not be {@link Ext.form.BasicForm#submit submitted}.</p>
      */
     disabled : false,
+    /**
+     * @cfg {Boolean} submitValue False to clear the name attribute on the field so that it is not submitted during a form post.
+     * Defaults to <tt>true</tt>.
+     */
+    submitValue: true,
 
     // private
     isFormField : true,
@@ -53455,7 +55790,9 @@ var form = new Ext.form.FormPanel({
             this.autoEl = cfg;
         }
         Ext.form.Field.superclass.onRender.call(this, ct, position);
-
+        if(this.submitValue === false){
+            this.el.dom.removeAttribute('name');
+        }
         var type = this.el.dom.type;
         if(type){
             if(type == 'password'){
@@ -53464,7 +55801,7 @@ var form = new Ext.form.FormPanel({
             this.el.addClass('x-form-'+type);
         }
         if(this.readOnly){
-            this.el.dom.readOnly = true;
+            this.setReadOnly(true);
         }
         if(this.tabIndex !== undefined){
             this.el.dom.setAttribute('tabIndex', this.tabIndex);
@@ -53512,6 +55849,17 @@ var form = new Ext.form.FormPanel({
         return String(this.getValue()) !== String(this.originalValue);
     },
 
+    /**
+     * Sets the read only state of this field.
+     * @param {Boolean} readOnly Whether the field should be read only.
+     */
+    setReadOnly : function(readOnly){
+        if(this.rendered){
+            this.el.dom.readOnly = readOnly;
+        }
+        this.readOnly = readOnly;
+    },
+
     // private
     afterRender : function(){
         Ext.form.Field.superclass.afterRender.call(this);
@@ -53556,6 +55904,13 @@ var form = new Ext.form.FormPanel({
         }
         if(!this.hasFocus){
             this.hasFocus = true;
+            /**
+             * <p>The value that the Field had at the time it was last focused. This is the value that is passed
+             * to the {@link #change} event which is fired if the value has been changed when the Field is blurred.</p>
+             * <p><b>This will be undefined until the Field has been visited.</b> Compare {@link #originalValue}.</p>
+             * @type mixed
+             * @property startValue
+             */
             this.startValue = this.getValue();
             this.fireEvent('focus', this);
         }
@@ -53571,7 +55926,7 @@ var form = new Ext.form.FormPanel({
             this.el.removeClass(this.focusClass);
         }
         this.hasFocus = false;
-        if(this.validationEvent !== false && (this.validateOnBlur || this.validationEvent != 'blur')){
+        if(this.validationEvent !== false && (this.validateOnBlur || this.validationEvent == 'blur')){
             this.validate();
         }
         var v = this.getValue();
@@ -53636,9 +55991,19 @@ var form = new Ext.form.FormPanel({
     },
 
     /**
-     * Mark this field as invalid, using {@link #msgTarget} to determine how to
-     * display the error and applying {@link #invalidClass} to the field's element.
-     * <b>Note</b>: this method does not actually make the field
+     * Gets the active error message for this field.
+     * @return {String} Returns the active error message on the field, if there is no error, an empty string is returned.
+     */
+    getActiveError : function(){
+        return this.activeError || '';
+    },
+
+    /**
+     * <p>Display an error message associated with this field, using {@link #msgTarget} to determine how to
+     * display the message and applying {@link #invalidClass} to the field's UI element.</p>
+     * <p><b>Note</b>: this method does not cause the Field's {@link #validate} method to return <code>false</code>
+     * if the value does <i>pass</i> validation. So simply marking a Field as invalid will not prevent
+     * submission of forms submitted with the {@link Ext.form.Action.Submit#clientValidation} option set.</p>
      * {@link #isValid invalid}.
      * @param {String} msg (optional) The validation message (defaults to {@link #invalidText})
      */
@@ -53659,6 +56024,7 @@ var form = new Ext.form.FormPanel({
                 t.style.display = this.msgDisplay;
             }
         }
+        this.activeError = msg;
         this.fireEvent('invalid', this, msg);
     },
 
@@ -53681,6 +56047,7 @@ var form = new Ext.form.FormPanel({
                 t.style.display = 'none';
             }
         }
+        delete this.activeError;
         this.fireEvent('valid', this);
     },
 
@@ -53695,7 +56062,12 @@ var form = new Ext.form.FormPanel({
             this.el.findParent('.x-form-field-wrap', 5, true);   // else direct field wrap
     },
 
-    // private
+    // Alignment for 'under' target
+    alignErrorEl : function(){
+        this.errorEl.setWidth(this.getErrorCt().getWidth(true) - 20);
+    },
+
+    // Alignment for 'side' target
     alignErrorIcon : function(){
         this.errorIcon.alignTo(this.el, 'tl-tr', [2, 0]);
     },
@@ -53802,8 +56174,12 @@ Ext.form.MessageTargets = {
                     return;
                 }
                 field.errorEl = elp.createChild({cls:'x-form-invalid-msg'});
-                field.errorEl.setWidth(elp.getWidth(true)-20);
+                field.on('resize', field.alignErrorEl, field);
+                field.on('destroy', function(){
+                    Ext.destroy(this.errorEl);
+                }, field);
             }
+            field.alignErrorEl();
             field.errorEl.update(msg);
             Ext.form.Field.msgFx[field.msgFx].show(field.errorEl, field);
         },
@@ -53826,19 +56202,21 @@ Ext.form.MessageTargets = {
                     return;
                 }
                 field.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});
+                field.on('resize', field.alignErrorIcon, field);
+                field.on('destroy', function(){
+                    Ext.destroy(this.errorIcon);
+                }, field);
             }
             field.alignErrorIcon();
             field.errorIcon.dom.qtip = msg;
             field.errorIcon.dom.qclass = 'x-form-invalid-tip';
             field.errorIcon.show();
-            field.on('resize', field.alignErrorIcon, field);
         },
         clear: function(field){
             field.el.removeClass(field.invalidClass);
             if(field.errorIcon){
                 field.errorIcon.dom.qtip = '';
                 field.errorIcon.hide();
-                field.un('resize', field.alignErrorIcon, field);
             }else{
                 field.el.dom.title = '';
             }
@@ -54155,10 +56533,15 @@ var myField = new Ext.form.NumberField({
 
     // private
     onKeyUpBuffered : function(e){
-        if(!e.isNavKeyPress()){
+        if(this.doAutoSize(e)){
             this.autoSize();
         }
     },
+    
+    // private
+    doAutoSize : function(e){
+        return !e.isNavKeyPress();
+    },
 
     // private
     onKeyUp : function(e){
@@ -54213,12 +56596,18 @@ var myField = new Ext.form.NumberField({
 
     // private
     filterKeys : function(e){
-        // special keys don't generate charCodes, so leave them alone
-        if(e.ctrlKey || e.isSpecialKey()){
+        if(e.ctrlKey){
             return;
         }
-        
-        if(!this.maskRe.test(String.fromCharCode(e.getCharCode()))){
+        var k = e.getKey();
+        if(Ext.isGecko && (e.isNavKeyPress() || k == e.BACKSPACE || (k == e.DELETE && e.button == -1))){
+            return;
+        }
+        var cc = String.fromCharCode(e.getCharCode());
+        if(!Ext.isGecko && e.isSpecialKey() && !cc){
+            return;
+        }
+        if(!this.maskRe.test(cc)){
             e.stopEvent();
         }
     },
@@ -54385,8 +56774,8 @@ var myField = new Ext.form.NumberField({
         var d = document.createElement('div');
         d.appendChild(document.createTextNode(v));
         v = d.innerHTML;
-        d = null;
         Ext.removeNode(d);
+        d = null;
         v += '&#160;';
         var w = Math.min(this.growMax, Math.max(this.metrics.getWidth(v) + /* add extra padding */ 10, this.growMin));
         this.el.setWidth(w);
@@ -54402,348 +56791,390 @@ var myField = new Ext.form.NumberField({
        }
 });
 Ext.reg('textfield', Ext.form.TextField);
-/**\r
- * @class Ext.form.TriggerField\r
- * @extends Ext.form.TextField\r
- * Provides a convenient wrapper for TextFields that adds a clickable trigger button (looks like a combobox by default).\r
- * The trigger has no default action, so you must assign a function to implement the trigger click handler by\r
- * overriding {@link #onTriggerClick}. You can create a TriggerField directly, as it renders exactly like a combobox\r
- * for which you can provide a custom implementation.  For example:\r
- * <pre><code>\r
-var trigger = new Ext.form.TriggerField();\r
-trigger.onTriggerClick = myTriggerFn;\r
-trigger.applyToMarkup('my-field');\r
-</code></pre>\r
- *\r
- * However, in general you will most likely want to use TriggerField as the base class for a reusable component.\r
- * {@link Ext.form.DateField} and {@link Ext.form.ComboBox} are perfect examples of this.\r
- * \r
- * @constructor\r
- * Create a new TriggerField.\r
- * @param {Object} config Configuration options (valid {@Ext.form.TextField} config options will also be applied\r
- * to the base TextField)\r
- * @xtype trigger\r
- */\r
-Ext.form.TriggerField = Ext.extend(Ext.form.TextField,  {\r
-    /**\r
-     * @cfg {String} triggerClass\r
-     * An additional CSS class used to style the trigger button.  The trigger will always get the\r
-     * class <tt>'x-form-trigger'</tt> by default and <tt>triggerClass</tt> will be <b>appended</b> if specified.\r
-     */\r
-    /**\r
-     * @cfg {Mixed} triggerConfig\r
-     * <p>A {@link Ext.DomHelper DomHelper} config object specifying the structure of the\r
-     * trigger element for this Field. (Optional).</p>\r
-     * <p>Specify this when you need a customized element to act as the trigger button for a TriggerField.</p>\r
-     * <p>Note that when using this option, it is the developer's responsibility to ensure correct sizing, positioning\r
-     * and appearance of the trigger.  Defaults to:</p>\r
-     * <pre><code>{tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.triggerClass}</code></pre>\r
-     */\r
-    /**\r
-     * @cfg {String/Object} autoCreate <p>A {@link Ext.DomHelper DomHelper} element spec, or true for a default\r
-     * element spec. Used to create the {@link Ext.Component#getEl Element} which will encapsulate this Component.\r
-     * See <tt>{@link Ext.Component#autoEl autoEl}</tt> for details.  Defaults to:</p>\r
-     * <pre><code>{tag: "input", type: "text", size: "16", autocomplete: "off"}</code></pre>\r
-     */\r
-    defaultAutoCreate : {tag: "input", type: "text", size: "16", autocomplete: "off"},\r
-    /**\r
-     * @cfg {Boolean} hideTrigger <tt>true</tt> to hide the trigger element and display only the base\r
-     * text field (defaults to <tt>false</tt>)\r
-     */\r
-    hideTrigger:false,\r
-    /**\r
-     * @cfg {Boolean} editable <tt>false</tt> to prevent the user from typing text directly into the field,\r
-     * the field will only respond to a click on the trigger to set the value. (defaults to <tt>true</tt>)\r
-     */\r
-    editable: true,\r
-    /**\r
-     * @cfg {String} wrapFocusClass The class added to the to the wrap of the trigger element. Defaults to\r
-     * <tt>x-trigger-wrap-focus</tt>.\r
-     */\r
-    wrapFocusClass: 'x-trigger-wrap-focus',\r
-    /**\r
-     * @hide \r
-     * @method autoSize\r
-     */\r
-    autoSize: Ext.emptyFn,\r
-    // private\r
-    monitorTab : true,\r
-    // private\r
-    deferHeight : true,\r
-    // private\r
-    mimicing : false,\r
-    \r
-    actionMode: 'wrap',\r
-    \r
-    defaultTriggerWidth: 17,\r
-\r
-    // private\r
-    onResize : function(w, h){\r
-        Ext.form.TriggerField.superclass.onResize.call(this, w, h);\r
-        var tw = this.getTriggerWidth();\r
-        if(Ext.isNumber(w)){\r
-            this.el.setWidth(w - tw);\r
-        }\r
-        this.wrap.setWidth(this.el.getWidth() + tw);\r
-    },\r
-    \r
-    getTriggerWidth: function(){\r
-        var tw = this.trigger.getWidth();\r
-        if(!this.hideTrigger && tw === 0){\r
-            tw = this.defaultTriggerWidth;\r
-        }\r
-        return tw;\r
-    },\r
-\r
-    // private\r
-    alignErrorIcon : function(){\r
-        if(this.wrap){\r
-            this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);\r
-        }\r
-    },\r
-\r
-    // private\r
-    onRender : function(ct, position){\r
-        this.doc = Ext.isIE ? Ext.getBody() : Ext.getDoc();\r
-        Ext.form.TriggerField.superclass.onRender.call(this, ct, position);\r
-\r
-        this.wrap = this.el.wrap({cls: 'x-form-field-wrap x-form-field-trigger-wrap'});\r
-        this.trigger = this.wrap.createChild(this.triggerConfig ||\r
-                {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.triggerClass});\r
-        if(this.hideTrigger){\r
-            this.trigger.setDisplayed(false);\r
-        }\r
-        this.initTrigger();\r
-        if(!this.width){\r
-            this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth());\r
-        }\r
-        if(!this.editable){\r
-            this.editable = true;\r
-            this.setEditable(false);\r
-        }\r
-        this.resizeEl = this.positionEl = this.wrap;\r
-    },\r
-\r
-    afterRender : function(){\r
-        Ext.form.TriggerField.superclass.afterRender.call(this);\r
-    },\r
-\r
-    // private\r
-    initTrigger : function(){\r
-        this.mon(this.trigger, 'click', this.onTriggerClick, this, {preventDefault:true});\r
-        this.trigger.addClassOnOver('x-form-trigger-over');\r
-        this.trigger.addClassOnClick('x-form-trigger-click');\r
-    },\r
-\r
-    // private\r
-    onDestroy : function(){\r
-        Ext.destroy(this.trigger, this.wrap);\r
-        if (this.mimicing){\r
-            this.doc.un('mousedown', this.mimicBlur, this);\r
-        }\r
-        Ext.form.TriggerField.superclass.onDestroy.call(this);\r
-    },\r
-\r
-    // private\r
-    onFocus : function(){\r
-        Ext.form.TriggerField.superclass.onFocus.call(this);\r
-        if(!this.mimicing){\r
-            this.wrap.addClass(this.wrapFocusClass);\r
-            this.mimicing = true;\r
-            this.doc.on('mousedown', this.mimicBlur, this, {delay: 10});\r
-            if(this.monitorTab){\r
-                this.on('specialkey', this.checkTab, this);\r
-            }\r
-        }\r
-    },\r
-\r
-    // private\r
-    checkTab : function(me, e){\r
-        if(e.getKey() == e.TAB){\r
-            this.triggerBlur();\r
-        }\r
-    },\r
-\r
-    // private\r
-    onBlur : Ext.emptyFn,\r
-\r
-    // private\r
-    mimicBlur : function(e){\r
-        if(!this.isDestroyed && !this.wrap.contains(e.target) && this.validateBlur(e)){\r
-            this.triggerBlur();\r
-        }\r
-    },\r
-\r
-    // private\r
-    triggerBlur : function(){\r
-        this.mimicing = false;\r
-        this.doc.un('mousedown', this.mimicBlur, this);\r
-        if(this.monitorTab && this.el){\r
-            this.un('specialkey', this.checkTab, this);\r
-        }\r
-        Ext.form.TriggerField.superclass.onBlur.call(this);\r
-        if(this.wrap){\r
-            this.wrap.removeClass(this.wrapFocusClass);\r
-        }\r
-    },\r
-\r
-    beforeBlur : Ext.emptyFn, \r
-    \r
-    /**\r
-     * Allow or prevent the user from directly editing the field text.  If false is passed,\r
-     * the user will only be able to modify the field using the trigger.  This method\r
-     * is the runtime equivalent of setting the 'editable' config option at config time.\r
-     * @param {Boolean} value True to allow the user to directly edit the field text\r
-     */\r
-    setEditable : function(value){\r
-        if(value == this.editable){\r
-            return;\r
-        }\r
-        this.editable = value;\r
-        if(!value){\r
-            this.el.addClass('x-trigger-noedit').on('click', this.onTriggerClick, this).dom.setAttribute('readOnly', true);\r
-        }else{\r
-            this.el.removeClass('x-trigger-noedit').un('click', this.onTriggerClick,  this).dom.removeAttribute('readOnly');\r
-        }\r
-    },\r
-\r
-    // private\r
-    // This should be overriden by any subclass that needs to check whether or not the field can be blurred.\r
-    validateBlur : function(e){\r
-        return true;\r
-    },\r
-\r
-    /**\r
-     * The function that should handle the trigger's click event.  This method does nothing by default\r
-     * until overridden by an implementing function.  See Ext.form.ComboBox and Ext.form.DateField for\r
-     * sample implementations.\r
-     * @method\r
-     * @param {EventObject} e\r
-     */\r
-    onTriggerClick : Ext.emptyFn\r
-\r
-    /**\r
-     * @cfg {Boolean} grow @hide\r
-     */\r
-    /**\r
-     * @cfg {Number} growMin @hide\r
-     */\r
-    /**\r
-     * @cfg {Number} growMax @hide\r
-     */\r
-});\r
-\r
-/**\r
- * @class Ext.form.TwinTriggerField\r
- * @extends Ext.form.TriggerField\r
- * TwinTriggerField is not a public class to be used directly.  It is meant as an abstract base class\r
- * to be extended by an implementing class.  For an example of implementing this class, see the custom\r
- * SearchField implementation here:\r
- * <a href="http://extjs.com/deploy/ext/examples/form/custom.html">http://extjs.com/deploy/ext/examples/form/custom.html</a>\r
- */\r
-Ext.form.TwinTriggerField = Ext.extend(Ext.form.TriggerField, {\r
-    /**\r
-     * @cfg {Mixed} triggerConfig\r
-     * <p>A {@link Ext.DomHelper DomHelper} config object specifying the structure of the trigger elements\r
-     * for this Field. (Optional).</p>\r
-     * <p>Specify this when you need a customized element to contain the two trigger elements for this Field.\r
-     * Each trigger element must be marked by the CSS class <tt>x-form-trigger</tt> (also see\r
-     * <tt>{@link #trigger1Class}</tt> and <tt>{@link #trigger2Class}</tt>).</p>\r
-     * <p>Note that when using this option, it is the developer's responsibility to ensure correct sizing,\r
-     * positioning and appearance of the triggers.</p>\r
-     */\r
-    /**\r
-     * @cfg {String} trigger1Class\r
-     * An additional CSS class used to style the trigger button.  The trigger will always get the\r
-     * class <tt>'x-form-trigger'</tt> by default and <tt>triggerClass</tt> will be <b>appended</b> if specified.\r
-     */\r
-    /**\r
-     * @cfg {String} trigger2Class\r
-     * An additional CSS class used to style the trigger button.  The trigger will always get the\r
-     * class <tt>'x-form-trigger'</tt> by default and <tt>triggerClass</tt> will be <b>appended</b> if specified.\r
-     */\r
-\r
-    initComponent : function(){\r
-        Ext.form.TwinTriggerField.superclass.initComponent.call(this);\r
-\r
-        this.triggerConfig = {\r
-            tag:'span', cls:'x-form-twin-triggers', cn:[\r
-            {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger1Class},\r
-            {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger2Class}\r
-        ]};\r
-    },\r
-\r
-    getTrigger : function(index){\r
-        return this.triggers[index];\r
-    },\r
-\r
-    initTrigger : function(){\r
-        var ts = this.trigger.select('.x-form-trigger', true);\r
-        var triggerField = this;\r
-        ts.each(function(t, all, index){\r
-            var triggerIndex = 'Trigger'+(index+1);\r
-            t.hide = function(){\r
-                var w = triggerField.wrap.getWidth();\r
-                this.dom.style.display = 'none';\r
-                triggerField.el.setWidth(w-triggerField.trigger.getWidth());\r
-                this['hidden' + triggerIndex] = true;\r
-            };\r
-            t.show = function(){\r
-                var w = triggerField.wrap.getWidth();\r
-                this.dom.style.display = '';\r
-                triggerField.el.setWidth(w-triggerField.trigger.getWidth());\r
-                this['hidden' + triggerIndex] = false;\r
-            };\r
-            \r
-            if(this['hide'+triggerIndex]){\r
-                t.dom.style.display = 'none';\r
-                this['hidden' + triggerIndex] = true;\r
-            }\r
-            this.mon(t, 'click', this['on'+triggerIndex+'Click'], this, {preventDefault:true});\r
-            t.addClassOnOver('x-form-trigger-over');\r
-            t.addClassOnClick('x-form-trigger-click');\r
-        }, this);\r
-        this.triggers = ts.elements;\r
-    },\r
-    \r
-    getTriggerWidth: function(){\r
-        var tw = 0;\r
-        Ext.each(this.triggers, function(t, index){\r
-            var triggerIndex = 'Trigger' + (index + 1),\r
-                w = t.getWidth();\r
-            if(w === 0 && !this['hidden' + triggerIndex]){\r
-                tw += this.defaultTriggerWidth;\r
-            }else{\r
-                tw += w;\r
-            }\r
-        }, this);\r
-        return tw;\r
-    },\r
-    \r
-    // private\r
-    onDestroy : function() {\r
-        Ext.destroy(this.triggers);\r
-        Ext.form.TwinTriggerField.superclass.onDestroy.call(this);\r
-    },\r
-\r
-    /**\r
-     * The function that should handle the trigger's click event.  This method does nothing by default\r
-     * until overridden by an implementing function. See {@link Ext.form.TriggerField#onTriggerClick}\r
-     * for additional information.  \r
-     * @method\r
-     * @param {EventObject} e\r
-     */\r
-    onTrigger1Click : Ext.emptyFn,\r
-    /**\r
-     * The function that should handle the trigger's click event.  This method does nothing by default\r
-     * until overridden by an implementing function. See {@link Ext.form.TriggerField#onTriggerClick}\r
-     * for additional information.  \r
-     * @method\r
-     * @param {EventObject} e\r
-     */\r
-    onTrigger2Click : Ext.emptyFn\r
-});\r
-Ext.reg('trigger', Ext.form.TriggerField);/**
+/**
+ * @class Ext.form.TriggerField
+ * @extends Ext.form.TextField
+ * Provides a convenient wrapper for TextFields that adds a clickable trigger button (looks like a combobox by default).
+ * The trigger has no default action, so you must assign a function to implement the trigger click handler by
+ * overriding {@link #onTriggerClick}. You can create a TriggerField directly, as it renders exactly like a combobox
+ * for which you can provide a custom implementation.  For example:
+ * <pre><code>
+var trigger = new Ext.form.TriggerField();
+trigger.onTriggerClick = myTriggerFn;
+trigger.applyToMarkup('my-field');
+</code></pre>
+ *
+ * However, in general you will most likely want to use TriggerField as the base class for a reusable component.
+ * {@link Ext.form.DateField} and {@link Ext.form.ComboBox} are perfect examples of this.
+ *
+ * @constructor
+ * Create a new TriggerField.
+ * @param {Object} config Configuration options (valid {@Ext.form.TextField} config options will also be applied
+ * to the base TextField)
+ * @xtype trigger
+ */
+Ext.form.TriggerField = Ext.extend(Ext.form.TextField,  {
+    /**
+     * @cfg {String} triggerClass
+     * An additional CSS class used to style the trigger button.  The trigger will always get the
+     * class <tt>'x-form-trigger'</tt> by default and <tt>triggerClass</tt> will be <b>appended</b> if specified.
+     */
+    /**
+     * @cfg {Mixed} triggerConfig
+     * <p>A {@link Ext.DomHelper DomHelper} config object specifying the structure of the
+     * trigger element for this Field. (Optional).</p>
+     * <p>Specify this when you need a customized element to act as the trigger button for a TriggerField.</p>
+     * <p>Note that when using this option, it is the developer's responsibility to ensure correct sizing, positioning
+     * and appearance of the trigger.  Defaults to:</p>
+     * <pre><code>{tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.triggerClass}</code></pre>
+     */
+    /**
+     * @cfg {String/Object} autoCreate <p>A {@link Ext.DomHelper DomHelper} element spec, or true for a default
+     * element spec. Used to create the {@link Ext.Component#getEl Element} which will encapsulate this Component.
+     * See <tt>{@link Ext.Component#autoEl autoEl}</tt> for details.  Defaults to:</p>
+     * <pre><code>{tag: "input", type: "text", size: "16", autocomplete: "off"}</code></pre>
+     */
+    defaultAutoCreate : {tag: "input", type: "text", size: "16", autocomplete: "off"},
+    /**
+     * @cfg {Boolean} hideTrigger <tt>true</tt> to hide the trigger element and display only the base
+     * text field (defaults to <tt>false</tt>)
+     */
+    hideTrigger:false,
+    /**
+     * @cfg {Boolean} editable <tt>false</tt> to prevent the user from typing text directly into the field,
+     * the field will only respond to a click on the trigger to set the value. (defaults to <tt>true</tt>).
+     */
+    editable: true,
+    /**
+     * @cfg {Boolean} readOnly <tt>true</tt> to prevent the user from changing the field, and
+     * hides the trigger.  Superceeds the editable and hideTrigger options if the value is true.
+     * (defaults to <tt>false</tt>)
+     */
+    readOnly: false,
+    /**
+     * @cfg {String} wrapFocusClass The class added to the to the wrap of the trigger element. Defaults to
+     * <tt>x-trigger-wrap-focus</tt>.
+     */
+    wrapFocusClass: 'x-trigger-wrap-focus',
+    /**
+     * @hide
+     * @method autoSize
+     */
+    autoSize: Ext.emptyFn,
+    // private
+    monitorTab : true,
+    // private
+    deferHeight : true,
+    // private
+    mimicing : false,
+
+    actionMode: 'wrap',
+
+    defaultTriggerWidth: 17,
+
+    // private
+    onResize : function(w, h){
+        Ext.form.TriggerField.superclass.onResize.call(this, w, h);
+        var tw = this.getTriggerWidth();
+        if(Ext.isNumber(w)){
+            this.el.setWidth(w - tw);
+        }
+        this.wrap.setWidth(this.el.getWidth() + tw);
+    },
+
+    getTriggerWidth: function(){
+        var tw = this.trigger.getWidth();
+        if(!this.hideTrigger && tw === 0){
+            tw = this.defaultTriggerWidth;
+        }
+        return tw;
+    },
+
+    // private
+    alignErrorIcon : function(){
+        if(this.wrap){
+            this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
+        }
+    },
+
+    // private
+    onRender : function(ct, position){
+        this.doc = Ext.isIE ? Ext.getBody() : Ext.getDoc();
+        Ext.form.TriggerField.superclass.onRender.call(this, ct, position);
+
+        this.wrap = this.el.wrap({cls: 'x-form-field-wrap x-form-field-trigger-wrap'});
+        this.trigger = this.wrap.createChild(this.triggerConfig ||
+                {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.triggerClass});
+        this.initTrigger();
+        if(!this.width){
+            this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth());
+        }
+        this.resizeEl = this.positionEl = this.wrap;
+    },
+
+    updateEditState: function(){
+        if(this.rendered){
+            if (this.readOnly) {
+                this.el.dom.readOnly = true;
+                this.el.addClass('x-trigger-noedit');
+                this.mun(this.el, 'click', this.onTriggerClick, this);
+                this.trigger.setDisplayed(false);
+            } else {
+                if (!this.editable) {
+                    this.el.dom.readOnly = true;
+                    this.el.addClass('x-trigger-noedit');
+                    this.mon(this.el, 'click', this.onTriggerClick, this);
+                } else {
+                    this.el.dom.readOnly = false;
+                    this.el.removeClass('x-trigger-noedit');
+                    this.mun(this.el, 'click', this.onTriggerClick, this);
+                }
+                this.trigger.setDisplayed(!this.hideTrigger);
+            }
+            this.onResize(this.width || this.wrap.getWidth());
+        }
+    },
+
+    setHideTrigger: function(hideTrigger){
+        if(hideTrigger != this.hideTrigger){
+            this.hideTrigger = hideTrigger;
+            this.updateEditState();
+        }
+    },
+
+    /**
+     * @param {Boolean} value True to allow the user to directly edit the field text
+     * Allow or prevent the user from directly editing the field text.  If false is passed,
+     * the user will only be able to modify the field using the trigger.  Will also add
+     * a click event to the text field which will call the trigger. This method
+     * is the runtime equivalent of setting the 'editable' config option at config time.
+     */
+    setEditable: function(editable){
+        if(editable != this.editable){
+            this.editable = editable;
+            this.updateEditState();
+        }
+    },
+
+    /**
+     * @param {Boolean} value True to prevent the user changing the field and explicitly
+     * hide the trigger.
+     * Setting this to true will superceed settings editable and hideTrigger.
+     * Setting this to false will defer back to editable and hideTrigger. This method
+     * is the runtime equivalent of setting the 'readOnly' config option at config time.
+     */
+    setReadOnly: function(readOnly){
+        if(readOnly != this.readOnly){
+            this.readOnly = readOnly;
+            this.updateEditState();
+        }
+    },
+
+    afterRender : function(){
+        Ext.form.TriggerField.superclass.afterRender.call(this);
+        this.updateEditState();
+    },
+
+    // private
+    initTrigger : function(){
+        this.mon(this.trigger, 'click', this.onTriggerClick, this, {preventDefault:true});
+        this.trigger.addClassOnOver('x-form-trigger-over');
+        this.trigger.addClassOnClick('x-form-trigger-click');
+    },
+
+    // private
+    onDestroy : function(){
+        Ext.destroy(this.trigger, this.wrap);
+        if (this.mimicing){
+            this.doc.un('mousedown', this.mimicBlur, this);
+        }
+        delete this.doc;
+        Ext.form.TriggerField.superclass.onDestroy.call(this);
+    },
+
+    // private
+    onFocus : function(){
+        Ext.form.TriggerField.superclass.onFocus.call(this);
+        if(!this.mimicing){
+            this.wrap.addClass(this.wrapFocusClass);
+            this.mimicing = true;
+            this.doc.on('mousedown', this.mimicBlur, this, {delay: 10});
+            if(this.monitorTab){
+                this.on('specialkey', this.checkTab, this);
+            }
+        }
+    },
+
+    // private
+    checkTab : function(me, e){
+        if(e.getKey() == e.TAB){
+            this.triggerBlur();
+        }
+    },
+
+    // private
+    onBlur : Ext.emptyFn,
+
+    // private
+    mimicBlur : function(e){
+        if(!this.isDestroyed && !this.wrap.contains(e.target) && this.validateBlur(e)){
+            this.triggerBlur();
+        }
+    },
+
+    // private
+    triggerBlur : function(){
+        this.mimicing = false;
+        this.doc.un('mousedown', this.mimicBlur, this);
+        if(this.monitorTab && this.el){
+            this.un('specialkey', this.checkTab, this);
+        }
+        Ext.form.TriggerField.superclass.onBlur.call(this);
+        if(this.wrap){
+            this.wrap.removeClass(this.wrapFocusClass);
+        }
+    },
+
+    beforeBlur : Ext.emptyFn,
+
+    // private
+    // This should be overriden by any subclass that needs to check whether or not the field can be blurred.
+    validateBlur : function(e){
+        return true;
+    },
+
+    /**
+     * The function that should handle the trigger's click event.  This method does nothing by default
+     * until overridden by an implementing function.  See Ext.form.ComboBox and Ext.form.DateField for
+     * sample implementations.
+     * @method
+     * @param {EventObject} e
+     */
+    onTriggerClick : Ext.emptyFn
+
+    /**
+     * @cfg {Boolean} grow @hide
+     */
+    /**
+     * @cfg {Number} growMin @hide
+     */
+    /**
+     * @cfg {Number} growMax @hide
+     */
+});
+
+/**
+ * @class Ext.form.TwinTriggerField
+ * @extends Ext.form.TriggerField
+ * TwinTriggerField is not a public class to be used directly.  It is meant as an abstract base class
+ * to be extended by an implementing class.  For an example of implementing this class, see the custom
+ * SearchField implementation here:
+ * <a href="http://extjs.com/deploy/ext/examples/form/custom.html">http://extjs.com/deploy/ext/examples/form/custom.html</a>
+ */
+Ext.form.TwinTriggerField = Ext.extend(Ext.form.TriggerField, {
+    /**
+     * @cfg {Mixed} triggerConfig
+     * <p>A {@link Ext.DomHelper DomHelper} config object specifying the structure of the trigger elements
+     * for this Field. (Optional).</p>
+     * <p>Specify this when you need a customized element to contain the two trigger elements for this Field.
+     * Each trigger element must be marked by the CSS class <tt>x-form-trigger</tt> (also see
+     * <tt>{@link #trigger1Class}</tt> and <tt>{@link #trigger2Class}</tt>).</p>
+     * <p>Note that when using this option, it is the developer's responsibility to ensure correct sizing,
+     * positioning and appearance of the triggers.</p>
+     */
+    /**
+     * @cfg {String} trigger1Class
+     * An additional CSS class used to style the trigger button.  The trigger will always get the
+     * class <tt>'x-form-trigger'</tt> by default and <tt>triggerClass</tt> will be <b>appended</b> if specified.
+     */
+    /**
+     * @cfg {String} trigger2Class
+     * An additional CSS class used to style the trigger button.  The trigger will always get the
+     * class <tt>'x-form-trigger'</tt> by default and <tt>triggerClass</tt> will be <b>appended</b> if specified.
+     */
+
+    initComponent : function(){
+        Ext.form.TwinTriggerField.superclass.initComponent.call(this);
+
+        this.triggerConfig = {
+            tag:'span', cls:'x-form-twin-triggers', cn:[
+            {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger1Class},
+            {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger2Class}
+        ]};
+    },
+
+    getTrigger : function(index){
+        return this.triggers[index];
+    },
+
+    initTrigger : function(){
+        var ts = this.trigger.select('.x-form-trigger', true);
+        var triggerField = this;
+        ts.each(function(t, all, index){
+            var triggerIndex = 'Trigger'+(index+1);
+            t.hide = function(){
+                var w = triggerField.wrap.getWidth();
+                this.dom.style.display = 'none';
+                triggerField.el.setWidth(w-triggerField.trigger.getWidth());
+                this['hidden' + triggerIndex] = true;
+            };
+            t.show = function(){
+                var w = triggerField.wrap.getWidth();
+                this.dom.style.display = '';
+                triggerField.el.setWidth(w-triggerField.trigger.getWidth());
+                this['hidden' + triggerIndex] = false;
+            };
+
+            if(this['hide'+triggerIndex]){
+                t.dom.style.display = 'none';
+                this['hidden' + triggerIndex] = true;
+            }
+            this.mon(t, 'click', this['on'+triggerIndex+'Click'], this, {preventDefault:true});
+            t.addClassOnOver('x-form-trigger-over');
+            t.addClassOnClick('x-form-trigger-click');
+        }, this);
+        this.triggers = ts.elements;
+    },
+
+    getTriggerWidth: function(){
+        var tw = 0;
+        Ext.each(this.triggers, function(t, index){
+            var triggerIndex = 'Trigger' + (index + 1),
+                w = t.getWidth();
+            if(w === 0 && !this['hidden' + triggerIndex]){
+                tw += this.defaultTriggerWidth;
+            }else{
+                tw += w;
+            }
+        }, this);
+        return tw;
+    },
+
+    // private
+    onDestroy : function() {
+        Ext.destroy(this.triggers);
+        Ext.form.TwinTriggerField.superclass.onDestroy.call(this);
+    },
+
+    /**
+     * The function that should handle the trigger's click event.  This method does nothing by default
+     * until overridden by an implementing function. See {@link Ext.form.TriggerField#onTriggerClick}
+     * for additional information.
+     * @method
+     * @param {EventObject} e
+     */
+    onTrigger1Click : Ext.emptyFn,
+    /**
+     * The function that should handle the trigger's click event.  This method does nothing by default
+     * until overridden by an implementing function. See {@link Ext.form.TriggerField#onTriggerClick}
+     * for additional information.
+     * @method
+     * @param {EventObject} e
+     */
+    onTrigger2Click : Ext.emptyFn
+});
+Ext.reg('trigger', Ext.form.TriggerField);
+/**
  * @class Ext.form.TextArea
  * @extends Ext.form.TextField
  * Multiline text field.  Can be used as a direct replacement for traditional textarea fields, plus adds
@@ -54765,7 +57196,6 @@ Ext.form.TextArea = Ext.extend(Ext.form.TextField,  {
      */
     growMax: 1000,
     growAppend : '&#160;\n&#160;',
-    growPad : Ext.isWebKit ? -6 : 0,
 
     enterIsSpecial : false,
 
@@ -54804,7 +57234,7 @@ Ext.form.TextArea = Ext.extend(Ext.form.TextField,  {
     },
 
     onDestroy : function(){
-        Ext.destroy(this.textSizeEl);
+        Ext.removeNode(this.textSizeEl);
         Ext.form.TextArea.superclass.onDestroy.call(this);
     },
 
@@ -54813,13 +57243,10 @@ Ext.form.TextArea = Ext.extend(Ext.form.TextField,  {
             this.fireEvent("specialkey", this, e);
         }
     },
-
+    
     // private
-    onKeyUp : function(e){
-        if(!e.isNavKeyPress() || e.getKey() == e.ENTER){
-            this.autoSize();
-        }
-        Ext.form.TextArea.superclass.onKeyUp.call(this, e);
+    doAutoSize : function(e){
+        return !e.isNavKeyPress() || e.getKey() == e.ENTER;
     },
 
     /**
@@ -54830,23 +57257,22 @@ Ext.form.TextArea = Ext.extend(Ext.form.TextField,  {
         if(!this.grow || !this.textSizeEl){
             return;
         }
-        var el = this.el;
-        var v = el.dom.value;
-        var ts = this.textSizeEl;
-        ts.innerHTML = '';
-        ts.appendChild(document.createTextNode(v));
-        v = ts.innerHTML;
+        var el = this.el,
+            v = Ext.util.Format.htmlEncode(el.dom.value),
+            ts = this.textSizeEl,
+            h;
+            
         Ext.fly(ts).setWidth(this.el.getWidth());
         if(v.length < 1){
             v = "&#160;&#160;";
         }else{
             v += this.growAppend;
             if(Ext.isIE){
-                v = v.replace(/\n/g, '<br />');
+                v = v.replace(/\n/g, '&#160;<br />');
             }
         }
         ts.innerHTML = v;
-        var h = Math.min(this.growMax, Math.max(ts.offsetHeight, this.growMin) + this.growPad);
+        h = Math.min(this.growMax, Math.max(ts.offsetHeight, this.growMin));
         if(h != this.lastHeight){
             this.lastHeight = h;
             this.el.setHeight(h);
@@ -54959,10 +57385,26 @@ Ext.form.NumberField = Ext.extend(Ext.form.TextField,  {
     },
 
     setValue : function(v){
-       v = typeof v == 'number' ? v : parseFloat(String(v).replace(this.decimalSeparator, "."));
+       v = Ext.isNumber(v) ? v : parseFloat(String(v).replace(this.decimalSeparator, "."));
         v = isNaN(v) ? '' : String(v).replace(".", this.decimalSeparator);
         return Ext.form.NumberField.superclass.setValue.call(this, v);
     },
+    
+    /**
+     * Replaces any existing {@link #minValue} with the new value.
+     * @param {Number} value The minimum value
+     */
+    setMinValue : function(value){
+        this.minValue = Ext.num(value, Number.NEGATIVE_INFINITY);
+    },
+    
+    /**
+     * Replaces any existing {@link #maxValue} with the new value.
+     * @param {Number} value The maximum value
+     */
+    setMaxValue : function(value){
+        this.maxValue = Ext.num(value, Number.MAX_VALUE);    
+    },
 
     // private
     parseValue : function(value){
@@ -55121,6 +57563,18 @@ disabledDates: ["^03"]
         this.disabledDatesRE = null;
         this.initDisabledDays();
     },
+    
+    initEvents: function() {
+        Ext.form.DateField.superclass.initEvents.call(this);
+        this.keyNav = new Ext.KeyNav(this.el, {
+            "down": function(e) {
+                this.onTriggerClick();
+            },
+            scope: this,
+            forceKeyDown: true
+        });
+    },
+
 
     // private
     initDisabledDays : function(){
@@ -55286,7 +57740,7 @@ dateField.setValue('2006-05-04');
 
     // private
     onDestroy : function(){
-               Ext.destroy(this.menu);
+               Ext.destroy(this.menu, this.keyNav);
         Ext.form.DateField.superclass.onDestroy.call(this);
     },
 
@@ -55307,7 +57761,8 @@ dateField.setValue('2006-05-04');
         }
         if(this.menu == null){
             this.menu = new Ext.menu.DateMenu({
-                hideOnClick: false
+                hideOnClick: false,
+                focusOnSelect: false
             });
         }
         this.onFocus();
@@ -55460,4612 +57915,4789 @@ Ext.form.DisplayField = Ext.extend(Ext.form.Field,  {
 });\r
 \r
 Ext.reg('displayfield', Ext.form.DisplayField);\r
-/**\r
- * @class Ext.form.ComboBox\r
- * @extends Ext.form.TriggerField\r
- * <p>A combobox control with support for autocomplete, remote-loading, paging and many other features.</p>\r
- * <p>A ComboBox works in a similar manner to a traditional HTML &lt;select> field. The difference is\r
- * that to submit the {@link #valueField}, you must specify a {@link #hiddenName} to create a hidden input\r
- * field to hold the value of the valueField. The <i>{@link #displayField}</i> is shown in the text field\r
- * which is named according to the {@link #name}.</p>\r
- * <p><b><u>Events</u></b></p>\r
- * <p>To do something when something in ComboBox is selected, configure the select event:<pre><code>\r
-var cb = new Ext.form.ComboBox({\r
-    // all of your config options\r
-    listeners:{\r
-         scope: yourScope,\r
-         'select': yourFunction\r
-    }\r
-});\r
-\r
-// Alternatively, you can assign events after the object is created:\r
-var cb = new Ext.form.ComboBox(yourOptions);\r
-cb.on('select', yourFunction, yourScope);\r
- * </code></pre></p>\r
- *\r
- * <p><b><u>ComboBox in Grid</u></b></p>\r
- * <p>If using a ComboBox in an {@link Ext.grid.EditorGridPanel Editor Grid} a {@link Ext.grid.Column#renderer renderer}\r
- * will be needed to show the displayField when the editor is not active.  Set up the renderer manually, or implement\r
- * a reusable render, for example:<pre><code>\r
-// create reusable renderer\r
-Ext.util.Format.comboRenderer = function(combo){\r
-    return function(value){\r
-        var record = combo.findRecord(combo.{@link #valueField}, value);\r
-        return record ? record.get(combo.{@link #displayField}) : combo.{@link #valueNotFoundText};\r
-    }\r
-}\r
-\r
-// create the combo instance\r
-var combo = new Ext.form.ComboBox({\r
-    {@link #typeAhead}: true,\r
-    {@link #triggerAction}: 'all',\r
-    {@link #lazyRender}:true,\r
-    {@link #mode}: 'local',\r
-    {@link #store}: new Ext.data.ArrayStore({\r
-        id: 0,\r
-        fields: [\r
-            'myId',\r
-            'displayText'\r
-        ],\r
-        data: [[1, 'item1'], [2, 'item2']]\r
-    }),\r
-    {@link #valueField}: 'myId',\r
-    {@link #displayField}: 'displayText'\r
-});\r
-\r
-// snippet of column model used within grid\r
-var cm = new Ext.grid.ColumnModel([{\r
-       ...\r
-    },{\r
-       header: "Some Header",\r
-       dataIndex: 'whatever',\r
-       width: 130,\r
-       editor: combo, // specify reference to combo instance\r
-       renderer: Ext.util.Format.comboRenderer(combo) // pass combo instance to reusable renderer\r
-    },\r
-    ...\r
-]);\r
- * </code></pre></p>\r
- *\r
- * <p><b><u>Filtering</u></b></p>\r
- * <p>A ComboBox {@link #doQuery uses filtering itself}, for information about filtering the ComboBox\r
- * store manually see <tt>{@link #lastQuery}</tt>.</p>\r
- * @constructor\r
- * Create a new ComboBox.\r
- * @param {Object} config Configuration options\r
- * @xtype combo\r
- */\r
-Ext.form.ComboBox = Ext.extend(Ext.form.TriggerField, {\r
-    /**\r
-     * @cfg {Mixed} transform The id, DOM node or element of an existing HTML SELECT to convert to a ComboBox.\r
-     * Note that if you specify this and the combo is going to be in an {@link Ext.form.BasicForm} or\r
-     * {@link Ext.form.FormPanel}, you must also set <tt>{@link #lazyRender} = true</tt>.\r
-     */\r
-    /**\r
-     * @cfg {Boolean} lazyRender <tt>true</tt> to prevent the ComboBox from rendering until requested\r
-     * (should always be used when rendering into an {@link Ext.Editor} (e.g. {@link Ext.grid.EditorGridPanel Grids}),\r
-     * defaults to <tt>false</tt>).\r
-     */\r
-    /**\r
-     * @cfg {String/Object} autoCreate <p>A {@link Ext.DomHelper DomHelper} element spec, or <tt>true</tt> for a default\r
-     * element spec. Used to create the {@link Ext.Component#getEl Element} which will encapsulate this Component.\r
-     * See <tt>{@link Ext.Component#autoEl autoEl}</tt> for details.  Defaults to:</p>\r
-     * <pre><code>{tag: "input", type: "text", size: "24", autocomplete: "off"}</code></pre>\r
-     */\r
-    /**\r
-     * @cfg {Ext.data.Store/Array} store The data source to which this combo is bound (defaults to <tt>undefined</tt>).\r
-     * Acceptable values for this property are:\r
-     * <div class="mdetail-params"><ul>\r
-     * <li><b>any {@link Ext.data.Store Store} subclass</b></li>\r
-     * <li><b>an Array</b> : Arrays will be converted to a {@link Ext.data.ArrayStore} internally,\r
-     * automatically generating {@link Ext.data.Field#name field names} to work with all data components.\r
-     * <div class="mdetail-params"><ul>\r
-     * <li><b>1-dimensional array</b> : (e.g., <tt>['Foo','Bar']</tt>)<div class="sub-desc">\r
-     * A 1-dimensional array will automatically be expanded (each array item will be used for both the combo\r
-     * {@link #valueField} and {@link #displayField})</div></li>\r
-     * <li><b>2-dimensional array</b> : (e.g., <tt>[['f','Foo'],['b','Bar']]</tt>)<div class="sub-desc">\r
-     * For a multi-dimensional array, the value in index 0 of each item will be assumed to be the combo\r
-     * {@link #valueField}, while the value at index 1 is assumed to be the combo {@link #displayField}.\r
-     * </div></li></ul></div></li></ul></div>\r
-     * <p>See also <tt>{@link #mode}</tt>.</p>\r
-     */\r
-    /**\r
-     * @cfg {String} title If supplied, a header element is created containing this text and added into the top of\r
-     * the dropdown list (defaults to undefined, with no header element)\r
-     */\r
-\r
-    // private\r
-    defaultAutoCreate : {tag: "input", type: "text", size: "24", autocomplete: "off"},\r
-    /**\r
-     * @cfg {Number} listWidth The width (used as a parameter to {@link Ext.Element#setWidth}) of the dropdown\r
-     * list (defaults to the width of the ComboBox field).  See also <tt>{@link #minListWidth}\r
-     */\r
-    /**\r
-     * @cfg {String} displayField The underlying {@link Ext.data.Field#name data field name} to bind to this\r
-     * ComboBox (defaults to undefined if <tt>{@link #mode} = 'remote'</tt> or <tt>'field1'</tt> if\r
-     * {@link #transform transforming a select} or if the {@link #store field name is autogenerated based on\r
-     * the store configuration}).\r
-     * <p>See also <tt>{@link #valueField}</tt>.</p>\r
-     * <p><b>Note</b>: if using a ComboBox in an {@link Ext.grid.EditorGridPanel Editor Grid} a\r
-     * {@link Ext.grid.Column#renderer renderer} will be needed to show the displayField when the editor is not\r
-     * active.</p>\r
-     */\r
-    /**\r
-     * @cfg {String} valueField The underlying {@link Ext.data.Field#name data value name} to bind to this\r
-     * ComboBox (defaults to undefined if <tt>{@link #mode} = 'remote'</tt> or <tt>'field2'</tt> if\r
-     * {@link #transform transforming a select} or if the {@link #store field name is autogenerated based on\r
-     * the store configuration}).\r
-     * <p><b>Note</b>: use of a <tt>valueField</tt> requires the user to make a selection in order for a value to be\r
-     * mapped.  See also <tt>{@link #hiddenName}</tt>, <tt>{@link #hiddenValue}</tt>, and <tt>{@link #displayField}</tt>.</p>\r
-     */\r
-    /**\r
-     * @cfg {String} hiddenName If specified, a hidden form field with this name is dynamically generated to store the\r
-     * field's data value (defaults to the underlying DOM element's name). Required for the combo's value to automatically\r
-     * post during a form submission.  See also {@link #valueField}.\r
-     * <p><b>Note</b>: the hidden field's id will also default to this name if {@link #hiddenId} is not specified.\r
-     * The ComboBox {@link Ext.Component#id id} and the <tt>{@link #hiddenId}</tt> <b>should be different</b>, since\r
-     * no two DOM nodes should share the same id.  So, if the ComboBox <tt>{@link Ext.form.Field#name name}</tt> and\r
-     * <tt>hiddenName</tt> are the same, you should specify a unique <tt>{@link #hiddenId}</tt>.</p>\r
-     */\r
-    /**\r
-     * @cfg {String} hiddenId If <tt>{@link #hiddenName}</tt> is specified, <tt>hiddenId</tt> can also be provided\r
-     * to give the hidden field a unique id (defaults to the <tt>{@link #hiddenName}</tt>).  The <tt>hiddenId</tt>\r
-     * and combo {@link Ext.Component#id id} should be different, since no two DOM\r
-     * nodes should share the same id.\r
-     */\r
-    /**\r
-     * @cfg {String} hiddenValue Sets the initial value of the hidden field if {@link #hiddenName} is\r
-     * specified to contain the selected {@link #valueField}, from the Store. Defaults to the configured\r
-     * <tt>{@link Ext.form.Field#value value}</tt>.\r
-     */\r
-    /**\r
-     * @cfg {String} listClass The CSS class to add to the predefined <tt>'x-combo-list'</tt> class\r
-     * applied the dropdown list element (defaults to '').\r
-     */\r
-    listClass : '',\r
-    /**\r
-     * @cfg {String} selectedClass CSS class to apply to the selected item in the dropdown list\r
-     * (defaults to <tt>'x-combo-selected'</tt>)\r
-     */\r
-    selectedClass : 'x-combo-selected',\r
-    /**\r
-     * @cfg {String} listEmptyText The empty text to display in the data view if no items are found.\r
-     * (defaults to '')\r
-     */\r
-    listEmptyText: '',\r
-    /**\r
-     * @cfg {String} triggerClass An additional CSS class used to style the trigger button.  The trigger will always\r
-     * get the class <tt>'x-form-trigger'</tt> and <tt>triggerClass</tt> will be <b>appended</b> if specified\r
-     * (defaults to <tt>'x-form-arrow-trigger'</tt> which displays a downward arrow icon).\r
-     */\r
-    triggerClass : 'x-form-arrow-trigger',\r
-    /**\r
-     * @cfg {Boolean/String} shadow <tt>true</tt> or <tt>"sides"</tt> for the default effect, <tt>"frame"</tt> for\r
-     * 4-way shadow, and <tt>"drop"</tt> for bottom-right\r
-     */\r
-    shadow : 'sides',\r
-    /**\r
-     * @cfg {String} listAlign A valid anchor position value. See <tt>{@link Ext.Element#alignTo}</tt> for details\r
-     * on supported anchor positions (defaults to <tt>'tl-bl?'</tt>)\r
-     */\r
-    listAlign : 'tl-bl?',\r
-    /**\r
-     * @cfg {Number} maxHeight The maximum height in pixels of the dropdown list before scrollbars are shown\r
-     * (defaults to <tt>300</tt>)\r
-     */\r
-    maxHeight : 300,\r
-    /**\r
-     * @cfg {Number} minHeight The minimum height in pixels of the dropdown list when the list is constrained by its\r
-     * distance to the viewport edges (defaults to <tt>90</tt>)\r
-     */\r
-    minHeight : 90,\r
-    /**\r
-     * @cfg {String} triggerAction The action to execute when the trigger is clicked.\r
-     * <div class="mdetail-params"><ul>\r
-     * <li><b><tt>'query'</tt></b> : <b>Default</b>\r
-     * <p class="sub-desc">{@link #doQuery run the query} using the {@link Ext.form.Field#getRawValue raw value}.</p></li>\r
-     * <li><b><tt>'all'</tt></b> :\r
-     * <p class="sub-desc">{@link #doQuery run the query} specified by the <tt>{@link #allQuery}</tt> config option</p></li>\r
-     * </ul></div>\r
-     * <p>See also <code>{@link #queryParam}</code>.</p>\r
-     */\r
-    triggerAction : 'query',\r
-    /**\r
-     * @cfg {Number} minChars The minimum number of characters the user must type before autocomplete and\r
-     * {@link #typeAhead} activate (defaults to <tt>4</tt> if <tt>{@link #mode} = 'remote'</tt> or <tt>0</tt> if\r
-     * <tt>{@link #mode} = 'local'</tt>, does not apply if\r
-     * <tt>{@link Ext.form.TriggerField#editable editable} = false</tt>).\r
-     */\r
-    minChars : 4,\r
-    /**\r
-     * @cfg {Boolean} typeAhead <tt>true</tt> to populate and autoselect the remainder of the text being\r
-     * typed after a configurable delay ({@link #typeAheadDelay}) if it matches a known value (defaults\r
-     * to <tt>false</tt>)\r
-     */\r
-    typeAhead : false,\r
-    /**\r
-     * @cfg {Number} queryDelay The length of time in milliseconds to delay between the start of typing and\r
-     * sending the query to filter the dropdown list (defaults to <tt>500</tt> if <tt>{@link #mode} = 'remote'</tt>\r
-     * or <tt>10</tt> if <tt>{@link #mode} = 'local'</tt>)\r
-     */\r
-    queryDelay : 500,\r
-    /**\r
-     * @cfg {Number} pageSize If greater than <tt>0</tt>, a {@link Ext.PagingToolbar} is displayed in the\r
-     * footer of the dropdown list and the {@link #doQuery filter queries} will execute with page start and\r
-     * {@link Ext.PagingToolbar#pageSize limit} parameters. Only applies when <tt>{@link #mode} = 'remote'</tt>\r
-     * (defaults to <tt>0</tt>).\r
-     */\r
-    pageSize : 0,\r
-    /**\r
-     * @cfg {Boolean} selectOnFocus <tt>true</tt> to select any existing text in the field immediately on focus.\r
-     * Only applies when <tt>{@link Ext.form.TriggerField#editable editable} = true</tt> (defaults to\r
-     * <tt>false</tt>).\r
-     */\r
-    selectOnFocus : false,\r
-    /**\r
-     * @cfg {String} queryParam Name of the query ({@link Ext.data.Store#baseParam baseParam} name for the store)\r
-     * as it will be passed on the querystring (defaults to <tt>'query'</tt>)\r
-     */\r
-    queryParam : 'query',\r
-    /**\r
-     * @cfg {String} loadingText The text to display in the dropdown list while data is loading.  Only applies\r
-     * when <tt>{@link #mode} = 'remote'</tt> (defaults to <tt>'Loading...'</tt>)\r
-     */\r
-    loadingText : 'Loading...',\r
-    /**\r
-     * @cfg {Boolean} resizable <tt>true</tt> to add a resize handle to the bottom of the dropdown list\r
-     * (creates an {@link Ext.Resizable} with 'se' {@link Ext.Resizable#pinned pinned} handles).\r
-     * Defaults to <tt>false</tt>.\r
-     */\r
-    resizable : false,\r
-    /**\r
-     * @cfg {Number} handleHeight The height in pixels of the dropdown list resize handle if\r
-     * <tt>{@link #resizable} = true</tt> (defaults to <tt>8</tt>)\r
-     */\r
-    handleHeight : 8,\r
-    /**\r
-     * @cfg {String} allQuery The text query to send to the server to return all records for the list\r
-     * with no filtering (defaults to '')\r
-     */\r
-    allQuery: '',\r
-    /**\r
-     * @cfg {String} mode Acceptable values are:\r
-     * <div class="mdetail-params"><ul>\r
-     * <li><b><tt>'remote'</tt></b> : <b>Default</b>\r
-     * <p class="sub-desc">Automatically loads the <tt>{@link #store}</tt> the <b>first</b> time the trigger\r
-     * is clicked. If you do not want the store to be automatically loaded the first time the trigger is\r
-     * clicked, set to <tt>'local'</tt> and manually load the store.  To force a requery of the store\r
-     * <b>every</b> time the trigger is clicked see <tt>{@link #lastQuery}</tt>.</p></li>\r
-     * <li><b><tt>'local'</tt></b> :\r
-     * <p class="sub-desc">ComboBox loads local data</p>\r
-     * <pre><code>\r
-var combo = new Ext.form.ComboBox({\r
-    renderTo: document.body,\r
-    mode: 'local',\r
-    store: new Ext.data.ArrayStore({\r
-        id: 0,\r
-        fields: [\r
-            'myId',  // numeric value is the key\r
-            'displayText'\r
-        ],\r
-        data: [[1, 'item1'], [2, 'item2']]  // data is local\r
-    }),\r
-    valueField: 'myId',\r
-    displayField: 'displayText',\r
-    triggerAction: 'all'\r
-});\r
-     * </code></pre></li>\r
-     * </ul></div>\r
-     */\r
-    mode: 'remote',\r
-    /**\r
-     * @cfg {Number} minListWidth The minimum width of the dropdown list in pixels (defaults to <tt>70</tt>, will\r
-     * be ignored if <tt>{@link #listWidth}</tt> has a higher value)\r
-     */\r
-    minListWidth : 70,\r
-    /**\r
-     * @cfg {Boolean} forceSelection <tt>true</tt> to restrict the selected value to one of the values in the list,\r
-     * <tt>false</tt> to allow the user to set arbitrary text into the field (defaults to <tt>false</tt>)\r
-     */\r
-    forceSelection : false,\r
-    /**\r
-     * @cfg {Number} typeAheadDelay The length of time in milliseconds to wait until the typeahead text is displayed\r
-     * if <tt>{@link #typeAhead} = true</tt> (defaults to <tt>250</tt>)\r
-     */\r
-    typeAheadDelay : 250,\r
-    /**\r
-     * @cfg {String} valueNotFoundText When using a name/value combo, if the value passed to setValue is not found in\r
-     * the store, valueNotFoundText will be displayed as the field text if defined (defaults to undefined). If this\r
-     * default text is used, it means there is no value set and no validation will occur on this field.\r
-     */\r
-\r
-    /**\r
-     * @cfg {Boolean} lazyInit <tt>true</tt> to not initialize the list for this combo until the field is focused\r
-     * (defaults to <tt>true</tt>)\r
-     */\r
-    lazyInit : true,\r
-\r
-    /**\r
-     * The value of the match string used to filter the store. Delete this property to force a requery.\r
-     * Example use:\r
-     * <pre><code>\r
-var combo = new Ext.form.ComboBox({\r
-    ...\r
-    mode: 'remote',\r
-    ...\r
-    listeners: {\r
-        // delete the previous query in the beforequery event or set\r
-        // combo.lastQuery = null (this will reload the store the next time it expands)\r
-        beforequery: function(qe){\r
-            delete qe.combo.lastQuery;\r
-        }\r
-    }\r
-});\r
-     * </code></pre>\r
-     * To make sure the filter in the store is not cleared the first time the ComboBox trigger is used\r
-     * configure the combo with <tt>lastQuery=''</tt>. Example use:\r
-     * <pre><code>\r
-var combo = new Ext.form.ComboBox({\r
-    ...\r
-    mode: 'local',\r
-    triggerAction: 'all',\r
-    lastQuery: ''\r
-});\r
-     * </code></pre>\r
-     * @property lastQuery\r
-     * @type String\r
-     */\r
-\r
-    // private\r
-    initComponent : function(){\r
-        Ext.form.ComboBox.superclass.initComponent.call(this);\r
-        this.addEvents(\r
-            /**\r
-             * @event expand\r
-             * Fires when the dropdown list is expanded\r
-             * @param {Ext.form.ComboBox} combo This combo box\r
-             */\r
-            'expand',\r
-            /**\r
-             * @event collapse\r
-             * Fires when the dropdown list is collapsed\r
-             * @param {Ext.form.ComboBox} combo This combo box\r
-             */\r
-            'collapse',\r
-            /**\r
-             * @event beforeselect\r
-             * Fires before a list item is selected. Return false to cancel the selection.\r
-             * @param {Ext.form.ComboBox} combo This combo box\r
-             * @param {Ext.data.Record} record The data record returned from the underlying store\r
-             * @param {Number} index The index of the selected item in the dropdown list\r
-             */\r
-            'beforeselect',\r
-            /**\r
-             * @event select\r
-             * Fires when a list item is selected\r
-             * @param {Ext.form.ComboBox} combo This combo box\r
-             * @param {Ext.data.Record} record The data record returned from the underlying store\r
-             * @param {Number} index The index of the selected item in the dropdown list\r
-             */\r
-            'select',\r
-            /**\r
-             * @event beforequery\r
-             * Fires before all queries are processed. Return false to cancel the query or set the queryEvent's\r
-             * cancel property to true.\r
-             * @param {Object} queryEvent An object that has these properties:<ul>\r
-             * <li><code>combo</code> : Ext.form.ComboBox <div class="sub-desc">This combo box</div></li>\r
-             * <li><code>query</code> : String <div class="sub-desc">The query</div></li>\r
-             * <li><code>forceAll</code> : Boolean <div class="sub-desc">True to force "all" query</div></li>\r
-             * <li><code>cancel</code> : Boolean <div class="sub-desc">Set to true to cancel the query</div></li>\r
-             * </ul>\r
-             */\r
-            'beforequery'\r
-        );\r
-        if(this.transform){\r
-            var s = Ext.getDom(this.transform);\r
-            if(!this.hiddenName){\r
-                this.hiddenName = s.name;\r
-            }\r
-            if(!this.store){\r
-                this.mode = 'local';\r
-                var d = [], opts = s.options;\r
-                for(var i = 0, len = opts.length;i < len; i++){\r
-                    var o = opts[i],\r
-                        value = (o.hasAttribute ? o.hasAttribute('value') : o.getAttributeNode('value').specified) ? o.value : o.text;\r
-                    if(o.selected && Ext.isEmpty(this.value, true)) {\r
-                        this.value = value;\r
-                    }\r
-                    d.push([value, o.text]);\r
-                }\r
-                this.store = new Ext.data.ArrayStore({\r
-                    'id': 0,\r
-                    fields: ['value', 'text'],\r
-                    data : d,\r
-                    autoDestroy: true\r
-                });\r
-                this.valueField = 'value';\r
-                this.displayField = 'text';\r
-            }\r
-            s.name = Ext.id(); // wipe out the name in case somewhere else they have a reference\r
-            if(!this.lazyRender){\r
-                this.target = true;\r
-                this.el = Ext.DomHelper.insertBefore(s, this.autoCreate || this.defaultAutoCreate);\r
-                this.render(this.el.parentNode, s);\r
-                Ext.removeNode(s); // remove it\r
-            }else{\r
-                Ext.removeNode(s); // remove it\r
-            }\r
-        }\r
-        //auto-configure store from local array data\r
-        else if(this.store){\r
-            this.store = Ext.StoreMgr.lookup(this.store);\r
-            if(this.store.autoCreated){\r
-                this.displayField = this.valueField = 'field1';\r
-                if(!this.store.expandData){\r
-                    this.displayField = 'field2';\r
-                }\r
-                this.mode = 'local';\r
-            }\r
-        }\r
-\r
-        this.selectedIndex = -1;\r
-        if(this.mode == 'local'){\r
-            if(!Ext.isDefined(this.initialConfig.queryDelay)){\r
-                this.queryDelay = 10;\r
-            }\r
-            if(!Ext.isDefined(this.initialConfig.minChars)){\r
-                this.minChars = 0;\r
-            }\r
-        }\r
-    },\r
-\r
-    // private\r
-    onRender : function(ct, position){\r
-        Ext.form.ComboBox.superclass.onRender.call(this, ct, position);\r
-        if(this.hiddenName){\r
-            this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName,\r
-                    id: (this.hiddenId||this.hiddenName)}, 'before', true);\r
-\r
-            // prevent input submission\r
-            this.el.dom.removeAttribute('name');\r
-        }\r
-        if(Ext.isGecko){\r
-            this.el.dom.setAttribute('autocomplete', 'off');\r
-        }\r
-\r
-        if(!this.lazyInit){\r
-            this.initList();\r
-        }else{\r
-            this.on('focus', this.initList, this, {single: true});\r
-        }\r
-    },\r
-\r
-    // private\r
-    initValue : function(){\r
-        Ext.form.ComboBox.superclass.initValue.call(this);\r
-        if(this.hiddenField){\r
-            this.hiddenField.value =\r
-                Ext.isDefined(this.hiddenValue) ? this.hiddenValue :\r
-                Ext.isDefined(this.value) ? this.value : '';\r
-        }\r
-    },\r
-\r
-    // private\r
-    initList : function(){\r
-        if(!this.list){\r
-            var cls = 'x-combo-list';\r
-\r
-            this.list = new Ext.Layer({\r
-                parentEl: this.getListParent(),\r
-                shadow: this.shadow,\r
-                cls: [cls, this.listClass].join(' '),\r
-                constrain:false\r
-            });\r
-\r
-            var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);\r
-            this.list.setSize(lw, 0);\r
-            this.list.swallowEvent('mousewheel');\r
-            this.assetHeight = 0;\r
-            if(this.syncFont !== false){\r
-                this.list.setStyle('font-size', this.el.getStyle('font-size'));\r
-            }\r
-            if(this.title){\r
-                this.header = this.list.createChild({cls:cls+'-hd', html: this.title});\r
-                this.assetHeight += this.header.getHeight();\r
-            }\r
-\r
-            this.innerList = this.list.createChild({cls:cls+'-inner'});\r
-            this.mon(this.innerList, 'mouseover', this.onViewOver, this);\r
-            this.mon(this.innerList, 'mousemove', this.onViewMove, this);\r
-            this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));\r
-\r
-            if(this.pageSize){\r
-                this.footer = this.list.createChild({cls:cls+'-ft'});\r
-                this.pageTb = new Ext.PagingToolbar({\r
-                    store: this.store,\r
-                    pageSize: this.pageSize,\r
-                    renderTo:this.footer\r
-                });\r
-                this.assetHeight += this.footer.getHeight();\r
-            }\r
-\r
-            if(!this.tpl){\r
-                /**\r
-                * @cfg {String/Ext.XTemplate} tpl <p>The template string, or {@link Ext.XTemplate} instance to\r
-                * use to display each item in the dropdown list. The dropdown list is displayed in a\r
-                * DataView. See {@link #view}.</p>\r
-                * <p>The default template string is:</p><pre><code>\r
-                  '&lt;tpl for=".">&lt;div class="x-combo-list-item">{' + this.displayField + '}&lt;/div>&lt;/tpl>'\r
-                * </code></pre>\r
-                * <p>Override the default value to create custom UI layouts for items in the list.\r
-                * For example:</p><pre><code>\r
-                  '&lt;tpl for=".">&lt;div ext:qtip="{state}. {nick}" class="x-combo-list-item">{state}&lt;/div>&lt;/tpl>'\r
-                * </code></pre>\r
-                * <p>The template <b>must</b> contain one or more substitution parameters using field\r
-                * names from the Combo's</b> {@link #store Store}. In the example above an\r
-                * <pre>ext:qtip</pre> attribute is added to display other fields from the Store.</p>\r
-                * <p>To preserve the default visual look of list items, add the CSS class name\r
-                * <pre>x-combo-list-item</pre> to the template's container element.</p>\r
-                * <p>Also see {@link #itemSelector} for additional details.</p>\r
-                */\r
-                this.tpl = '<tpl for="."><div class="'+cls+'-item">{' + this.displayField + '}</div></tpl>';\r
-                /**\r
-                 * @cfg {String} itemSelector\r
-                 * <p>A simple CSS selector (e.g. div.some-class or span:first-child) that will be\r
-                 * used to determine what nodes the {@link #view Ext.DataView} which handles the dropdown\r
-                 * display will be working with.</p>\r
-                 * <p><b>Note</b>: this setting is <b>required</b> if a custom XTemplate has been\r
-                 * specified in {@link #tpl} which assigns a class other than <pre>'x-combo-list-item'</pre>\r
-                 * to dropdown list items</b>\r
-                 */\r
-            }\r
-\r
-            /**\r
-            * The {@link Ext.DataView DataView} used to display the ComboBox's options.\r
-            * @type Ext.DataView\r
-            */\r
-            this.view = new Ext.DataView({\r
-                applyTo: this.innerList,\r
-                tpl: this.tpl,\r
-                singleSelect: true,\r
-                selectedClass: this.selectedClass,\r
-                itemSelector: this.itemSelector || '.' + cls + '-item',\r
-                emptyText: this.listEmptyText\r
-            });\r
-\r
-            this.mon(this.view, 'click', this.onViewClick, this);\r
-\r
-            this.bindStore(this.store, true);\r
-\r
-            if(this.resizable){\r
-                this.resizer = new Ext.Resizable(this.list,  {\r
-                   pinned:true, handles:'se'\r
-                });\r
-                this.mon(this.resizer, 'resize', function(r, w, h){\r
-                    this.maxHeight = h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight;\r
-                    this.listWidth = w;\r
-                    this.innerList.setWidth(w - this.list.getFrameWidth('lr'));\r
-                    this.restrictHeight();\r
-                }, this);\r
-\r
-                this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom', this.handleHeight+'px');\r
-            }\r
-        }\r
-    },\r
-\r
-    /**\r
-     * <p>Returns the element used to house this ComboBox's pop-up list. Defaults to the document body.</p>\r
-     * A custom implementation may be provided as a configuration option if the floating list needs to be rendered\r
-     * to a different Element. An example might be rendering the list inside a Menu so that clicking\r
-     * the list does not hide the Menu:<pre><code>\r
-var store = new Ext.data.ArrayStore({\r
-    autoDestroy: true,\r
-    fields: ['initials', 'fullname'],\r
-    data : [\r
-        ['FF', 'Fred Flintstone'],\r
-        ['BR', 'Barney Rubble']\r
-    ]\r
-});\r
-\r
-var combo = new Ext.form.ComboBox({\r
-    store: store,\r
-    displayField: 'fullname',\r
-    emptyText: 'Select a name...',\r
-    forceSelection: true,\r
-    getListParent: function() {\r
-        return this.el.up('.x-menu');\r
-    },\r
-    iconCls: 'no-icon', //use iconCls if placing within menu to shift to right side of menu\r
-    mode: 'local',\r
-    selectOnFocus: true,\r
-    triggerAction: 'all',\r
-    typeAhead: true,\r
-    width: 135\r
-});\r
-\r
-var menu = new Ext.menu.Menu({\r
-    id: 'mainMenu',\r
-    items: [\r
-        combo // A Field in a Menu\r
-    ]\r
-});\r
-</code></pre>\r
-     */\r
-    getListParent : function() {\r
-        return document.body;\r
-    },\r
-\r
-    /**\r
-     * Returns the store associated with this combo.\r
-     * @return {Ext.data.Store} The store\r
-     */\r
-    getStore : function(){\r
-        return this.store;\r
-    },\r
-\r
-    // private\r
-    bindStore : function(store, initial){\r
-        if(this.store && !initial){\r
-            if(this.store !== store && this.store.autoDestroy){\r
-                this.store.destroy();\r
-            }else{\r
-                this.store.un('beforeload', this.onBeforeLoad, this);\r
-                this.store.un('load', this.onLoad, this);\r
-                this.store.un('exception', this.collapse, this);\r
-            }\r
-            if(!store){\r
-                this.store = null;\r
-                if(this.view){\r
-                    this.view.bindStore(null);\r
-                }\r
-                if(this.pageTb){\r
-                    this.pageTb.bindStore(null);\r
-                }\r
-            }\r
-        }\r
-        if(store){\r
-            if(!initial) {\r
-                this.lastQuery = null;\r
-                if(this.pageTb) {\r
-                    this.pageTb.bindStore(store);\r
-                }\r
-            }\r
-\r
-            this.store = Ext.StoreMgr.lookup(store);\r
-            this.store.on({\r
-                scope: this,\r
-                beforeload: this.onBeforeLoad,\r
-                load: this.onLoad,\r
-                exception: this.collapse\r
-            });\r
-\r
-            if(this.view){\r
-                this.view.bindStore(store);\r
-            }\r
-        }\r
-    },\r
-\r
-    // private\r
-    initEvents : function(){\r
-        Ext.form.ComboBox.superclass.initEvents.call(this);\r
-\r
-        this.keyNav = new Ext.KeyNav(this.el, {\r
-            "up" : function(e){\r
-                this.inKeyMode = true;\r
-                this.selectPrev();\r
-            },\r
-\r
-            "down" : function(e){\r
-                if(!this.isExpanded()){\r
-                    this.onTriggerClick();\r
-                }else{\r
-                    this.inKeyMode = true;\r
-                    this.selectNext();\r
-                }\r
-            },\r
-\r
-            "enter" : function(e){\r
-                this.onViewClick();\r
-            },\r
-\r
-            "esc" : function(e){\r
-                this.collapse();\r
-            },\r
-\r
-            "tab" : function(e){\r
-                this.onViewClick(false);\r
-                return true;\r
-            },\r
-\r
-            scope : this,\r
-\r
-            doRelay : function(e, h, hname){\r
-                if(hname == 'down' || this.scope.isExpanded()){\r
-                    // this MUST be called before ComboBox#fireKey()\r
-                    var relay = Ext.KeyNav.prototype.doRelay.apply(this, arguments);\r
-                    if(!Ext.isIE && Ext.EventManager.useKeydown){\r
-                        // call Combo#fireKey() for browsers which use keydown event (except IE)\r
-                        this.scope.fireKey(e);\r
-                    }\r
-                    return relay;\r
-                }\r
-                return true;\r
-            },\r
-\r
-            forceKeyDown : true,\r
-            defaultEventAction: 'stopEvent'\r
-        });\r
-        this.queryDelay = Math.max(this.queryDelay || 10,\r
-                this.mode == 'local' ? 10 : 250);\r
-        this.dqTask = new Ext.util.DelayedTask(this.initQuery, this);\r
-        if(this.typeAhead){\r
-            this.taTask = new Ext.util.DelayedTask(this.onTypeAhead, this);\r
-        }\r
-        if(this.editable !== false && !this.enableKeyEvents){\r
-            this.mon(this.el, 'keyup', this.onKeyUp, this);\r
-        }\r
-    },\r
-\r
-    // private\r
-    onDestroy : function(){\r
-        if (this.dqTask){\r
-            this.dqTask.cancel();\r
-            this.dqTask = null;\r
-        }\r
-        this.bindStore(null);\r
-        Ext.destroy(\r
-            this.resizer,\r
-            this.view,\r
-            this.pageTb,\r
-            this.list\r
-        );\r
-        Ext.form.ComboBox.superclass.onDestroy.call(this);\r
-    },\r
-\r
-    // private\r
-    fireKey : function(e){\r
-        if (!this.isExpanded()) {\r
-            Ext.form.ComboBox.superclass.fireKey.call(this, e);\r
-        }\r
-    },\r
-\r
-    // private\r
-    onResize : function(w, h){\r
-        Ext.form.ComboBox.superclass.onResize.apply(this, arguments);\r
-        if(this.isVisible() && this.list){\r
-            this.doResize(w);\r
-        }else{\r
-            this.bufferSize = w;\r
-        }\r
-    },\r
-    \r
-    doResize: function(w){\r
-        if(!Ext.isDefined(this.listWidth)){\r
-            var lw = Math.max(w, this.minListWidth);\r
-            this.list.setWidth(lw);\r
-            this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));\r
-        }    \r
-    },\r
-\r
-    // private\r
-    onEnable : function(){\r
-        Ext.form.ComboBox.superclass.onEnable.apply(this, arguments);\r
-        if(this.hiddenField){\r
-            this.hiddenField.disabled = false;\r
-        }\r
-    },\r
-\r
-    // private\r
-    onDisable : function(){\r
-        Ext.form.ComboBox.superclass.onDisable.apply(this, arguments);\r
-        if(this.hiddenField){\r
-            this.hiddenField.disabled = true;\r
-        }\r
-    },\r
-\r
-    // private\r
-    onBeforeLoad : function(){\r
-        if(!this.hasFocus){\r
-            return;\r
-        }\r
-        this.innerList.update(this.loadingText ?\r
-               '<div class="loading-indicator">'+this.loadingText+'</div>' : '');\r
-        this.restrictHeight();\r
-        this.selectedIndex = -1;\r
-    },\r
-\r
-    // private\r
-    onLoad : function(){\r
-        if(!this.hasFocus){\r
-            return;\r
-        }\r
-        if(this.store.getCount() > 0 || this.listEmptyText){\r
-            this.expand();\r
-            this.restrictHeight();\r
-            if(this.lastQuery == this.allQuery){\r
-                if(this.editable){\r
-                    this.el.dom.select();\r
-                }\r
-                if(!this.selectByValue(this.value, true)){\r
-                    this.select(0, true);\r
-                }\r
-            }else{\r
-                this.selectNext();\r
-                if(this.typeAhead && this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE){\r
-                    this.taTask.delay(this.typeAheadDelay);\r
-                }\r
-            }\r
-        }else{\r
-            this.onEmptyResults();\r
-        }\r
-        //this.el.focus();\r
-    },\r
-\r
-    // private\r
-    onTypeAhead : function(){\r
-        if(this.store.getCount() > 0){\r
-            var r = this.store.getAt(0);\r
-            var newValue = r.data[this.displayField];\r
-            var len = newValue.length;\r
-            var selStart = this.getRawValue().length;\r
-            if(selStart != len){\r
-                this.setRawValue(newValue);\r
-                this.selectText(selStart, newValue.length);\r
-            }\r
-        }\r
-    },\r
-\r
-    // private\r
-    onSelect : function(record, index){\r
-        if(this.fireEvent('beforeselect', this, record, index) !== false){\r
-            this.setValue(record.data[this.valueField || this.displayField]);\r
-            this.collapse();\r
-            this.fireEvent('select', this, record, index);\r
-        }\r
-    },\r
-\r
-    // inherit docs\r
-    getName: function(){\r
-        var hf = this.hiddenField;\r
-        return hf && hf.name ? hf.name : this.hiddenName || Ext.form.ComboBox.superclass.getName.call(this);\r
-    },\r
-\r
-    /**\r
-     * Returns the currently selected field value or empty string if no value is set.\r
-     * @return {String} value The selected value\r
-     */\r
-    getValue : function(){\r
-        if(this.valueField){\r
-            return Ext.isDefined(this.value) ? this.value : '';\r
-        }else{\r
-            return Ext.form.ComboBox.superclass.getValue.call(this);\r
-        }\r
-    },\r
-\r
-    /**\r
-     * Clears any text/value currently set in the field\r
-     */\r
-    clearValue : function(){\r
-        if(this.hiddenField){\r
-            this.hiddenField.value = '';\r
-        }\r
-        this.setRawValue('');\r
-        this.lastSelectionText = '';\r
-        this.applyEmptyText();\r
-        this.value = '';\r
-    },\r
-\r
-    /**\r
-     * Sets the specified value into the field.  If the value finds a match, the corresponding record text\r
-     * will be displayed in the field.  If the value does not match the data value of an existing item,\r
-     * and the valueNotFoundText config option is defined, it will be displayed as the default field text.\r
-     * Otherwise the field will be blank (although the value will still be set).\r
-     * @param {String} value The value to match\r
-     * @return {Ext.form.Field} this\r
-     */\r
-    setValue : function(v){\r
-        var text = v;\r
-        if(this.valueField){\r
-            var r = this.findRecord(this.valueField, v);\r
-            if(r){\r
-                text = r.data[this.displayField];\r
-            }else if(Ext.isDefined(this.valueNotFoundText)){\r
-                text = this.valueNotFoundText;\r
-            }\r
-        }\r
-        this.lastSelectionText = text;\r
-        if(this.hiddenField){\r
-            this.hiddenField.value = v;\r
-        }\r
-        Ext.form.ComboBox.superclass.setValue.call(this, text);\r
-        this.value = v;\r
-        return this;\r
-    },\r
-\r
-    // private\r
-    findRecord : function(prop, value){\r
-        var record;\r
-        if(this.store.getCount() > 0){\r
-            this.store.each(function(r){\r
-                if(r.data[prop] == value){\r
-                    record = r;\r
-                    return false;\r
-                }\r
-            });\r
-        }\r
-        return record;\r
-    },\r
-\r
-    // private\r
-    onViewMove : function(e, t){\r
-        this.inKeyMode = false;\r
-    },\r
-\r
-    // private\r
-    onViewOver : function(e, t){\r
-        if(this.inKeyMode){ // prevent key nav and mouse over conflicts\r
-            return;\r
-        }\r
-        var item = this.view.findItemFromChild(t);\r
-        if(item){\r
-            var index = this.view.indexOf(item);\r
-            this.select(index, false);\r
-        }\r
-    },\r
-\r
-    // private\r
-    onViewClick : function(doFocus){\r
-        var index = this.view.getSelectedIndexes()[0],\r
-            s = this.store,\r
-            r = s.getAt(index);\r
-        if(r){\r
-            this.onSelect(r, index);\r
-        }else if(s.getCount() === 0){\r
-            this.onEmptyResults();\r
-        }\r
-        if(doFocus !== false){\r
-            this.el.focus();\r
-        }\r
-    },\r
-\r
-    // private\r
-    restrictHeight : function(){\r
-        this.innerList.dom.style.height = '';\r
-        var inner = this.innerList.dom,\r
-            pad = this.list.getFrameWidth('tb') + (this.resizable ? this.handleHeight : 0) + this.assetHeight,\r
-            h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight),\r
-            ha = this.getPosition()[1]-Ext.getBody().getScroll().top,\r
-            hb = Ext.lib.Dom.getViewHeight()-ha-this.getSize().height,\r
-            space = Math.max(ha, hb, this.minHeight || 0)-this.list.shadowOffset-pad-5;\r
-            \r
-        h = Math.min(h, space, this.maxHeight);\r
-\r
-        this.innerList.setHeight(h);\r
-        this.list.beginUpdate();\r
-        this.list.setHeight(h+pad);\r
-        this.list.alignTo(this.wrap, this.listAlign);\r
-        this.list.endUpdate();\r
-    },\r
-\r
-    // private\r
-    onEmptyResults : function(){\r
-        this.collapse();\r
-    },\r
-\r
-    /**\r
-     * Returns true if the dropdown list is expanded, else false.\r
-     */\r
-    isExpanded : function(){\r
-        return this.list && this.list.isVisible();\r
-    },\r
-\r
-    /**\r
-     * Select an item in the dropdown list by its data value. This function does NOT cause the select event to fire.\r
-     * The store must be loaded and the list expanded for this function to work, otherwise use setValue.\r
-     * @param {String} value The data value of the item to select\r
-     * @param {Boolean} scrollIntoView False to prevent the dropdown list from autoscrolling to display the\r
-     * selected item if it is not currently in view (defaults to true)\r
-     * @return {Boolean} True if the value matched an item in the list, else false\r
-     */\r
-    selectByValue : function(v, scrollIntoView){\r
-        if(!Ext.isEmpty(v, true)){\r
-            var r = this.findRecord(this.valueField || this.displayField, v);\r
-            if(r){\r
-                this.select(this.store.indexOf(r), scrollIntoView);\r
-                return true;\r
-            }\r
-        }\r
-        return false;\r
-    },\r
-\r
-    /**\r
-     * Select an item in the dropdown list by its numeric index in the list. This function does NOT cause the select event to fire.\r
-     * The store must be loaded and the list expanded for this function to work, otherwise use setValue.\r
-     * @param {Number} index The zero-based index of the list item to select\r
-     * @param {Boolean} scrollIntoView False to prevent the dropdown list from autoscrolling to display the\r
-     * selected item if it is not currently in view (defaults to true)\r
-     */\r
-    select : function(index, scrollIntoView){\r
-        this.selectedIndex = index;\r
-        this.view.select(index);\r
-        if(scrollIntoView !== false){\r
-            var el = this.view.getNode(index);\r
-            if(el){\r
-                this.innerList.scrollChildIntoView(el, false);\r
-            }\r
-        }\r
-    },\r
-\r
-    // private\r
-    selectNext : function(){\r
-        var ct = this.store.getCount();\r
-        if(ct > 0){\r
-            if(this.selectedIndex == -1){\r
-                this.select(0);\r
-            }else if(this.selectedIndex < ct-1){\r
-                this.select(this.selectedIndex+1);\r
-            }\r
-        }\r
-    },\r
-\r
-    // private\r
-    selectPrev : function(){\r
-        var ct = this.store.getCount();\r
-        if(ct > 0){\r
-            if(this.selectedIndex == -1){\r
-                this.select(0);\r
-            }else if(this.selectedIndex !== 0){\r
-                this.select(this.selectedIndex-1);\r
-            }\r
-        }\r
-    },\r
-\r
-    // private\r
-    onKeyUp : function(e){\r
-        var k = e.getKey();\r
-        if(this.editable !== false && (k == e.BACKSPACE || !e.isSpecialKey())){\r
-            this.lastKey = k;\r
-            this.dqTask.delay(this.queryDelay);\r
-        }\r
-        Ext.form.ComboBox.superclass.onKeyUp.call(this, e);\r
-    },\r
-\r
-    // private\r
-    validateBlur : function(){\r
-        return !this.list || !this.list.isVisible();\r
-    },\r
-\r
-    // private\r
-    initQuery : function(){\r
-        this.doQuery(this.getRawValue());\r
-    },\r
-\r
-    // private\r
-    beforeBlur : function(){\r
-        var val = this.getRawValue(),\r
-            rec = this.findRecord(this.displayField, val);\r
-        if(!rec && this.forceSelection){\r
-            if(val.length > 0 && val != this.emptyText){\r
-                this.el.dom.value = Ext.isDefined(this.lastSelectionText) ? this.lastSelectionText : '';\r
-                this.applyEmptyText();\r
-            }else{\r
-                this.clearValue();\r
-            }\r
-        }else{\r
-            if(rec){\r
-                val = rec.get(this.valueField || this.displayField);\r
-            }\r
-            this.setValue(val);\r
-        }\r
-    },\r
-\r
-    /**\r
-     * Execute a query to filter the dropdown list.  Fires the {@link #beforequery} event prior to performing the\r
-     * query allowing the query action to be canceled if needed.\r
-     * @param {String} query The SQL query to execute\r
-     * @param {Boolean} forceAll <tt>true</tt> to force the query to execute even if there are currently fewer\r
-     * characters in the field than the minimum specified by the <tt>{@link #minChars}</tt> config option.  It\r
-     * also clears any filter previously saved in the current store (defaults to <tt>false</tt>)\r
-     */\r
-    doQuery : function(q, forceAll){\r
-        q = Ext.isEmpty(q) ? '' : q;\r
-        var qe = {\r
-            query: q,\r
-            forceAll: forceAll,\r
-            combo: this,\r
-            cancel:false\r
-        };\r
-        if(this.fireEvent('beforequery', qe)===false || qe.cancel){\r
-            return false;\r
-        }\r
-        q = qe.query;\r
-        forceAll = qe.forceAll;\r
-        if(forceAll === true || (q.length >= this.minChars)){\r
-            if(this.lastQuery !== q){\r
-                this.lastQuery = q;\r
-                if(this.mode == 'local'){\r
-                    this.selectedIndex = -1;\r
-                    if(forceAll){\r
-                        this.store.clearFilter();\r
-                    }else{\r
-                        this.store.filter(this.displayField, q);\r
-                    }\r
-                    this.onLoad();\r
-                }else{\r
-                    this.store.baseParams[this.queryParam] = q;\r
-                    this.store.load({\r
-                        params: this.getParams(q)\r
-                    });\r
-                    this.expand();\r
-                }\r
-            }else{\r
-                this.selectedIndex = -1;\r
-                this.onLoad();\r
-            }\r
-        }\r
-    },\r
-\r
-    // private\r
-    getParams : function(q){\r
-        var p = {};\r
-        //p[this.queryParam] = q;\r
-        if(this.pageSize){\r
-            p.start = 0;\r
-            p.limit = this.pageSize;\r
-        }\r
-        return p;\r
-    },\r
-\r
-    /**\r
-     * Hides the dropdown list if it is currently expanded. Fires the {@link #collapse} event on completion.\r
-     */\r
-    collapse : function(){\r
-        if(!this.isExpanded()){\r
-            return;\r
-        }\r
-        this.list.hide();\r
-        Ext.getDoc().un('mousewheel', this.collapseIf, this);\r
-        Ext.getDoc().un('mousedown', this.collapseIf, this);\r
-        this.fireEvent('collapse', this);\r
-    },\r
-\r
-    // private\r
-    collapseIf : function(e){\r
-        if(!e.within(this.wrap) && !e.within(this.list)){\r
-            this.collapse();\r
-        }\r
-    },\r
-\r
-    /**\r
-     * Expands the dropdown list if it is currently hidden. Fires the {@link #expand} event on completion.\r
-     */\r
-    expand : function(){\r
-        if(this.isExpanded() || !this.hasFocus){\r
-            return;\r
-        }\r
-        if(this.bufferSize){\r
-            this.doResize(this.bufferSize);\r
-            delete this.bufferSize;\r
-        }\r
-        this.list.alignTo(this.wrap, this.listAlign);\r
-        this.list.show();\r
-        if(Ext.isGecko2){\r
-            this.innerList.setOverflow('auto'); // necessary for FF 2.0/Mac\r
-        }\r
-        Ext.getDoc().on({\r
-            scope: this,\r
-            mousewheel: this.collapseIf,\r
-            mousedown: this.collapseIf\r
-        });\r
-        this.fireEvent('expand', this);\r
-    },\r
-\r
-    /**\r
-     * @method onTriggerClick\r
-     * @hide\r
-     */\r
-    // private\r
-    // Implements the default empty TriggerField.onTriggerClick function\r
-    onTriggerClick : function(){\r
-        if(this.disabled){\r
-            return;\r
-        }\r
-        if(this.isExpanded()){\r
-            this.collapse();\r
-            this.el.focus();\r
-        }else {\r
-            this.onFocus({});\r
-            if(this.triggerAction == 'all') {\r
-                this.doQuery(this.allQuery, true);\r
-            } else {\r
-                this.doQuery(this.getRawValue());\r
-            }\r
-            this.el.focus();\r
-        }\r
-    }\r
-\r
-    /**\r
-     * @hide\r
-     * @method autoSize\r
-     */\r
-    /**\r
-     * @cfg {Boolean} grow @hide\r
-     */\r
-    /**\r
-     * @cfg {Number} growMin @hide\r
-     */\r
-    /**\r
-     * @cfg {Number} growMax @hide\r
-     */\r
-\r
-});\r
-Ext.reg('combo', Ext.form.ComboBox);/**
- * @class Ext.form.Checkbox
- * @extends Ext.form.Field
- * Single checkbox field.  Can be used as a direct replacement for traditional checkbox fields.
+/**
+ * @class Ext.form.ComboBox
+ * @extends Ext.form.TriggerField
+ * <p>A combobox control with support for autocomplete, remote-loading, paging and many other features.</p>
+ * <p>A ComboBox works in a similar manner to a traditional HTML &lt;select> field. The difference is
+ * that to submit the {@link #valueField}, you must specify a {@link #hiddenName} to create a hidden input
+ * field to hold the value of the valueField. The <i>{@link #displayField}</i> is shown in the text field
+ * which is named according to the {@link #name}.</p>
+ * <p><b><u>Events</u></b></p>
+ * <p>To do something when something in ComboBox is selected, configure the select event:<pre><code>
+var cb = new Ext.form.ComboBox({
+    // all of your config options
+    listeners:{
+         scope: yourScope,
+         'select': yourFunction
+    }
+});
+
+// Alternatively, you can assign events after the object is created:
+var cb = new Ext.form.ComboBox(yourOptions);
+cb.on('select', yourFunction, yourScope);
+ * </code></pre></p>
+ *
+ * <p><b><u>ComboBox in Grid</u></b></p>
+ * <p>If using a ComboBox in an {@link Ext.grid.EditorGridPanel Editor Grid} a {@link Ext.grid.Column#renderer renderer}
+ * will be needed to show the displayField when the editor is not active.  Set up the renderer manually, or implement
+ * a reusable render, for example:<pre><code>
+// create reusable renderer
+Ext.util.Format.comboRenderer = function(combo){
+    return function(value){
+        var record = combo.findRecord(combo.{@link #valueField}, value);
+        return record ? record.get(combo.{@link #displayField}) : combo.{@link #valueNotFoundText};
+    }
+}
+
+// create the combo instance
+var combo = new Ext.form.ComboBox({
+    {@link #typeAhead}: true,
+    {@link #triggerAction}: 'all',
+    {@link #lazyRender}:true,
+    {@link #mode}: 'local',
+    {@link #store}: new Ext.data.ArrayStore({
+        id: 0,
+        fields: [
+            'myId',
+            'displayText'
+        ],
+        data: [[1, 'item1'], [2, 'item2']]
+    }),
+    {@link #valueField}: 'myId',
+    {@link #displayField}: 'displayText'
+});
+
+// snippet of column model used within grid
+var cm = new Ext.grid.ColumnModel([{
+       ...
+    },{
+       header: "Some Header",
+       dataIndex: 'whatever',
+       width: 130,
+       editor: combo, // specify reference to combo instance
+       renderer: Ext.util.Format.comboRenderer(combo) // pass combo instance to reusable renderer
+    },
+    ...
+]);
+ * </code></pre></p>
+ *
+ * <p><b><u>Filtering</u></b></p>
+ * <p>A ComboBox {@link #doQuery uses filtering itself}, for information about filtering the ComboBox
+ * store manually see <tt>{@link #lastQuery}</tt>.</p>
  * @constructor
- * Creates a new Checkbox
+ * Create a new ComboBox.
  * @param {Object} config Configuration options
- * @xtype checkbox
+ * @xtype combo
  */
-Ext.form.Checkbox = Ext.extend(Ext.form.Field,  {
+Ext.form.ComboBox = Ext.extend(Ext.form.TriggerField, {
     /**
-     * @cfg {String} focusClass The CSS class to use when the checkbox receives focus (defaults to undefined)
+     * @cfg {Mixed} transform The id, DOM node or element of an existing HTML SELECT to convert to a ComboBox.
+     * Note that if you specify this and the combo is going to be in an {@link Ext.form.BasicForm} or
+     * {@link Ext.form.FormPanel}, you must also set <tt>{@link #lazyRender} = true</tt>.
      */
-    focusClass : undefined,
     /**
-     * @cfg {String} fieldClass The default CSS class for the checkbox (defaults to 'x-form-field')
+     * @cfg {Boolean} lazyRender <tt>true</tt> to prevent the ComboBox from rendering until requested
+     * (should always be used when rendering into an {@link Ext.Editor} (e.g. {@link Ext.grid.EditorGridPanel Grids}),
+     * defaults to <tt>false</tt>).
      */
-    fieldClass : 'x-form-field',
     /**
-     * @cfg {Boolean} checked <tt>true</tt> if the checkbox should render initially checked (defaults to <tt>false</tt>)
+     * @cfg {String/Object} autoCreate <p>A {@link Ext.DomHelper DomHelper} element spec, or <tt>true</tt> for a default
+     * element spec. Used to create the {@link Ext.Component#getEl Element} which will encapsulate this Component.
+     * See <tt>{@link Ext.Component#autoEl autoEl}</tt> for details.  Defaults to:</p>
+     * <pre><code>{tag: "input", type: "text", size: "24", autocomplete: "off"}</code></pre>
      */
-    checked : false,
     /**
-     * @cfg {String/Object} autoCreate A DomHelper element spec, or true for a default element spec (defaults to
-     * {tag: 'input', type: 'checkbox', autocomplete: 'off'})
+     * @cfg {Ext.data.Store/Array} store The data source to which this combo is bound (defaults to <tt>undefined</tt>).
+     * Acceptable values for this property are:
+     * <div class="mdetail-params"><ul>
+     * <li><b>any {@link Ext.data.Store Store} subclass</b></li>
+     * <li><b>an Array</b> : Arrays will be converted to a {@link Ext.data.ArrayStore} internally,
+     * automatically generating {@link Ext.data.Field#name field names} to work with all data components.
+     * <div class="mdetail-params"><ul>
+     * <li><b>1-dimensional array</b> : (e.g., <tt>['Foo','Bar']</tt>)<div class="sub-desc">
+     * A 1-dimensional array will automatically be expanded (each array item will be used for both the combo
+     * {@link #valueField} and {@link #displayField})</div></li>
+     * <li><b>2-dimensional array</b> : (e.g., <tt>[['f','Foo'],['b','Bar']]</tt>)<div class="sub-desc">
+     * For a multi-dimensional array, the value in index 0 of each item will be assumed to be the combo
+     * {@link #valueField}, while the value at index 1 is assumed to be the combo {@link #displayField}.
+     * </div></li></ul></div></li></ul></div>
+     * <p>See also <tt>{@link #mode}</tt>.</p>
      */
-    defaultAutoCreate : { tag: 'input', type: 'checkbox', autocomplete: 'off'},
     /**
-     * @cfg {String} boxLabel The text that appears beside the checkbox
+     * @cfg {String} title If supplied, a header element is created containing this text and added into the top of
+     * the dropdown list (defaults to undefined, with no header element)
      */
+
+    // private
+    defaultAutoCreate : {tag: "input", type: "text", size: "24", autocomplete: "off"},
     /**
-     * @cfg {String} inputValue The value that should go into the generated input element's value attribute
+     * @cfg {Number} listWidth The width (used as a parameter to {@link Ext.Element#setWidth}) of the dropdown
+     * list (defaults to the width of the ComboBox field).  See also <tt>{@link #minListWidth}
      */
     /**
-     * @cfg {Function} handler A function called when the {@link #checked} value changes (can be used instead of 
-     * handling the check event). The handler is passed the following parameters:
+     * @cfg {String} displayField The underlying {@link Ext.data.Field#name data field name} to bind to this
+     * ComboBox (defaults to undefined if <tt>{@link #mode} = 'remote'</tt> or <tt>'field1'</tt> if
+     * {@link #transform transforming a select} or if the {@link #store field name is autogenerated based on
+     * the store configuration}).
+     * <p>See also <tt>{@link #valueField}</tt>.</p>
+     * <p><b>Note</b>: if using a ComboBox in an {@link Ext.grid.EditorGridPanel Editor Grid} a
+     * {@link Ext.grid.Column#renderer renderer} will be needed to show the displayField when the editor is not
+     * active.</p>
+     */
+    /**
+     * @cfg {String} valueField The underlying {@link Ext.data.Field#name data value name} to bind to this
+     * ComboBox (defaults to undefined if <tt>{@link #mode} = 'remote'</tt> or <tt>'field2'</tt> if
+     * {@link #transform transforming a select} or if the {@link #store field name is autogenerated based on
+     * the store configuration}).
+     * <p><b>Note</b>: use of a <tt>valueField</tt> requires the user to make a selection in order for a value to be
+     * mapped.  See also <tt>{@link #hiddenName}</tt>, <tt>{@link #hiddenValue}</tt>, and <tt>{@link #displayField}</tt>.</p>
+     */
+    /**
+     * @cfg {String} hiddenName If specified, a hidden form field with this name is dynamically generated to store the
+     * field's data value (defaults to the underlying DOM element's name). Required for the combo's value to automatically
+     * post during a form submission.  See also {@link #valueField}.
+     * <p><b>Note</b>: the hidden field's id will also default to this name if {@link #hiddenId} is not specified.
+     * The ComboBox {@link Ext.Component#id id} and the <tt>{@link #hiddenId}</tt> <b>should be different</b>, since
+     * no two DOM nodes should share the same id.  So, if the ComboBox <tt>{@link Ext.form.Field#name name}</tt> and
+     * <tt>hiddenName</tt> are the same, you should specify a unique <tt>{@link #hiddenId}</tt>.</p>
+     */
+    /**
+     * @cfg {String} hiddenId If <tt>{@link #hiddenName}</tt> is specified, <tt>hiddenId</tt> can also be provided
+     * to give the hidden field a unique id (defaults to the <tt>{@link #hiddenName}</tt>).  The <tt>hiddenId</tt>
+     * and combo {@link Ext.Component#id id} should be different, since no two DOM
+     * nodes should share the same id.
+     */
+    /**
+     * @cfg {String} hiddenValue Sets the initial value of the hidden field if {@link #hiddenName} is
+     * specified to contain the selected {@link #valueField}, from the Store. Defaults to the configured
+     * <tt>{@link Ext.form.Field#value value}</tt>.
+     */
+    /**
+     * @cfg {String} listClass The CSS class to add to the predefined <tt>'x-combo-list'</tt> class
+     * applied the dropdown list element (defaults to '').
+     */
+    listClass : '',
+    /**
+     * @cfg {String} selectedClass CSS class to apply to the selected item in the dropdown list
+     * (defaults to <tt>'x-combo-selected'</tt>)
+     */
+    selectedClass : 'x-combo-selected',
+    /**
+     * @cfg {String} listEmptyText The empty text to display in the data view if no items are found.
+     * (defaults to '')
+     */
+    listEmptyText: '',
+    /**
+     * @cfg {String} triggerClass An additional CSS class used to style the trigger button.  The trigger will always
+     * get the class <tt>'x-form-trigger'</tt> and <tt>triggerClass</tt> will be <b>appended</b> if specified
+     * (defaults to <tt>'x-form-arrow-trigger'</tt> which displays a downward arrow icon).
+     */
+    triggerClass : 'x-form-arrow-trigger',
+    /**
+     * @cfg {Boolean/String} shadow <tt>true</tt> or <tt>"sides"</tt> for the default effect, <tt>"frame"</tt> for
+     * 4-way shadow, and <tt>"drop"</tt> for bottom-right
+     */
+    shadow : 'sides',
+    /**
+     * @cfg {String/Array} listAlign A valid anchor position value. See <tt>{@link Ext.Element#alignTo}</tt> for details
+     * on supported anchor positions and offsets. To specify x/y offsets as well, this value
+     * may be specified as an Array of <tt>{@link Ext.Element#alignTo}</tt> method arguments.</p>
+     * <pre><code>[ 'tl-bl?', [6,0] ]</code></pre>(defaults to <tt>'tl-bl?'</tt>)
+     */
+    listAlign : 'tl-bl?',
+    /**
+     * @cfg {Number} maxHeight The maximum height in pixels of the dropdown list before scrollbars are shown
+     * (defaults to <tt>300</tt>)
+     */
+    maxHeight : 300,
+    /**
+     * @cfg {Number} minHeight The minimum height in pixels of the dropdown list when the list is constrained by its
+     * distance to the viewport edges (defaults to <tt>90</tt>)
+     */
+    minHeight : 90,
+    /**
+     * @cfg {String} triggerAction The action to execute when the trigger is clicked.
      * <div class="mdetail-params"><ul>
-     * <li><b>checkbox</b> : Ext.form.Checkbox<div class="sub-desc">The Checkbox being toggled.</div></li>
-     * <li><b>checked</b> : Boolean<div class="sub-desc">The new checked state of the checkbox.</div></li>
+     * <li><b><tt>'query'</tt></b> : <b>Default</b>
+     * <p class="sub-desc">{@link #doQuery run the query} using the {@link Ext.form.Field#getRawValue raw value}.</p></li>
+     * <li><b><tt>'all'</tt></b> :
+     * <p class="sub-desc">{@link #doQuery run the query} specified by the <tt>{@link #allQuery}</tt> config option</p></li>
      * </ul></div>
+     * <p>See also <code>{@link #queryParam}</code>.</p>
      */
+    triggerAction : 'query',
     /**
-     * @cfg {Object} scope An object to use as the scope ('this' reference) of the {@link #handler} function
-     * (defaults to this Checkbox).
+     * @cfg {Number} minChars The minimum number of characters the user must type before autocomplete and
+     * {@link #typeAhead} activate (defaults to <tt>4</tt> if <tt>{@link #mode} = 'remote'</tt> or <tt>0</tt> if
+     * <tt>{@link #mode} = 'local'</tt>, does not apply if
+     * <tt>{@link Ext.form.TriggerField#editable editable} = false</tt>).
+     */
+    minChars : 4,
+    /**
+     * @cfg {Boolean} autoSelect <tt>true</tt> to select the first result gathered by the data store (defaults
+     * to <tt>true</tt>).  A false value would require a manual selection from the dropdown list to set the components value
+     * unless the value of ({@link #typeAheadDelay}) were true.
+     */
+    autoSelect : true,
+    /**
+     * @cfg {Boolean} typeAhead <tt>true</tt> to populate and autoselect the remainder of the text being
+     * typed after a configurable delay ({@link #typeAheadDelay}) if it matches a known value (defaults
+     * to <tt>false</tt>)
+     */
+    typeAhead : false,
+    /**
+     * @cfg {Number} queryDelay The length of time in milliseconds to delay between the start of typing and
+     * sending the query to filter the dropdown list (defaults to <tt>500</tt> if <tt>{@link #mode} = 'remote'</tt>
+     * or <tt>10</tt> if <tt>{@link #mode} = 'local'</tt>)
+     */
+    queryDelay : 500,
+    /**
+     * @cfg {Number} pageSize If greater than <tt>0</tt>, a {@link Ext.PagingToolbar} is displayed in the
+     * footer of the dropdown list and the {@link #doQuery filter queries} will execute with page start and
+     * {@link Ext.PagingToolbar#pageSize limit} parameters. Only applies when <tt>{@link #mode} = 'remote'</tt>
+     * (defaults to <tt>0</tt>).
+     */
+    pageSize : 0,
+    /**
+     * @cfg {Boolean} selectOnFocus <tt>true</tt> to select any existing text in the field immediately on focus.
+     * Only applies when <tt>{@link Ext.form.TriggerField#editable editable} = true</tt> (defaults to
+     * <tt>false</tt>).
+     */
+    selectOnFocus : false,
+    /**
+     * @cfg {String} queryParam Name of the query ({@link Ext.data.Store#baseParam baseParam} name for the store)
+     * as it will be passed on the querystring (defaults to <tt>'query'</tt>)
+     */
+    queryParam : 'query',
+    /**
+     * @cfg {String} loadingText The text to display in the dropdown list while data is loading.  Only applies
+     * when <tt>{@link #mode} = 'remote'</tt> (defaults to <tt>'Loading...'</tt>)
+     */
+    loadingText : 'Loading...',
+    /**
+     * @cfg {Boolean} resizable <tt>true</tt> to add a resize handle to the bottom of the dropdown list
+     * (creates an {@link Ext.Resizable} with 'se' {@link Ext.Resizable#pinned pinned} handles).
+     * Defaults to <tt>false</tt>.
+     */
+    resizable : false,
+    /**
+     * @cfg {Number} handleHeight The height in pixels of the dropdown list resize handle if
+     * <tt>{@link #resizable} = true</tt> (defaults to <tt>8</tt>)
+     */
+    handleHeight : 8,
+    /**
+     * @cfg {String} allQuery The text query to send to the server to return all records for the list
+     * with no filtering (defaults to '')
+     */
+    allQuery: '',
+    /**
+     * @cfg {String} mode Acceptable values are:
+     * <div class="mdetail-params"><ul>
+     * <li><b><tt>'remote'</tt></b> : <b>Default</b>
+     * <p class="sub-desc">Automatically loads the <tt>{@link #store}</tt> the <b>first</b> time the trigger
+     * is clicked. If you do not want the store to be automatically loaded the first time the trigger is
+     * clicked, set to <tt>'local'</tt> and manually load the store.  To force a requery of the store
+     * <b>every</b> time the trigger is clicked see <tt>{@link #lastQuery}</tt>.</p></li>
+     * <li><b><tt>'local'</tt></b> :
+     * <p class="sub-desc">ComboBox loads local data</p>
+     * <pre><code>
+var combo = new Ext.form.ComboBox({
+    renderTo: document.body,
+    mode: 'local',
+    store: new Ext.data.ArrayStore({
+        id: 0,
+        fields: [
+            'myId',  // numeric value is the key
+            'displayText'
+        ],
+        data: [[1, 'item1'], [2, 'item2']]  // data is local
+    }),
+    valueField: 'myId',
+    displayField: 'displayText',
+    triggerAction: 'all'
+});
+     * </code></pre></li>
+     * </ul></div>
+     */
+    mode: 'remote',
+    /**
+     * @cfg {Number} minListWidth The minimum width of the dropdown list in pixels (defaults to <tt>70</tt>, will
+     * be ignored if <tt>{@link #listWidth}</tt> has a higher value)
+     */
+    minListWidth : 70,
+    /**
+     * @cfg {Boolean} forceSelection <tt>true</tt> to restrict the selected value to one of the values in the list,
+     * <tt>false</tt> to allow the user to set arbitrary text into the field (defaults to <tt>false</tt>)
+     */
+    forceSelection : false,
+    /**
+     * @cfg {Number} typeAheadDelay The length of time in milliseconds to wait until the typeahead text is displayed
+     * if <tt>{@link #typeAhead} = true</tt> (defaults to <tt>250</tt>)
+     */
+    typeAheadDelay : 250,
+    /**
+     * @cfg {String} valueNotFoundText When using a name/value combo, if the value passed to setValue is not found in
+     * the store, valueNotFoundText will be displayed as the field text if defined (defaults to undefined). If this
+     * default text is used, it means there is no value set and no validation will occur on this field.
+     */
+
+    /**
+     * @cfg {Boolean} lazyInit <tt>true</tt> to not initialize the list for this combo until the field is focused
+     * (defaults to <tt>true</tt>)
+     */
+    lazyInit : true,
+
+    /**
+     * @cfg {Boolean} clearFilterOnReset <tt>true</tt> to clear any filters on the store (when in local mode) when reset is called
+     * (defaults to <tt>true</tt>)
+     */
+    clearFilterOnReset : true,
+
+    /**
+     * @cfg {Boolean} submitValue False to clear the name attribute on the field so that it is not submitted during a form post.
+     * If a hiddenName is specified, setting this to true will cause both the hidden field and the element to be submitted.
+     * Defaults to <tt>undefined</tt>.
+     */
+    submitValue: undefined,
+
+    /**
+     * The value of the match string used to filter the store. Delete this property to force a requery.
+     * Example use:
+     * <pre><code>
+var combo = new Ext.form.ComboBox({
+    ...
+    mode: 'remote',
+    ...
+    listeners: {
+        // delete the previous query in the beforequery event or set
+        // combo.lastQuery = null (this will reload the store the next time it expands)
+        beforequery: function(qe){
+            delete qe.combo.lastQuery;
+        }
+    }
+});
+     * </code></pre>
+     * To make sure the filter in the store is not cleared the first time the ComboBox trigger is used
+     * configure the combo with <tt>lastQuery=''</tt>. Example use:
+     * <pre><code>
+var combo = new Ext.form.ComboBox({
+    ...
+    mode: 'local',
+    triggerAction: 'all',
+    lastQuery: ''
+});
+     * </code></pre>
+     * @property lastQuery
+     * @type String
      */
 
     // private
-    actionMode : 'wrap',
-    
-       // private
     initComponent : function(){
-        Ext.form.Checkbox.superclass.initComponent.call(this);
+        Ext.form.ComboBox.superclass.initComponent.call(this);
         this.addEvents(
             /**
-             * @event check
-             * Fires when the checkbox is checked or unchecked.
-             * @param {Ext.form.Checkbox} this This checkbox
-             * @param {Boolean} checked The new checked value
+             * @event expand
+             * Fires when the dropdown list is expanded
+             * @param {Ext.form.ComboBox} combo This combo box
              */
-            'check'
+            'expand',
+            /**
+             * @event collapse
+             * Fires when the dropdown list is collapsed
+             * @param {Ext.form.ComboBox} combo This combo box
+             */
+            'collapse',
+
+            /**
+             * @event beforeselect
+             * Fires before a list item is selected. Return false to cancel the selection.
+             * @param {Ext.form.ComboBox} combo This combo box
+             * @param {Ext.data.Record} record The data record returned from the underlying store
+             * @param {Number} index The index of the selected item in the dropdown list
+             */
+            'beforeselect',
+            /**
+             * @event select
+             * Fires when a list item is selected
+             * @param {Ext.form.ComboBox} combo This combo box
+             * @param {Ext.data.Record} record The data record returned from the underlying store
+             * @param {Number} index The index of the selected item in the dropdown list
+             */
+            'select',
+            /**
+             * @event beforequery
+             * Fires before all queries are processed. Return false to cancel the query or set the queryEvent's
+             * cancel property to true.
+             * @param {Object} queryEvent An object that has these properties:<ul>
+             * <li><code>combo</code> : Ext.form.ComboBox <div class="sub-desc">This combo box</div></li>
+             * <li><code>query</code> : String <div class="sub-desc">The query</div></li>
+             * <li><code>forceAll</code> : Boolean <div class="sub-desc">True to force "all" query</div></li>
+             * <li><code>cancel</code> : Boolean <div class="sub-desc">Set to true to cancel the query</div></li>
+             * </ul>
+             */
+            'beforequery'
         );
+        if(this.transform){
+            var s = Ext.getDom(this.transform);
+            if(!this.hiddenName){
+                this.hiddenName = s.name;
+            }
+            if(!this.store){
+                this.mode = 'local';
+                var d = [], opts = s.options;
+                for(var i = 0, len = opts.length;i < len; i++){
+                    var o = opts[i],
+                        value = (o.hasAttribute ? o.hasAttribute('value') : o.getAttributeNode('value').specified) ? o.value : o.text;
+                    if(o.selected && Ext.isEmpty(this.value, true)) {
+                        this.value = value;
+                    }
+                    d.push([value, o.text]);
+                }
+                this.store = new Ext.data.ArrayStore({
+                    'id': 0,
+                    fields: ['value', 'text'],
+                    data : d,
+                    autoDestroy: true
+                });
+                this.valueField = 'value';
+                this.displayField = 'text';
+            }
+            s.name = Ext.id(); // wipe out the name in case somewhere else they have a reference
+            if(!this.lazyRender){
+                this.target = true;
+                this.el = Ext.DomHelper.insertBefore(s, this.autoCreate || this.defaultAutoCreate);
+                this.render(this.el.parentNode, s);
+            }
+            Ext.removeNode(s);
+        }
+        //auto-configure store from local array data
+        else if(this.store){
+            this.store = Ext.StoreMgr.lookup(this.store);
+            if(this.store.autoCreated){
+                this.displayField = this.valueField = 'field1';
+                if(!this.store.expandData){
+                    this.displayField = 'field2';
+                }
+                this.mode = 'local';
+            }
+        }
+
+        this.selectedIndex = -1;
+        if(this.mode == 'local'){
+            if(!Ext.isDefined(this.initialConfig.queryDelay)){
+                this.queryDelay = 10;
+            }
+            if(!Ext.isDefined(this.initialConfig.minChars)){
+                this.minChars = 0;
+            }
+        }
     },
 
     // private
-    onResize : function(){
-        Ext.form.Checkbox.superclass.onResize.apply(this, arguments);
-        if(!this.boxLabel && !this.fieldLabel){
-            this.el.alignTo(this.wrap, 'c-c');
+    onRender : function(ct, position){
+        if(this.hiddenName && !Ext.isDefined(this.submitValue)){
+            this.submitValue = false;
+        }
+        Ext.form.ComboBox.superclass.onRender.call(this, ct, position);
+        if(this.hiddenName){
+            this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName,
+                    id: (this.hiddenId||this.hiddenName)}, 'before', true);
+
+        }
+        if(Ext.isGecko){
+            this.el.dom.setAttribute('autocomplete', 'off');
+        }
+
+        if(!this.lazyInit){
+            this.initList();
+        }else{
+            this.on('focus', this.initList, this, {single: true});
         }
     },
 
     // private
-    initEvents : function(){
-        Ext.form.Checkbox.superclass.initEvents.call(this);
-        this.mon(this.el, {
-            scope: this,
-            click: this.onClick,
-            change: this.onClick
-        });
+    initValue : function(){
+        Ext.form.ComboBox.superclass.initValue.call(this);
+        if(this.hiddenField){
+            this.hiddenField.value =
+                Ext.value(Ext.isDefined(this.hiddenValue) ? this.hiddenValue : this.value, '');
+        }
+    },
+
+    // private
+    initList : function(){
+        if(!this.list){
+            var cls = 'x-combo-list',
+                listParent = Ext.getDom(this.getListParent() || Ext.getBody()),
+                zindex = parseInt(Ext.fly(listParent).getStyle('z-index') ,10);
+
+            if (this.ownerCt && !zindex){
+                this.findParentBy(function(ct){
+                    zindex = parseInt(ct.getPositionEl().getStyle('z-index'), 10);
+                    return !!zindex;
+                });
+            }
+
+            this.list = new Ext.Layer({
+                parentEl: listParent,
+                shadow: this.shadow,
+                cls: [cls, this.listClass].join(' '),
+                constrain:false,
+                zindex: (zindex || 12000) + 5
+            });
+
+            var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);
+            this.list.setSize(lw, 0);
+            this.list.swallowEvent('mousewheel');
+            this.assetHeight = 0;
+            if(this.syncFont !== false){
+                this.list.setStyle('font-size', this.el.getStyle('font-size'));
+            }
+            if(this.title){
+                this.header = this.list.createChild({cls:cls+'-hd', html: this.title});
+                this.assetHeight += this.header.getHeight();
+            }
+
+            this.innerList = this.list.createChild({cls:cls+'-inner'});
+            this.mon(this.innerList, 'mouseover', this.onViewOver, this);
+            this.mon(this.innerList, 'mousemove', this.onViewMove, this);
+            this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
+
+            if(this.pageSize){
+                this.footer = this.list.createChild({cls:cls+'-ft'});
+                this.pageTb = new Ext.PagingToolbar({
+                    store: this.store,
+                    pageSize: this.pageSize,
+                    renderTo:this.footer
+                });
+                this.assetHeight += this.footer.getHeight();
+            }
+
+            if(!this.tpl){
+                /**
+                * @cfg {String/Ext.XTemplate} tpl <p>The template string, or {@link Ext.XTemplate} instance to
+                * use to display each item in the dropdown list. The dropdown list is displayed in a
+                * DataView. See {@link #view}.</p>
+                * <p>The default template string is:</p><pre><code>
+                  '&lt;tpl for=".">&lt;div class="x-combo-list-item">{' + this.displayField + '}&lt;/div>&lt;/tpl>'
+                * </code></pre>
+                * <p>Override the default value to create custom UI layouts for items in the list.
+                * For example:</p><pre><code>
+                  '&lt;tpl for=".">&lt;div ext:qtip="{state}. {nick}" class="x-combo-list-item">{state}&lt;/div>&lt;/tpl>'
+                * </code></pre>
+                * <p>The template <b>must</b> contain one or more substitution parameters using field
+                * names from the Combo's</b> {@link #store Store}. In the example above an
+                * <pre>ext:qtip</pre> attribute is added to display other fields from the Store.</p>
+                * <p>To preserve the default visual look of list items, add the CSS class name
+                * <pre>x-combo-list-item</pre> to the template's container element.</p>
+                * <p>Also see {@link #itemSelector} for additional details.</p>
+                */
+                this.tpl = '<tpl for="."><div class="'+cls+'-item">{' + this.displayField + '}</div></tpl>';
+                /**
+                 * @cfg {String} itemSelector
+                 * <p>A simple CSS selector (e.g. div.some-class or span:first-child) that will be
+                 * used to determine what nodes the {@link #view Ext.DataView} which handles the dropdown
+                 * display will be working with.</p>
+                 * <p><b>Note</b>: this setting is <b>required</b> if a custom XTemplate has been
+                 * specified in {@link #tpl} which assigns a class other than <pre>'x-combo-list-item'</pre>
+                 * to dropdown list items</b>
+                 */
+            }
+
+            /**
+            * The {@link Ext.DataView DataView} used to display the ComboBox's options.
+            * @type Ext.DataView
+            */
+            this.view = new Ext.DataView({
+                applyTo: this.innerList,
+                tpl: this.tpl,
+                singleSelect: true,
+                selectedClass: this.selectedClass,
+                itemSelector: this.itemSelector || '.' + cls + '-item',
+                emptyText: this.listEmptyText,
+                deferEmptyText: false
+            });
+
+            this.mon(this.view, {
+                containerclick : this.onViewClick,
+                click : this.onViewClick,
+                scope :this
+            });
+
+            this.bindStore(this.store, true);
+
+            if(this.resizable){
+                this.resizer = new Ext.Resizable(this.list,  {
+                   pinned:true, handles:'se'
+                });
+                this.mon(this.resizer, 'resize', function(r, w, h){
+                    this.maxHeight = h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight;
+                    this.listWidth = w;
+                    this.innerList.setWidth(w - this.list.getFrameWidth('lr'));
+                    this.restrictHeight();
+                }, this);
+
+                this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom', this.handleHeight+'px');
+            }
+        }
     },
 
     /**
-     * @hide
-     * Overridden and disabled. The editor element does not support standard valid/invalid marking.
-     * @method
+     * <p>Returns the element used to house this ComboBox's pop-up list. Defaults to the document body.</p>
+     * A custom implementation may be provided as a configuration option if the floating list needs to be rendered
+     * to a different Element. An example might be rendering the list inside a Menu so that clicking
+     * the list does not hide the Menu:<pre><code>
+var store = new Ext.data.ArrayStore({
+    autoDestroy: true,
+    fields: ['initials', 'fullname'],
+    data : [
+        ['FF', 'Fred Flintstone'],
+        ['BR', 'Barney Rubble']
+    ]
+});
+
+var combo = new Ext.form.ComboBox({
+    store: store,
+    displayField: 'fullname',
+    emptyText: 'Select a name...',
+    forceSelection: true,
+    getListParent: function() {
+        return this.el.up('.x-menu');
+    },
+    iconCls: 'no-icon', //use iconCls if placing within menu to shift to right side of menu
+    mode: 'local',
+    selectOnFocus: true,
+    triggerAction: 'all',
+    typeAhead: true,
+    width: 135
+});
+
+var menu = new Ext.menu.Menu({
+    id: 'mainMenu',
+    items: [
+        combo // A Field in a Menu
+    ]
+});
+</code></pre>
      */
-    markInvalid : Ext.emptyFn,
+    getListParent : function() {
+        return document.body;
+    },
+
     /**
-     * @hide
-     * Overridden and disabled. The editor element does not support standard valid/invalid marking.
-     * @method
+     * Returns the store associated with this combo.
+     * @return {Ext.data.Store} The store
      */
-    clearInvalid : Ext.emptyFn,
+    getStore : function(){
+        return this.store;
+    },
 
     // private
-    onRender : function(ct, position){
-        Ext.form.Checkbox.superclass.onRender.call(this, ct, position);
-        if(this.inputValue !== undefined){
-            this.el.dom.value = this.inputValue;
+    bindStore : function(store, initial){
+        if(this.store && !initial){
+            if(this.store !== store && this.store.autoDestroy){
+                this.store.destroy();
+            }else{
+                this.store.un('beforeload', this.onBeforeLoad, this);
+                this.store.un('load', this.onLoad, this);
+                this.store.un('exception', this.collapse, this);
+            }
+            if(!store){
+                this.store = null;
+                if(this.view){
+                    this.view.bindStore(null);
+                }
+                if(this.pageTb){
+                    this.pageTb.bindStore(null);
+                }
+            }
         }
-        this.wrap = this.el.wrap({cls: 'x-form-check-wrap'});
-        if(this.boxLabel){
-            this.wrap.createChild({tag: 'label', htmlFor: this.el.id, cls: 'x-form-cb-label', html: this.boxLabel});
+        if(store){
+            if(!initial) {
+                this.lastQuery = null;
+                if(this.pageTb) {
+                    this.pageTb.bindStore(store);
+                }
+            }
+
+            this.store = Ext.StoreMgr.lookup(store);
+            this.store.on({
+                scope: this,
+                beforeload: this.onBeforeLoad,
+                load: this.onLoad,
+                exception: this.collapse
+            });
+
+            if(this.view){
+                this.view.bindStore(store);
+            }
         }
-        if(this.checked){
-            this.setValue(true);
-        }else{
-            this.checked = this.el.dom.checked;
+    },
+
+    reset : function(){
+        Ext.form.ComboBox.superclass.reset.call(this);
+        if(this.clearFilterOnReset && this.mode == 'local'){
+            this.store.clearFilter();
         }
-        // Need to repaint for IE, otherwise positioning is broken
-        if(Ext.isIE){
-            this.wrap.repaint();
+    },
+
+    // private
+    initEvents : function(){
+        Ext.form.ComboBox.superclass.initEvents.call(this);
+
+
+        this.keyNav = new Ext.KeyNav(this.el, {
+            "up" : function(e){
+                this.inKeyMode = true;
+                this.selectPrev();
+            },
+
+            "down" : function(e){
+                if(!this.isExpanded()){
+                    this.onTriggerClick();
+                }else{
+                    this.inKeyMode = true;
+                    this.selectNext();
+                }
+            },
+
+            "enter" : function(e){
+                this.onViewClick();
+            },
+
+            "esc" : function(e){
+                this.collapse();
+            },
+
+            "tab" : function(e){
+                this.collapse();
+                return true;
+            },
+
+            scope : this,
+
+            doRelay : function(e, h, hname){
+                if(hname == 'down' || this.scope.isExpanded()){
+                    // this MUST be called before ComboBox#fireKey()
+                    var relay = Ext.KeyNav.prototype.doRelay.apply(this, arguments);
+                    if(!Ext.isIE && Ext.EventManager.useKeydown){
+                        // call Combo#fireKey() for browsers which use keydown event (except IE)
+                        this.scope.fireKey(e);
+                    }
+                    return relay;
+                }
+                return true;
+            },
+
+            forceKeyDown : true,
+            defaultEventAction: 'stopEvent'
+        });
+        this.queryDelay = Math.max(this.queryDelay || 10,
+                this.mode == 'local' ? 10 : 250);
+        this.dqTask = new Ext.util.DelayedTask(this.initQuery, this);
+        if(this.typeAhead){
+            this.taTask = new Ext.util.DelayedTask(this.onTypeAhead, this);
+        }
+        if(!this.enableKeyEvents){
+            this.mon(this.el, 'keyup', this.onKeyUp, this);
         }
-        this.resizeEl = this.positionEl = this.wrap;
     },
 
+
     // private
     onDestroy : function(){
-        Ext.destroy(this.wrap);
-        Ext.form.Checkbox.superclass.onDestroy.call(this);
+        if (this.dqTask){
+            this.dqTask.cancel();
+            this.dqTask = null;
+        }
+        this.bindStore(null);
+        Ext.destroy(
+            this.resizer,
+            this.view,
+            this.pageTb,
+            this.list
+        );
+        Ext.destroyMembers(this, 'hiddenField');
+        Ext.form.ComboBox.superclass.onDestroy.call(this);
     },
 
     // private
-    initValue : function() {
-        this.originalValue = this.getValue();
+    fireKey : function(e){
+        if (!this.isExpanded()) {
+            Ext.form.ComboBox.superclass.fireKey.call(this, e);
+        }
+    },
+
+    // private
+    onResize : function(w, h){
+        Ext.form.ComboBox.superclass.onResize.apply(this, arguments);
+        if(this.isVisible() && this.list){
+            this.doResize(w);
+        }else{
+            this.bufferSize = w;
+        }
+    },
+
+    doResize: function(w){
+        if(!Ext.isDefined(this.listWidth)){
+            var lw = Math.max(w, this.minListWidth);
+            this.list.setWidth(lw);
+            this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
+        }
+    },
+
+    // private
+    onEnable : function(){
+        Ext.form.ComboBox.superclass.onEnable.apply(this, arguments);
+        if(this.hiddenField){
+            this.hiddenField.disabled = false;
+        }
+    },
+
+    // private
+    onDisable : function(){
+        Ext.form.ComboBox.superclass.onDisable.apply(this, arguments);
+        if(this.hiddenField){
+            this.hiddenField.disabled = true;
+        }
+    },
+
+    // private
+    onBeforeLoad : function(){
+        if(!this.hasFocus){
+            return;
+        }
+        this.innerList.update(this.loadingText ?
+               '<div class="loading-indicator">'+this.loadingText+'</div>' : '');
+        this.restrictHeight();
+        this.selectedIndex = -1;
+    },
+
+    // private
+    onLoad : function(){
+        if(!this.hasFocus){
+            return;
+        }
+        if(this.store.getCount() > 0 || this.listEmptyText){
+            this.expand();
+            this.restrictHeight();
+            if(this.lastQuery == this.allQuery){
+                if(this.editable){
+                    this.el.dom.select();
+                }
+
+                if(this.autoSelect !== false && !this.selectByValue(this.value, true)){
+                    this.select(0, true);
+                }
+            }else{
+                if(this.autoSelect !== false){
+                    this.selectNext();
+                }
+                if(this.typeAhead && this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE){
+                    this.taTask.delay(this.typeAheadDelay);
+                }
+            }
+        }else{
+            this.collapse();
+        }
+
+    },
+
+    // private
+    onTypeAhead : function(){
+        if(this.store.getCount() > 0){
+            var r = this.store.getAt(0);
+            var newValue = r.data[this.displayField];
+            var len = newValue.length;
+            var selStart = this.getRawValue().length;
+            if(selStart != len){
+                this.setRawValue(newValue);
+                this.selectText(selStart, newValue.length);
+            }
+        }
+    },
+
+    // private
+    assertValue  : function(){
+
+        var val = this.getRawValue(),
+            rec = this.findRecord(this.displayField, val);
+
+        if(!rec && this.forceSelection){
+            if(val.length > 0 && val != this.emptyText){
+                this.el.dom.value = Ext.value(this.lastSelectionText, '');
+                this.applyEmptyText();
+            }else{
+                this.clearValue();
+            }
+        }else{
+            if(rec){
+                val = rec.get(this.valueField || this.displayField);
+            }
+            this.setValue(val);
+        }
+
+    },
+
+    // private
+    onSelect : function(record, index){
+        if(this.fireEvent('beforeselect', this, record, index) !== false){
+            this.setValue(record.data[this.valueField || this.displayField]);
+            this.collapse();
+            this.fireEvent('select', this, record, index);
+        }
+    },
+
+    // inherit docs
+    getName: function(){
+        var hf = this.hiddenField;
+        return hf && hf.name ? hf.name : this.hiddenName || Ext.form.ComboBox.superclass.getName.call(this);
     },
 
     /**
-     * Returns the checked state of the checkbox.
-     * @return {Boolean} True if checked, else false
+     * Returns the currently selected field value or empty string if no value is set.
+     * @return {String} value The selected value
      */
     getValue : function(){
-        if(this.rendered){
-            return this.el.dom.checked;
+        if(this.valueField){
+            return Ext.isDefined(this.value) ? this.value : '';
+        }else{
+            return Ext.form.ComboBox.superclass.getValue.call(this);
         }
-        return this.checked;
     },
 
-       // private
-    onClick : function(){
-        if(this.el.dom.checked != this.checked){
-            this.setValue(this.el.dom.checked);
+    /**
+     * Clears any text/value currently set in the field
+     */
+    clearValue : function(){
+        if(this.hiddenField){
+            this.hiddenField.value = '';
         }
+        this.setRawValue('');
+        this.lastSelectionText = '';
+        this.applyEmptyText();
+        this.value = '';
     },
 
     /**
-     * Sets the checked state of the checkbox, fires the 'check' event, and calls a
-     * <code>{@link #handler}</code> (if configured).
-     * @param {Boolean/String} checked The following values will check the checkbox:
-     * <code>true, 'true', '1', or 'on'</code>. Any other value will uncheck the checkbox.
+     * Sets the specified value into the field.  If the value finds a match, the corresponding record text
+     * will be displayed in the field.  If the value does not match the data value of an existing item,
+     * and the valueNotFoundText config option is defined, it will be displayed as the default field text.
+     * Otherwise the field will be blank (although the value will still be set).
+     * @param {String} value The value to match
      * @return {Ext.form.Field} this
      */
     setValue : function(v){
-        var checked = this.checked ;
-        this.checked = (v === true || v === 'true' || v == '1' || String(v).toLowerCase() == 'on');
-        if(this.rendered){
-            this.el.dom.checked = this.checked;
-            this.el.dom.defaultChecked = this.checked;
-        }
-        if(checked != this.checked){
-            this.fireEvent('check', this, this.checked);
-            if(this.handler){
-                this.handler.call(this.scope || this, this, this.checked);
+        var text = v;
+        if(this.valueField){
+            var r = this.findRecord(this.valueField, v);
+            if(r){
+                text = r.data[this.displayField];
+            }else if(Ext.isDefined(this.valueNotFoundText)){
+                text = this.valueNotFoundText;
             }
         }
+        this.lastSelectionText = text;
+        if(this.hiddenField){
+            this.hiddenField.value = Ext.value(v, '');
+        }
+        Ext.form.ComboBox.superclass.setValue.call(this, text);
+        this.value = v;
         return this;
-    }
-});
-Ext.reg('checkbox', Ext.form.Checkbox);
-/**\r
- * @class Ext.form.CheckboxGroup\r
- * @extends Ext.form.Field\r
- * <p>A grouping container for {@link Ext.form.Checkbox} controls.</p>\r
- * <p>Sample usage:</p>\r
- * <pre><code>\r
-var myCheckboxGroup = new Ext.form.CheckboxGroup({\r
-    id:'myGroup',\r
-    xtype: 'checkboxgroup',\r
-    fieldLabel: 'Single Column',\r
-    itemCls: 'x-check-group-alt',\r
-    // Put all controls in a single column with width 100%\r
-    columns: 1,\r
-    items: [\r
-        {boxLabel: 'Item 1', name: 'cb-col-1'},\r
-        {boxLabel: 'Item 2', name: 'cb-col-2', checked: true},\r
-        {boxLabel: 'Item 3', name: 'cb-col-3'}\r
-    ]\r
-});\r
- * </code></pre>\r
- * @constructor\r
- * Creates a new CheckboxGroup\r
- * @param {Object} config Configuration options\r
- * @xtype checkboxgroup\r
- */\r
-Ext.form.CheckboxGroup = Ext.extend(Ext.form.Field, {\r
-    /**\r
-     * @cfg {Array} items An Array of {@link Ext.form.Checkbox Checkbox}es or Checkbox config objects\r
-     * to arrange in the group.\r
-     */\r
-    /**\r
-     * @cfg {String/Number/Array} columns Specifies the number of columns to use when displaying grouped\r
-     * checkbox/radio controls using automatic layout.  This config can take several types of values:\r
-     * <ul><li><b>'auto'</b> : <p class="sub-desc">The controls will be rendered one per column on one row and the width\r
-     * of each column will be evenly distributed based on the width of the overall field container. This is the default.</p></li>\r
-     * <li><b>Number</b> : <p class="sub-desc">If you specific a number (e.g., 3) that number of columns will be \r
-     * created and the contained controls will be automatically distributed based on the value of {@link #vertical}.</p></li>\r
-     * <li><b>Array</b> : Object<p class="sub-desc">You can also specify an array of column widths, mixing integer\r
-     * (fixed width) and float (percentage width) values as needed (e.g., [100, .25, .75]). Any integer values will\r
-     * be rendered first, then any float values will be calculated as a percentage of the remaining space. Float\r
-     * values do not have to add up to 1 (100%) although if you want the controls to take up the entire field\r
-     * container you should do so.</p></li></ul>\r
-     */\r
-    columns : 'auto',\r
-    /**\r
-     * @cfg {Boolean} vertical True to distribute contained controls across columns, completely filling each column \r
-     * top to bottom before starting on the next column.  The number of controls in each column will be automatically\r
-     * calculated to keep columns as even as possible.  The default value is false, so that controls will be added\r
-     * to columns one at a time, completely filling each row left to right before starting on the next row.\r
-     */\r
-    vertical : false,\r
-    /**\r
-     * @cfg {Boolean} allowBlank False to validate that at least one item in the group is checked (defaults to true).\r
-     * If no items are selected at validation time, {@link @blankText} will be used as the error text.\r
-     */\r
-    allowBlank : true,\r
-    /**\r
-     * @cfg {String} blankText Error text to display if the {@link #allowBlank} validation fails (defaults to "You must \r
-     * select at least one item in this group")\r
-     */\r
-    blankText : "You must select at least one item in this group",\r
-    \r
-    // private\r
-    defaultType : 'checkbox',\r
-    \r
-    // private\r
-    groupCls : 'x-form-check-group',\r
-    \r
-    // private\r
-    initComponent: function(){\r
-        this.addEvents(\r
-            /**\r
-             * @event change\r
-             * Fires when the state of a child checkbox changes.\r
-             * @param {Ext.form.CheckboxGroup} this\r
-             * @param {Array} checked An array containing the checked boxes.\r
-             */\r
-            'change'\r
-        );   \r
-        Ext.form.CheckboxGroup.superclass.initComponent.call(this);\r
-    },\r
-    \r
-    // private\r
-    onRender : function(ct, position){\r
-        if(!this.el){\r
-            var panelCfg = {\r
-                id: this.id,\r
-                cls: this.groupCls,\r
-                layout: 'column',\r
-                border: false,\r
-                renderTo: ct,\r
-                bufferResize: false // Default this to false, since it doesn't really have a proper ownerCt.\r
-            };\r
-            var colCfg = {\r
-                defaultType: this.defaultType,\r
-                layout: 'form',\r
-                border: false,\r
-                defaults: {\r
-                    hideLabel: true,\r
-                    anchor: '100%'\r
-                }\r
-            };\r
-            \r
-            if(this.items[0].items){\r
-                \r
-                // The container has standard ColumnLayout configs, so pass them in directly\r
-                \r
-                Ext.apply(panelCfg, {\r
-                    layoutConfig: {columns: this.items.length},\r
-                    defaults: this.defaults,\r
-                    items: this.items\r
-                });\r
-                for(var i=0, len=this.items.length; i<len; i++){\r
-                    Ext.applyIf(this.items[i], colCfg);\r
-                }\r
-                \r
-            }else{\r
-                \r
-                // The container has field item configs, so we have to generate the column\r
-                // panels first then move the items into the columns as needed.\r
-                \r
-                var numCols, cols = [];\r
-                \r
-                if(typeof this.columns == 'string'){ // 'auto' so create a col per item\r
-                    this.columns = this.items.length;\r
-                }\r
-                if(!Ext.isArray(this.columns)){\r
-                    var cs = [];\r
-                    for(var i=0; i<this.columns; i++){\r
-                        cs.push((100/this.columns)*.01); // distribute by even %\r
-                    }\r
-                    this.columns = cs;\r
-                }\r
-                \r
-                numCols = this.columns.length;\r
-                \r
-                // Generate the column configs with the correct width setting\r
-                for(var i=0; i<numCols; i++){\r
-                    var cc = Ext.apply({items:[]}, colCfg);\r
-                    cc[this.columns[i] <= 1 ? 'columnWidth' : 'width'] = this.columns[i];\r
-                    if(this.defaults){\r
-                        cc.defaults = Ext.apply(cc.defaults || {}, this.defaults)\r
-                    }\r
-                    cols.push(cc);\r
-                };\r
-                \r
-                // Distribute the original items into the columns\r
-                if(this.vertical){\r
-                    var rows = Math.ceil(this.items.length / numCols), ri = 0;\r
-                    for(var i=0, len=this.items.length; i<len; i++){\r
-                        if(i>0 && i%rows==0){\r
-                            ri++;\r
-                        }\r
-                        if(this.items[i].fieldLabel){\r
-                            this.items[i].hideLabel = false;\r
-                        }\r
-                        cols[ri].items.push(this.items[i]);\r
-                    };\r
-                }else{\r
-                    for(var i=0, len=this.items.length; i<len; i++){\r
-                        var ci = i % numCols;\r
-                        if(this.items[i].fieldLabel){\r
-                            this.items[i].hideLabel = false;\r
-                        }\r
-                        cols[ci].items.push(this.items[i]);\r
-                    };\r
-                }\r
-                \r
-                Ext.apply(panelCfg, {\r
-                    layoutConfig: {columns: numCols},\r
-                    items: cols\r
-                });\r
-            }\r
-            \r
-            this.panel = new Ext.Panel(panelCfg);\r
-            this.panel.ownerCt = this;\r
-            this.el = this.panel.getEl();\r
-            \r
-            if(this.forId && this.itemCls){\r
-                var l = this.el.up(this.itemCls).child('label', true);\r
-                if(l){\r
-                    l.setAttribute('htmlFor', this.forId);\r
-                }\r
-            }\r
-            \r
-            var fields = this.panel.findBy(function(c){\r
-                return c.isFormField;\r
-            }, this);\r
-            \r
-            this.items = new Ext.util.MixedCollection();\r
-            this.items.addAll(fields);\r
-        }\r
-        Ext.form.CheckboxGroup.superclass.onRender.call(this, ct, position);\r
-    },\r
-    \r
-    initValue : function(){\r
-        if(this.value){\r
-            this.setValue.apply(this, this.buffered ? this.value : [this.value]);\r
-            delete this.buffered;\r
-            delete this.value;\r
-        }\r
-    },\r
-    \r
-    afterRender : function(){\r
-        Ext.form.CheckboxGroup.superclass.afterRender.call(this);\r
-        this.eachItem(function(item){\r
-            item.on('check', this.fireChecked, this);\r
-            item.inGroup = true;\r
-        });\r
-    },\r
-    \r
-    // private\r
-    doLayout: function(){\r
-        //ugly method required to layout hidden items\r
-        if(this.rendered){\r
-            this.panel.forceLayout = this.ownerCt.forceLayout;\r
-            this.panel.doLayout();\r
-        }\r
-    },\r
-    \r
-    // private\r
-    fireChecked: function(){\r
-        var arr = [];\r
-        this.eachItem(function(item){\r
-            if(item.checked){\r
-                arr.push(item);\r
-            }\r
-        });\r
-        this.fireEvent('change', this, arr);\r
-    },\r
-    \r
-    // private\r
-    validateValue : function(value){\r
-        if(!this.allowBlank){\r
-            var blank = true;\r
-            this.eachItem(function(f){\r
-                if(f.checked){\r
-                    return (blank = false);\r
-                }\r
-            });\r
-            if(blank){\r
-                this.markInvalid(this.blankText);\r
-                return false;\r
-            }\r
-        }\r
-        return true;\r
-    },\r
-    \r
-    // private\r
-    isDirty: function(){\r
-        //override the behaviour to check sub items.\r
-        if (this.disabled || !this.rendered) {\r
-            return false;\r
-        }\r
-\r
-        var dirty = false;\r
-        this.eachItem(function(item){\r
-            if(item.isDirty()){\r
-                dirty = true;\r
-                return false;\r
-            }\r
-        });\r
-        return dirty;\r
-    },\r
-    \r
-    // private\r
-    onDisable : function(){\r
-        this.eachItem(function(item){\r
-            item.disable();\r
-        });\r
-    },\r
-\r
-    // private\r
-    onEnable : function(){\r
-        this.eachItem(function(item){\r
-            item.enable();\r
-        });\r
-    },\r
-    \r
-    // private\r
-    doLayout: function(){\r
-        if(this.rendered){\r
-            this.panel.forceLayout = this.ownerCt.forceLayout;\r
-            this.panel.doLayout();\r
-        }\r
-    },\r
-    \r
-    // private\r
-    onResize : function(w, h){\r
-        this.panel.setSize(w, h);\r
-        this.panel.doLayout();\r
-    },\r
-    \r
-    // inherit docs from Field\r
-    reset : function(){\r
-        Ext.form.CheckboxGroup.superclass.reset.call(this);\r
-        this.eachItem(function(c){\r
-            if(c.reset){\r
-                c.reset();\r
-            }\r
-        });\r
-    },\r
-    \r
-    /**\r
-     * {@link Ext.form.Checkbox#setValue Set the value(s)} of an item or items\r
-     * in the group. Examples illustrating how this method may be called:\r
-     * <pre><code>\r
-// call with name and value\r
-myCheckboxGroup.setValue('cb-col-1', true);\r
-// call with an array of boolean values \r
-myCheckboxGroup.setValue([true, false, false]);\r
-// call with an object literal specifying item:value pairs\r
-myCheckboxGroup.setValue({\r
-    'cb-col-2': false,\r
-    'cb-col-3': true\r
-});\r
-// use comma separated string to set items with name to true (checked)\r
-myCheckboxGroup.setValue('cb-col-1,cb-col-3');\r
-     * </code></pre>\r
-     * See {@link Ext.form.Checkbox#setValue} for additional information.\r
-     * @param {Mixed} id The checkbox to check, or as described by example shown.\r
-     * @param {Boolean} value (optional) The value to set the item.\r
-     * @return {Ext.form.CheckboxGroup} this\r
-     */\r
-    setValue: function(){\r
-        if(this.rendered){\r
-            this.onSetValue.apply(this, arguments);\r
-        }else{\r
-            this.buffered = true;\r
-            this.value = arguments;\r
-        }\r
-        return this;\r
-    },\r
-    \r
-    onSetValue: function(id, value){\r
-        if(arguments.length == 1){\r
-            if(Ext.isArray(id)){\r
-                // an array of boolean values\r
-                Ext.each(id, function(val, idx){\r
-                    var item = this.items.itemAt(idx);\r
-                    if(item){\r
-                        item.setValue(val);\r
-                    }\r
-                }, this);\r
-            }else if(Ext.isObject(id)){\r
-                // set of name/value pairs\r
-                for(var i in id){\r
-                    var f = this.getBox(i);\r
-                    if(f){\r
-                        f.setValue(id[i]);\r
-                    }\r
-                }\r
-            }else{\r
-                this.setValueForItem(id);\r
-            }\r
-        }else{\r
-            var f = this.getBox(id);\r
-            if(f){\r
-                f.setValue(value);\r
-            }\r
-        }\r
-    },\r
-    \r
-    // private\r
-    onDestroy: function(){\r
-        Ext.destroy(this.panel);\r
-        Ext.form.CheckboxGroup.superclass.onDestroy.call(this);\r
-\r
-    },\r
-    \r
-    setValueForItem : function(val){\r
-        val = String(val).split(',');\r
-        this.eachItem(function(item){\r
-            if(val.indexOf(item.inputValue)> -1){\r
-                item.setValue(true);\r
-            }\r
-        });\r
-    },\r
-    \r
-    // private\r
-    getBox : function(id){\r
-        var box = null;\r
-        this.eachItem(function(f){\r
-            if(id == f || f.dataIndex == id || f.id == id || f.getName() == id){\r
-                box = f;\r
-                return false;\r
-            }\r
-        });\r
-        return box;\r
-    },\r
-    \r
-    /**\r
-     * Gets an array of the selected {@link Ext.form.Checkbox} in the group.\r
-     * @return {Array} An array of the selected checkboxes.\r
-     */\r
-    getValue : function(){\r
-        var out = [];\r
-        this.eachItem(function(item){\r
-            if(item.checked){\r
-                out.push(item);\r
-            }\r
-        });\r
-        return out;\r
-    },\r
-    \r
-    // private\r
-    eachItem: function(fn){\r
-        if(this.items && this.items.each){\r
-            this.items.each(fn, this);\r
-        }\r
-    },\r
-    \r
-    /**\r
-     * @cfg {String} name\r
-     * @hide\r
-     */\r
-\r
-    /**\r
-     * @method getRawValue\r
-     * @hide\r
-     */\r
-    getRawValue : Ext.emptyFn,\r
-    \r
-    /**\r
-     * @method setRawValue\r
-     * @hide\r
-     */\r
-    setRawValue : Ext.emptyFn\r
-    \r
-});\r
-\r
-Ext.reg('checkboxgroup', Ext.form.CheckboxGroup);\r
-/**
- * @class Ext.form.Radio
- * @extends Ext.form.Checkbox
- * Single radio field.  Same as Checkbox, but provided as a convenience for automatically setting the input type.
- * Radio grouping is handled automatically by the browser if you give each radio in a group the same name.
- * @constructor
- * Creates a new Radio
- * @param {Object} config Configuration options
- * @xtype radio
- */
-Ext.form.Radio = Ext.extend(Ext.form.Checkbox, {
-    inputType: 'radio',
+    },
+
+    // private
+    findRecord : function(prop, value){
+        var record;
+        if(this.store.getCount() > 0){
+            this.store.each(function(r){
+                if(r.data[prop] == value){
+                    record = r;
+                    return false;
+                }
+            });
+        }
+        return record;
+    },
+
+    // private
+    onViewMove : function(e, t){
+        this.inKeyMode = false;
+    },
+
+    // private
+    onViewOver : function(e, t){
+        if(this.inKeyMode){ // prevent key nav and mouse over conflicts
+            return;
+        }
+        var item = this.view.findItemFromChild(t);
+        if(item){
+            var index = this.view.indexOf(item);
+            this.select(index, false);
+        }
+    },
+
+    // private
+    onViewClick : function(doFocus){
+        var index = this.view.getSelectedIndexes()[0],
+            s = this.store,
+            r = s.getAt(index);
+        if(r){
+            this.onSelect(r, index);
+        }else {
+            this.collapse();
+        }
+        if(doFocus !== false){
+            this.el.focus();
+        }
+    },
+
+
+    // private
+    restrictHeight : function(){
+        this.innerList.dom.style.height = '';
+        var inner = this.innerList.dom,
+            pad = this.list.getFrameWidth('tb') + (this.resizable ? this.handleHeight : 0) + this.assetHeight,
+            h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight),
+            ha = this.getPosition()[1]-Ext.getBody().getScroll().top,
+            hb = Ext.lib.Dom.getViewHeight()-ha-this.getSize().height,
+            space = Math.max(ha, hb, this.minHeight || 0)-this.list.shadowOffset-pad-5;
+
+        h = Math.min(h, space, this.maxHeight);
+
+        this.innerList.setHeight(h);
+        this.list.beginUpdate();
+        this.list.setHeight(h+pad);
+        this.list.alignTo.apply(this.list, [this.el].concat(this.listAlign));
+        this.list.endUpdate();
+    },
 
     /**
-     * Overridden and disabled. The editor element does not support standard valid/invalid marking. @hide
-     * @method
+     * Returns true if the dropdown list is expanded, else false.
      */
-    markInvalid : Ext.emptyFn,
+    isExpanded : function(){
+        return this.list && this.list.isVisible();
+    },
+
     /**
-     * Overridden and disabled. The editor element does not support standard valid/invalid marking. @hide
-     * @method
+     * Select an item in the dropdown list by its data value. This function does NOT cause the select event to fire.
+     * The store must be loaded and the list expanded for this function to work, otherwise use setValue.
+     * @param {String} value The data value of the item to select
+     * @param {Boolean} scrollIntoView False to prevent the dropdown list from autoscrolling to display the
+     * selected item if it is not currently in view (defaults to true)
+     * @return {Boolean} True if the value matched an item in the list, else false
      */
-    clearInvalid : Ext.emptyFn,
+    selectByValue : function(v, scrollIntoView){
+        if(!Ext.isEmpty(v, true)){
+            var r = this.findRecord(this.valueField || this.displayField, v);
+            if(r){
+                this.select(this.store.indexOf(r), scrollIntoView);
+                return true;
+            }
+        }
+        return false;
+    },
 
     /**
-     * If this radio is part of a group, it will return the selected value
-     * @return {String}
+     * Select an item in the dropdown list by its numeric index in the list. This function does NOT cause the select event to fire.
+     * The store must be loaded and the list expanded for this function to work, otherwise use setValue.
+     * @param {Number} index The zero-based index of the list item to select
+     * @param {Boolean} scrollIntoView False to prevent the dropdown list from autoscrolling to display the
+     * selected item if it is not currently in view (defaults to true)
      */
-    getGroupValue : function(){
-       var p = this.el.up('form') || Ext.getBody();
-        var c = p.child('input[name='+this.el.dom.name+']:checked', true);
-        return c ? c.value : null;
+    select : function(index, scrollIntoView){
+        this.selectedIndex = index;
+        this.view.select(index);
+        if(scrollIntoView !== false){
+            var el = this.view.getNode(index);
+            if(el){
+                this.innerList.scrollChildIntoView(el, false);
+            }
+        }
+
     },
 
     // private
-    onClick : function(){
-       if(this.el.dom.checked != this.checked){
-                       var els = this.getCheckEl().select('input[name=' + this.el.dom.name + ']');
-                       els.each(function(el){
-                               if(el.dom.id == this.id){
-                                       this.setValue(true);
-                               }else{
-                                       Ext.getCmp(el.dom.id).setValue(false);
-                               }
-                       }, this);
-               }
+    selectNext : function(){
+        var ct = this.store.getCount();
+        if(ct > 0){
+            if(this.selectedIndex == -1){
+                this.select(0);
+            }else if(this.selectedIndex < ct-1){
+                this.select(this.selectedIndex+1);
+            }
+        }
     },
 
-    /**
-     * Sets either the checked/unchecked status of this Radio, or, if a string value
-     * is passed, checks a sibling Radio of the same name whose value is the value specified.
-     * @param value {String/Boolean} Checked value, or the value of the sibling radio button to check.
-     * @return {Ext.form.Field} this
-     */
-    setValue : function(v){
-       if (typeof v == 'boolean') {
-            Ext.form.Radio.superclass.setValue.call(this, v);
-        } else {
-            var r = this.getCheckEl().child('input[name=' + this.el.dom.name + '][value=' + v + ']', true);
-            if(r){
-                Ext.getCmp(r.id).setValue(true);
+    // private
+    selectPrev : function(){
+        var ct = this.store.getCount();
+        if(ct > 0){
+            if(this.selectedIndex == -1){
+                this.select(0);
+            }else if(this.selectedIndex !== 0){
+                this.select(this.selectedIndex-1);
             }
         }
-        return this;
     },
-    
+
     // private
-    getCheckEl: function(){
-        if(this.inGroup){
-            return this.el.up('.x-form-radio-group')
+    onKeyUp : function(e){
+        var k = e.getKey();
+        if(this.editable !== false && this.readOnly !== true && (k == e.BACKSPACE || !e.isSpecialKey())){
+
+            this.lastKey = k;
+            this.dqTask.delay(this.queryDelay);
         }
-        return this.el.up('form') || Ext.getBody();
-    }
-});
-Ext.reg('radio', Ext.form.Radio);
-/**\r
- * @class Ext.form.RadioGroup\r
- * @extends Ext.form.CheckboxGroup\r
- * A grouping container for {@link Ext.form.Radio} controls.\r
- * @constructor\r
- * Creates a new RadioGroup\r
- * @param {Object} config Configuration options\r
- * @xtype radiogroup\r
- */\r
-Ext.form.RadioGroup = Ext.extend(Ext.form.CheckboxGroup, {\r
-    /**\r
-     * @cfg {Boolean} allowBlank True to allow every item in the group to be blank (defaults to true).\r
-     * If allowBlank = false and no items are selected at validation time, {@link @blankText} will\r
-     * be used as the error text.\r
-     */\r
-    allowBlank : true,\r
-    /**\r
-     * @cfg {String} blankText Error text to display if the {@link #allowBlank} validation fails\r
-     * (defaults to 'You must select one item in this group')\r
-     */\r
-    blankText : 'You must select one item in this group',\r
-    \r
-    // private\r
-    defaultType : 'radio',\r
-    \r
-    // private\r
-    groupCls : 'x-form-radio-group',\r
-    \r
-    /**\r
-     * @event change\r
-     * Fires when the state of a child radio changes.\r
-     * @param {Ext.form.RadioGroup} this\r
-     * @param {Ext.form.Radio} checked The checked radio\r
-     */\r
-    \r
-    /**\r
-     * Gets the selected {@link Ext.form.Radio} in the group, if it exists.\r
-     * @return {Ext.form.Radio} The selected radio.\r
-     */\r
-    getValue : function(){\r
-        var out = null;\r
-        this.eachItem(function(item){\r
-            if(item.checked){\r
-                out = item;\r
-                return false;\r
-            }\r
-        });\r
-        return out;\r
-    },\r
-    \r
-    /**\r
-     * Sets the checked radio in the group.\r
-     * @param {String/Ext.form.Radio} id The radio to check.\r
-     * @param {Boolean} value The value to set the radio.\r
-     * @return {Ext.form.RadioGroup} this\r
-     */\r
-    onSetValue : function(id, value){\r
-        if(arguments.length > 1){\r
-            var f = this.getBox(id);\r
-            if(f){\r
-                f.setValue(value);\r
-                if(f.checked){\r
-                    this.eachItem(function(item){\r
-                        if (item !== f){\r
-                            item.setValue(false);\r
-                        }\r
-                    });\r
-                }\r
-            }\r
-        }else{\r
-            this.setValueForItem(id);\r
-        }\r
-    },\r
-    \r
-    setValueForItem : function(val){\r
-        val = String(val).split(',')[0];\r
-        this.eachItem(function(item){\r
-            item.setValue(val == item.inputValue);\r
-        });\r
-    },\r
-    \r
-    // private\r
-    fireChecked : function(){\r
-        if(!this.checkTask){\r
-            this.checkTask = new Ext.util.DelayedTask(this.bufferChecked, this);\r
-        }\r
-        this.checkTask.delay(10);\r
-    },\r
-    \r
-    // private\r
-    bufferChecked : function(){\r
-        var out = null;\r
-        this.eachItem(function(item){\r
-            if(item.checked){\r
-                out = item;\r
-                return false;\r
-            }\r
-        });\r
-        this.fireEvent('change', this, out);\r
-    },\r
-    \r
-    onDestroy : function(){\r
-        if(this.checkTask){\r
-            this.checkTask.cancel();\r
-            this.checkTask = null;\r
-        }\r
-        Ext.form.RadioGroup.superclass.onDestroy.call(this);\r
-    }\r
-\r
-});\r
-\r
-Ext.reg('radiogroup', Ext.form.RadioGroup);\r
-/**\r
- * @class Ext.form.Hidden\r
- * @extends Ext.form.Field\r
- * A basic hidden field for storing hidden values in forms that need to be passed in the form submit.\r
- * @constructor\r
- * Create a new Hidden field.\r
- * @param {Object} config Configuration options\r
- * @xtype hidden\r
- */\r
-Ext.form.Hidden = Ext.extend(Ext.form.Field, {\r
-    // private\r
-    inputType : 'hidden',\r
-\r
-    // private\r
-    onRender : function(){\r
-        Ext.form.Hidden.superclass.onRender.apply(this, arguments);\r
-    },\r
-\r
-    // private\r
-    initEvents : function(){\r
-        this.originalValue = this.getValue();\r
-    },\r
-\r
-    // These are all private overrides\r
-    setSize : Ext.emptyFn,\r
-    setWidth : Ext.emptyFn,\r
-    setHeight : Ext.emptyFn,\r
-    setPosition : Ext.emptyFn,\r
-    setPagePosition : Ext.emptyFn,\r
-    markInvalid : Ext.emptyFn,\r
-    clearInvalid : Ext.emptyFn\r
-});\r
-Ext.reg('hidden', Ext.form.Hidden);/**
- * @class Ext.form.BasicForm
- * @extends Ext.util.Observable
- * <p>Encapsulates the DOM &lt;form> element at the heart of the {@link Ext.form.FormPanel FormPanel} class, and provides
- * input field management, validation, submission, and form loading services.</p>
- * <p>By default, Ext Forms are submitted through Ajax, using an instance of {@link Ext.form.Action.Submit}.
- * To enable normal browser submission of an Ext Form, use the {@link #standardSubmit} config option.</p>
- * <p><b><u>File Uploads</u></b></p>
- * <p>{@link #fileUpload File uploads} are not performed using Ajax submission, that
- * is they are <b>not</b> performed using XMLHttpRequests. Instead the form is submitted in the standard
- * manner with the DOM <tt>&lt;form></tt> element temporarily modified to have its
- * <a href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-target">target</a> set to refer
- * to a dynamically generated, hidden <tt>&lt;iframe></tt> which is inserted into the document
- * but removed after the return data has been gathered.</p>
- * <p>The server response is parsed by the browser to create the document for the IFRAME. If the
- * server is using JSON to send the return object, then the
- * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17">Content-Type</a> header
- * must be set to "text/html" in order to tell the browser to insert the text unchanged into the document body.</p>
- * <p>Characters which are significant to an HTML parser must be sent as HTML entities, so encode
- * "&lt;" as "&amp;lt;", "&amp;" as "&amp;amp;" etc.</p>
- * <p>The response text is retrieved from the document, and a fake XMLHttpRequest object
- * is created containing a <tt>responseText</tt> property in order to conform to the
- * requirements of event handlers and callbacks.</p>
- * <p>Be aware that file upload packets are sent with the content type <a href="http://www.faqs.org/rfcs/rfc2388.html">multipart/form</a>
- * and some server technologies (notably JEE) may require some custom processing in order to
- * retrieve parameter names and parameter values from the packet content.</p>
- * @constructor
- * @param {Mixed} el The form element or its id
- * @param {Object} config Configuration options
- */
-Ext.form.BasicForm = function(el, config){
-    Ext.apply(this, config);
-    if(Ext.isString(this.paramOrder)){
-        this.paramOrder = this.paramOrder.split(/[\s,|]/);
-    }
-    /**
-     * @property items
-     * A {@link Ext.util.MixedCollection MixedCollection) containing all the Ext.form.Fields in this form.
-     * @type MixedCollection
-     */
-    this.items = new Ext.util.MixedCollection(false, function(o){
-        return o.getItemId();
-    });
-    this.addEvents(
-        /**
-         * @event beforeaction
-         * Fires before any action is performed. Return false to cancel the action.
-         * @param {Form} this
-         * @param {Action} action The {@link Ext.form.Action} to be performed
-         */
-        'beforeaction',
-        /**
-         * @event actionfailed
-         * Fires when an action fails.
-         * @param {Form} this
-         * @param {Action} action The {@link Ext.form.Action} that failed
-         */
-        'actionfailed',
-        /**
-         * @event actioncomplete
-         * Fires when an action is completed.
-         * @param {Form} this
-         * @param {Action} action The {@link Ext.form.Action} that completed
-         */
-        'actioncomplete'
-    );
+        Ext.form.ComboBox.superclass.onKeyUp.call(this, e);
+    },
 
-    if(el){
-        this.initEl(el);
-    }
-    Ext.form.BasicForm.superclass.constructor.call(this);
-};
+    // private
+    validateBlur : function(){
+        return !this.list || !this.list.isVisible();
+    },
+
+    // private
+    initQuery : function(){
+        this.doQuery(this.getRawValue());
+    },
+
+    // private
+    beforeBlur : function(){
+        this.assertValue();
+    },
+
+    // private
+    postBlur  : function(){
+        Ext.form.ComboBox.superclass.postBlur.call(this);
+        this.collapse();
+        this.inKeyMode = false;
+    },
+
+    /**
+     * Execute a query to filter the dropdown list.  Fires the {@link #beforequery} event prior to performing the
+     * query allowing the query action to be canceled if needed.
+     * @param {String} query The SQL query to execute
+     * @param {Boolean} forceAll <tt>true</tt> to force the query to execute even if there are currently fewer
+     * characters in the field than the minimum specified by the <tt>{@link #minChars}</tt> config option.  It
+     * also clears any filter previously saved in the current store (defaults to <tt>false</tt>)
+     */
+    doQuery : function(q, forceAll){
+        q = Ext.isEmpty(q) ? '' : q;
+        var qe = {
+            query: q,
+            forceAll: forceAll,
+            combo: this,
+            cancel:false
+        };
+        if(this.fireEvent('beforequery', qe)===false || qe.cancel){
+            return false;
+        }
+        q = qe.query;
+        forceAll = qe.forceAll;
+        if(forceAll === true || (q.length >= this.minChars)){
+            if(this.lastQuery !== q){
+                this.lastQuery = q;
+                if(this.mode == 'local'){
+                    this.selectedIndex = -1;
+                    if(forceAll){
+                        this.store.clearFilter();
+                    }else{
+                        this.store.filter(this.displayField, q);
+                    }
+                    this.onLoad();
+                }else{
+                    this.store.baseParams[this.queryParam] = q;
+                    this.store.load({
+                        params: this.getParams(q)
+                    });
+                    this.expand();
+                }
+            }else{
+                this.selectedIndex = -1;
+                this.onLoad();
+            }
+        }
+    },
+
+    // private
+    getParams : function(q){
+        var p = {};
+        //p[this.queryParam] = q;
+        if(this.pageSize){
+            p.start = 0;
+            p.limit = this.pageSize;
+        }
+        return p;
+    },
 
-Ext.extend(Ext.form.BasicForm, Ext.util.Observable, {
     /**
-     * @cfg {String} method
-     * The request method to use (GET or POST) for form actions if one isn't supplied in the action options.
+     * Hides the dropdown list if it is currently expanded. Fires the {@link #collapse} event on completion.
      */
+    collapse : function(){
+        if(!this.isExpanded()){
+            return;
+        }
+        this.list.hide();
+        Ext.getDoc().un('mousewheel', this.collapseIf, this);
+        Ext.getDoc().un('mousedown', this.collapseIf, this);
+        this.fireEvent('collapse', this);
+    },
+
+    // private
+    collapseIf : function(e){
+        if(!e.within(this.wrap) && !e.within(this.list)){
+            this.collapse();
+        }
+    },
+
     /**
-     * @cfg {DataReader} reader
-     * An Ext.data.DataReader (e.g. {@link Ext.data.XmlReader}) to be used to read
-     * data when executing 'load' actions. This is optional as there is built-in
-     * support for processing JSON.  For additional information on using an XMLReader
-     * see the example provided in examples/form/xml-form.html.
+     * Expands the dropdown list if it is currently hidden. Fires the {@link #expand} event on completion.
      */
+    expand : function(){
+        if(this.isExpanded() || !this.hasFocus){
+            return;
+        }
+        if(this.bufferSize){
+            this.doResize(this.bufferSize);
+            delete this.bufferSize;
+        }
+        this.list.alignTo.apply(this.list, [this.el].concat(this.listAlign));
+        this.list.show();
+        if(Ext.isGecko2){
+            this.innerList.setOverflow('auto'); // necessary for FF 2.0/Mac
+        }
+        this.mon(Ext.getDoc(), {
+            scope: this,
+            mousewheel: this.collapseIf,
+            mousedown: this.collapseIf
+        });
+        this.fireEvent('expand', this);
+    },
+
     /**
-     * @cfg {DataReader} errorReader
-     * <p>An Ext.data.DataReader (e.g. {@link Ext.data.XmlReader}) to be used to
-     * read field error messages returned from 'submit' actions. This is optional
-     * as there is built-in support for processing JSON.</p>
-     * <p>The Records which provide messages for the invalid Fields must use the
-     * Field name (or id) as the Record ID, and must contain a field called 'msg'
-     * which contains the error message.</p>
-     * <p>The errorReader does not have to be a full-blown implementation of a
-     * DataReader. It simply needs to implement a <tt>read(xhr)</tt> function
-     * which returns an Array of Records in an object with the following
-     * structure:</p><pre><code>
-{
-    records: recordArray
-}
-</code></pre>
+     * @method onTriggerClick
+     * @hide
      */
+    // private
+    // Implements the default empty TriggerField.onTriggerClick function
+    onTriggerClick : function(){
+        if(this.readOnly || this.disabled){
+            return;
+        }
+        if(this.isExpanded()){
+            this.collapse();
+            this.el.focus();
+        }else {
+            this.onFocus({});
+            if(this.triggerAction == 'all') {
+                this.doQuery(this.allQuery, true);
+            } else {
+                this.doQuery(this.getRawValue());
+            }
+            this.el.focus();
+        }
+    }
+
     /**
-     * @cfg {String} url
-     * The URL to use for form actions if one isn't supplied in the
-     * <code>{@link #doAction doAction} options</code>.
+     * @hide
+     * @method autoSize
      */
     /**
-     * @cfg {Boolean} fileUpload
-     * Set to true if this form is a file upload.
-     * <p>File uploads are not performed using normal 'Ajax' techniques, that is they are <b>not</b>
-     * performed using XMLHttpRequests. Instead the form is submitted in the standard manner with the
-     * DOM <tt>&lt;form></tt> element temporarily modified to have its
-     * <a href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-target">target</a> set to refer
-     * to a dynamically generated, hidden <tt>&lt;iframe></tt> which is inserted into the document
-     * but removed after the return data has been gathered.</p>
-     * <p>The server response is parsed by the browser to create the document for the IFRAME. If the
-     * server is using JSON to send the return object, then the
-     * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17">Content-Type</a> header
-     * must be set to "text/html" in order to tell the browser to insert the text unchanged into the document body.</p>
-     * <p>Characters which are significant to an HTML parser must be sent as HTML entities, so encode
-     * "&lt;" as "&amp;lt;", "&amp;" as "&amp;amp;" etc.</p>
-     * <p>The response text is retrieved from the document, and a fake XMLHttpRequest object
-     * is created containing a <tt>responseText</tt> property in order to conform to the
-     * requirements of event handlers and callbacks.</p>
-     * <p>Be aware that file upload packets are sent with the content type <a href="http://www.faqs.org/rfcs/rfc2388.html">multipart/form</a>
-     * and some server technologies (notably JEE) may require some custom processing in order to
-     * retrieve parameter names and parameter values from the packet content.</p>
+     * @cfg {Boolean} grow @hide
      */
     /**
-     * @cfg {Object} baseParams
-     * <p>Parameters to pass with all requests. e.g. baseParams: {id: '123', foo: 'bar'}.</p>
-     * <p>Parameters are encoded as standard HTTP parameters using {@link Ext#urlEncode}.</p>
+     * @cfg {Number} growMin @hide
      */
     /**
-     * @cfg {Number} timeout Timeout for form actions in seconds (default is 30 seconds).
+     * @cfg {Number} growMax @hide
      */
-    timeout: 30,
 
-    /**
-     * @cfg {Object} api (Optional) If specified load and submit actions will be handled
-     * with {@link Ext.form.Action.DirectLoad} and {@link Ext.form.Action.DirectSubmit}.
-     * Methods which have been imported by Ext.Direct can be specified here to load and submit
-     * forms.
-     * Such as the following:<pre><code>
-api: {
-    load: App.ss.MyProfile.load,
-    submit: App.ss.MyProfile.submit
-}
-</code></pre>
-     * <p>Load actions can use <code>{@link #paramOrder}</code> or <code>{@link #paramsAsHash}</code>
-     * to customize how the load method is invoked.
-     * Submit actions will always use a standard form submit. The formHandler configuration must
-     * be set on the associated server-side method which has been imported by Ext.Direct</p>
+});
+Ext.reg('combo', Ext.form.ComboBox);
+/**
+ * @class Ext.form.Checkbox
+ * @extends Ext.form.Field
+ * Single checkbox field.  Can be used as a direct replacement for traditional checkbox fields.
+ * @constructor
+ * Creates a new Checkbox
+ * @param {Object} config Configuration options
+ * @xtype checkbox
+ */
+Ext.form.Checkbox = Ext.extend(Ext.form.Field,  {
+    /**
+     * @cfg {String} focusClass The CSS class to use when the checkbox receives focus (defaults to undefined)
      */
-
+    focusClass : undefined,
     /**
-     * @cfg {Array/String} paramOrder <p>A list of params to be executed server side.
-     * Defaults to <tt>undefined</tt>. Only used for the <code>{@link #api}</code>
-     * <code>load</code> configuration.</p>
-     * <br><p>Specify the params in the order in which they must be executed on the
-     * server-side as either (1) an Array of String values, or (2) a String of params
-     * delimited by either whitespace, comma, or pipe. For example,
-     * any of the following would be acceptable:</p><pre><code>
-paramOrder: ['param1','param2','param3']
-paramOrder: 'param1 param2 param3'
-paramOrder: 'param1,param2,param3'
-paramOrder: 'param1|param2|param'
-     </code></pre>
+     * @cfg {String} fieldClass The default CSS class for the checkbox (defaults to 'x-form-field')
      */
-    paramOrder: undefined,
-
+    fieldClass : 'x-form-field',
     /**
-     * @cfg {Boolean} paramsAsHash Only used for the <code>{@link #api}</code>
-     * <code>load</code> configuration. Send parameters as a collection of named
-     * arguments (defaults to <tt>false</tt>). Providing a
-     * <tt>{@link #paramOrder}</tt> nullifies this configuration.
+     * @cfg {Boolean} checked <tt>true</tt> if the checkbox should render initially checked (defaults to <tt>false</tt>)
      */
-    paramsAsHash: false,
-
+    checked : false,
     /**
-     * @cfg {String} waitTitle
-     * The default title to show for the waiting message box (defaults to <tt>'Please Wait...'</tt>)
+     * @cfg {String/Object} autoCreate A DomHelper element spec, or true for a default element spec (defaults to
+     * {tag: 'input', type: 'checkbox', autocomplete: 'off'})
      */
-    waitTitle: 'Please Wait...',
-
-    // private
-    activeAction : null,
-
+    defaultAutoCreate : { tag: 'input', type: 'checkbox', autocomplete: 'off'},
     /**
-     * @cfg {Boolean} trackResetOnLoad If set to <tt>true</tt>, {@link #reset}() resets to the last loaded
-     * or {@link #setValues}() data instead of when the form was first created.  Defaults to <tt>false</tt>.
+     * @cfg {String} boxLabel The text that appears beside the checkbox
      */
-    trackResetOnLoad : false,
-
     /**
-     * @cfg {Boolean} standardSubmit
-     * <p>If set to <tt>true</tt>, standard HTML form submits are used instead
-     * of XHR (Ajax) style form submissions. Defaults to <tt>false</tt>.</p>
-     * <br><p><b>Note:</b> When using <code>standardSubmit</code>, the
-     * <code>options</code> to <code>{@link #submit}</code> are ignored because
-     * Ext's Ajax infrastracture is bypassed. To pass extra parameters (e.g.
-     * <code>baseParams</code> and <code>params</code>), utilize hidden fields
-     * to submit extra data, for example:</p>
-     * <pre><code>
-new Ext.FormPanel({
-    standardSubmit: true,
-    baseParams: {
-        foo: 'bar'
-    },
-    {@link url}: 'myProcess.php',
-    items: [{
-        xtype: 'textfield',
-        name: 'userName'
-    }],
-    buttons: [{
-        text: 'Save',
-        handler: function(){
-            var fp = this.ownerCt.ownerCt,
-                form = fp.getForm();
-            if (form.isValid()) {
-                // check if there are baseParams and if
-                // hiddent items have been added already
-                if (fp.baseParams && !fp.paramsAdded) {
-                    // add hidden items for all baseParams
-                    for (i in fp.baseParams) {
-                        fp.add({
-                            xtype: 'hidden',
-                            name: i,
-                            value: fp.baseParams[i]
-                        });
-                    }
-                    fp.doLayout();
-                    // set a custom flag to prevent re-adding
-                    fp.paramsAdded = true;
-                }
-                form.{@link #submit}();
-            }
-        }
-    }]
-});
-     * </code></pre>
+     * @cfg {String} inputValue The value that should go into the generated input element's value attribute
      */
     /**
-     * By default wait messages are displayed with Ext.MessageBox.wait. You can target a specific
-     * element by passing it or its id or mask the form itself by passing in true.
-     * @type Mixed
-     * @property waitMsgTarget
+     * @cfg {Function} handler A function called when the {@link #checked} value changes (can be used instead of 
+     * handling the check event). The handler is passed the following parameters:
+     * <div class="mdetail-params"><ul>
+     * <li><b>checkbox</b> : Ext.form.Checkbox<div class="sub-desc">The Checkbox being toggled.</div></li>
+     * <li><b>checked</b> : Boolean<div class="sub-desc">The new checked state of the checkbox.</div></li>
+     * </ul></div>
      */
-
-    // private
-    initEl : function(el){
-        this.el = Ext.get(el);
-        this.id = this.el.id || Ext.id();
-        if(!this.standardSubmit){
-            this.el.on('submit', this.onSubmit, this);
-        }
-        this.el.addClass('x-form');
-    },
-
     /**
-     * Get the HTML form Element
-     * @return Ext.Element
+     * @cfg {Object} scope An object to use as the scope ('this' reference) of the {@link #handler} function
+     * (defaults to this Checkbox).
      */
-    getEl: function(){
-        return this.el;
-    },
 
     // private
-    onSubmit : function(e){
-        e.stopEvent();
+    actionMode : 'wrap',
+    
+       // private
+    initComponent : function(){
+        Ext.form.Checkbox.superclass.initComponent.call(this);
+        this.addEvents(
+            /**
+             * @event check
+             * Fires when the checkbox is checked or unchecked.
+             * @param {Ext.form.Checkbox} this This checkbox
+             * @param {Boolean} checked The new checked value
+             */
+            'check'
+        );
     },
 
     // private
-    destroy: function() {
-        this.items.each(function(f){
-            Ext.destroy(f);
-        });
-        if(this.el){
-            this.el.removeAllListeners();
-            this.el.remove();
+    onResize : function(){
+        Ext.form.Checkbox.superclass.onResize.apply(this, arguments);
+        if(!this.boxLabel && !this.fieldLabel){
+            this.el.alignTo(this.wrap, 'c-c');
         }
-        this.purgeListeners();
     },
 
-    /**
-     * Returns true if client-side validation on the form is successful.
-     * @return Boolean
-     */
-    isValid : function(){
-        var valid = true;
-        this.items.each(function(f){
-           if(!f.validate()){
-               valid = false;
-           }
+    // private
+    initEvents : function(){
+        Ext.form.Checkbox.superclass.initEvents.call(this);
+        this.mon(this.el, {
+            scope: this,
+            click: this.onClick,
+            change: this.onClick
         });
-        return valid;
     },
 
     /**
-     * <p>Returns true if any fields in this form have changed from their original values.</p>
-     * <p>Note that if this BasicForm was configured with {@link #trackResetOnLoad} then the
-     * Fields' <i>original values</i> are updated when the values are loaded by {@link #setValues}
-     * or {@link #loadRecord}.</p>
-     * @return Boolean
+     * @hide
+     * Overridden and disabled. The editor element does not support standard valid/invalid marking.
+     * @method
      */
-    isDirty : function(){
-        var dirty = false;
-        this.items.each(function(f){
-           if(f.isDirty()){
-               dirty = true;
-               return false;
-           }
-        });
-        return dirty;
-    },
-
+    markInvalid : Ext.emptyFn,
     /**
-     * Performs a predefined action ({@link Ext.form.Action.Submit} or
-     * {@link Ext.form.Action.Load}) or a custom extension of {@link Ext.form.Action}
-     * to perform application-specific processing.
-     * @param {String/Object} actionName The name of the predefined action type,
-     * or instance of {@link Ext.form.Action} to perform.
-     * @param {Object} options (optional) The options to pass to the {@link Ext.form.Action}.
-     * All of the config options listed below are supported by both the
-     * {@link Ext.form.Action.Submit submit} and {@link Ext.form.Action.Load load}
-     * actions unless otherwise noted (custom actions could also accept
-     * other config options):<ul>
-     *
-     * <li><b>url</b> : String<div class="sub-desc">The url for the action (defaults
-     * to the form's {@link #url}.)</div></li>
-     *
-     * <li><b>method</b> : String<div class="sub-desc">The form method to use (defaults
-     * to the form's method, or POST if not defined)</div></li>
-     *
-     * <li><b>params</b> : String/Object<div class="sub-desc"><p>The params to pass
-     * (defaults to the form's baseParams, or none if not defined)</p>
-     * <p>Parameters are encoded as standard HTTP parameters using {@link Ext#urlEncode}.</p></div></li>
-     *
-     * <li><b>headers</b> : Object<div class="sub-desc">Request headers to set for the action
-     * (defaults to the form's default headers)</div></li>
-     *
-     * <li><b>success</b> : Function<div class="sub-desc">The callback that will
-     * be invoked after a successful response (see top of
-     * {@link Ext.form.Action.Submit submit} and {@link Ext.form.Action.Load load}
-     * for a description of what constitutes a successful response).
-     * The function is passed the following parameters:<ul>
-     * <li><tt>form</tt> : Ext.form.BasicForm<div class="sub-desc">The form that requested the action</div></li>
-     * <li><tt>action</tt> : The {@link Ext.form.Action Action} object which performed the operation.
-     * <div class="sub-desc">The action object contains these properties of interest:<ul>
-     * <li><tt>{@link Ext.form.Action#response response}</tt></li>
-     * <li><tt>{@link Ext.form.Action#result result}</tt> : interrogate for custom postprocessing</li>
-     * <li><tt>{@link Ext.form.Action#type type}</tt></li>
-     * </ul></div></li></ul></div></li>
-     *
-     * <li><b>failure</b> : Function<div class="sub-desc">The callback that will be invoked after a
-     * failed transaction attempt. The function is passed the following parameters:<ul>
-     * <li><tt>form</tt> : The {@link Ext.form.BasicForm} that requested the action.</li>
-     * <li><tt>action</tt> : The {@link Ext.form.Action Action} object which performed the operation.
-     * <div class="sub-desc">The action object contains these properties of interest:<ul>
-     * <li><tt>{@link Ext.form.Action#failureType failureType}</tt></li>
-     * <li><tt>{@link Ext.form.Action#response response}</tt></li>
-     * <li><tt>{@link Ext.form.Action#result result}</tt> : interrogate for custom postprocessing</li>
-     * <li><tt>{@link Ext.form.Action#type type}</tt></li>
-     * </ul></div></li></ul></div></li>
-     *
-     * <li><b>scope</b> : Object<div class="sub-desc">The scope in which to call the
-     * callback functions (The <tt>this</tt> reference for the callback functions).</div></li>
-     *
-     * <li><b>clientValidation</b> : Boolean<div class="sub-desc">Submit Action only.
-     * Determines whether a Form's fields are validated in a final call to
-     * {@link Ext.form.BasicForm#isValid isValid} prior to submission. Set to <tt>false</tt>
-     * to prevent this. If undefined, pre-submission field validation is performed.</div></li></ul>
-     *
-     * @return {BasicForm} this
+     * @hide
+     * Overridden and disabled. The editor element does not support standard valid/invalid marking.
+     * @method
      */
-    doAction : function(action, options){
-        if(Ext.isString(action)){
-            action = new Ext.form.Action.ACTION_TYPES[action](this, options);
+    clearInvalid : Ext.emptyFn,
+
+    // private
+    onRender : function(ct, position){
+        Ext.form.Checkbox.superclass.onRender.call(this, ct, position);
+        if(this.inputValue !== undefined){
+            this.el.dom.value = this.inputValue;
         }
-        if(this.fireEvent('beforeaction', this, action) !== false){
-            this.beforeAction(action);
-            action.run.defer(100, action);
+        this.wrap = this.el.wrap({cls: 'x-form-check-wrap'});
+        if(this.boxLabel){
+            this.wrap.createChild({tag: 'label', htmlFor: this.el.id, cls: 'x-form-cb-label', html: this.boxLabel});
         }
-        return this;
+        if(this.checked){
+            this.setValue(true);
+        }else{
+            this.checked = this.el.dom.checked;
+        }
+        // Need to repaint for IE, otherwise positioning is broken
+        if(Ext.isIE){
+            this.wrap.repaint();
+        }
+        this.resizeEl = this.positionEl = this.wrap;
     },
 
-    /**
-     * Shortcut to {@link #doAction do} a {@link Ext.form.Action.Submit submit action}.
-     * @param {Object} options The options to pass to the action (see {@link #doAction} for details).<br>
-     * <p><b>Note:</b> this is ignored when using the {@link #standardSubmit} option.</p>
-     * <p>The following code:</p><pre><code>
-myFormPanel.getForm().submit({
-    clientValidation: true,
-    url: 'updateConsignment.php',
-    params: {
-        newStatus: 'delivered'
+    // private
+    onDestroy : function(){
+        Ext.destroy(this.wrap);
+        Ext.form.Checkbox.superclass.onDestroy.call(this);
     },
-    success: function(form, action) {
-       Ext.Msg.alert('Success', action.result.msg);
+
+    // private
+    initValue : function() {
+        this.originalValue = this.getValue();
     },
-    failure: function(form, action) {
-        switch (action.failureType) {
-            case Ext.form.Action.CLIENT_INVALID:
-                Ext.Msg.alert('Failure', 'Form fields may not be submitted with invalid values');
-                break;
-            case Ext.form.Action.CONNECT_FAILURE:
-                Ext.Msg.alert('Failure', 'Ajax communication failed');
-                break;
-            case Ext.form.Action.SERVER_INVALID:
-               Ext.Msg.alert('Failure', action.result.msg);
-       }
-    }
-});
-</code></pre>
-     * would process the following server response for a successful submission:<pre><code>
-{
-    "success":true, // note this is Boolean, not string
-    "msg":"Consignment updated"
-}
-</code></pre>
-     * and the following server response for a failed submission:<pre><code>
-{
-    "success":false, // note this is Boolean, not string
-    "msg":"You do not have permission to perform this operation"
-}
-</code></pre>
-     * @return {BasicForm} this
+
+    /**
+     * Returns the checked state of the checkbox.
+     * @return {Boolean} True if checked, else false
      */
-    submit : function(options){
-        if(this.standardSubmit){
-            var v = this.isValid();
-            if(v){
-                var el = this.el.dom;
-                if(this.url && Ext.isEmpty(el.action)){
-                    el.action = this.url;
-                }
-                el.submit();
-            }
-            return v;
+    getValue : function(){
+        if(this.rendered){
+            return this.el.dom.checked;
         }
-        var submitAction = String.format('{0}submit', this.api ? 'direct' : '');
-        this.doAction(submitAction, options);
-        return this;
+        return this.checked;
     },
 
-    /**
-     * Shortcut to {@link #doAction do} a {@link Ext.form.Action.Load load action}.
-     * @param {Object} options The options to pass to the action (see {@link #doAction} for details)
-     * @return {BasicForm} this
-     */
-    load : function(options){
-        var loadAction = String.format('{0}load', this.api ? 'direct' : '');
-        this.doAction(loadAction, options);
-        return this;
+       // private
+    onClick : function(){
+        if(this.el.dom.checked != this.checked){
+            this.setValue(this.el.dom.checked);
+        }
     },
 
     /**
-     * Persists the values in this form into the passed {@link Ext.data.Record} object in a beginEdit/endEdit block.
-     * @param {Record} record The record to edit
-     * @return {BasicForm} this
+     * Sets the checked state of the checkbox, fires the 'check' event, and calls a
+     * <code>{@link #handler}</code> (if configured).
+     * @param {Boolean/String} checked The following values will check the checkbox:
+     * <code>true, 'true', '1', or 'on'</code>. Any other value will uncheck the checkbox.
+     * @return {Ext.form.Field} this
      */
-    updateRecord : function(record){
-        record.beginEdit();
-        var fs = record.fields;
-        fs.each(function(f){
-            var field = this.findField(f.name);
-            if(field){
-                record.set(f.name, field.getValue());
+    setValue : function(v){
+        var checked = this.checked ;
+        this.checked = (v === true || v === 'true' || v == '1' || String(v).toLowerCase() == 'on');
+        if(this.rendered){
+            this.el.dom.checked = this.checked;
+            this.el.dom.defaultChecked = this.checked;
+        }
+        if(checked != this.checked){
+            this.fireEvent('check', this, this.checked);
+            if(this.handler){
+                this.handler.call(this.scope || this, this, this.checked);
             }
-        }, this);
-        record.endEdit();
+        }
         return this;
-    },
-
+    }
+});
+Ext.reg('checkbox', Ext.form.Checkbox);
+/**
+ * @class Ext.form.CheckboxGroup
+ * @extends Ext.form.Field
+ * <p>A grouping container for {@link Ext.form.Checkbox} controls.</p>
+ * <p>Sample usage:</p>
+ * <pre><code>
+var myCheckboxGroup = new Ext.form.CheckboxGroup({
+    id:'myGroup',
+    xtype: 'checkboxgroup',
+    fieldLabel: 'Single Column',
+    itemCls: 'x-check-group-alt',
+    // Put all controls in a single column with width 100%
+    columns: 1,
+    items: [
+        {boxLabel: 'Item 1', name: 'cb-col-1'},
+        {boxLabel: 'Item 2', name: 'cb-col-2', checked: true},
+        {boxLabel: 'Item 3', name: 'cb-col-3'}
+    ]
+});
+ * </code></pre>
+ * @constructor
+ * Creates a new CheckboxGroup
+ * @param {Object} config Configuration options
+ * @xtype checkboxgroup
+ */
+Ext.form.CheckboxGroup = Ext.extend(Ext.form.Field, {
     /**
-     * Loads an {@link Ext.data.Record} into this form by calling {@link #setValues} with the
-     * {@link Ext.data.Record#data record data}.
-     * See also {@link #trackResetOnLoad}.
-     * @param {Record} record The record to load
-     * @return {BasicForm} this
+     * @cfg {Array} items An Array of {@link Ext.form.Checkbox Checkbox}es or Checkbox config objects
+     * to arrange in the group.
      */
-    loadRecord : function(record){
-        this.setValues(record.data);
-        return this;
-    },
+    /**
+     * @cfg {String/Number/Array} columns Specifies the number of columns to use when displaying grouped
+     * checkbox/radio controls using automatic layout.  This config can take several types of values:
+     * <ul><li><b>'auto'</b> : <p class="sub-desc">The controls will be rendered one per column on one row and the width
+     * of each column will be evenly distributed based on the width of the overall field container. This is the default.</p></li>
+     * <li><b>Number</b> : <p class="sub-desc">If you specific a number (e.g., 3) that number of columns will be
+     * created and the contained controls will be automatically distributed based on the value of {@link #vertical}.</p></li>
+     * <li><b>Array</b> : Object<p class="sub-desc">You can also specify an array of column widths, mixing integer
+     * (fixed width) and float (percentage width) values as needed (e.g., [100, .25, .75]). Any integer values will
+     * be rendered first, then any float values will be calculated as a percentage of the remaining space. Float
+     * values do not have to add up to 1 (100%) although if you want the controls to take up the entire field
+     * container you should do so.</p></li></ul>
+     */
+    columns : 'auto',
+    /**
+     * @cfg {Boolean} vertical True to distribute contained controls across columns, completely filling each column
+     * top to bottom before starting on the next column.  The number of controls in each column will be automatically
+     * calculated to keep columns as even as possible.  The default value is false, so that controls will be added
+     * to columns one at a time, completely filling each row left to right before starting on the next row.
+     */
+    vertical : false,
+    /**
+     * @cfg {Boolean} allowBlank False to validate that at least one item in the group is checked (defaults to true).
+     * If no items are selected at validation time, {@link @blankText} will be used as the error text.
+     */
+    allowBlank : true,
+    /**
+     * @cfg {String} blankText Error text to display if the {@link #allowBlank} validation fails (defaults to "You must
+     * select at least one item in this group")
+     */
+    blankText : "You must select at least one item in this group",
 
     // private
-    beforeAction : function(action){
-        var o = action.options;
-        if(o.waitMsg){
-            if(this.waitMsgTarget === true){
-                this.el.mask(o.waitMsg, 'x-mask-loading');
-            }else if(this.waitMsgTarget){
-                this.waitMsgTarget = Ext.get(this.waitMsgTarget);
-                this.waitMsgTarget.mask(o.waitMsg, 'x-mask-loading');
-            }else{
-                Ext.MessageBox.wait(o.waitMsg, o.waitTitle || this.waitTitle);
-            }
-        }
-    },
+    defaultType : 'checkbox',
 
     // private
-    afterAction : function(action, success){
-        this.activeAction = null;
-        var o = action.options;
-        if(o.waitMsg){
-            if(this.waitMsgTarget === true){
-                this.el.unmask();
-            }else if(this.waitMsgTarget){
-                this.waitMsgTarget.unmask();
-            }else{
-                Ext.MessageBox.updateProgress(1);
-                Ext.MessageBox.hide();
-            }
-        }
-        if(success){
-            if(o.reset){
-                this.reset();
-            }
-            Ext.callback(o.success, o.scope, [this, action]);
-            this.fireEvent('actioncomplete', this, action);
-        }else{
-            Ext.callback(o.failure, o.scope, [this, action]);
-            this.fireEvent('actionfailed', this, action);
-        }
+    groupCls : 'x-form-check-group',
+
+    // private
+    initComponent: function(){
+        this.addEvents(
+            /**
+             * @event change
+             * Fires when the state of a child checkbox changes.
+             * @param {Ext.form.CheckboxGroup} this
+             * @param {Array} checked An array containing the checked boxes.
+             */
+            'change'
+        );
+        this.on('change', this.validate, this);
+        Ext.form.CheckboxGroup.superclass.initComponent.call(this);
     },
 
-    /**
-     * Find a {@link Ext.form.Field} in this form.
-     * @param {String} id The value to search for (specify either a {@link Ext.Component#id id},
-     * {@link Ext.grid.Column#dataIndex dataIndex}, {@link Ext.form.Field#getName name or hiddenName}).
-     * @return Field
-     */
-    findField : function(id){
-        var field = this.items.get(id);
-        if(!Ext.isObject(field)){
-            this.items.each(function(f){
-                if(f.isFormField && (f.dataIndex == id || f.id == id || f.getName() == id)){
-                    field = f;
-                    return false;
+    // private
+    onRender : function(ct, position){
+        if(!this.el){
+            var panelCfg = {
+                autoEl: {
+                    id: this.id
+                },
+                cls: this.groupCls,
+                layout: 'column',
+                renderTo: ct,
+                bufferResize: false // Default this to false, since it doesn't really have a proper ownerCt.
+            };
+            var colCfg = {
+                xtype: 'container',
+                defaultType: this.defaultType,
+                layout: 'form',
+                defaults: {
+                    hideLabel: true,
+                    anchor: '100%'
                 }
-            });
-        }
-        return field || null;
-    },
+            };
 
+            if(this.items[0].items){
 
-    /**
-     * Mark fields in this form invalid in bulk.
-     * @param {Array/Object} errors Either an array in the form [{id:'fieldId', msg:'The message'},...] or an object hash of {id: msg, id2: msg2}
-     * @return {BasicForm} this
-     */
-    markInvalid : function(errors){
-        if(Ext.isArray(errors)){
-            for(var i = 0, len = errors.length; i < len; i++){
-                var fieldError = errors[i];
-                var f = this.findField(fieldError.id);
-                if(f){
-                    f.markInvalid(fieldError.msg);
+                // The container has standard ColumnLayout configs, so pass them in directly
+
+                Ext.apply(panelCfg, {
+                    layoutConfig: {columns: this.items.length},
+                    defaults: this.defaults,
+                    items: this.items
+                });
+                for(var i=0, len=this.items.length; i<len; i++){
+                    Ext.applyIf(this.items[i], colCfg);
+                }
+
+            }else{
+
+                // The container has field item configs, so we have to generate the column
+                // panels first then move the items into the columns as needed.
+
+                var numCols, cols = [];
+
+                if(typeof this.columns == 'string'){ // 'auto' so create a col per item
+                    this.columns = this.items.length;
+                }
+                if(!Ext.isArray(this.columns)){
+                    var cs = [];
+                    for(var i=0; i<this.columns; i++){
+                        cs.push((100/this.columns)*.01); // distribute by even %
+                    }
+                    this.columns = cs;
+                }
+
+                numCols = this.columns.length;
+
+                // Generate the column configs with the correct width setting
+                for(var i=0; i<numCols; i++){
+                    var cc = Ext.apply({items:[]}, colCfg);
+                    cc[this.columns[i] <= 1 ? 'columnWidth' : 'width'] = this.columns[i];
+                    if(this.defaults){
+                        cc.defaults = Ext.apply(cc.defaults || {}, this.defaults)
+                    }
+                    cols.push(cc);
+                };
+
+                // Distribute the original items into the columns
+                if(this.vertical){
+                    var rows = Math.ceil(this.items.length / numCols), ri = 0;
+                    for(var i=0, len=this.items.length; i<len; i++){
+                        if(i>0 && i%rows==0){
+                            ri++;
+                        }
+                        if(this.items[i].fieldLabel){
+                            this.items[i].hideLabel = false;
+                        }
+                        cols[ri].items.push(this.items[i]);
+                    };
+                }else{
+                    for(var i=0, len=this.items.length; i<len; i++){
+                        var ci = i % numCols;
+                        if(this.items[i].fieldLabel){
+                            this.items[i].hideLabel = false;
+                        }
+                        cols[ci].items.push(this.items[i]);
+                    };
                 }
+
+                Ext.apply(panelCfg, {
+                    layoutConfig: {columns: numCols},
+                    items: cols
+                });
             }
-        }else{
-            var field, id;
-            for(id in errors){
-                if(!Ext.isFunction(errors[id]) && (field = this.findField(id))){
-                    field.markInvalid(errors[id]);
+
+            this.panel = new Ext.Container(panelCfg);
+            this.panel.ownerCt = this;
+            this.el = this.panel.getEl();
+
+            if(this.forId && this.itemCls){
+                var l = this.el.up(this.itemCls).child('label', true);
+                if(l){
+                    l.setAttribute('htmlFor', this.forId);
                 }
             }
+
+            var fields = this.panel.findBy(function(c){
+                return c.isFormField;
+            }, this);
+
+            this.items = new Ext.util.MixedCollection();
+            this.items.addAll(fields);
         }
-        return this;
+        Ext.form.CheckboxGroup.superclass.onRender.call(this, ct, position);
     },
 
-    /**
-     * Set values for fields in this form in bulk.
-     * @param {Array/Object} values Either an array in the form:<pre><code>
-[{id:'clientName', value:'Fred. Olsen Lines'},
- {id:'portOfLoading', value:'FXT'},
- {id:'portOfDischarge', value:'OSL'} ]</code></pre>
-     * or an object hash of the form:<pre><code>
-{
-    clientName: 'Fred. Olsen Lines',
-    portOfLoading: 'FXT',
-    portOfDischarge: 'OSL'
-}</code></pre>
-     * @return {BasicForm} this
-     */
-    setValues : function(values){
-        if(Ext.isArray(values)){ // array of objects
-            for(var i = 0, len = values.length; i < len; i++){
-                var v = values[i];
-                var f = this.findField(v.id);
-                if(f){
-                    f.setValue(v.value);
-                    if(this.trackResetOnLoad){
-                        f.originalValue = f.getValue();
-                    }
-                }
+    initValue : function(){
+        if(this.value){
+            this.setValue.apply(this, this.buffered ? this.value : [this.value]);
+            delete this.buffered;
+            delete this.value;
+        }
+    },
+
+    afterRender : function(){
+        Ext.form.CheckboxGroup.superclass.afterRender.call(this);
+        this.eachItem(function(item){
+            item.on('check', this.fireChecked, this);
+            item.inGroup = true;
+        });
+    },
+
+    // private
+    doLayout: function(){
+        //ugly method required to layout hidden items
+        if(this.rendered){
+            this.panel.forceLayout = this.ownerCt.forceLayout;
+            this.panel.doLayout();
+        }
+    },
+
+    // private
+    fireChecked: function(){
+        var arr = [];
+        this.eachItem(function(item){
+            if(item.checked){
+                arr.push(item);
             }
-        }else{ // object hash
-            var field, id;
-            for(id in values){
-                if(!Ext.isFunction(values[id]) && (field = this.findField(id))){
-                    field.setValue(values[id]);
-                    if(this.trackResetOnLoad){
-                        field.originalValue = field.getValue();
-                    }
+        });
+        this.fireEvent('change', this, arr);
+    },
+
+    // private
+    validateValue : function(value){
+        if(!this.allowBlank){
+            var blank = true;
+            this.eachItem(function(f){
+                if(f.checked){
+                    return (blank = false);
                 }
+            });
+            if(blank){
+                this.markInvalid(this.blankText);
+                return false;
             }
         }
-        return this;
+        return true;
     },
 
-    /**
-     * <p>Returns the fields in this form as an object with key/value pairs as they would be submitted using a standard form submit.
-     * If multiple fields exist with the same name they are returned as an array.</p>
-     * <p><b>Note:</b> The values are collected from all enabled HTML input elements within the form, <u>not</u> from
-     * the Ext Field objects. This means that all returned values are Strings (or Arrays of Strings) and that the
-     * value can potentially be the emptyText of a field.</p>
-     * @param {Boolean} asString (optional) Pass true to return the values as a string. (defaults to false, returning an Object)
-     * @return {String/Object}
-     */
-    getValues : function(asString){
-        var fs = Ext.lib.Ajax.serializeForm(this.el.dom);
-        if(asString === true){
-            return fs;
+    // private
+    isDirty: function(){
+        //override the behaviour to check sub items.
+        if (this.disabled || !this.rendered) {
+            return false;
         }
-        return Ext.urlDecode(fs);
+
+        var dirty = false;
+        this.eachItem(function(item){
+            if(item.isDirty()){
+                dirty = true;
+                return false;
+            }
+        });
+        return dirty;
     },
 
-    getFieldValues : function(){
-        var o = {};
-        this.items.each(function(f){
-           o[f.getName()] = f.getValue();
+    // private
+    onDisable : function(){
+        this.eachItem(function(item){
+            item.disable();
         });
-        return o;
     },
 
-    /**
-     * Clears all invalid messages in this form.
-     * @return {BasicForm} this
-     */
-    clearInvalid : function(){
-        this.items.each(function(f){
-           f.clearInvalid();
+    // private
+    onEnable : function(){
+        this.eachItem(function(item){
+            item.enable();
         });
-        return this;
     },
 
-    /**
-     * Resets this form.
-     * @return {BasicForm} this
-     */
+    // private
+    doLayout: function(){
+        if(this.rendered){
+            this.panel.forceLayout = this.ownerCt.forceLayout;
+            this.panel.doLayout();
+        }
+    },
+
+    // private
+    onResize : function(w, h){
+        this.panel.setSize(w, h);
+        this.panel.doLayout();
+    },
+
+    // inherit docs from Field
     reset : function(){
-        this.items.each(function(f){
-            f.reset();
+        this.eachItem(function(c){
+            if(c.reset){
+                c.reset();
+            }
         });
-        return this;
+        // Defer the clearInvalid so if BaseForm's collection is being iterated it will be called AFTER it is complete.
+        // Important because reset is being called on both the group and the individual items.
+        (function() {
+            this.clearInvalid();
+        }).defer(50, this);
     },
 
     /**
-     * Add Ext.form Components to this form's Collection. This does not result in rendering of
-     * the passed Component, it just enables the form to validate Fields, and distribute values to
-     * Fields.
-     * <p><b>You will not usually call this function. In order to be rendered, a Field must be added
-     * to a {@link Ext.Container Container}, usually an {@link Ext.form.FormPanel FormPanel}.
-     * The FormPanel to which the field is added takes care of adding the Field to the BasicForm's
-     * collection.</b></p>
-     * @param {Field} field1
-     * @param {Field} field2 (optional)
-     * @param {Field} etc (optional)
-     * @return {BasicForm} this
+     * {@link Ext.form.Checkbox#setValue Set the value(s)} of an item or items
+     * in the group. Examples illustrating how this method may be called:
+     * <pre><code>
+// call with name and value
+myCheckboxGroup.setValue('cb-col-1', true);
+// call with an array of boolean values
+myCheckboxGroup.setValue([true, false, false]);
+// call with an object literal specifying item:value pairs
+myCheckboxGroup.setValue({
+    'cb-col-2': false,
+    'cb-col-3': true
+});
+// use comma separated string to set items with name to true (checked)
+myCheckboxGroup.setValue('cb-col-1,cb-col-3');
+     * </code></pre>
+     * See {@link Ext.form.Checkbox#setValue} for additional information.
+     * @param {Mixed} id The checkbox to check, or as described by example shown.
+     * @param {Boolean} value (optional) The value to set the item.
+     * @return {Ext.form.CheckboxGroup} this
      */
-    add : function(){
-        this.items.addAll(Array.prototype.slice.call(arguments, 0));
+    setValue: function(){
+        if(this.rendered){
+            this.onSetValue.apply(this, arguments);
+        }else{
+            this.buffered = true;
+            this.value = arguments;
+        }
         return this;
     },
 
+    onSetValue: function(id, value){
+        if(arguments.length == 1){
+            if(Ext.isArray(id)){
+                // an array of boolean values
+                Ext.each(id, function(val, idx){
+                    var item = this.items.itemAt(idx);
+                    if(item){
+                        item.setValue(val);
+                    }
+                }, this);
+            }else if(Ext.isObject(id)){
+                // set of name/value pairs
+                for(var i in id){
+                    var f = this.getBox(i);
+                    if(f){
+                        f.setValue(id[i]);
+                    }
+                }
+            }else{
+                this.setValueForItem(id);
+            }
+        }else{
+            var f = this.getBox(id);
+            if(f){
+                f.setValue(value);
+            }
+        }
+    },
+
+    // private
+    beforeDestroy: function(){
+        Ext.destroy(this.panel);
+        Ext.form.CheckboxGroup.superclass.beforeDestroy.call(this);
 
-    /**
-     * Removes a field from the items collection (does NOT remove its markup).
-     * @param {Field} field
-     * @return {BasicForm} this
-     */
-    remove : function(field){
-        this.items.remove(field);
-        return this;
     },
 
-    /**
-     * Iterates through the {@link Ext.form.Field Field}s which have been {@link #add add}ed to this BasicForm,
-     * checks them for an id attribute, and calls {@link Ext.form.Field#applyToMarkup} on the existing dom element with that id.
-     * @return {BasicForm} this
-     */
-    render : function(){
-        this.items.each(function(f){
-            if(f.isFormField && !f.rendered && document.getElementById(f.id)){ // if the element exists
-                f.applyToMarkup(f.id);
+    setValueForItem : function(val){
+        val = String(val).split(',');
+        this.eachItem(function(item){
+            if(val.indexOf(item.inputValue)> -1){
+                item.setValue(true);
             }
         });
-        return this;
     },
 
-    /**
-     * Calls {@link Ext#apply} for all fields in this form with the passed object.
-     * @param {Object} values
-     * @return {BasicForm} this
-     */
-    applyToFields : function(o){
-        this.items.each(function(f){
-           Ext.apply(f, o);
+    // private
+    getBox : function(id){
+        var box = null;
+        this.eachItem(function(f){
+            if(id == f || f.dataIndex == id || f.id == id || f.getName() == id){
+                box = f;
+                return false;
+            }
         });
-        return this;
+        return box;
     },
 
     /**
-     * Calls {@link Ext#applyIf} for all field in this form with the passed object.
-     * @param {Object} values
-     * @return {BasicForm} this
+     * Gets an array of the selected {@link Ext.form.Checkbox} in the group.
+     * @return {Array} An array of the selected checkboxes.
      */
-    applyIfToFields : function(o){
-        this.items.each(function(f){
-           Ext.applyIf(f, o);
+    getValue : function(){
+        var out = [];
+        this.eachItem(function(item){
+            if(item.checked){
+                out.push(item);
+            }
         });
-        return this;
+        return out;
     },
 
-    callFieldMethod : function(fnName, args){
-        args = args || [];
-        this.items.each(function(f){
-            if(Ext.isFunction(f[fnName])){
-                f[fnName].apply(f, args);
-            }
-        });
-        return this;
-    }
-});
+    // private
+    eachItem: function(fn){
+        if(this.items && this.items.each){
+            this.items.each(fn, this);
+        }
+    },
 
-// back compat
-Ext.BasicForm = Ext.form.BasicForm;/**
- * @class Ext.form.FormPanel
- * @extends Ext.Panel
- * <p>Standard form container.</p>
- * 
- * <p><b><u>Layout</u></b></p>
- * <p>By default, FormPanel is configured with <tt>layout:'form'</tt> to use an {@link Ext.layout.FormLayout}
- * layout manager, which styles and renders fields and labels correctly. When nesting additional Containers
- * within a FormPanel, you should ensure that any descendant Containers which host input Fields use the
- * {@link Ext.layout.FormLayout} layout manager.</p>
- * 
- * <p><b><u>BasicForm</u></b></p>
- * <p>Although <b>not listed</b> as configuration options of FormPanel, the FormPanel class accepts all
- * of the config options required to configure its internal {@link Ext.form.BasicForm} for:
- * <div class="mdetail-params"><ul>
- * <li>{@link Ext.form.BasicForm#fileUpload file uploads}</li>
- * <li>functionality for {@link Ext.form.BasicForm#doAction loading, validating and submitting} the form</li>
- * </ul></div>
- *  
- * <p><b>Note</b>: If subclassing FormPanel, any configuration options for the BasicForm must be applied to
- * the <tt><b>initialConfig</b></tt> property of the FormPanel. Applying {@link Ext.form.BasicForm BasicForm}
- * configuration settings to <b><tt>this</tt></b> will <b>not</b> affect the BasicForm's configuration.</p>
- * 
- * <p><b><u>Form Validation</u></b></p>
- * <p>For information on form validation see the following:</p>
- * <div class="mdetail-params"><ul>
- * <li>{@link Ext.form.TextField}</li>
- * <li>{@link Ext.form.VTypes}</li>
- * <li>{@link Ext.form.BasicForm#doAction BasicForm.doAction <b>clientValidation</b> notes}</li>
- * <li><tt>{@link Ext.form.FormPanel#monitorValid monitorValid}</tt></li>
- * </ul></div>
- * 
- * <p><b><u>Form Submission</u></b></p>
- * <p>By default, Ext Forms are submitted through Ajax, using {@link Ext.form.Action}. To enable normal browser
- * submission of the {@link Ext.form.BasicForm BasicForm} contained in this FormPanel, see the
- * <tt><b>{@link Ext.form.BasicForm#standardSubmit standardSubmit}</b></tt> option.</p>
- * 
- * @constructor
- * @param {Object} config Configuration options
- * @xtype form
- */
-Ext.FormPanel = Ext.extend(Ext.Panel, {
-       /**
-        * @cfg {String} formId (optional) The id of the FORM tag (defaults to an auto-generated id).
-        */
-    /**
-     * @cfg {Boolean} hideLabels
-     * <p><tt>true</tt> to hide field labels by default (sets <tt>display:none</tt>). Defaults to
-     * <tt>false</tt>.</p>
-     * <p>Also see {@link Ext.Component}.<tt>{@link Ext.Component#hideLabel hideLabel}</tt>.
-     */
     /**
-     * @cfg {Number} labelPad
-     * The default padding in pixels for field labels (defaults to <tt>5</tt>). <tt>labelPad</tt> only
-     * applies if <tt>{@link #labelWidth}</tt> is also specified, otherwise it will be ignored.
+     * @cfg {String} name
+     * @hide
      */
+
     /**
-     * @cfg {String} labelSeparator
-     * See {@link Ext.Component}.<tt>{@link Ext.Component#labelSeparator labelSeparator}</tt>
+     * @method getRawValue
+     * @hide
      */
+    getRawValue : Ext.emptyFn,
+
     /**
-     * @cfg {Number} labelWidth The width of labels in pixels. This property cascades to child containers
-     * and can be overridden on any child container (e.g., a fieldset can specify a different <tt>labelWidth</tt>
-     * for its fields) (defaults to <tt>100</tt>).
+     * @method setRawValue
+     * @hide
      */
+    setRawValue : Ext.emptyFn
+
+});
+
+Ext.reg('checkboxgroup', Ext.form.CheckboxGroup);
+/**
+ * @class Ext.form.Radio
+ * @extends Ext.form.Checkbox
+ * Single radio field.  Same as Checkbox, but provided as a convenience for automatically setting the input type.
+ * Radio grouping is handled automatically by the browser if you give each radio in a group the same name.
+ * @constructor
+ * Creates a new Radio
+ * @param {Object} config Configuration options
+ * @xtype radio
+ */
+Ext.form.Radio = Ext.extend(Ext.form.Checkbox, {
+    inputType: 'radio',
+
     /**
-     * @cfg {String} itemCls A css class to apply to the x-form-item of fields. This property cascades to child containers.
+     * Overridden and disabled. The editor element does not support standard valid/invalid marking. @hide
+     * @method
      */
+    markInvalid : Ext.emptyFn,
     /**
-     * @cfg {Array} buttons
-     * An array of {@link Ext.Button}s or {@link Ext.Button} configs used to add buttons to the footer of this FormPanel.<br>
-     * <p>Buttons in the footer of a FormPanel may be configured with the option <tt>formBind: true</tt>. This causes
-     * the form's {@link #monitorValid valid state monitor task} to enable/disable those Buttons depending on
-     * the form's valid/invalid state.</p>
+     * Overridden and disabled. The editor element does not support standard valid/invalid marking. @hide
+     * @method
      */
-
+    clearInvalid : Ext.emptyFn,
 
     /**
-     * @cfg {Number} minButtonWidth Minimum width of all buttons in pixels (defaults to <tt>75</tt>).
+     * If this radio is part of a group, it will return the selected value
+     * @return {String}
      */
-    minButtonWidth : 75,
+    getGroupValue : function(){
+       var p = this.el.up('form') || Ext.getBody();
+        var c = p.child('input[name='+this.el.dom.name+']:checked', true);
+        return c ? c.value : null;
+    },
+
+    // private
+    onClick : function(){
+       if(this.el.dom.checked != this.checked){
+                       var els = this.getCheckEl().select('input[name=' + this.el.dom.name + ']');
+                       els.each(function(el){
+                               if(el.dom.id == this.id){
+                                       this.setValue(true);
+                               }else{
+                                       Ext.getCmp(el.dom.id).setValue(false);
+                               }
+                       }, this);
+               }
+    },
 
     /**
-     * @cfg {String} labelAlign The label alignment value used for the <tt>text-align</tt> specification
-     * for the <b>container</b>. Valid values are <tt>"left</tt>", <tt>"top"</tt> or <tt>"right"</tt>
-     * (defaults to <tt>"left"</tt>). This property cascades to child <b>containers</b> and can be
-     * overridden on any child <b>container</b> (e.g., a fieldset can specify a different <tt>labelAlign</tt>
-     * for its fields).
+     * Sets either the checked/unchecked status of this Radio, or, if a string value
+     * is passed, checks a sibling Radio of the same name whose value is the value specified.
+     * @param value {String/Boolean} Checked value, or the value of the sibling radio button to check.
+     * @return {Ext.form.Field} this
      */
-    labelAlign : 'left',
+    setValue : function(v){
+       if (typeof v == 'boolean') {
+            Ext.form.Radio.superclass.setValue.call(this, v);
+        } else if (this.rendered) {
+            var r = this.getCheckEl().child('input[name=' + this.el.dom.name + '][value=' + v + ']', true);
+            if(r){
+                Ext.getCmp(r.id).setValue(true);
+            }
+        }
+        return this;
+    },
 
+    // private
+    getCheckEl: function(){
+        if(this.inGroup){
+            return this.el.up('.x-form-radio-group')
+        }
+        return this.el.up('form') || Ext.getBody();
+    }
+});
+Ext.reg('radio', Ext.form.Radio);
+/**
+ * @class Ext.form.RadioGroup
+ * @extends Ext.form.CheckboxGroup
+ * A grouping container for {@link Ext.form.Radio} controls.
+ * @constructor
+ * Creates a new RadioGroup
+ * @param {Object} config Configuration options
+ * @xtype radiogroup
+ */
+Ext.form.RadioGroup = Ext.extend(Ext.form.CheckboxGroup, {
     /**
-     * @cfg {Boolean} monitorValid If <tt>true</tt>, the form monitors its valid state <b>client-side</b> and
-     * regularly fires the {@link #clientvalidation} event passing that state.<br>
-     * <p>When monitoring valid state, the FormPanel enables/disables any of its configured
-     * {@link #buttons} which have been configured with <code>formBind: true</code> depending
-     * on whether the {@link Ext.form.BasicForm#isValid form is valid} or not. Defaults to <tt>false</tt></p>
+     * @cfg {Array} items An Array of {@link Ext.form.Radio Radio}s or Radio config objects
+     * to arrange in the group.
      */
-    monitorValid : false,
-
     /**
-     * @cfg {Number} monitorPoll The milliseconds to poll valid state, ignored if monitorValid is not true (defaults to 200)
+     * @cfg {Boolean} allowBlank True to allow every item in the group to be blank (defaults to true).
+     * If allowBlank = false and no items are selected at validation time, {@link @blankText} will
+     * be used as the error text.
      */
-    monitorPoll : 200,
-
+    allowBlank : true,
     /**
-     * @cfg {String} layout Defaults to <tt>'form'</tt>.  Normally this configuration property should not be altered. 
-     * For additional details see {@link Ext.layout.FormLayout} and {@link Ext.Container#layout Ext.Container.layout}.
+     * @cfg {String} blankText Error text to display if the {@link #allowBlank} validation fails
+     * (defaults to 'You must select one item in this group')
      */
-    layout : 'form',
-
+    blankText : 'You must select one item in this group',
+    
     // private
-    initComponent : function(){
-        this.form = this.createForm();
-        Ext.FormPanel.superclass.initComponent.call(this);
-
-        this.bodyCfg = {
-            tag: 'form',
-            cls: this.baseCls + '-body',
-            method : this.method || 'POST',
-            id : this.formId || Ext.id()
-        };
-        if(this.fileUpload) {
-            this.bodyCfg.enctype = 'multipart/form-data';
-        }
-        this.initItems();
-        
-        this.addEvents(
-            /**
-             * @event clientvalidation
-             * If the monitorValid config option is true, this event fires repetitively to notify of valid state
-             * @param {Ext.form.FormPanel} this
-             * @param {Boolean} valid true if the form has passed client-side validation
-             */
-            'clientvalidation'
-        );
-
-        this.relayEvents(this.form, ['beforeaction', 'actionfailed', 'actioncomplete']);
-    },
-
+    defaultType : 'radio',
+    
     // private
-    createForm : function(){
-        var config = Ext.applyIf({listeners: {}}, this.initialConfig);
-        return new Ext.form.BasicForm(null, config);
+    groupCls : 'x-form-radio-group',
+    
+    /**
+     * @event change
+     * Fires when the state of a child radio changes.
+     * @param {Ext.form.RadioGroup} this
+     * @param {Ext.form.Radio} checked The checked radio
+     */
+    
+    /**
+     * Gets the selected {@link Ext.form.Radio} in the group, if it exists.
+     * @return {Ext.form.Radio} The selected radio.
+     */
+    getValue : function(){
+        var out = null;
+        this.eachItem(function(item){
+            if(item.checked){
+                out = item;
+                return false;
+            }
+        });
+        return out;
     },
-
-    // private
-    initFields : function(){
-        var f = this.form;
-        var formPanel = this;
-        var fn = function(c){
-            if(formPanel.isField(c)){
-                f.add(c);
-            }else if(c.findBy && c != formPanel){
-                formPanel.applySettings(c);
-                //each check required for check/radio groups.
-                if(c.items && c.items.each){
-                    c.items.each(fn, this);
+    
+    /**
+     * Sets the checked radio in the group.
+     * @param {String/Ext.form.Radio} id The radio to check.
+     * @param {Boolean} value The value to set the radio.
+     * @return {Ext.form.RadioGroup} this
+     */
+    onSetValue : function(id, value){
+        if(arguments.length > 1){
+            var f = this.getBox(id);
+            if(f){
+                f.setValue(value);
+                if(f.checked){
+                    this.eachItem(function(item){
+                        if (item !== f){
+                            item.setValue(false);
+                        }
+                    });
                 }
             }
-        };
-        this.items.each(fn, this);
+        }else{
+            this.setValueForItem(id);
+        }
     },
     
-    // private
-    applySettings: function(c){
-        var ct = c.ownerCt;
-        Ext.applyIf(c, {
-            labelAlign: ct.labelAlign,
-            labelWidth: ct.labelWidth,
-            itemCls: ct.itemCls
+    setValueForItem : function(val){
+        val = String(val).split(',')[0];
+        this.eachItem(function(item){
+            item.setValue(val == item.inputValue);
         });
     },
-
-    // private
-    getLayoutTarget : function(){
-        return this.form.el;
-    },
-
-    /**
-     * Provides access to the {@link Ext.form.BasicForm Form} which this Panel contains.
-     * @return {Ext.form.BasicForm} The {@link Ext.form.BasicForm Form} which this Panel contains.
-     */
-    getForm : function(){
-        return this.form;
-    },
-
+    
     // private
-    onRender : function(ct, position){
-        this.initFields();
-        Ext.FormPanel.superclass.onRender.call(this, ct, position);
-        this.form.initEl(this.body);
+    fireChecked : function(){
+        if(!this.checkTask){
+            this.checkTask = new Ext.util.DelayedTask(this.bufferChecked, this);
+        }
+        this.checkTask.delay(10);
     },
     
     // private
-    beforeDestroy : function(){
-        this.stopMonitoring();
-        Ext.FormPanel.superclass.beforeDestroy.call(this);
-        /*
-         * Clear the items here to prevent them being destroyed again.
-         * Don't move this behaviour to BasicForm because it can be used
-         * on it's own.
-         */
-        this.form.items.clear();
-        Ext.destroy(this.form);
+    bufferChecked : function(){
+        var out = null;
+        this.eachItem(function(item){
+            if(item.checked){
+                out = item;
+                return false;
+            }
+        });
+        this.fireEvent('change', this, out);
     },
+    
+    onDestroy : function(){
+        if(this.checkTask){
+            this.checkTask.cancel();
+            this.checkTask = null;
+        }
+        Ext.form.RadioGroup.superclass.onDestroy.call(this);
+    }
 
-       // Determine if a Component is usable as a form Field.
-    isField : function(c) {
-        return !!c.setValue && !!c.getValue && !!c.markInvalid && !!c.clearInvalid;
-    },
+});
 
-    // private
-    initEvents : function(){
-        Ext.FormPanel.superclass.initEvents.call(this);
-        // Listeners are required here to catch bubbling events from children.
-        this.on({
-            scope: this,
-            add: this.onAddEvent,
-            remove: this.onRemoveEvent
+Ext.reg('radiogroup', Ext.form.RadioGroup);
+/**\r
+ * @class Ext.form.Hidden\r
+ * @extends Ext.form.Field\r
+ * A basic hidden field for storing hidden values in forms that need to be passed in the form submit.\r
+ * @constructor\r
+ * Create a new Hidden field.\r
+ * @param {Object} config Configuration options\r
+ * @xtype hidden\r
+ */\r
+Ext.form.Hidden = Ext.extend(Ext.form.Field, {\r
+    // private\r
+    inputType : 'hidden',\r
+\r
+    // private\r
+    onRender : function(){\r
+        Ext.form.Hidden.superclass.onRender.apply(this, arguments);\r
+    },\r
+\r
+    // private\r
+    initEvents : function(){\r
+        this.originalValue = this.getValue();\r
+    },\r
+\r
+    // These are all private overrides\r
+    setSize : Ext.emptyFn,\r
+    setWidth : Ext.emptyFn,\r
+    setHeight : Ext.emptyFn,\r
+    setPosition : Ext.emptyFn,\r
+    setPagePosition : Ext.emptyFn,\r
+    markInvalid : Ext.emptyFn,\r
+    clearInvalid : Ext.emptyFn\r
+});\r
+Ext.reg('hidden', Ext.form.Hidden);/**
+ * @class Ext.form.BasicForm
+ * @extends Ext.util.Observable
+ * <p>Encapsulates the DOM &lt;form> element at the heart of the {@link Ext.form.FormPanel FormPanel} class, and provides
+ * input field management, validation, submission, and form loading services.</p>
+ * <p>By default, Ext Forms are submitted through Ajax, using an instance of {@link Ext.form.Action.Submit}.
+ * To enable normal browser submission of an Ext Form, use the {@link #standardSubmit} config option.</p>
+ * <p><b><u>File Uploads</u></b></p>
+ * <p>{@link #fileUpload File uploads} are not performed using Ajax submission, that
+ * is they are <b>not</b> performed using XMLHttpRequests. Instead the form is submitted in the standard
+ * manner with the DOM <tt>&lt;form></tt> element temporarily modified to have its
+ * <a href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-target">target</a> set to refer
+ * to a dynamically generated, hidden <tt>&lt;iframe></tt> which is inserted into the document
+ * but removed after the return data has been gathered.</p>
+ * <p>The server response is parsed by the browser to create the document for the IFRAME. If the
+ * server is using JSON to send the return object, then the
+ * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17">Content-Type</a> header
+ * must be set to "text/html" in order to tell the browser to insert the text unchanged into the document body.</p>
+ * <p>Characters which are significant to an HTML parser must be sent as HTML entities, so encode
+ * "&lt;" as "&amp;lt;", "&amp;" as "&amp;amp;" etc.</p>
+ * <p>The response text is retrieved from the document, and a fake XMLHttpRequest object
+ * is created containing a <tt>responseText</tt> property in order to conform to the
+ * requirements of event handlers and callbacks.</p>
+ * <p>Be aware that file upload packets are sent with the content type <a href="http://www.faqs.org/rfcs/rfc2388.html">multipart/form</a>
+ * and some server technologies (notably JEE) may require some custom processing in order to
+ * retrieve parameter names and parameter values from the packet content.</p>
+ * @constructor
+ * @param {Mixed} el The form element or its id
+ * @param {Object} config Configuration options
+ */
+Ext.form.BasicForm = Ext.extend(Ext.util.Observable, {
+    
+    constructor: function(el, config){
+        Ext.apply(this, config);
+        if(Ext.isString(this.paramOrder)){
+            this.paramOrder = this.paramOrder.split(/[\s,|]/);
+        }
+        /**
+         * A {@link Ext.util.MixedCollection MixedCollection} containing all the Ext.form.Fields in this form.
+         * @type MixedCollection
+         * @property items
+         */
+        this.items = new Ext.util.MixedCollection(false, function(o){
+            return o.getItemId();
         });
-        if(this.monitorValid){ // initialize after render
-            this.startMonitoring();
+        this.addEvents(
+            /**
+             * @event beforeaction
+             * Fires before any action is performed. Return false to cancel the action.
+             * @param {Form} this
+             * @param {Action} action The {@link Ext.form.Action} to be performed
+             */
+            'beforeaction',
+            /**
+             * @event actionfailed
+             * Fires when an action fails.
+             * @param {Form} this
+             * @param {Action} action The {@link Ext.form.Action} that failed
+             */
+            'actionfailed',
+            /**
+             * @event actioncomplete
+             * Fires when an action is completed.
+             * @param {Form} this
+             * @param {Action} action The {@link Ext.form.Action} that completed
+             */
+            'actioncomplete'
+        );
+
+        if(el){
+            this.initEl(el);
         }
+        Ext.form.BasicForm.superclass.constructor.call(this);    
     },
     
-    // private
-    onAdd: function(c){
-        Ext.FormPanel.superclass.onAdd.call(this, c);  
-        this.processAdd(c);
-    },
+    /**
+     * @cfg {String} method
+     * The request method to use (GET or POST) for form actions if one isn't supplied in the action options.
+     */
+    /**
+     * @cfg {DataReader} reader
+     * An Ext.data.DataReader (e.g. {@link Ext.data.XmlReader}) to be used to read
+     * data when executing 'load' actions. This is optional as there is built-in
+     * support for processing JSON.  For additional information on using an XMLReader
+     * see the example provided in examples/form/xml-form.html.
+     */
+    /**
+     * @cfg {DataReader} errorReader
+     * <p>An Ext.data.DataReader (e.g. {@link Ext.data.XmlReader}) to be used to
+     * read field error messages returned from 'submit' actions. This is optional
+     * as there is built-in support for processing JSON.</p>
+     * <p>The Records which provide messages for the invalid Fields must use the
+     * Field name (or id) as the Record ID, and must contain a field called 'msg'
+     * which contains the error message.</p>
+     * <p>The errorReader does not have to be a full-blown implementation of a
+     * DataReader. It simply needs to implement a <tt>read(xhr)</tt> function
+     * which returns an Array of Records in an object with the following
+     * structure:</p><pre><code>
+{
+    records: recordArray
+}
+</code></pre>
+     */
+    /**
+     * @cfg {String} url
+     * The URL to use for form actions if one isn't supplied in the
+     * <code>{@link #doAction doAction} options</code>.
+     */
+    /**
+     * @cfg {Boolean} fileUpload
+     * Set to true if this form is a file upload.
+     * <p>File uploads are not performed using normal 'Ajax' techniques, that is they are <b>not</b>
+     * performed using XMLHttpRequests. Instead the form is submitted in the standard manner with the
+     * DOM <tt>&lt;form></tt> element temporarily modified to have its
+     * <a href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-target">target</a> set to refer
+     * to a dynamically generated, hidden <tt>&lt;iframe></tt> which is inserted into the document
+     * but removed after the return data has been gathered.</p>
+     * <p>The server response is parsed by the browser to create the document for the IFRAME. If the
+     * server is using JSON to send the return object, then the
+     * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17">Content-Type</a> header
+     * must be set to "text/html" in order to tell the browser to insert the text unchanged into the document body.</p>
+     * <p>Characters which are significant to an HTML parser must be sent as HTML entities, so encode
+     * "&lt;" as "&amp;lt;", "&amp;" as "&amp;amp;" etc.</p>
+     * <p>The response text is retrieved from the document, and a fake XMLHttpRequest object
+     * is created containing a <tt>responseText</tt> property in order to conform to the
+     * requirements of event handlers and callbacks.</p>
+     * <p>Be aware that file upload packets are sent with the content type <a href="http://www.faqs.org/rfcs/rfc2388.html">multipart/form</a>
+     * and some server technologies (notably JEE) may require some custom processing in order to
+     * retrieve parameter names and parameter values from the packet content.</p>
+     */
+    /**
+     * @cfg {Object} baseParams
+     * <p>Parameters to pass with all requests. e.g. baseParams: {id: '123', foo: 'bar'}.</p>
+     * <p>Parameters are encoded as standard HTTP parameters using {@link Ext#urlEncode}.</p>
+     */
+    /**
+     * @cfg {Number} timeout Timeout for form actions in seconds (default is 30 seconds).
+     */
+    timeout: 30,
+
+    /**
+     * @cfg {Object} api (Optional) If specified load and submit actions will be handled
+     * with {@link Ext.form.Action.DirectLoad} and {@link Ext.form.Action.DirectSubmit}.
+     * Methods which have been imported by Ext.Direct can be specified here to load and submit
+     * forms.
+     * Such as the following:<pre><code>
+api: {
+    load: App.ss.MyProfile.load,
+    submit: App.ss.MyProfile.submit
+}
+</code></pre>
+     * <p>Load actions can use <code>{@link #paramOrder}</code> or <code>{@link #paramsAsHash}</code>
+     * to customize how the load method is invoked.
+     * Submit actions will always use a standard form submit. The formHandler configuration must
+     * be set on the associated server-side method which has been imported by Ext.Direct</p>
+     */
+
+    /**
+     * @cfg {Array/String} paramOrder <p>A list of params to be executed server side.
+     * Defaults to <tt>undefined</tt>. Only used for the <code>{@link #api}</code>
+     * <code>load</code> configuration.</p>
+     * <br><p>Specify the params in the order in which they must be executed on the
+     * server-side as either (1) an Array of String values, or (2) a String of params
+     * delimited by either whitespace, comma, or pipe. For example,
+     * any of the following would be acceptable:</p><pre><code>
+paramOrder: ['param1','param2','param3']
+paramOrder: 'param1 param2 param3'
+paramOrder: 'param1,param2,param3'
+paramOrder: 'param1|param2|param'
+     </code></pre>
+     */
+    paramOrder: undefined,
+
+    /**
+     * @cfg {Boolean} paramsAsHash Only used for the <code>{@link #api}</code>
+     * <code>load</code> configuration. Send parameters as a collection of named
+     * arguments (defaults to <tt>false</tt>). Providing a
+     * <tt>{@link #paramOrder}</tt> nullifies this configuration.
+     */
+    paramsAsHash: false,
     
+    /**
+     * @cfg {String} waitTitle
+     * The default title to show for the waiting message box (defaults to <tt>'Please Wait...'</tt>)
+     */
+    waitTitle: 'Please Wait...',
+
     // private
-    onAddEvent: function(ct, c){
-        if(ct !== this){
-            this.processAdd(c);
-        }
+    activeAction : null,
+
+    /**
+     * @cfg {Boolean} trackResetOnLoad If set to <tt>true</tt>, {@link #reset}() resets to the last loaded
+     * or {@link #setValues}() data instead of when the form was first created.  Defaults to <tt>false</tt>.
+     */
+    trackResetOnLoad : false,
+
+    /**
+     * @cfg {Boolean} standardSubmit
+     * <p>If set to <tt>true</tt>, standard HTML form submits are used instead
+     * of XHR (Ajax) style form submissions. Defaults to <tt>false</tt>.</p>
+     * <br><p><b>Note:</b> When using <code>standardSubmit</code>, the
+     * <code>options</code> to <code>{@link #submit}</code> are ignored because
+     * Ext's Ajax infrastracture is bypassed. To pass extra parameters (e.g.
+     * <code>baseParams</code> and <code>params</code>), utilize hidden fields
+     * to submit extra data, for example:</p>
+     * <pre><code>
+new Ext.FormPanel({
+    standardSubmit: true,
+    baseParams: {
+        foo: 'bar'
     },
-    
+    {@link url}: 'myProcess.php',
+    items: [{
+        xtype: 'textfield',
+        name: 'userName'
+    }],
+    buttons: [{
+        text: 'Save',
+        handler: function(){
+            var fp = this.ownerCt.ownerCt,
+                form = fp.getForm();
+            if (form.isValid()) {
+                // check if there are baseParams and if
+                // hiddent items have been added already
+                if (fp.baseParams && !fp.paramsAdded) {
+                    // add hidden items for all baseParams
+                    for (i in fp.baseParams) {
+                        fp.add({
+                            xtype: 'hidden',
+                            name: i,
+                            value: fp.baseParams[i]
+                        });
+                    }
+                    fp.doLayout();
+                    // set a custom flag to prevent re-adding
+                    fp.paramsAdded = true;
+                }
+                form.{@link #submit}();
+            }
+        }
+    }]
+});
+     * </code></pre>
+     */
+    /**
+     * By default wait messages are displayed with Ext.MessageBox.wait. You can target a specific
+     * element by passing it or its id or mask the form itself by passing in true.
+     * @type Mixed
+     * @property waitMsgTarget
+     */
+
     // private
-    processAdd : function(c){
-               // If a single form Field, add it
-        if(this.isField(c)){
-            this.form.add(c);
-               // If a Container, add any Fields it might contain
-        }else if(c.findBy){
-            this.applySettings(c);
-            this.form.add.apply(this.form, c.findBy(this.isField));
+    initEl : function(el){
+        this.el = Ext.get(el);
+        this.id = this.el.id || Ext.id();
+        if(!this.standardSubmit){
+            this.el.on('submit', this.onSubmit, this);
         }
+        this.el.addClass('x-form');
     },
-    
-    // private
-    onRemove: function(c){
-        Ext.FormPanel.superclass.onRemove.call(this, c);
-        this.processRemove(c);
+
+    /**
+     * Get the HTML form Element
+     * @return Ext.Element
+     */
+    getEl: function(){
+        return this.el;
     },
-    
-    onRemoveEvent: function(ct, c){
-        if(ct !== this){
-            this.processRemove(c);
-        }
+
+    // private
+    onSubmit : function(e){
+        e.stopEvent();
     },
-       
+
     // private
-    processRemove : function(c){
-               // If a single form Field, remove it
-        if(this.isField(c)){
-               this.form.remove(c);
-               // If a Container, remove any Fields it might contain
-        }else if(c.findBy){
-            Ext.each(c.findBy(this.isField), this.form.remove, this.form);
+    destroy: function() {
+        this.items.each(function(f){
+            Ext.destroy(f);
+        });
+        if(this.el){
+            this.el.removeAllListeners();
+            this.el.remove();
         }
+        this.purgeListeners();
     },
 
     /**
-     * Starts monitoring of the valid state of this form. Usually this is done by passing the config
-     * option "monitorValid"
+     * Returns true if client-side validation on the form is successful.
+     * @return Boolean
      */
-    startMonitoring : function(){
-        if(!this.validTask){
-            this.validTask = new Ext.util.TaskRunner();
-            this.validTask.start({
-                run : this.bindHandler,
-                interval : this.monitorPoll || 200,
-                scope: this
-            });
-        }
+    isValid : function(){
+        var valid = true;
+        this.items.each(function(f){
+           if(!f.validate()){
+               valid = false;
+           }
+        });
+        return valid;
     },
 
     /**
-     * Stops monitoring of the valid state of this form
+     * <p>Returns true if any fields in this form have changed from their original values.</p>
+     * <p>Note that if this BasicForm was configured with {@link #trackResetOnLoad} then the
+     * Fields' <i>original values</i> are updated when the values are loaded by {@link #setValues}
+     * or {@link #loadRecord}.</p>
+     * @return Boolean
      */
-    stopMonitoring : function(){
-        if(this.validTask){
-            this.validTask.stopAll();
-            this.validTask = null;
-        }
+    isDirty : function(){
+        var dirty = false;
+        this.items.each(function(f){
+           if(f.isDirty()){
+               dirty = true;
+               return false;
+           }
+        });
+        return dirty;
     },
 
     /**
-     * This is a proxy for the underlying BasicForm's {@link Ext.form.BasicForm#load} call.
-     * @param {Object} options The options to pass to the action (see {@link Ext.form.BasicForm#doAction} for details)
+     * Performs a predefined action ({@link Ext.form.Action.Submit} or
+     * {@link Ext.form.Action.Load}) or a custom extension of {@link Ext.form.Action}
+     * to perform application-specific processing.
+     * @param {String/Object} actionName The name of the predefined action type,
+     * or instance of {@link Ext.form.Action} to perform.
+     * @param {Object} options (optional) The options to pass to the {@link Ext.form.Action}.
+     * All of the config options listed below are supported by both the
+     * {@link Ext.form.Action.Submit submit} and {@link Ext.form.Action.Load load}
+     * actions unless otherwise noted (custom actions could also accept
+     * other config options):<ul>
+     *
+     * <li><b>url</b> : String<div class="sub-desc">The url for the action (defaults
+     * to the form's {@link #url}.)</div></li>
+     *
+     * <li><b>method</b> : String<div class="sub-desc">The form method to use (defaults
+     * to the form's method, or POST if not defined)</div></li>
+     *
+     * <li><b>params</b> : String/Object<div class="sub-desc"><p>The params to pass
+     * (defaults to the form's baseParams, or none if not defined)</p>
+     * <p>Parameters are encoded as standard HTTP parameters using {@link Ext#urlEncode}.</p></div></li>
+     *
+     * <li><b>headers</b> : Object<div class="sub-desc">Request headers to set for the action
+     * (defaults to the form's default headers)</div></li>
+     *
+     * <li><b>success</b> : Function<div class="sub-desc">The callback that will
+     * be invoked after a successful response (see top of
+     * {@link Ext.form.Action.Submit submit} and {@link Ext.form.Action.Load load}
+     * for a description of what constitutes a successful response).
+     * The function is passed the following parameters:<ul>
+     * <li><tt>form</tt> : Ext.form.BasicForm<div class="sub-desc">The form that requested the action</div></li>
+     * <li><tt>action</tt> : The {@link Ext.form.Action Action} object which performed the operation.
+     * <div class="sub-desc">The action object contains these properties of interest:<ul>
+     * <li><tt>{@link Ext.form.Action#response response}</tt></li>
+     * <li><tt>{@link Ext.form.Action#result result}</tt> : interrogate for custom postprocessing</li>
+     * <li><tt>{@link Ext.form.Action#type type}</tt></li>
+     * </ul></div></li></ul></div></li>
+     *
+     * <li><b>failure</b> : Function<div class="sub-desc">The callback that will be invoked after a
+     * failed transaction attempt. The function is passed the following parameters:<ul>
+     * <li><tt>form</tt> : The {@link Ext.form.BasicForm} that requested the action.</li>
+     * <li><tt>action</tt> : The {@link Ext.form.Action Action} object which performed the operation.
+     * <div class="sub-desc">The action object contains these properties of interest:<ul>
+     * <li><tt>{@link Ext.form.Action#failureType failureType}</tt></li>
+     * <li><tt>{@link Ext.form.Action#response response}</tt></li>
+     * <li><tt>{@link Ext.form.Action#result result}</tt> : interrogate for custom postprocessing</li>
+     * <li><tt>{@link Ext.form.Action#type type}</tt></li>
+     * </ul></div></li></ul></div></li>
+     *
+     * <li><b>scope</b> : Object<div class="sub-desc">The scope in which to call the
+     * callback functions (The <tt>this</tt> reference for the callback functions).</div></li>
+     *
+     * <li><b>clientValidation</b> : Boolean<div class="sub-desc">Submit Action only.
+     * Determines whether a Form's fields are validated in a final call to
+     * {@link Ext.form.BasicForm#isValid isValid} prior to submission. Set to <tt>false</tt>
+     * to prevent this. If undefined, pre-submission field validation is performed.</div></li></ul>
+     *
+     * @return {BasicForm} this
      */
-    load : function(){
-        this.form.load.apply(this.form, arguments);  
-    },
-
-    // private
-    onDisable : function(){
-        Ext.FormPanel.superclass.onDisable.call(this);
-        if(this.form){
-            this.form.items.each(function(){
-                 this.disable();
-            });
+    doAction : function(action, options){
+        if(Ext.isString(action)){
+            action = new Ext.form.Action.ACTION_TYPES[action](this, options);
         }
-    },
-
-    // private
-    onEnable : function(){
-        Ext.FormPanel.superclass.onEnable.call(this);
-        if(this.form){
-            this.form.items.each(function(){
-                 this.enable();
-            });
+        if(this.fireEvent('beforeaction', this, action) !== false){
+            this.beforeAction(action);
+            action.run.defer(100, action);
         }
+        return this;
     },
 
-    // private
-    bindHandler : function(){
-        var valid = true;
-        this.form.items.each(function(f){
-            if(!f.isValid(true)){
-                valid = false;
-                return false;
-            }
-        });
-        if(this.fbar){
-            var fitems = this.fbar.items.items;
-            for(var i = 0, len = fitems.length; i < len; i++){
-                var btn = fitems[i];
-                if(btn.formBind === true && btn.disabled === valid){
-                    btn.setDisabled(!valid);
+    /**
+     * Shortcut to {@link #doAction do} a {@link Ext.form.Action.Submit submit action}.
+     * @param {Object} options The options to pass to the action (see {@link #doAction} for details).<br>
+     * <p><b>Note:</b> this is ignored when using the {@link #standardSubmit} option.</p>
+     * <p>The following code:</p><pre><code>
+myFormPanel.getForm().submit({
+    clientValidation: true,
+    url: 'updateConsignment.php',
+    params: {
+        newStatus: 'delivered'
+    },
+    success: function(form, action) {
+       Ext.Msg.alert('Success', action.result.msg);
+    },
+    failure: function(form, action) {
+        switch (action.failureType) {
+            case Ext.form.Action.CLIENT_INVALID:
+                Ext.Msg.alert('Failure', 'Form fields may not be submitted with invalid values');
+                break;
+            case Ext.form.Action.CONNECT_FAILURE:
+                Ext.Msg.alert('Failure', 'Ajax communication failed');
+                break;
+            case Ext.form.Action.SERVER_INVALID:
+               Ext.Msg.alert('Failure', action.result.msg);
+       }
+    }
+});
+</code></pre>
+     * would process the following server response for a successful submission:<pre><code>
+{
+    "success":true, // note this is Boolean, not string
+    "msg":"Consignment updated"
+}
+</code></pre>
+     * and the following server response for a failed submission:<pre><code>
+{
+    "success":false, // note this is Boolean, not string
+    "msg":"You do not have permission to perform this operation"
+}
+</code></pre>
+     * @return {BasicForm} this
+     */
+    submit : function(options){
+        if(this.standardSubmit){
+            var v = this.isValid();
+            if(v){
+                var el = this.el.dom;
+                if(this.url && Ext.isEmpty(el.action)){
+                    el.action = this.url;
                 }
+                el.submit();
             }
+            return v;
         }
-        this.fireEvent('clientvalidation', this, valid);
-    }
-});
-Ext.reg('form', Ext.FormPanel);
-
-Ext.form.FormPanel = Ext.FormPanel;
+        var submitAction = String.format('{0}submit', this.api ? 'direct' : '');
+        this.doAction(submitAction, options);
+        return this;
+    },
 
+    /**
+     * Shortcut to {@link #doAction do} a {@link Ext.form.Action.Load load action}.
+     * @param {Object} options The options to pass to the action (see {@link #doAction} for details)
+     * @return {BasicForm} this
+     */
+    load : function(options){
+        var loadAction = String.format('{0}load', this.api ? 'direct' : '');
+        this.doAction(loadAction, options);
+        return this;
+    },
+
+    /**
+     * Persists the values in this form into the passed {@link Ext.data.Record} object in a beginEdit/endEdit block.
+     * @param {Record} record The record to edit
+     * @return {BasicForm} this
+     */
+    updateRecord : function(record){
+        record.beginEdit();
+        var fs = record.fields;
+        fs.each(function(f){
+            var field = this.findField(f.name);
+            if(field){
+                record.set(f.name, field.getValue());
+            }
+        }, this);
+        record.endEdit();
+        return this;
+    },
+
+    /**
+     * Loads an {@link Ext.data.Record} into this form by calling {@link #setValues} with the
+     * {@link Ext.data.Record#data record data}.
+     * See also {@link #trackResetOnLoad}.
+     * @param {Record} record The record to load
+     * @return {BasicForm} this
+     */
+    loadRecord : function(record){
+        this.setValues(record.data);
+        return this;
+    },
+
+    // private
+    beforeAction : function(action){
+        var o = action.options;
+        if(o.waitMsg){
+            if(this.waitMsgTarget === true){
+                this.el.mask(o.waitMsg, 'x-mask-loading');
+            }else if(this.waitMsgTarget){
+                this.waitMsgTarget = Ext.get(this.waitMsgTarget);
+                this.waitMsgTarget.mask(o.waitMsg, 'x-mask-loading');
+            }else{
+                Ext.MessageBox.wait(o.waitMsg, o.waitTitle || this.waitTitle);
+            }
+        }
+    },
+
+    // private
+    afterAction : function(action, success){
+        this.activeAction = null;
+        var o = action.options;
+        if(o.waitMsg){
+            if(this.waitMsgTarget === true){
+                this.el.unmask();
+            }else if(this.waitMsgTarget){
+                this.waitMsgTarget.unmask();
+            }else{
+                Ext.MessageBox.updateProgress(1);
+                Ext.MessageBox.hide();
+            }
+        }
+        if(success){
+            if(o.reset){
+                this.reset();
+            }
+            Ext.callback(o.success, o.scope, [this, action]);
+            this.fireEvent('actioncomplete', this, action);
+        }else{
+            Ext.callback(o.failure, o.scope, [this, action]);
+            this.fireEvent('actionfailed', this, action);
+        }
+    },
+
+    /**
+     * Find a {@link Ext.form.Field} in this form.
+     * @param {String} id The value to search for (specify either a {@link Ext.Component#id id},
+     * {@link Ext.grid.Column#dataIndex dataIndex}, {@link Ext.form.Field#getName name or hiddenName}).
+     * @return Field
+     */
+    findField : function(id){
+        var field = this.items.get(id);
+        if(!Ext.isObject(field)){
+            this.items.each(function(f){
+                if(f.isFormField && (f.dataIndex == id || f.id == id || f.getName() == id)){
+                    field = f;
+                    return false;
+                }
+            });
+        }
+        return field || null;
+    },
+
+
+    /**
+     * Mark fields in this form invalid in bulk.
+     * @param {Array/Object} errors Either an array in the form [{id:'fieldId', msg:'The message'},...] or an object hash of {id: msg, id2: msg2}
+     * @return {BasicForm} this
+     */
+    markInvalid : function(errors){
+        if(Ext.isArray(errors)){
+            for(var i = 0, len = errors.length; i < len; i++){
+                var fieldError = errors[i];
+                var f = this.findField(fieldError.id);
+                if(f){
+                    f.markInvalid(fieldError.msg);
+                }
+            }
+        }else{
+            var field, id;
+            for(id in errors){
+                if(!Ext.isFunction(errors[id]) && (field = this.findField(id))){
+                    field.markInvalid(errors[id]);
+                }
+            }
+        }
+        return this;
+    },
+
+    /**
+     * Set values for fields in this form in bulk.
+     * @param {Array/Object} values Either an array in the form:<pre><code>
+[{id:'clientName', value:'Fred. Olsen Lines'},
+ {id:'portOfLoading', value:'FXT'},
+ {id:'portOfDischarge', value:'OSL'} ]</code></pre>
+     * or an object hash of the form:<pre><code>
+{
+    clientName: 'Fred. Olsen Lines',
+    portOfLoading: 'FXT',
+    portOfDischarge: 'OSL'
+}</code></pre>
+     * @return {BasicForm} this
+     */
+    setValues : function(values){
+        if(Ext.isArray(values)){ // array of objects
+            for(var i = 0, len = values.length; i < len; i++){
+                var v = values[i];
+                var f = this.findField(v.id);
+                if(f){
+                    f.setValue(v.value);
+                    if(this.trackResetOnLoad){
+                        f.originalValue = f.getValue();
+                    }
+                }
+            }
+        }else{ // object hash
+            var field, id;
+            for(id in values){
+                if(!Ext.isFunction(values[id]) && (field = this.findField(id))){
+                    field.setValue(values[id]);
+                    if(this.trackResetOnLoad){
+                        field.originalValue = field.getValue();
+                    }
+                }
+            }
+        }
+        return this;
+    },
+
+    /**
+     * <p>Returns the fields in this form as an object with key/value pairs as they would be submitted using a standard form submit.
+     * If multiple fields exist with the same name they are returned as an array.</p>
+     * <p><b>Note:</b> The values are collected from all enabled HTML input elements within the form, <u>not</u> from
+     * the Ext Field objects. This means that all returned values are Strings (or Arrays of Strings) and that the
+     * value can potentially be the emptyText of a field.</p>
+     * @param {Boolean} asString (optional) Pass true to return the values as a string. (defaults to false, returning an Object)
+     * @return {String/Object}
+     */
+    getValues : function(asString){
+        var fs = Ext.lib.Ajax.serializeForm(this.el.dom);
+        if(asString === true){
+            return fs;
+        }
+        return Ext.urlDecode(fs);
+    },
+
+    /**
+     * Retrieves the fields in the form as a set of key/value pairs, using the {@link Ext.form.Field#getValue getValue()} method.
+     * If multiple fields exist with the same name they are returned as an array.
+     * @param {Boolean} dirtyOnly (optional) True to return only fields that are dirty.
+     * @return {Object} The values in the form
+     */
+    getFieldValues : function(dirtyOnly){
+        var o = {},
+            n,
+            key,
+            val;
+        this.items.each(function(f){
+            if(dirtyOnly !== true || f.isDirty()){
+                n = f.getName();
+                key = o[n];
+                val = f.getValue();
+                
+                if(Ext.isDefined(key)){
+                    if(Ext.isArray(key)){
+                        o[n].push(val);
+                    }else{
+                        o[n] = [key, val];
+                    }
+                }else{
+                    o[n] = val;
+                }
+            }
+        });
+        return o;
+    },
+
+    /**
+     * Clears all invalid messages in this form.
+     * @return {BasicForm} this
+     */
+    clearInvalid : function(){
+        this.items.each(function(f){
+           f.clearInvalid();
+        });
+        return this;
+    },
+
+    /**
+     * Resets this form.
+     * @return {BasicForm} this
+     */
+    reset : function(){
+        this.items.each(function(f){
+            f.reset();
+        });
+        return this;
+    },
+
+    /**
+     * Add Ext.form Components to this form's Collection. This does not result in rendering of
+     * the passed Component, it just enables the form to validate Fields, and distribute values to
+     * Fields.
+     * <p><b>You will not usually call this function. In order to be rendered, a Field must be added
+     * to a {@link Ext.Container Container}, usually an {@link Ext.form.FormPanel FormPanel}.
+     * The FormPanel to which the field is added takes care of adding the Field to the BasicForm's
+     * collection.</b></p>
+     * @param {Field} field1
+     * @param {Field} field2 (optional)
+     * @param {Field} etc (optional)
+     * @return {BasicForm} this
+     */
+    add : function(){
+        this.items.addAll(Array.prototype.slice.call(arguments, 0));
+        return this;
+    },
+
+
+    /**
+     * Removes a field from the items collection (does NOT remove its markup).
+     * @param {Field} field
+     * @return {BasicForm} this
+     */
+    remove : function(field){
+        this.items.remove(field);
+        return this;
+    },
+
+    /**
+     * Iterates through the {@link Ext.form.Field Field}s which have been {@link #add add}ed to this BasicForm,
+     * checks them for an id attribute, and calls {@link Ext.form.Field#applyToMarkup} on the existing dom element with that id.
+     * @return {BasicForm} this
+     */
+    render : function(){
+        this.items.each(function(f){
+            if(f.isFormField && !f.rendered && document.getElementById(f.id)){ // if the element exists
+                f.applyToMarkup(f.id);
+            }
+        });
+        return this;
+    },
+
+    /**
+     * Calls {@link Ext#apply} for all fields in this form with the passed object.
+     * @param {Object} values
+     * @return {BasicForm} this
+     */
+    applyToFields : function(o){
+        this.items.each(function(f){
+           Ext.apply(f, o);
+        });
+        return this;
+    },
+
+    /**
+     * Calls {@link Ext#applyIf} for all field in this form with the passed object.
+     * @param {Object} values
+     * @return {BasicForm} this
+     */
+    applyIfToFields : function(o){
+        this.items.each(function(f){
+           Ext.applyIf(f, o);
+        });
+        return this;
+    },
+
+    callFieldMethod : function(fnName, args){
+        args = args || [];
+        this.items.each(function(f){
+            if(Ext.isFunction(f[fnName])){
+                f[fnName].apply(f, args);
+            }
+        });
+        return this;
+    }
+});
+
+// back compat
+Ext.BasicForm = Ext.form.BasicForm;/**
+ * @class Ext.form.FormPanel
+ * @extends Ext.Panel
+ * <p>Standard form container.</p>
+ *
+ * <p><b><u>Layout</u></b></p>
+ * <p>By default, FormPanel is configured with <tt>layout:'form'</tt> to use an {@link Ext.layout.FormLayout}
+ * layout manager, which styles and renders fields and labels correctly. When nesting additional Containers
+ * within a FormPanel, you should ensure that any descendant Containers which host input Fields use the
+ * {@link Ext.layout.FormLayout} layout manager.</p>
+ *
+ * <p><b><u>BasicForm</u></b></p>
+ * <p>Although <b>not listed</b> as configuration options of FormPanel, the FormPanel class accepts all
+ * of the config options required to configure its internal {@link Ext.form.BasicForm} for:
+ * <div class="mdetail-params"><ul>
+ * <li>{@link Ext.form.BasicForm#fileUpload file uploads}</li>
+ * <li>functionality for {@link Ext.form.BasicForm#doAction loading, validating and submitting} the form</li>
+ * </ul></div>
+ *
+ * <p><b>Note</b>: If subclassing FormPanel, any configuration options for the BasicForm must be applied to
+ * the <tt><b>initialConfig</b></tt> property of the FormPanel. Applying {@link Ext.form.BasicForm BasicForm}
+ * configuration settings to <b><tt>this</tt></b> will <b>not</b> affect the BasicForm's configuration.</p>
+ *
+ * <p><b><u>Form Validation</u></b></p>
+ * <p>For information on form validation see the following:</p>
+ * <div class="mdetail-params"><ul>
+ * <li>{@link Ext.form.TextField}</li>
+ * <li>{@link Ext.form.VTypes}</li>
+ * <li>{@link Ext.form.BasicForm#doAction BasicForm.doAction <b>clientValidation</b> notes}</li>
+ * <li><tt>{@link Ext.form.FormPanel#monitorValid monitorValid}</tt></li>
+ * </ul></div>
+ *
+ * <p><b><u>Form Submission</u></b></p>
+ * <p>By default, Ext Forms are submitted through Ajax, using {@link Ext.form.Action}. To enable normal browser
+ * submission of the {@link Ext.form.BasicForm BasicForm} contained in this FormPanel, see the
+ * <tt><b>{@link Ext.form.BasicForm#standardSubmit standardSubmit}</b></tt> option.</p>
+ *
+ * @constructor
+ * @param {Object} config Configuration options
+ * @xtype form
+ */
+Ext.FormPanel = Ext.extend(Ext.Panel, {
+    /**
+     * @cfg {String} formId (optional) The id of the FORM tag (defaults to an auto-generated id).
+     */
+    /**
+     * @cfg {Boolean} hideLabels
+     * <p><tt>true</tt> to hide field labels by default (sets <tt>display:none</tt>). Defaults to
+     * <tt>false</tt>.</p>
+     * <p>Also see {@link Ext.Component}.<tt>{@link Ext.Component#hideLabel hideLabel}</tt>.
+     */
+    /**
+     * @cfg {Number} labelPad
+     * The default padding in pixels for field labels (defaults to <tt>5</tt>). <tt>labelPad</tt> only
+     * applies if <tt>{@link #labelWidth}</tt> is also specified, otherwise it will be ignored.
+     */
+    /**
+     * @cfg {String} labelSeparator
+     * See {@link Ext.Component}.<tt>{@link Ext.Component#labelSeparator labelSeparator}</tt>
+     */
+    /**
+     * @cfg {Number} labelWidth The width of labels in pixels. This property cascades to child containers
+     * and can be overridden on any child container (e.g., a fieldset can specify a different <tt>labelWidth</tt>
+     * for its fields) (defaults to <tt>100</tt>).
+     */
+    /**
+     * @cfg {String} itemCls A css class to apply to the x-form-item of fields. This property cascades to child containers.
+     */
+    /**
+     * @cfg {Array} buttons
+     * An array of {@link Ext.Button}s or {@link Ext.Button} configs used to add buttons to the footer of this FormPanel.<br>
+     * <p>Buttons in the footer of a FormPanel may be configured with the option <tt>formBind: true</tt>. This causes
+     * the form's {@link #monitorValid valid state monitor task} to enable/disable those Buttons depending on
+     * the form's valid/invalid state.</p>
+     */
+
+
+    /**
+     * @cfg {Number} minButtonWidth Minimum width of all buttons in pixels (defaults to <tt>75</tt>).
+     */
+    minButtonWidth : 75,
+
+    /**
+     * @cfg {String} labelAlign The label alignment value used for the <tt>text-align</tt> specification
+     * for the <b>container</b>. Valid values are <tt>"left</tt>", <tt>"top"</tt> or <tt>"right"</tt>
+     * (defaults to <tt>"left"</tt>). This property cascades to child <b>containers</b> and can be
+     * overridden on any child <b>container</b> (e.g., a fieldset can specify a different <tt>labelAlign</tt>
+     * for its fields).
+     */
+    labelAlign : 'left',
+
+    /**
+     * @cfg {Boolean} monitorValid If <tt>true</tt>, the form monitors its valid state <b>client-side</b> and
+     * regularly fires the {@link #clientvalidation} event passing that state.<br>
+     * <p>When monitoring valid state, the FormPanel enables/disables any of its configured
+     * {@link #buttons} which have been configured with <code>formBind: true</code> depending
+     * on whether the {@link Ext.form.BasicForm#isValid form is valid} or not. Defaults to <tt>false</tt></p>
+     */
+    monitorValid : false,
+
+    /**
+     * @cfg {Number} monitorPoll The milliseconds to poll valid state, ignored if monitorValid is not true (defaults to 200)
+     */
+    monitorPoll : 200,
+
+    /**
+     * @cfg {String} layout Defaults to <tt>'form'</tt>.  Normally this configuration property should not be altered.
+     * For additional details see {@link Ext.layout.FormLayout} and {@link Ext.Container#layout Ext.Container.layout}.
+     */
+    layout : 'form',
+
+    // private
+    initComponent : function(){
+        this.form = this.createForm();
+        Ext.FormPanel.superclass.initComponent.call(this);
+
+        this.bodyCfg = {
+            tag: 'form',
+            cls: this.baseCls + '-body',
+            method : this.method || 'POST',
+            id : this.formId || Ext.id()
+        };
+        if(this.fileUpload) {
+            this.bodyCfg.enctype = 'multipart/form-data';
+        }
+        this.initItems();
+
+        this.addEvents(
+            /**
+             * @event clientvalidation
+             * If the monitorValid config option is true, this event fires repetitively to notify of valid state
+             * @param {Ext.form.FormPanel} this
+             * @param {Boolean} valid true if the form has passed client-side validation
+             */
+            'clientvalidation'
+        );
+
+        this.relayEvents(this.form, ['beforeaction', 'actionfailed', 'actioncomplete']);
+    },
+
+    // private
+    createForm : function(){
+        var config = Ext.applyIf({listeners: {}}, this.initialConfig);
+        return new Ext.form.BasicForm(null, config);
+    },
+
+    // private
+    initFields : function(){
+        var f = this.form;
+        var formPanel = this;
+        var fn = function(c){
+            if(formPanel.isField(c)){
+                f.add(c);
+            }else if(c.findBy && c != formPanel){
+                formPanel.applySettings(c);
+                //each check required for check/radio groups.
+                if(c.items && c.items.each){
+                    c.items.each(fn, this);
+                }
+            }
+        };
+        this.items.each(fn, this);
+    },
+
+    // private
+    applySettings: function(c){
+        var ct = c.ownerCt;
+        Ext.applyIf(c, {
+            labelAlign: ct.labelAlign,
+            labelWidth: ct.labelWidth,
+            itemCls: ct.itemCls
+        });
+    },
+
+    // private
+    getLayoutTarget : function(){
+        return this.form.el;
+    },
+
+    /**
+     * Provides access to the {@link Ext.form.BasicForm Form} which this Panel contains.
+     * @return {Ext.form.BasicForm} The {@link Ext.form.BasicForm Form} which this Panel contains.
+     */
+    getForm : function(){
+        return this.form;
+    },
+
+    // private
+    onRender : function(ct, position){
+        this.initFields();
+        Ext.FormPanel.superclass.onRender.call(this, ct, position);
+        this.form.initEl(this.body);
+    },
+
+    // private
+    beforeDestroy : function(){
+        this.stopMonitoring();
+        /*
+         * Don't move this behaviour to BasicForm because it can be used
+         * on it's own.
+         */
+        Ext.destroy(this.form);
+        this.form.items.clear();
+        Ext.FormPanel.superclass.beforeDestroy.call(this);
+    },
+
+    // Determine if a Component is usable as a form Field.
+    isField : function(c) {
+        return !!c.setValue && !!c.getValue && !!c.markInvalid && !!c.clearInvalid;
+    },
+
+    // private
+    initEvents : function(){
+        Ext.FormPanel.superclass.initEvents.call(this);
+        // Listeners are required here to catch bubbling events from children.
+        this.on({
+            scope: this,
+            add: this.onAddEvent,
+            remove: this.onRemoveEvent
+        });
+        if(this.monitorValid){ // initialize after render
+            this.startMonitoring();
+        }
+    },
+
+    // private
+    onAdd: function(c){
+        Ext.FormPanel.superclass.onAdd.call(this, c);
+        this.processAdd(c);
+    },
+
+    // private
+    onAddEvent: function(ct, c){
+        if(ct !== this){
+            this.processAdd(c);
+        }
+    },
+
+    // private
+    processAdd : function(c){
+        // If a single form Field, add it
+        if(this.isField(c)){
+            this.form.add(c);
+        // If a Container, add any Fields it might contain
+        }else if(c.findBy){
+            this.applySettings(c);
+            this.form.add.apply(this.form, c.findBy(this.isField));
+        }
+    },
+
+    // private
+    onRemove: function(c){
+        Ext.FormPanel.superclass.onRemove.call(this, c);
+        this.processRemove(c);
+    },
+
+    onRemoveEvent: function(ct, c){
+        if(ct !== this){
+            this.processRemove(c);
+        }
+    },
+
+    // private
+    processRemove : function(c){
+        // If a single form Field, remove it
+        if(this.isField(c)){
+            this.form.remove(c);
+        // If a Container, its already destroyed by the time it gets here.  Remove any references to destroyed fields.
+        }else if(c.findBy){
+            var isDestroyed = function(o) {
+                return !!o.isDestroyed;
+            }
+            this.form.items.filterBy(isDestroyed, this.form).each(this.form.remove, this.form);
+        }
+    },
+
+    /**
+     * Starts monitoring of the valid state of this form. Usually this is done by passing the config
+     * option "monitorValid"
+     */
+    startMonitoring : function(){
+        if(!this.validTask){
+            this.validTask = new Ext.util.TaskRunner();
+            this.validTask.start({
+                run : this.bindHandler,
+                interval : this.monitorPoll || 200,
+                scope: this
+            });
+        }
+    },
+
+    /**
+     * Stops monitoring of the valid state of this form
+     */
+    stopMonitoring : function(){
+        if(this.validTask){
+            this.validTask.stopAll();
+            this.validTask = null;
+        }
+    },
+
+    /**
+     * This is a proxy for the underlying BasicForm's {@link Ext.form.BasicForm#load} call.
+     * @param {Object} options The options to pass to the action (see {@link Ext.form.BasicForm#doAction} for details)
+     */
+    load : function(){
+        this.form.load.apply(this.form, arguments);
+    },
+
+    // private
+    onDisable : function(){
+        Ext.FormPanel.superclass.onDisable.call(this);
+        if(this.form){
+            this.form.items.each(function(){
+                 this.disable();
+            });
+        }
+    },
+
+    // private
+    onEnable : function(){
+        Ext.FormPanel.superclass.onEnable.call(this);
+        if(this.form){
+            this.form.items.each(function(){
+                 this.enable();
+            });
+        }
+    },
+
+    // private
+    bindHandler : function(){
+        var valid = true;
+        this.form.items.each(function(f){
+            if(!f.isValid(true)){
+                valid = false;
+                return false;
+            }
+        });
+        if(this.fbar){
+            var fitems = this.fbar.items.items;
+            for(var i = 0, len = fitems.length; i < len; i++){
+                var btn = fitems[i];
+                if(btn.formBind === true && btn.disabled === valid){
+                    btn.setDisabled(!valid);
+                }
+            }
+        }
+        this.fireEvent('clientvalidation', this, valid);
+    }
+});
+Ext.reg('form', Ext.FormPanel);
+
+Ext.form.FormPanel = Ext.FormPanel;
 /**\r
- * @class Ext.form.FieldSet\r
- * @extends Ext.Panel\r
- * Standard container used for grouping items within a {@link Ext.form.FormPanel form}.\r
- * <pre><code>\r
-var form = new Ext.FormPanel({\r
-    title: 'Simple Form with FieldSets',\r
-    labelWidth: 75, // label settings here cascade unless overridden\r
-    url: 'save-form.php',\r
-    frame:true,\r
-    bodyStyle:'padding:5px 5px 0',\r
-    width: 700,\r
-    renderTo: document.body,\r
-    layout:'column', // arrange items in columns\r
-    defaults: {      // defaults applied to items\r
-        layout: 'form',\r
-        border: false,\r
-        bodyStyle: 'padding:4px'\r
-    },\r
-    items: [{\r
-        // Fieldset in Column 1\r
-        xtype:'fieldset',\r
-        columnWidth: 0.5,\r
-        title: 'Fieldset 1',\r
-        collapsible: true,\r
-        autoHeight:true,\r
-        defaults: {\r
-            anchor: '-20' // leave room for error icon\r
-        },\r
-        defaultType: 'textfield',\r
-        items :[{\r
-                fieldLabel: 'Field 1'\r
-            }, {\r
-                fieldLabel: 'Field 2'\r
-            }, {\r
-                fieldLabel: 'Field 3'\r
-            }\r
-        ]\r
-    },{\r
-        // Fieldset in Column 2 - Panel inside\r
-        xtype:'fieldset',\r
-        title: 'Show Panel', // title, header, or checkboxToggle creates fieldset header\r
-        autoHeight:true,\r
-        columnWidth: 0.5,\r
-        checkboxToggle: true,\r
-        collapsed: true, // fieldset initially collapsed\r
-        layout:'anchor',\r
-        items :[{\r
-            xtype: 'panel',\r
-            anchor: '100%',\r
-            title: 'Panel inside a fieldset',\r
-            frame: true,\r
-            height: 100\r
-        }]\r
-    }]\r
-});\r
- * </code></pre>\r
- * @constructor\r
- * @param {Object} config Configuration options\r
- * @xtype fieldset\r
- */\r
-Ext.form.FieldSet = Ext.extend(Ext.Panel, {\r
-    /**\r
-     * @cfg {Mixed} checkboxToggle <tt>true</tt> to render a checkbox into the fieldset frame just\r
-     * in front of the legend to expand/collapse the fieldset when the checkbox is toggled. (defaults\r
-     * to <tt>false</tt>).\r
-     * <p>A {@link Ext.DomHelper DomHelper} element spec may also be specified to create the checkbox.\r
-     * If <tt>true</tt> is specified, the default DomHelper config object used to create the element\r
-     * is:</p><pre><code>\r
-     * {tag: 'input', type: 'checkbox', name: this.checkboxName || this.id+'-checkbox'}\r
-     * </code></pre>   \r
-     */\r
-    /**\r
-     * @cfg {String} checkboxName The name to assign to the fieldset's checkbox if <tt>{@link #checkboxToggle} = true</tt>\r
-     * (defaults to <tt>'[checkbox id]-checkbox'</tt>).\r
-     */\r
-    /**\r
-     * @cfg {Boolean} collapsible\r
-     * <tt>true</tt> to make the fieldset collapsible and have the expand/collapse toggle button automatically\r
-     * rendered into the legend element, <tt>false</tt> to keep the fieldset statically sized with no collapse\r
-     * button (defaults to <tt>false</tt>). Another option is to configure <tt>{@link #checkboxToggle}</tt>.\r
-     */\r
-    /**\r
-     * @cfg {Number} labelWidth The width of labels. This property cascades to child containers.\r
-     */\r
-    /**\r
-     * @cfg {String} itemCls A css class to apply to the <tt>x-form-item</tt> of fields (see \r
-     * {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl} for details).\r
-     * This property cascades to child containers.\r
-     */\r
-    /**\r
-     * @cfg {String} baseCls The base CSS class applied to the fieldset (defaults to <tt>'x-fieldset'</tt>).\r
-     */\r
-    baseCls : 'x-fieldset',\r
-    /**\r
-     * @cfg {String} layout The {@link Ext.Container#layout} to use inside the fieldset (defaults to <tt>'form'</tt>).\r
-     */\r
-    layout : 'form',\r
-    /**\r
-     * @cfg {Boolean} animCollapse\r
-     * <tt>true</tt> to animate the transition when the panel is collapsed, <tt>false</tt> to skip the\r
-     * animation (defaults to <tt>false</tt>).\r
-     */\r
-    animCollapse : false,\r
-\r
-    // private\r
-    onRender : function(ct, position){\r
-        if(!this.el){\r
-            this.el = document.createElement('fieldset');\r
-            this.el.id = this.id;\r
-            if (this.title || this.header || this.checkboxToggle) {\r
-                this.el.appendChild(document.createElement('legend')).className = 'x-fieldset-header';\r
-            }\r
-        }\r
-\r
-        Ext.form.FieldSet.superclass.onRender.call(this, ct, position);\r
-\r
-        if(this.checkboxToggle){\r
-            var o = typeof this.checkboxToggle == 'object' ?\r
-                    this.checkboxToggle :\r
-                    {tag: 'input', type: 'checkbox', name: this.checkboxName || this.id+'-checkbox'};\r
-            this.checkbox = this.header.insertFirst(o);\r
-            this.checkbox.dom.checked = !this.collapsed;\r
-            this.mon(this.checkbox, 'click', this.onCheckClick, this);\r
-        }\r
-    },\r
-\r
-    // private\r
-    onCollapse : function(doAnim, animArg){\r
-        if(this.checkbox){\r
-            this.checkbox.dom.checked = false;\r
-        }\r
-        Ext.form.FieldSet.superclass.onCollapse.call(this, doAnim, animArg);\r
-\r
-    },\r
-\r
-    // private\r
-    onExpand : function(doAnim, animArg){\r
-        if(this.checkbox){\r
-            this.checkbox.dom.checked = true;\r
-        }\r
-        Ext.form.FieldSet.superclass.onExpand.call(this, doAnim, animArg);\r
-    },\r
-\r
-    /**\r
-     * This function is called by the fieldset's checkbox when it is toggled (only applies when\r
-     * checkboxToggle = true).  This method should never be called externally, but can be\r
-     * overridden to provide custom behavior when the checkbox is toggled if needed.\r
-     */\r
-    onCheckClick : function(){\r
-        this[this.checkbox.dom.checked ? 'expand' : 'collapse']();\r
-    }\r
-\r
-    /**\r
-     * @cfg {String/Number} activeItem\r
-     * @hide\r
-     */\r
-    /**\r
-     * @cfg {Mixed} applyTo\r
-     * @hide\r
-     */\r
-    /**\r
-     * @cfg {Boolean} bodyBorder\r
-     * @hide\r
-     */\r
-    /**\r
-     * @cfg {Boolean} border\r
-     * @hide\r
-     */\r
-    /**\r
-     * @cfg {Boolean/Number} bufferResize\r
-     * @hide\r
-     */\r
-    /**\r
-     * @cfg {Boolean} collapseFirst\r
-     * @hide\r
-     */\r
-    /**\r
-     * @cfg {String} defaultType\r
-     * @hide\r
-     */\r
-    /**\r
-     * @cfg {String} disabledClass\r
-     * @hide\r
-     */\r
-    /**\r
-     * @cfg {String} elements\r
-     * @hide\r
-     */\r
-    /**\r
-     * @cfg {Boolean} floating\r
-     * @hide\r
-     */\r
-    /**\r
-     * @cfg {Boolean} footer\r
-     * @hide\r
-     */\r
-    /**\r
-     * @cfg {Boolean} frame\r
-     * @hide\r
-     */\r
-    /**\r
-     * @cfg {Boolean} header\r
-     * @hide\r
-     */\r
-    /**\r
-     * @cfg {Boolean} headerAsText\r
-     * @hide\r
-     */\r
-    /**\r
-     * @cfg {Boolean} hideCollapseTool\r
-     * @hide\r
-     */\r
-    /**\r
-     * @cfg {String} iconCls\r
-     * @hide\r
-     */\r
-    /**\r
-     * @cfg {Boolean/String} shadow\r
-     * @hide\r
-     */\r
-    /**\r
-     * @cfg {Number} shadowOffset\r
-     * @hide\r
-     */\r
-    /**\r
-     * @cfg {Boolean} shim\r
-     * @hide\r
-     */\r
-    /**\r
-     * @cfg {Object/Array} tbar\r
-     * @hide\r
-     */\r
-    /**\r
-     * @cfg {Array} tools\r
-     * @hide\r
-     */\r
-    /**\r
-     * @cfg {Ext.Template/Ext.XTemplate} toolTemplate\r
-     * @hide\r
-     */\r
-    /**\r
-     * @cfg {String} xtype\r
-     * @hide\r
-     */\r
-    /**\r
-     * @property header\r
-     * @hide\r
-     */\r
-    /**\r
-     * @property footer\r
-     * @hide\r
-     */\r
-    /**\r
-     * @method focus\r
-     * @hide\r
-     */\r
-    /**\r
-     * @method getBottomToolbar\r
-     * @hide\r
-     */\r
-    /**\r
-     * @method getTopToolbar\r
-     * @hide\r
-     */\r
-    /**\r
-     * @method setIconClass\r
-     * @hide\r
-     */\r
-    /**\r
-     * @event activate\r
-     * @hide\r
-     */\r
-    /**\r
-     * @event beforeclose\r
-     * @hide\r
-     */\r
-    /**\r
-     * @event bodyresize\r
-     * @hide\r
-     */\r
-    /**\r
-     * @event close\r
-     * @hide\r
-     */\r
-    /**\r
-     * @event deactivate\r
-     * @hide\r
-     */\r
-});\r
-Ext.reg('fieldset', Ext.form.FieldSet);\r
-/**\r
- * @class Ext.form.HtmlEditor\r
- * @extends Ext.form.Field\r
- * Provides a lightweight HTML Editor component. Some toolbar features are not supported by Safari and will be \r
- * automatically hidden when needed.  These are noted in the config options where appropriate.\r
- * <br><br>The editor's toolbar buttons have tooltips defined in the {@link #buttonTips} property, but they are not \r
- * enabled by default unless the global {@link Ext.QuickTips} singleton is {@link Ext.QuickTips#init initialized}.\r
- * <br><br><b>Note: The focus/blur and validation marking functionality inherited from Ext.form.Field is NOT\r
- * supported by this editor.</b>\r
- * <br><br>An Editor is a sensitive component that can't be used in all spots standard fields can be used. Putting an Editor within\r
- * any element that has display set to 'none' can cause problems in Safari and Firefox due to their default iframe reloading bugs.\r
- * <br><br>Example usage:\r
+ * @class Ext.form.FieldSet\r
+ * @extends Ext.Panel\r
+ * Standard container used for grouping items within a {@link Ext.form.FormPanel form}.\r
  * <pre><code>\r
-// Simple example rendered with default options:\r
-Ext.QuickTips.init();  // enable tooltips\r
-new Ext.form.HtmlEditor({\r
-    renderTo: Ext.getBody(),\r
-    width: 800,\r
-    height: 300\r
-});\r
-\r
-// Passed via xtype into a container and with custom options:\r
-Ext.QuickTips.init();  // enable tooltips\r
-new Ext.Panel({\r
-    title: 'HTML Editor',\r
-    renderTo: Ext.getBody(),\r
-    width: 600,\r
-    height: 300,\r
-    frame: true,\r
-    layout: 'fit',\r
-    items: {\r
-        xtype: 'htmleditor',\r
-        enableColors: false,\r
-        enableAlignments: false\r
-    }\r
-});\r
-</code></pre>\r
- * @constructor\r
- * Create a new HtmlEditor\r
- * @param {Object} config\r
- * @xtype htmleditor\r
- */\r
-\r
-Ext.form.HtmlEditor = Ext.extend(Ext.form.Field, {\r
-    /**\r
-     * @cfg {Boolean} enableFormat Enable the bold, italic and underline buttons (defaults to true)\r
-     */\r
-    enableFormat : true,\r
-    /**\r
-     * @cfg {Boolean} enableFontSize Enable the increase/decrease font size buttons (defaults to true)\r
-     */\r
-    enableFontSize : true,\r
-    /**\r
-     * @cfg {Boolean} enableColors Enable the fore/highlight color buttons (defaults to true)\r
-     */\r
-    enableColors : true,\r
-    /**\r
-     * @cfg {Boolean} enableAlignments Enable the left, center, right alignment buttons (defaults to true)\r
-     */\r
-    enableAlignments : true,\r
-    /**\r
-     * @cfg {Boolean} enableLists Enable the bullet and numbered list buttons. Not available in Safari. (defaults to true)\r
-     */\r
-    enableLists : true,\r
-    /**\r
-     * @cfg {Boolean} enableSourceEdit Enable the switch to source edit button. Not available in Safari. (defaults to true)\r
-     */\r
-    enableSourceEdit : true,\r
-    /**\r
-     * @cfg {Boolean} enableLinks Enable the create link button. Not available in Safari. (defaults to true)\r
-     */\r
-    enableLinks : true,\r
-    /**\r
-     * @cfg {Boolean} enableFont Enable font selection. Not available in Safari. (defaults to true)\r
-     */\r
-    enableFont : true,\r
-    /**\r
-     * @cfg {String} createLinkText The default text for the create link prompt\r
-     */\r
-    createLinkText : 'Please enter the URL for the link:',\r
-    /**\r
-     * @cfg {String} defaultLinkValue The default value for the create link prompt (defaults to http:/ /)\r
-     */\r
-    defaultLinkValue : 'http:/'+'/',\r
-    /**\r
-     * @cfg {Array} fontFamilies An array of available font families\r
-     */\r
-    fontFamilies : [\r
-        'Arial',\r
-        'Courier New',\r
-        'Tahoma',\r
-        'Times New Roman',\r
-        'Verdana'\r
-    ],\r
-    defaultFont: 'tahoma',\r
-    /**\r
-     * @cfg {String} defaultValue A default value to be put into the editor to resolve focus issues (defaults to &#8203; (Zero-width space), &nbsp; (Non-breaking space) in Opera and IE6).\r
-     */\r
-    defaultValue: (Ext.isOpera || Ext.isIE6) ? '&#160;' : '&#8203;',\r
-\r
-    // private properties\r
-    actionMode: 'wrap',\r
-    validationEvent : false,\r
-    deferHeight: true,\r
-    initialized : false,\r
-    activated : false,\r
-    sourceEditMode : false,\r
-    onFocus : Ext.emptyFn,\r
-    iframePad:3,\r
-    hideMode:'offsets',\r
-    defaultAutoCreate : {\r
-        tag: "textarea",\r
-        style:"width:500px;height:300px;",\r
-        autocomplete: "off"\r
-    },\r
-\r
-    // private\r
-    initComponent : function(){\r
-        this.addEvents(\r
-            /**\r
-             * @event initialize\r
-             * Fires when the editor is fully initialized (including the iframe)\r
-             * @param {HtmlEditor} this\r
-             */\r
-            'initialize',\r
-            /**\r
-             * @event activate\r
-             * Fires when the editor is first receives the focus. Any insertion must wait\r
-             * until after this event.\r
-             * @param {HtmlEditor} this\r
-             */\r
-            'activate',\r
-             /**\r
-             * @event beforesync\r
-             * Fires before the textarea is updated with content from the editor iframe. Return false\r
-             * to cancel the sync.\r
-             * @param {HtmlEditor} this\r
-             * @param {String} html\r
-             */\r
-            'beforesync',\r
-             /**\r
-             * @event beforepush\r
-             * Fires before the iframe editor is updated with content from the textarea. Return false\r
-             * to cancel the push.\r
-             * @param {HtmlEditor} this\r
-             * @param {String} html\r
-             */\r
-            'beforepush',\r
-             /**\r
-             * @event sync\r
-             * Fires when the textarea is updated with content from the editor iframe.\r
-             * @param {HtmlEditor} this\r
-             * @param {String} html\r
-             */\r
-            'sync',\r
-             /**\r
-             * @event push\r
-             * Fires when the iframe editor is updated with content from the textarea.\r
-             * @param {HtmlEditor} this\r
-             * @param {String} html\r
-             */\r
-            'push',\r
-             /**\r
-             * @event editmodechange\r
-             * Fires when the editor switches edit modes\r
-             * @param {HtmlEditor} this\r
-             * @param {Boolean} sourceEdit True if source edit, false if standard editing.\r
-             */\r
-            'editmodechange'\r
-        )\r
-    },\r
-\r
-    // private\r
-    createFontOptions : function(){\r
-        var buf = [], fs = this.fontFamilies, ff, lc;\r
-        for(var i = 0, len = fs.length; i< len; i++){\r
-            ff = fs[i];\r
-            lc = ff.toLowerCase();\r
-            buf.push(\r
-                '<option value="',lc,'" style="font-family:',ff,';"',\r
-                    (this.defaultFont == lc ? ' selected="true">' : '>'),\r
-                    ff,\r
-                '</option>'\r
-            );\r
-        }\r
-        return buf.join('');\r
-    },\r
-    \r
-    /*\r
-     * Protected method that will not generally be called directly. It\r
-     * is called when the editor creates its toolbar. Override this method if you need to\r
-     * add custom toolbar buttons.\r
-     * @param {HtmlEditor} editor\r
-     */\r
-    createToolbar : function(editor){\r
-        \r
-        var tipsEnabled = Ext.QuickTips && Ext.QuickTips.isEnabled();\r
-        \r
-        function btn(id, toggle, handler){\r
-            return {\r
-                itemId : id,\r
-                cls : 'x-btn-icon',\r
-                iconCls: 'x-edit-'+id,\r
-                enableToggle:toggle !== false,\r
-                scope: editor,\r
-                handler:handler||editor.relayBtnCmd,\r
-                clickEvent:'mousedown',\r
-                tooltip: tipsEnabled ? editor.buttonTips[id] || undefined : undefined,\r
-                overflowText: editor.buttonTips[id].title || undefined,\r
-                tabIndex:-1\r
-            };\r
-        }\r
-\r
-        // build the toolbar\r
-        var tb = new Ext.Toolbar({\r
-            renderTo:this.wrap.dom.firstChild\r
-        });\r
-\r
-        // stop form submits\r
-        this.mon(tb.el, 'click', function(e){\r
-            e.preventDefault();\r
-        });\r
-\r
-        if(this.enableFont && !Ext.isSafari2){\r
-            this.fontSelect = tb.el.createChild({\r
-                tag:'select',\r
-                cls:'x-font-select',\r
-                html: this.createFontOptions()\r
-            });\r
-            this.mon(this.fontSelect, 'change', function(){\r
-                var font = this.fontSelect.dom.value;\r
-                this.relayCmd('fontname', font);\r
-                this.deferFocus();\r
-            }, this);\r
-\r
-            tb.add(\r
-                this.fontSelect.dom,\r
-                '-'\r
-            );\r
-        }\r
-\r
-        if(this.enableFormat){\r
-            tb.add(\r
-                btn('bold'),\r
-                btn('italic'),\r
-                btn('underline')\r
-            );\r
-        }\r
-\r
-        if(this.enableFontSize){\r
-            tb.add(\r
-                '-',\r
-                btn('increasefontsize', false, this.adjustFont),\r
-                btn('decreasefontsize', false, this.adjustFont)\r
-            );\r
-        }\r
-\r
-        if(this.enableColors){\r
-            tb.add(\r
-                '-', {\r
-                    itemId:'forecolor',\r
-                    cls:'x-btn-icon',\r
-                    iconCls: 'x-edit-forecolor',\r
-                    clickEvent:'mousedown',\r
-                    tooltip: tipsEnabled ? editor.buttonTips.forecolor || undefined : undefined,\r
-                    tabIndex:-1,\r
-                    menu : new Ext.menu.ColorMenu({\r
-                        allowReselect: true,\r
-                        focus: Ext.emptyFn,\r
-                        value:'000000',\r
-                        plain:true,\r
-                        listeners: {\r
-                            scope: this,\r
-                            select: function(cp, color){\r
-                                this.execCmd('forecolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);\r
-                                this.deferFocus();\r
-                            }\r
-                        },\r
-                        clickEvent:'mousedown'\r
-                    })\r
-                }, {\r
-                    itemId:'backcolor',\r
-                    cls:'x-btn-icon',\r
-                    iconCls: 'x-edit-backcolor',\r
-                    clickEvent:'mousedown',\r
-                    tooltip: tipsEnabled ? editor.buttonTips.backcolor || undefined : undefined,\r
-                    tabIndex:-1,\r
-                    menu : new Ext.menu.ColorMenu({\r
-                        focus: Ext.emptyFn,\r
-                        value:'FFFFFF',\r
-                        plain:true,\r
-                        allowReselect: true,\r
-                        listeners: {\r
-                            scope: this,\r
-                            select: function(cp, color){\r
-                                if(Ext.isGecko){\r
-                                    this.execCmd('useCSS', false);\r
-                                    this.execCmd('hilitecolor', color);\r
-                                    this.execCmd('useCSS', true);\r
-                                    this.deferFocus();\r
-                                }else{\r
-                                    this.execCmd(Ext.isOpera ? 'hilitecolor' : 'backcolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);\r
-                                    this.deferFocus();\r
-                                }\r
-                            }\r
-                        },\r
-                        clickEvent:'mousedown'\r
-                    })\r
-                }\r
-            );\r
-        }\r
-\r
-        if(this.enableAlignments){\r
-            tb.add(\r
-                '-',\r
-                btn('justifyleft'),\r
-                btn('justifycenter'),\r
-                btn('justifyright')\r
-            );\r
-        }\r
-\r
-        if(!Ext.isSafari2){\r
-            if(this.enableLinks){\r
-                tb.add(\r
-                    '-',\r
-                    btn('createlink', false, this.createLink)\r
-                );\r
-            }\r
-\r
-            if(this.enableLists){\r
-                tb.add(\r
-                    '-',\r
-                    btn('insertorderedlist'),\r
-                    btn('insertunorderedlist')\r
-                );\r
-            }\r
-            if(this.enableSourceEdit){\r
-                tb.add(\r
-                    '-',\r
-                    btn('sourceedit', true, function(btn){\r
-                        this.toggleSourceEdit(!this.sourceEditMode);\r
-                    })\r
-                );\r
-            }\r
-        }\r
-\r
-        this.tb = tb;\r
-    },\r
-\r
-    /**\r
-     * Protected method that will not generally be called directly. It\r
-     * is called when the editor initializes the iframe with HTML contents. Override this method if you\r
-     * want to change the initialization markup of the iframe (e.g. to add stylesheets).\r
-     */\r
-    getDocMarkup : function(){\r
-        return '<html><head><style type="text/css">body{border:0;margin:0;padding:3px;height:98%;cursor:text;}</style></head><body></body></html>';\r
-    },\r
-\r
-    // private\r
-    getEditorBody : function(){\r
-        return this.doc.body || this.doc.documentElement;\r
-    },\r
-\r
-    // private\r
-    getDoc : function(){\r
-        return Ext.isIE ? this.getWin().document : (this.iframe.contentDocument || this.getWin().document);\r
-    },\r
-\r
-    // private\r
-    getWin : function(){\r
-        return Ext.isIE ? this.iframe.contentWindow : window.frames[this.iframe.name];\r
-    },\r
-\r
-    // private\r
-    onRender : function(ct, position){\r
-        Ext.form.HtmlEditor.superclass.onRender.call(this, ct, position);\r
-        this.el.dom.style.border = '0 none';\r
-        this.el.dom.setAttribute('tabIndex', -1);\r
-        this.el.addClass('x-hidden');\r
-        if(Ext.isIE){ // fix IE 1px bogus margin\r
-            this.el.applyStyles('margin-top:-1px;margin-bottom:-1px;')\r
-        }\r
-        this.wrap = this.el.wrap({\r
-            cls:'x-html-editor-wrap', cn:{cls:'x-html-editor-tb'}\r
-        });\r
-\r
-        this.createToolbar(this);\r
-\r
-        this.disableItems(true);\r
-        // is this needed?\r
-        // this.tb.doLayout();\r
-\r
-        this.createIFrame();\r
-\r
-        if(!this.width){\r
-            var sz = this.el.getSize();\r
-            this.setSize(sz.width, this.height || sz.height);\r
-        }\r
-        this.resizeEl = this.positionEl = this.wrap;\r
-    },\r
-\r
-    createIFrame: function(){\r
-        var iframe = document.createElement('iframe');\r
-        iframe.name = Ext.id();\r
-        iframe.frameBorder = '0';\r
-        iframe.src = Ext.SSL_SECURE_URL;\r
-        this.wrap.dom.appendChild(iframe);\r
-\r
-        this.iframe = iframe;\r
-\r
-        this.monitorTask = Ext.TaskMgr.start({\r
-            run: this.checkDesignMode,\r
-            scope: this,\r
-            interval:100\r
-        });\r
-    },\r
-\r
-    initFrame : function(){\r
-        Ext.TaskMgr.stop(this.monitorTask);\r
-        this.doc = this.getDoc();\r
-        this.win = this.getWin();\r
-\r
-        this.doc.open();\r
-        this.doc.write(this.getDocMarkup());\r
-        this.doc.close();\r
-\r
-        var task = { // must defer to wait for browser to be ready\r
-            run : function(){\r
-                if(this.doc.body || this.doc.readyState == 'complete'){\r
-                    Ext.TaskMgr.stop(task);\r
-                    this.doc.designMode="on";\r
-                    this.initEditor.defer(10, this);\r
-                }\r
-            },\r
-            interval : 10,\r
-            duration:10000,\r
-            scope: this\r
-        };\r
-        Ext.TaskMgr.start(task);\r
-    },\r
-\r
-\r
-    checkDesignMode : function(){\r
-        if(this.wrap && this.wrap.dom.offsetWidth){\r
-            var doc = this.getDoc();\r
-            if(!doc){\r
-                return;\r
-            }\r
-            if(!doc.editorInitialized || String(doc.designMode).toLowerCase() != 'on'){\r
-                this.initFrame();\r
-            }\r
-        }\r
-    },\r
-    \r
-    disableItems: function(disabled){\r
-        if(this.fontSelect){\r
-            this.fontSelect.dom.disabled = disabled;\r
-        }\r
-        this.tb.items.each(function(item){\r
-            if(item.getItemId() != 'sourceedit'){\r
-                item.setDisabled(disabled);\r
-            }\r
-        });\r
-    },\r
-\r
-    // private\r
-    onResize : function(w, h){\r
-        Ext.form.HtmlEditor.superclass.onResize.apply(this, arguments);\r
-        if(this.el && this.iframe){\r
-            if(Ext.isNumber(w)){\r
-                var aw = w - this.wrap.getFrameWidth('lr');\r
-                this.el.setWidth(aw);\r
-                this.tb.setWidth(aw);\r
-                this.iframe.style.width = Math.max(aw, 0) + 'px';\r
-            }\r
-            if(Ext.isNumber(h)){\r
-                var ah = h - this.wrap.getFrameWidth('tb') - this.tb.el.getHeight();\r
-                this.el.setHeight(ah);\r
-                this.iframe.style.height = Math.max(ah, 0) + 'px';\r
-                if(this.doc){\r
-                    this.getEditorBody().style.height = Math.max((ah - (this.iframePad*2)), 0) + 'px';\r
-                }\r
-            }\r
-        }\r
-    },\r
-\r
-    /**\r
-     * Toggles the editor between standard and source edit mode.\r
-     * @param {Boolean} sourceEdit (optional) True for source edit, false for standard\r
-     */\r
-    toggleSourceEdit : function(sourceEditMode){\r
-        if(sourceEditMode === undefined){\r
-            sourceEditMode = !this.sourceEditMode;\r
-        }\r
-        this.sourceEditMode = sourceEditMode === true;\r
-        var btn = this.tb.items.get('sourceedit');\r
-        if(btn.pressed !== this.sourceEditMode){\r
-            btn.toggle(this.sourceEditMode);\r
-            if(!btn.xtbHidden){\r
-                return;\r
-            }\r
-        }\r
-        if(this.sourceEditMode){\r
-            this.disableItems(true);\r
-            this.syncValue();\r
-            this.iframe.className = 'x-hidden';\r
-            this.el.removeClass('x-hidden');\r
-            this.el.dom.removeAttribute('tabIndex');\r
-            this.el.focus();\r
-        }else{\r
-            if(this.initialized){\r
-                this.disableItems(false);\r
-            }\r
-            this.pushValue();\r
-            this.iframe.className = '';\r
-            this.el.addClass('x-hidden');\r
-            this.el.dom.setAttribute('tabIndex', -1);\r
-            this.deferFocus();\r
-        }\r
-        var lastSize = this.lastSize;\r
-        if(lastSize){\r
-            delete this.lastSize;\r
-            this.setSize(lastSize);\r
-        }\r
-        this.fireEvent('editmodechange', this, this.sourceEditMode);\r
-    },\r
-\r
-    // private used internally\r
-    createLink : function(){\r
-        var url = prompt(this.createLinkText, this.defaultLinkValue);\r
-        if(url && url != 'http:/'+'/'){\r
-            this.relayCmd('createlink', url);\r
-        }\r
-    },\r
-\r
-    // private\r
-    initEvents : function(){\r
-        this.originalValue = this.getValue();\r
-    },\r
-\r
-    /**\r
-     * Overridden and disabled. The editor element does not support standard valid/invalid marking. @hide\r
-     * @method\r
-     */\r
-    markInvalid : Ext.emptyFn,\r
-    \r
-    /**\r
-     * Overridden and disabled. The editor element does not support standard valid/invalid marking. @hide\r
-     * @method\r
-     */\r
-    clearInvalid : Ext.emptyFn,\r
-\r
-    // docs inherit from Field\r
-    setValue : function(v){\r
-        Ext.form.HtmlEditor.superclass.setValue.call(this, v);\r
-        this.pushValue();\r
-        return this;\r
-    },\r
-\r
-    /**\r
-     * Protected method that will not generally be called directly. If you need/want\r
-     * custom HTML cleanup, this is the method you should override.\r
-     * @param {String} html The HTML to be cleaned\r
-     * @return {String} The cleaned HTML\r
-     */\r
-    cleanHtml: function(html) {\r
-        html = String(html);\r
-        if(Ext.isWebKit){ // strip safari nonsense\r
-            html = html.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi, '');\r
-        }\r
-        \r
-        /*\r
-         * Neat little hack. Strips out all the non-digit characters from the default\r
-         * value and compares it to the character code of the first character in the string\r
-         * because it can cause encoding issues when posted to the server.\r
-         */\r
-        if(html.charCodeAt(0) == this.defaultValue.replace(/\D/g, '')){\r
-            html = html.substring(1);\r
-        }\r
-        return html;\r
-    },\r
-\r
-    /**\r
-     * Protected method that will not generally be called directly. Syncs the contents\r
-     * of the editor iframe with the textarea.\r
-     */\r
-    syncValue : function(){\r
-        if(this.initialized){\r
-            var bd = this.getEditorBody();\r
-            var html = bd.innerHTML;\r
-            if(Ext.isWebKit){\r
-                var bs = bd.getAttribute('style'); // Safari puts text-align styles on the body element!\r
-                var m = bs.match(/text-align:(.*?);/i);\r
-                if(m && m[1]){\r
-                    html = '<div style="'+m[0]+'">' + html + '</div>';\r
-                }\r
-            }\r
-            html = this.cleanHtml(html);\r
-            if(this.fireEvent('beforesync', this, html) !== false){\r
-                this.el.dom.value = html;\r
-                this.fireEvent('sync', this, html);\r
-            }\r
-        }\r
-    },\r
-    \r
-    //docs inherit from Field\r
-    getValue : function() {\r
-        this[this.sourceEditMode ? 'pushValue' : 'syncValue']();\r
-        return Ext.form.HtmlEditor.superclass.getValue.call(this);\r
-    },\r
-\r
-    /**\r
-     * Protected method that will not generally be called directly. Pushes the value of the textarea\r
-     * into the iframe editor.\r
-     */\r
-    pushValue : function(){\r
-        if(this.initialized){\r
-            var v = this.el.dom.value;\r
-            if(!this.activated && v.length < 1){\r
-                v = this.defaultValue;\r
-            }\r
-            if(this.fireEvent('beforepush', this, v) !== false){\r
-                this.getEditorBody().innerHTML = v;\r
-                if(Ext.isGecko){\r
-                    // Gecko hack, see: https://bugzilla.mozilla.org/show_bug.cgi?id=232791#c8\r
-                    var d = this.doc,\r
-                        mode = d.designMode.toLowerCase();\r
-                    \r
-                    d.designMode = mode.toggle('on', 'off');\r
-                    d.designMode = mode;\r
-                }\r
-                this.fireEvent('push', this, v);\r
-            }\r
-        }\r
-    },\r
-\r
-    // private\r
-    deferFocus : function(){\r
-        this.focus.defer(10, this);\r
-    },\r
-\r
-    // docs inherit from Field\r
-    focus : function(){\r
-        if(this.win && !this.sourceEditMode){\r
-            this.win.focus();\r
-        }else{\r
-            this.el.focus();\r
-        }\r
-    },\r
-\r
-    // private\r
-    initEditor : function(){\r
-        //Destroying the component during/before initEditor can cause issues.\r
-        try{\r
-            var dbody = this.getEditorBody();\r
-            var ss = this.el.getStyles('font-size', 'font-family', 'background-image', 'background-repeat');\r
-            ss['background-attachment'] = 'fixed'; // w3c\r
-            dbody.bgProperties = 'fixed'; // ie\r
-\r
-            Ext.DomHelper.applyStyles(dbody, ss);\r
-\r
-            if(this.doc){\r
-                try{\r
-                    Ext.EventManager.removeAll(this.doc);\r
-                }catch(e){}\r
-            }\r
-\r
-            this.doc = this.getDoc();\r
-\r
-            Ext.EventManager.on(this.doc, {\r
-                'mousedown': this.onEditorEvent,\r
-                'dblclick': this.onEditorEvent,\r
-                'click': this.onEditorEvent,\r
-                'keyup': this.onEditorEvent,\r
-                buffer:100,\r
-                scope: this\r
-            });\r
-\r
-            if(Ext.isGecko){\r
-                Ext.EventManager.on(this.doc, 'keypress', this.applyCommand, this);\r
-            }\r
-            if(Ext.isIE || Ext.isWebKit || Ext.isOpera){\r
-                Ext.EventManager.on(this.doc, 'keydown', this.fixKeys, this);\r
-            }\r
-            this.initialized = true;\r
-            this.fireEvent('initialize', this);\r
-            this.doc.editorInitialized = true;\r
-            this.pushValue();\r
-        }catch(e){}\r
-    },\r
-\r
-    // private\r
-    onDestroy : function(){\r
-        if(this.monitorTask){\r
-            Ext.TaskMgr.stop(this.monitorTask);\r
-        }\r
-        if(this.rendered){\r
-            Ext.destroy(this.tb);\r
-            if(this.wrap){\r
-                this.wrap.dom.innerHTML = '';\r
-                this.wrap.remove();\r
-            }\r
-        }\r
-        if(this.el){\r
-            this.el.removeAllListeners();\r
-            this.el.remove();\r
-        }\r
\r
-        if(this.doc){\r
-            try{\r
-                Ext.EventManager.removeAll(this.doc);\r
-                for (var prop in this.doc){\r
-                   delete this.doc[prop];\r
-                }\r
-            }catch(e){}\r
-        }\r
-        this.purgeListeners();\r
-    },\r
-\r
-    // private\r
-    onFirstFocus : function(){\r
-        this.activated = true;\r
-        this.disableItems(false);\r
-        if(Ext.isGecko){ // prevent silly gecko errors\r
-            this.win.focus();\r
-            var s = this.win.getSelection();\r
-            if(!s.focusNode || s.focusNode.nodeType != 3){\r
-                var r = s.getRangeAt(0);\r
-                r.selectNodeContents(this.getEditorBody());\r
-                r.collapse(true);\r
-                this.deferFocus();\r
-            }\r
-            try{\r
-                this.execCmd('useCSS', true);\r
-                this.execCmd('styleWithCSS', false);\r
-            }catch(e){}\r
-        }\r
-        this.fireEvent('activate', this);\r
+var form = new Ext.FormPanel({\r
+    title: 'Simple Form with FieldSets',\r
+    labelWidth: 75, // label settings here cascade unless overridden\r
+    url: 'save-form.php',\r
+    frame:true,\r
+    bodyStyle:'padding:5px 5px 0',\r
+    width: 700,\r
+    renderTo: document.body,\r
+    layout:'column', // arrange items in columns\r
+    defaults: {      // defaults applied to items\r
+        layout: 'form',\r
+        border: false,\r
+        bodyStyle: 'padding:4px'\r
     },\r
-\r
-    // private\r
-    adjustFont: function(btn){\r
-        var adjust = btn.getItemId() == 'increasefontsize' ? 1 : -1;\r
-\r
-        var v = parseInt(this.doc.queryCommandValue('FontSize') || 2, 10);\r
-        if((Ext.isSafari && !Ext.isSafari2) || Ext.isChrome || Ext.isAir){\r
-            // Safari 3 values\r
-            // 1 = 10px, 2 = 13px, 3 = 16px, 4 = 18px, 5 = 24px, 6 = 32px\r
-            if(v <= 10){\r
-                v = 1 + adjust;\r
-            }else if(v <= 13){\r
-                v = 2 + adjust;\r
-            }else if(v <= 16){\r
-                v = 3 + adjust;\r
-            }else if(v <= 18){\r
-                v = 4 + adjust;\r
-            }else if(v <= 24){\r
-                v = 5 + adjust;\r
-            }else {\r
-                v = 6 + adjust;\r
-            }\r
-            v = v.constrain(1, 6);\r
-        }else{\r
-            if(Ext.isSafari){ // safari\r
-                adjust *= 2;\r
+    items: [{\r
+        // Fieldset in Column 1\r
+        xtype:'fieldset',\r
+        columnWidth: 0.5,\r
+        title: 'Fieldset 1',\r
+        collapsible: true,\r
+        autoHeight:true,\r
+        defaults: {\r
+            anchor: '-20' // leave room for error icon\r
+        },\r
+        defaultType: 'textfield',\r
+        items :[{\r
+                fieldLabel: 'Field 1'\r
+            }, {\r
+                fieldLabel: 'Field 2'\r
+            }, {\r
+                fieldLabel: 'Field 3'\r
             }\r
-            v = Math.max(1, v+adjust) + (Ext.isSafari ? 'px' : 0);\r
-        }\r
-        this.execCmd('FontSize', v);\r
-    },\r
-\r
-    // private\r
-    onEditorEvent : function(e){\r
-        this.updateToolbar();\r
-    },\r
-\r
-\r
+        ]\r
+    },{\r
+        // Fieldset in Column 2 - Panel inside\r
+        xtype:'fieldset',\r
+        title: 'Show Panel', // title, header, or checkboxToggle creates fieldset header\r
+        autoHeight:true,\r
+        columnWidth: 0.5,\r
+        checkboxToggle: true,\r
+        collapsed: true, // fieldset initially collapsed\r
+        layout:'anchor',\r
+        items :[{\r
+            xtype: 'panel',\r
+            anchor: '100%',\r
+            title: 'Panel inside a fieldset',\r
+            frame: true,\r
+            height: 100\r
+        }]\r
+    }]\r
+});\r
+ * </code></pre>\r
+ * @constructor\r
+ * @param {Object} config Configuration options\r
+ * @xtype fieldset\r
+ */\r
+Ext.form.FieldSet = Ext.extend(Ext.Panel, {\r
     /**\r
-     * Protected method that will not generally be called directly. It triggers\r
-     * a toolbar update by reading the markup state of the current selection in the editor.\r
+     * @cfg {Mixed} checkboxToggle <tt>true</tt> to render a checkbox into the fieldset frame just\r
+     * in front of the legend to expand/collapse the fieldset when the checkbox is toggled. (defaults\r
+     * to <tt>false</tt>).\r
+     * <p>A {@link Ext.DomHelper DomHelper} element spec may also be specified to create the checkbox.\r
+     * If <tt>true</tt> is specified, the default DomHelper config object used to create the element\r
+     * is:</p><pre><code>\r
+     * {tag: 'input', type: 'checkbox', name: this.checkboxName || this.id+'-checkbox'}\r
+     * </code></pre>   \r
      */\r
-    updateToolbar: function(){\r
-\r
-        if(!this.activated){\r
-            this.onFirstFocus();\r
-            return;\r
-        }\r
-\r
-        var btns = this.tb.items.map, doc = this.doc;\r
-\r
-        if(this.enableFont && !Ext.isSafari2){\r
-            var name = (this.doc.queryCommandValue('FontName')||this.defaultFont).toLowerCase();\r
-            if(name != this.fontSelect.dom.value){\r
-                this.fontSelect.dom.value = name;\r
-            }\r
-        }\r
-        if(this.enableFormat){\r
-            btns.bold.toggle(doc.queryCommandState('bold'));\r
-            btns.italic.toggle(doc.queryCommandState('italic'));\r
-            btns.underline.toggle(doc.queryCommandState('underline'));\r
-        }\r
-        if(this.enableAlignments){\r
-            btns.justifyleft.toggle(doc.queryCommandState('justifyleft'));\r
-            btns.justifycenter.toggle(doc.queryCommandState('justifycenter'));\r
-            btns.justifyright.toggle(doc.queryCommandState('justifyright'));\r
-        }\r
-        if(!Ext.isSafari2 && this.enableLists){\r
-            btns.insertorderedlist.toggle(doc.queryCommandState('insertorderedlist'));\r
-            btns.insertunorderedlist.toggle(doc.queryCommandState('insertunorderedlist'));\r
-        }\r
-        \r
-        Ext.menu.MenuMgr.hideAll();\r
-\r
-        this.syncValue();\r
-    },\r
-\r
-    // private\r
-    relayBtnCmd : function(btn){\r
-        this.relayCmd(btn.getItemId());\r
-    },\r
-\r
     /**\r
-     * Executes a Midas editor command on the editor document and performs necessary focus and\r
-     * toolbar updates. <b>This should only be called after the editor is initialized.</b>\r
-     * @param {String} cmd The Midas command\r
-     * @param {String/Boolean} value (optional) The value to pass to the command (defaults to null)\r
+     * @cfg {String} checkboxName The name to assign to the fieldset's checkbox if <tt>{@link #checkboxToggle} = true</tt>\r
+     * (defaults to <tt>'[checkbox id]-checkbox'</tt>).\r
      */\r
-    relayCmd : function(cmd, value){\r
-        (function(){\r
-            this.focus();\r
-            this.execCmd(cmd, value);\r
-            this.updateToolbar();\r
-        }).defer(10, this);\r
-    },\r
-\r
     /**\r
-     * Executes a Midas editor command directly on the editor document.\r
-     * For visual commands, you should use {@link #relayCmd} instead.\r
-     * <b>This should only be called after the editor is initialized.</b>\r
-     * @param {String} cmd The Midas command\r
-     * @param {String/Boolean} value (optional) The value to pass to the command (defaults to null)\r
+     * @cfg {Boolean} collapsible\r
+     * <tt>true</tt> to make the fieldset collapsible and have the expand/collapse toggle button automatically\r
+     * rendered into the legend element, <tt>false</tt> to keep the fieldset statically sized with no collapse\r
+     * button (defaults to <tt>false</tt>). Another option is to configure <tt>{@link #checkboxToggle}</tt>.\r
      */\r
-    execCmd : function(cmd, value){\r
-        this.doc.execCommand(cmd, false, value === undefined ? null : value);\r
-        this.syncValue();\r
-    },\r
+    /**\r
+     * @cfg {Number} labelWidth The width of labels. This property cascades to child containers.\r
+     */\r
+    /**\r
+     * @cfg {String} itemCls A css class to apply to the <tt>x-form-item</tt> of fields (see \r
+     * {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl} for details).\r
+     * This property cascades to child containers.\r
+     */\r
+    /**\r
+     * @cfg {String} baseCls The base CSS class applied to the fieldset (defaults to <tt>'x-fieldset'</tt>).\r
+     */\r
+    baseCls : 'x-fieldset',\r
+    /**\r
+     * @cfg {String} layout The {@link Ext.Container#layout} to use inside the fieldset (defaults to <tt>'form'</tt>).\r
+     */\r
+    layout : 'form',\r
+    /**\r
+     * @cfg {Boolean} animCollapse\r
+     * <tt>true</tt> to animate the transition when the panel is collapsed, <tt>false</tt> to skip the\r
+     * animation (defaults to <tt>false</tt>).\r
+     */\r
+    animCollapse : false,\r
 \r
     // private\r
-    applyCommand : function(e){\r
-        if(e.ctrlKey){\r
-            var c = e.getCharCode(), cmd;\r
-            if(c > 0){\r
-                c = String.fromCharCode(c);\r
-                switch(c){\r
-                    case 'b':\r
-                        cmd = 'bold';\r
-                    break;\r
-                    case 'i':\r
-                        cmd = 'italic';\r
-                    break;\r
-                    case 'u':\r
-                        cmd = 'underline';\r
-                    break;\r
-                }\r
-                if(cmd){\r
-                    this.win.focus();\r
-                    this.execCmd(cmd);\r
-                    this.deferFocus();\r
-                    e.preventDefault();\r
-                }\r
+    onRender : function(ct, position){\r
+        if(!this.el){\r
+            this.el = document.createElement('fieldset');\r
+            this.el.id = this.id;\r
+            if (this.title || this.header || this.checkboxToggle) {\r
+                this.el.appendChild(document.createElement('legend')).className = this.baseCls + '-header';\r
             }\r
         }\r
-    },\r
 \r
-    /**\r
-     * Inserts the passed text at the current cursor position. Note: the editor must be initialized and activated\r
-     * to insert text.\r
-     * @param {String} text\r
-     */\r
-    insertAtCursor : function(text){\r
-        if(!this.activated){\r
-            return;\r
-        }\r
-        if(Ext.isIE){\r
-            this.win.focus();\r
-            var r = this.doc.selection.createRange();\r
-            if(r){\r
-                r.collapse(true);\r
-                r.pasteHTML(text);\r
-                this.syncValue();\r
-                this.deferFocus();\r
-            }\r
-        }else{\r
-            this.win.focus();\r
-            this.execCmd('InsertHTML', text);\r
-            this.deferFocus();\r
+        Ext.form.FieldSet.superclass.onRender.call(this, ct, position);\r
+\r
+        if(this.checkboxToggle){\r
+            var o = typeof this.checkboxToggle == 'object' ?\r
+                    this.checkboxToggle :\r
+                    {tag: 'input', type: 'checkbox', name: this.checkboxName || this.id+'-checkbox'};\r
+            this.checkbox = this.header.insertFirst(o);\r
+            this.checkbox.dom.checked = !this.collapsed;\r
+            this.mon(this.checkbox, 'click', this.onCheckClick, this);\r
         }\r
     },\r
 \r
     // private\r
-    fixKeys : function(){ // load time branching for fastest keydown performance\r
-        if(Ext.isIE){\r
-            return function(e){\r
-                var k = e.getKey(), r;\r
-                if(k == e.TAB){\r
-                    e.stopEvent();\r
-                    r = this.doc.selection.createRange();\r
-                    if(r){\r
-                        r.collapse(true);\r
-                        r.pasteHTML('&nbsp;&nbsp;&nbsp;&nbsp;');\r
-                        this.deferFocus();\r
-                    }\r
-                }else if(k == e.ENTER){\r
-                    r = this.doc.selection.createRange();\r
-                    if(r){\r
-                        var target = r.parentElement();\r
-                        if(!target || target.tagName.toLowerCase() != 'li'){\r
-                            e.stopEvent();\r
-                            r.pasteHTML('<br />');\r
-                            r.collapse(false);\r
-                            r.select();\r
-                        }\r
-                    }\r
-                }\r
-            };\r
-        }else if(Ext.isOpera){\r
-            return function(e){\r
-                var k = e.getKey();\r
-                if(k == e.TAB){\r
-                    e.stopEvent();\r
-                    this.win.focus();\r
-                    this.execCmd('InsertHTML','&nbsp;&nbsp;&nbsp;&nbsp;');\r
-                    this.deferFocus();\r
-                }\r
-            };\r
-        }else if(Ext.isWebKit){\r
-            return function(e){\r
-                var k = e.getKey();\r
-                if(k == e.TAB){\r
-                    e.stopEvent();\r
-                    this.execCmd('InsertText','\t');\r
-                    this.deferFocus();\r
-                }else if(k == e.ENTER){\r
-                    e.stopEvent();\r
-                    this.execCmd('InsertHtml','<br /><br />');\r
-                    this.deferFocus();\r
-                }\r
-             };\r
+    onCollapse : function(doAnim, animArg){\r
+        if(this.checkbox){\r
+            this.checkbox.dom.checked = false;\r
         }\r
-    }(),\r
+        Ext.form.FieldSet.superclass.onCollapse.call(this, doAnim, animArg);\r
 \r
-    /**\r
-     * Returns the editor's toolbar. <b>This is only available after the editor has been rendered.</b>\r
-     * @return {Ext.Toolbar}\r
-     */\r
-    getToolbar : function(){\r
-        return this.tb;\r
     },\r
 \r
-    /**\r
-     * Object collection of toolbar tooltips for the buttons in the editor. The key\r
-     * is the command id associated with that button and the value is a valid QuickTips object.\r
-     * For example:\r
-<pre><code>\r
-{\r
-    bold : {\r
-        title: 'Bold (Ctrl+B)',\r
-        text: 'Make the selected text bold.',\r
-        cls: 'x-html-editor-tip'\r
-    },\r
-    italic : {\r
-        title: 'Italic (Ctrl+I)',\r
-        text: 'Make the selected text italic.',\r
-        cls: 'x-html-editor-tip'\r
+    // private\r
+    onExpand : function(doAnim, animArg){\r
+        if(this.checkbox){\r
+            this.checkbox.dom.checked = true;\r
+        }\r
+        Ext.form.FieldSet.superclass.onExpand.call(this, doAnim, animArg);\r
     },\r
-    ...\r
-</code></pre>\r
-    * @type Object\r
+\r
+    /**\r
+     * This function is called by the fieldset's checkbox when it is toggled (only applies when\r
+     * checkboxToggle = true).  This method should never be called externally, but can be\r
+     * overridden to provide custom behavior when the checkbox is toggled if needed.\r
      */\r
-    buttonTips : {\r
-        bold : {\r
-            title: 'Bold (Ctrl+B)',\r
-            text: 'Make the selected text bold.',\r
-            cls: 'x-html-editor-tip'\r
-        },\r
-        italic : {\r
-            title: 'Italic (Ctrl+I)',\r
-            text: 'Make the selected text italic.',\r
-            cls: 'x-html-editor-tip'\r
-        },\r
-        underline : {\r
-            title: 'Underline (Ctrl+U)',\r
-            text: 'Underline the selected text.',\r
-            cls: 'x-html-editor-tip'\r
-        },\r
-        increasefontsize : {\r
-            title: 'Grow Text',\r
-            text: 'Increase the font size.',\r
-            cls: 'x-html-editor-tip'\r
-        },\r
-        decreasefontsize : {\r
-            title: 'Shrink Text',\r
-            text: 'Decrease the font size.',\r
-            cls: 'x-html-editor-tip'\r
-        },\r
-        backcolor : {\r
-            title: 'Text Highlight Color',\r
-            text: 'Change the background color of the selected text.',\r
-            cls: 'x-html-editor-tip'\r
-        },\r
-        forecolor : {\r
-            title: 'Font Color',\r
-            text: 'Change the color of the selected text.',\r
-            cls: 'x-html-editor-tip'\r
-        },\r
-        justifyleft : {\r
-            title: 'Align Text Left',\r
-            text: 'Align text to the left.',\r
-            cls: 'x-html-editor-tip'\r
-        },\r
-        justifycenter : {\r
-            title: 'Center Text',\r
-            text: 'Center text in the editor.',\r
-            cls: 'x-html-editor-tip'\r
-        },\r
-        justifyright : {\r
-            title: 'Align Text Right',\r
-            text: 'Align text to the right.',\r
-            cls: 'x-html-editor-tip'\r
-        },\r
-        insertunorderedlist : {\r
-            title: 'Bullet List',\r
-            text: 'Start a bulleted list.',\r
-            cls: 'x-html-editor-tip'\r
-        },\r
-        insertorderedlist : {\r
-            title: 'Numbered List',\r
-            text: 'Start a numbered list.',\r
-            cls: 'x-html-editor-tip'\r
-        },\r
-        createlink : {\r
-            title: 'Hyperlink',\r
-            text: 'Make the selected text a hyperlink.',\r
-            cls: 'x-html-editor-tip'\r
-        },\r
-        sourceedit : {\r
-            title: 'Source Edit',\r
-            text: 'Switch to source editing mode.',\r
-            cls: 'x-html-editor-tip'\r
-        }\r
+    onCheckClick : function(){\r
+        this[this.checkbox.dom.checked ? 'expand' : 'collapse']();\r
     }\r
 \r
-    // hide stuff that is not compatible\r
     /**\r
-     * @event blur\r
+     * @cfg {String/Number} activeItem\r
+     * @hide\r
+     */\r
+    /**\r
+     * @cfg {Mixed} applyTo\r
      * @hide\r
      */\r
     /**\r
-     * @event change\r
+     * @cfg {Boolean} bodyBorder\r
      * @hide\r
      */\r
     /**\r
-     * @event focus\r
+     * @cfg {Boolean} border\r
      * @hide\r
      */\r
     /**\r
-     * @event specialkey\r
+     * @cfg {Boolean/Number} bufferResize\r
      * @hide\r
      */\r
     /**\r
-     * @cfg {String} fieldClass @hide\r
+     * @cfg {Boolean} collapseFirst\r
+     * @hide\r
      */\r
     /**\r
-     * @cfg {String} focusClass @hide\r
+     * @cfg {String} defaultType\r
+     * @hide\r
      */\r
     /**\r
-     * @cfg {String} autoCreate @hide\r
+     * @cfg {String} disabledClass\r
+     * @hide\r
      */\r
     /**\r
-     * @cfg {String} inputType @hide\r
+     * @cfg {String} elements\r
+     * @hide\r
      */\r
     /**\r
-     * @cfg {String} invalidClass @hide\r
+     * @cfg {Boolean} floating\r
+     * @hide\r
      */\r
     /**\r
-     * @cfg {String} invalidText @hide\r
+     * @cfg {Boolean} footer\r
+     * @hide\r
      */\r
     /**\r
-     * @cfg {String} msgFx @hide\r
+     * @cfg {Boolean} frame\r
+     * @hide\r
      */\r
     /**\r
-     * @cfg {String} validateOnBlur @hide\r
+     * @cfg {Boolean} header\r
+     * @hide\r
      */\r
     /**\r
-     * @cfg {Boolean} allowDomMove  @hide\r
+     * @cfg {Boolean} headerAsText\r
+     * @hide\r
      */\r
     /**\r
-     * @cfg {String} applyTo @hide\r
+     * @cfg {Boolean} hideCollapseTool\r
+     * @hide\r
      */\r
     /**\r
-     * @cfg {String} autoHeight  @hide\r
+     * @cfg {String} iconCls\r
+     * @hide\r
      */\r
     /**\r
-     * @cfg {String} autoWidth  @hide\r
+     * @cfg {Boolean/String} shadow\r
+     * @hide\r
      */\r
     /**\r
-     * @cfg {String} cls  @hide\r
+     * @cfg {Number} shadowOffset\r
+     * @hide\r
      */\r
     /**\r
-     * @cfg {String} disabled  @hide\r
+     * @cfg {Boolean} shim\r
+     * @hide\r
      */\r
     /**\r
-     * @cfg {String} disabledClass  @hide\r
+     * @cfg {Object/Array} tbar\r
+     * @hide\r
      */\r
     /**\r
-     * @cfg {String} msgTarget  @hide\r
+     * @cfg {Array} tools\r
+     * @hide\r
      */\r
     /**\r
-     * @cfg {String} readOnly  @hide\r
+     * @cfg {Ext.Template/Ext.XTemplate} toolTemplate\r
+     * @hide\r
      */\r
     /**\r
-     * @cfg {String} style  @hide\r
+     * @cfg {String} xtype\r
+     * @hide\r
      */\r
     /**\r
-     * @cfg {String} validationDelay  @hide\r
+     * @property header\r
+     * @hide\r
      */\r
     /**\r
-     * @cfg {String} validationEvent  @hide\r
+     * @property footer\r
+     * @hide\r
      */\r
     /**\r
-     * @cfg {String} tabIndex  @hide\r
+     * @method focus\r
+     * @hide\r
      */\r
     /**\r
-     * @property disabled\r
+     * @method getBottomToolbar\r
      * @hide\r
      */\r
     /**\r
-     * @method applyToMarkup\r
+     * @method getTopToolbar\r
      * @hide\r
      */\r
     /**\r
-     * @method disable\r
+     * @method setIconClass\r
      * @hide\r
      */\r
     /**\r
-     * @method enable\r
+     * @event activate\r
      * @hide\r
      */\r
     /**\r
-     * @method validate\r
+     * @event beforeclose\r
      * @hide\r
      */\r
     /**\r
-     * @event valid\r
+     * @event bodyresize\r
      * @hide\r
      */\r
     /**\r
-     * @method setDisabled\r
+     * @event close\r
      * @hide\r
      */\r
     /**\r
-     * @cfg keys\r
+     * @event deactivate\r
      * @hide\r
      */\r
 });\r
+Ext.reg('fieldset', Ext.form.FieldSet);\r
+/**
+ * @class Ext.form.HtmlEditor
+ * @extends Ext.form.Field
+ * Provides a lightweight HTML Editor component. Some toolbar features are not supported by Safari and will be
+ * automatically hidden when needed.  These are noted in the config options where appropriate.
+ * <br><br>The editor's toolbar buttons have tooltips defined in the {@link #buttonTips} property, but they are not
+ * enabled by default unless the global {@link Ext.QuickTips} singleton is {@link Ext.QuickTips#init initialized}.
+ * <br><br><b>Note: The focus/blur and validation marking functionality inherited from Ext.form.Field is NOT
+ * supported by this editor.</b>
+ * <br><br>An Editor is a sensitive component that can't be used in all spots standard fields can be used. Putting an Editor within
+ * any element that has display set to 'none' can cause problems in Safari and Firefox due to their default iframe reloading bugs.
+ * <br><br>Example usage:
+ * <pre><code>
+// Simple example rendered with default options:
+Ext.QuickTips.init();  // enable tooltips
+new Ext.form.HtmlEditor({
+    renderTo: Ext.getBody(),
+    width: 800,
+    height: 300
+});
+
+// Passed via xtype into a container and with custom options:
+Ext.QuickTips.init();  // enable tooltips
+new Ext.Panel({
+    title: 'HTML Editor',
+    renderTo: Ext.getBody(),
+    width: 600,
+    height: 300,
+    frame: true,
+    layout: 'fit',
+    items: {
+        xtype: 'htmleditor',
+        enableColors: false,
+        enableAlignments: false
+    }
+});
+</code></pre>
+ * @constructor
+ * Create a new HtmlEditor
+ * @param {Object} config
+ * @xtype htmleditor
+ */
+
+Ext.form.HtmlEditor = Ext.extend(Ext.form.Field, {
+    /**
+     * @cfg {Boolean} enableFormat Enable the bold, italic and underline buttons (defaults to true)
+     */
+    enableFormat : true,
+    /**
+     * @cfg {Boolean} enableFontSize Enable the increase/decrease font size buttons (defaults to true)
+     */
+    enableFontSize : true,
+    /**
+     * @cfg {Boolean} enableColors Enable the fore/highlight color buttons (defaults to true)
+     */
+    enableColors : true,
+    /**
+     * @cfg {Boolean} enableAlignments Enable the left, center, right alignment buttons (defaults to true)
+     */
+    enableAlignments : true,
+    /**
+     * @cfg {Boolean} enableLists Enable the bullet and numbered list buttons. Not available in Safari. (defaults to true)
+     */
+    enableLists : true,
+    /**
+     * @cfg {Boolean} enableSourceEdit Enable the switch to source edit button. Not available in Safari. (defaults to true)
+     */
+    enableSourceEdit : true,
+    /**
+     * @cfg {Boolean} enableLinks Enable the create link button. Not available in Safari. (defaults to true)
+     */
+    enableLinks : true,
+    /**
+     * @cfg {Boolean} enableFont Enable font selection. Not available in Safari. (defaults to true)
+     */
+    enableFont : true,
+    /**
+     * @cfg {String} createLinkText The default text for the create link prompt
+     */
+    createLinkText : 'Please enter the URL for the link:',
+    /**
+     * @cfg {String} defaultLinkValue The default value for the create link prompt (defaults to http:/ /)
+     */
+    defaultLinkValue : 'http:/'+'/',
+    /**
+     * @cfg {Array} fontFamilies An array of available font families
+     */
+    fontFamilies : [
+        'Arial',
+        'Courier New',
+        'Tahoma',
+        'Times New Roman',
+        'Verdana'
+    ],
+    defaultFont: 'tahoma',
+    /**
+     * @cfg {String} defaultValue A default value to be put into the editor to resolve focus issues (defaults to &#160; (Non-breaking space) in Opera and IE6, &#8203; (Zero-width space) in all other browsers).
+     */
+    defaultValue: (Ext.isOpera || Ext.isIE6) ? '&#160;' : '&#8203;',
+
+    // private properties
+    actionMode: 'wrap',
+    validationEvent : false,
+    deferHeight: true,
+    initialized : false,
+    activated : false,
+    sourceEditMode : false,
+    onFocus : Ext.emptyFn,
+    iframePad:3,
+    hideMode:'offsets',
+    defaultAutoCreate : {
+        tag: "textarea",
+        style:"width:500px;height:300px;",
+        autocomplete: "off"
+    },
+
+    // private
+    initComponent : function(){
+        this.addEvents(
+            /**
+             * @event initialize
+             * Fires when the editor is fully initialized (including the iframe)
+             * @param {HtmlEditor} this
+             */
+            'initialize',
+            /**
+             * @event activate
+             * Fires when the editor is first receives the focus. Any insertion must wait
+             * until after this event.
+             * @param {HtmlEditor} this
+             */
+            'activate',
+             /**
+             * @event beforesync
+             * Fires before the textarea is updated with content from the editor iframe. Return false
+             * to cancel the sync.
+             * @param {HtmlEditor} this
+             * @param {String} html
+             */
+            'beforesync',
+             /**
+             * @event beforepush
+             * Fires before the iframe editor is updated with content from the textarea. Return false
+             * to cancel the push.
+             * @param {HtmlEditor} this
+             * @param {String} html
+             */
+            'beforepush',
+             /**
+             * @event sync
+             * Fires when the textarea is updated with content from the editor iframe.
+             * @param {HtmlEditor} this
+             * @param {String} html
+             */
+            'sync',
+             /**
+             * @event push
+             * Fires when the iframe editor is updated with content from the textarea.
+             * @param {HtmlEditor} this
+             * @param {String} html
+             */
+            'push',
+             /**
+             * @event editmodechange
+             * Fires when the editor switches edit modes
+             * @param {HtmlEditor} this
+             * @param {Boolean} sourceEdit True if source edit, false if standard editing.
+             */
+            'editmodechange'
+        )
+    },
+
+    // private
+    createFontOptions : function(){
+        var buf = [], fs = this.fontFamilies, ff, lc;
+        for(var i = 0, len = fs.length; i< len; i++){
+            ff = fs[i];
+            lc = ff.toLowerCase();
+            buf.push(
+                '<option value="',lc,'" style="font-family:',ff,';"',
+                    (this.defaultFont == lc ? ' selected="true">' : '>'),
+                    ff,
+                '</option>'
+            );
+        }
+        return buf.join('');
+    },
+
+    /*
+     * Protected method that will not generally be called directly. It
+     * is called when the editor creates its toolbar. Override this method if you need to
+     * add custom toolbar buttons.
+     * @param {HtmlEditor} editor
+     */
+    createToolbar : function(editor){
+        var items = [];
+        var tipsEnabled = Ext.QuickTips && Ext.QuickTips.isEnabled();\r
+
+
+        function btn(id, toggle, handler){
+            return {
+                itemId : id,
+                cls : 'x-btn-icon',
+                iconCls: 'x-edit-'+id,
+                enableToggle:toggle !== false,
+                scope: editor,
+                handler:handler||editor.relayBtnCmd,
+                clickEvent:'mousedown',
+                tooltip: tipsEnabled ? editor.buttonTips[id] || undefined : undefined,
+                overflowText: editor.buttonTips[id].title || undefined,
+                tabIndex:-1
+            };
+        }
+
+
+        if(this.enableFont && !Ext.isSafari2){\r
+            var fontSelectItem = new Ext.Toolbar.Item({\r
+               autoEl: {\r
+                    tag:'select',\r
+                    cls:'x-font-select',\r
+                    html: this.createFontOptions()\r
+               }\r
+            });
+
+            items.push(
+                fontSelectItem,
+                '-'
+            );
+        }
+
+        if(this.enableFormat){
+            items.push(
+                btn('bold'),
+                btn('italic'),
+                btn('underline')
+            );
+        }
+
+        if(this.enableFontSize){
+            items.push(
+                '-',
+                btn('increasefontsize', false, this.adjustFont),
+                btn('decreasefontsize', false, this.adjustFont)
+            );
+        }
+
+        if(this.enableColors){
+            items.push(
+                '-', {
+                    itemId:'forecolor',
+                    cls:'x-btn-icon',
+                    iconCls: 'x-edit-forecolor',
+                    clickEvent:'mousedown',
+                    tooltip: tipsEnabled ? editor.buttonTips.forecolor || undefined : undefined,
+                    tabIndex:-1,
+                    menu : new Ext.menu.ColorMenu({
+                        allowReselect: true,
+                        focus: Ext.emptyFn,
+                        value:'000000',
+                        plain:true,
+                        listeners: {
+                            scope: this,
+                            select: function(cp, color){
+                                this.execCmd('forecolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
+                                this.deferFocus();
+                            }
+                        },
+                        clickEvent:'mousedown'
+                    })
+                }, {
+                    itemId:'backcolor',
+                    cls:'x-btn-icon',
+                    iconCls: 'x-edit-backcolor',
+                    clickEvent:'mousedown',
+                    tooltip: tipsEnabled ? editor.buttonTips.backcolor || undefined : undefined,
+                    tabIndex:-1,
+                    menu : new Ext.menu.ColorMenu({
+                        focus: Ext.emptyFn,
+                        value:'FFFFFF',
+                        plain:true,
+                        allowReselect: true,
+                        listeners: {
+                            scope: this,
+                            select: function(cp, color){
+                                if(Ext.isGecko){
+                                    this.execCmd('useCSS', false);
+                                    this.execCmd('hilitecolor', color);
+                                    this.execCmd('useCSS', true);
+                                    this.deferFocus();
+                                }else{
+                                    this.execCmd(Ext.isOpera ? 'hilitecolor' : 'backcolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
+                                    this.deferFocus();
+                                }
+                            }
+                        },
+                        clickEvent:'mousedown'
+                    })
+                }
+            );
+        }
+
+        if(this.enableAlignments){
+            items.push(
+                '-',
+                btn('justifyleft'),
+                btn('justifycenter'),
+                btn('justifyright')
+            );
+        }
+
+        if(!Ext.isSafari2){
+            if(this.enableLinks){
+                items.push(
+                    '-',
+                    btn('createlink', false, this.createLink)
+                );
+            }
+
+            if(this.enableLists){
+                items.push(
+                    '-',
+                    btn('insertorderedlist'),
+                    btn('insertunorderedlist')
+                );
+            }
+            if(this.enableSourceEdit){
+                items.push(
+                    '-',
+                    btn('sourceedit', true, function(btn){
+                        this.toggleSourceEdit(!this.sourceEditMode);
+                    })
+                );
+            }
+        }\r
+\r
+        // build the toolbar\r
+        var tb = new Ext.Toolbar({\r
+            renderTo: this.wrap.dom.firstChild,\r
+            items: items\r
+        });\r
+\r
+        if (fontSelectItem) {\r
+            this.fontSelect = fontSelectItem.el;\r
+\r
+            this.mon(this.fontSelect, 'change', function(){\r
+                var font = this.fontSelect.dom.value;\r
+                this.relayCmd('fontname', font);\r
+                this.deferFocus();\r
+            }, this);\r
+        }\r
+\r
+\r
+        // stop form submits\r
+        this.mon(tb.el, 'click', function(e){\r
+            e.preventDefault();\r
+        });\r
+
+        this.tb = tb;
+    },
+
+    onDisable: function(){
+        this.wrap.mask();
+        Ext.form.HtmlEditor.superclass.onDisable.call(this);
+    },
+
+    onEnable: function(){
+        this.wrap.unmask();
+        Ext.form.HtmlEditor.superclass.onEnable.call(this);
+    },
+
+    setReadOnly: function(readOnly){
+
+        Ext.form.HtmlEditor.superclass.setReadOnly.call(this, readOnly);
+        if(this.initialized){\r
+            this.setDesignMode(!readOnly);\r
+            var bd = this.getEditorBody();\r
+            if(bd){\r
+                bd.style.cursor = this.readOnly ? 'default' : 'text';\r
+            }\r
+            this.disableItems(readOnly);\r
+        }\r
+    },
+
+    /**
+     * Protected method that will not generally be called directly. It
+     * is called when the editor initializes the iframe with HTML contents. Override this method if you
+     * want to change the initialization markup of the iframe (e.g. to add stylesheets).
+     *\r
+     * Note: IE8-Standards has unwanted scroller behavior, so the default meta tag forces IE7 compatibility\r
+     */
+    getDocMarkup : function(){
+        return '<html><head><meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" /><style type="text/css">body{border:0;margin:0;padding:3px;height:98%;cursor:text;}</style></head><body></body></html>';
+    },
+
+    // private
+    getEditorBody : function(){
+        var doc = this.getDoc();
+        return doc.body || doc.documentElement;
+    },
+
+    // private
+    getDoc : function(){
+        return Ext.isIE ? this.getWin().document : (this.iframe.contentDocument || this.getWin().document);
+    },
+
+    // private
+    getWin : function(){
+        return Ext.isIE ? this.iframe.contentWindow : window.frames[this.iframe.name];
+    },
+
+    // private
+    onRender : function(ct, position){
+        Ext.form.HtmlEditor.superclass.onRender.call(this, ct, position);
+        this.el.dom.style.border = '0 none';
+        this.el.dom.setAttribute('tabIndex', -1);
+        this.el.addClass('x-hidden');
+        if(Ext.isIE){ // fix IE 1px bogus margin
+            this.el.applyStyles('margin-top:-1px;margin-bottom:-1px;')
+        }
+        this.wrap = this.el.wrap({
+            cls:'x-html-editor-wrap', cn:{cls:'x-html-editor-tb'}
+        });
+
+        this.createToolbar(this);
+
+        this.disableItems(true);
+
+        this.tb.doLayout();
+
+        this.createIFrame();
+
+        if(!this.width){
+            var sz = this.el.getSize();
+            this.setSize(sz.width, this.height || sz.height);
+        }
+        this.resizeEl = this.positionEl = this.wrap;
+    },
+
+    createIFrame: function(){
+        var iframe = document.createElement('iframe');
+        iframe.name = Ext.id();
+        iframe.frameBorder = '0';
+        iframe.style.overflow = 'auto';\r
+
+        this.wrap.dom.appendChild(iframe);
+        this.iframe = iframe;
+
+        this.monitorTask = Ext.TaskMgr.start({
+            run: this.checkDesignMode,
+            scope: this,
+            interval:100
+        });
+    },
+
+    initFrame : function(){
+        Ext.TaskMgr.stop(this.monitorTask);
+        var doc = this.getDoc();
+        this.win = this.getWin();
+
+        doc.open();
+        doc.write(this.getDocMarkup());
+        doc.close();
+
+        var task = { // must defer to wait for browser to be ready
+            run : function(){
+                var doc = this.getDoc();
+                if(doc.body || doc.readyState == 'complete'){
+                    Ext.TaskMgr.stop(task);
+                    this.setDesignMode(true);
+                    this.initEditor.defer(10, this);
+                }
+            },
+            interval : 10,
+            duration:10000,
+            scope: this
+        };
+        Ext.TaskMgr.start(task);
+    },
+
+
+    checkDesignMode : function(){
+        if(this.wrap && this.wrap.dom.offsetWidth){
+            var doc = this.getDoc();
+            if(!doc){
+                return;
+            }
+            if(!doc.editorInitialized || this.getDesignMode() != 'on'){
+                this.initFrame();
+            }
+        }
+    },
+\r
+    /* private\r
+     * set current design mode. To enable, mode can be true or 'on', off otherwise\r
+     */\r
+    setDesignMode : function(mode){\r
+        var doc ;\r
+        if(doc = this.getDoc()){\r
+            if(this.readOnly){\r
+                mode = false;\r
+            }\r
+            doc.designMode = (/on|true/i).test(String(mode).toLowerCase()) ?'on':'off';\r
+        }\r
+\r
+    },\r
+\r
+    // private\r
+    getDesignMode : function(){
+        var doc = this.getDoc();\r
+        if(!doc){ return ''; }\r
+        return String(doc.designMode).toLowerCase();\r
+\r
+    },\r
+\r
+    disableItems: function(disabled){
+        if(this.fontSelect){
+            this.fontSelect.dom.disabled = disabled;
+        }
+        this.tb.items.each(function(item){
+            if(item.getItemId() != 'sourceedit'){
+                item.setDisabled(disabled);
+            }
+        });
+    },
+
+    // private
+    onResize : function(w, h){
+        Ext.form.HtmlEditor.superclass.onResize.apply(this, arguments);
+        if(this.el && this.iframe){
+            if(Ext.isNumber(w)){
+                var aw = w - this.wrap.getFrameWidth('lr');
+                this.el.setWidth(aw);
+                this.tb.setWidth(aw);
+                this.iframe.style.width = Math.max(aw, 0) + 'px';
+            }
+            if(Ext.isNumber(h)){
+                var ah = h - this.wrap.getFrameWidth('tb') - this.tb.el.getHeight();
+                this.el.setHeight(ah);
+                this.iframe.style.height = Math.max(ah, 0) + 'px';
+                var bd = this.getEditorBody();
+                if(bd){
+                    bd.style.height = Math.max((ah - (this.iframePad*2)), 0) + 'px';
+                }
+            }
+        }
+    },
+
+    /**
+     * Toggles the editor between standard and source edit mode.
+     * @param {Boolean} sourceEdit (optional) True for source edit, false for standard
+     */
+    toggleSourceEdit : function(sourceEditMode){
+        if(sourceEditMode === undefined){
+            sourceEditMode = !this.sourceEditMode;
+        }
+        this.sourceEditMode = sourceEditMode === true;
+        var btn = this.tb.getComponent('sourceedit');
+
+        if(btn.pressed !== this.sourceEditMode){
+            btn.toggle(this.sourceEditMode);
+            if(!btn.xtbHidden){
+                return;
+            }
+        }
+        if(this.sourceEditMode){
+            this.disableItems(true);
+            this.syncValue();
+            this.iframe.className = 'x-hidden';
+            this.el.removeClass('x-hidden');
+            this.el.dom.removeAttribute('tabIndex');
+            this.el.focus();
+        }else{
+            if(this.initialized){
+                this.disableItems(this.readOnly);
+            }
+            this.pushValue();
+            this.iframe.className = '';
+            this.el.addClass('x-hidden');
+            this.el.dom.setAttribute('tabIndex', -1);
+            this.deferFocus();
+        }
+        var lastSize = this.lastSize;
+        if(lastSize){
+            delete this.lastSize;
+            this.setSize(lastSize);
+        }
+        this.fireEvent('editmodechange', this, this.sourceEditMode);
+    },
+
+    // private used internally
+    createLink : function(){
+        var url = prompt(this.createLinkText, this.defaultLinkValue);
+        if(url && url != 'http:/'+'/'){
+            this.relayCmd('createlink', url);
+        }
+    },
+
+    // private
+    initEvents : function(){
+        this.originalValue = this.getValue();
+    },
+
+    /**
+     * Overridden and disabled. The editor element does not support standard valid/invalid marking. @hide
+     * @method
+     */
+    markInvalid : Ext.emptyFn,
+
+    /**
+     * Overridden and disabled. The editor element does not support standard valid/invalid marking. @hide
+     * @method
+     */
+    clearInvalid : Ext.emptyFn,
+
+    // docs inherit from Field
+    setValue : function(v){
+        Ext.form.HtmlEditor.superclass.setValue.call(this, v);
+        this.pushValue();
+        return this;
+    },
+
+    /**
+     * Protected method that will not generally be called directly. If you need/want
+     * custom HTML cleanup, this is the method you should override.
+     * @param {String} html The HTML to be cleaned
+     * @return {String} The cleaned HTML
+     */
+    cleanHtml: function(html) {
+        html = String(html);
+        if(Ext.isWebKit){ // strip safari nonsense
+            html = html.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi, '');
+        }
+
+        /*
+         * Neat little hack. Strips out all the non-digit characters from the default
+         * value and compares it to the character code of the first character in the string
+         * because it can cause encoding issues when posted to the server.
+         */
+        if(html.charCodeAt(0) == this.defaultValue.replace(/\D/g, '')){
+            html = html.substring(1);
+        }
+        return html;
+    },
+
+    /**
+     * Protected method that will not generally be called directly. Syncs the contents
+     * of the editor iframe with the textarea.
+     */
+    syncValue : function(){
+        if(this.initialized){
+            var bd = this.getEditorBody();
+            var html = bd.innerHTML;
+            if(Ext.isWebKit){
+                var bs = bd.getAttribute('style'); // Safari puts text-align styles on the body element!
+                var m = bs.match(/text-align:(.*?);/i);
+                if(m && m[1]){
+                    html = '<div style="'+m[0]+'">' + html + '</div>';
+                }
+            }
+            html = this.cleanHtml(html);
+            if(this.fireEvent('beforesync', this, html) !== false){
+                this.el.dom.value = html;
+                this.fireEvent('sync', this, html);
+            }
+        }
+    },
+
+    //docs inherit from Field
+    getValue : function() {
+        this[this.sourceEditMode ? 'pushValue' : 'syncValue']();
+        return Ext.form.HtmlEditor.superclass.getValue.call(this);
+    },
+
+    /**
+     * Protected method that will not generally be called directly. Pushes the value of the textarea
+     * into the iframe editor.
+     */
+    pushValue : function(){
+        if(this.initialized){
+            var v = this.el.dom.value;
+            if(!this.activated && v.length < 1){
+                v = this.defaultValue;
+            }
+            if(this.fireEvent('beforepush', this, v) !== false){
+                this.getEditorBody().innerHTML = v;
+                if(Ext.isGecko){
+                    // Gecko hack, see: https://bugzilla.mozilla.org/show_bug.cgi?id=232791#c8
+                    this.setDesignMode(false);  //toggle off first\r
+\r
+                }
+                this.setDesignMode(true);\r
+                this.fireEvent('push', this, v);
+            }
+\r
+        }
+    },
+
+    // private
+    deferFocus : function(){
+        this.focus.defer(10, this);
+    },
+
+    // docs inherit from Field
+    focus : function(){
+        if(this.win && !this.sourceEditMode){
+            this.win.focus();
+        }else{
+            this.el.focus();
+        }
+    },
+
+    // private
+    initEditor : function(){
+        //Destroying the component during/before initEditor can cause issues.
+        try{
+            var dbody = this.getEditorBody(),
+                ss = this.el.getStyles('font-size', 'font-family', 'background-image', 'background-repeat'),
+                doc,
+                fn;
+
+            ss['background-attachment'] = 'fixed'; // w3c
+            dbody.bgProperties = 'fixed'; // ie
+
+            Ext.DomHelper.applyStyles(dbody, ss);
+
+            doc = this.getDoc();
+
+            if(doc){
+                try{
+                    Ext.EventManager.removeAll(doc);
+                }catch(e){}
+            }
+
+            /*
+             * We need to use createDelegate here, because when using buffer, the delayed task is added
+             * as a property to the function. When the listener is removed, the task is deleted from the function.
+             * Since onEditorEvent is shared on the prototype, if we have multiple html editors, the first time one of the editors
+             * is destroyed, it causes the fn to be deleted from the prototype, which causes errors. Essentially, we're just anonymizing the function.
+             */
+            fn = this.onEditorEvent.createDelegate(this);
+            Ext.EventManager.on(doc, {
+                mousedown: fn,
+                dblclick: fn,
+                click: fn,
+                keyup: fn,
+                buffer:100
+            });
+
+            if(Ext.isGecko){
+                Ext.EventManager.on(doc, 'keypress', this.applyCommand, this);
+            }
+            if(Ext.isIE || Ext.isWebKit || Ext.isOpera){
+                Ext.EventManager.on(doc, 'keydown', this.fixKeys, this);
+            }
+            doc.editorInitialized = true;
+            this.initialized = true;
+            this.pushValue();
+            this.setReadOnly(this.readOnly);
+            this.fireEvent('initialize', this);
+        }catch(e){}
+    },
+
+    // private
+    onDestroy : function(){
+        if(this.monitorTask){
+            Ext.TaskMgr.stop(this.monitorTask);
+        }
+        if(this.rendered){
+            Ext.destroy(this.tb);
+            var doc = this.getDoc();
+            if(doc){
+                try{
+                    Ext.EventManager.removeAll(doc);
+                    for (var prop in doc){
+                        delete doc[prop];
+                    }
+                }catch(e){}
+            }
+            if(this.wrap){
+                this.wrap.dom.innerHTML = '';
+                this.wrap.remove();
+            }
+        }
+
+        if(this.el){
+            this.el.removeAllListeners();
+            this.el.remove();
+        }
+        this.purgeListeners();
+    },
+
+    // private
+    onFirstFocus : function(){
+        this.activated = true;
+        this.disableItems(this.readOnly);
+        if(Ext.isGecko){ // prevent silly gecko errors
+            this.win.focus();
+            var s = this.win.getSelection();
+            if(!s.focusNode || s.focusNode.nodeType != 3){
+                var r = s.getRangeAt(0);
+                r.selectNodeContents(this.getEditorBody());
+                r.collapse(true);
+                this.deferFocus();
+            }
+            try{
+                this.execCmd('useCSS', true);
+                this.execCmd('styleWithCSS', false);
+            }catch(e){}
+        }
+        this.fireEvent('activate', this);
+    },
+
+    // private
+    adjustFont: function(btn){
+        var adjust = btn.getItemId() == 'increasefontsize' ? 1 : -1,
+            doc = this.getDoc(),
+            v = parseInt(doc.queryCommandValue('FontSize') || 2, 10);
+        if((Ext.isSafari && !Ext.isSafari2) || Ext.isChrome || Ext.isAir){
+            // Safari 3 values
+            // 1 = 10px, 2 = 13px, 3 = 16px, 4 = 18px, 5 = 24px, 6 = 32px
+            if(v <= 10){
+                v = 1 + adjust;
+            }else if(v <= 13){
+                v = 2 + adjust;
+            }else if(v <= 16){
+                v = 3 + adjust;
+            }else if(v <= 18){
+                v = 4 + adjust;
+            }else if(v <= 24){
+                v = 5 + adjust;
+            }else {
+                v = 6 + adjust;
+            }
+            v = v.constrain(1, 6);
+        }else{
+            if(Ext.isSafari){ // safari
+                adjust *= 2;
+            }
+            v = Math.max(1, v+adjust) + (Ext.isSafari ? 'px' : 0);
+        }
+        this.execCmd('FontSize', v);
+    },
+
+    // private
+    onEditorEvent : function(e){
+        this.updateToolbar();
+    },
+
+
+    /**
+     * Protected method that will not generally be called directly. It triggers
+     * a toolbar update by reading the markup state of the current selection in the editor.
+     */
+    updateToolbar: function(){
+
+        if(this.readOnly){
+            return;
+        }
+
+        if(!this.activated){
+            this.onFirstFocus();
+            return;
+        }
+
+        var btns = this.tb.items.map,
+            doc = this.getDoc();
+
+        if(this.enableFont && !Ext.isSafari2){
+            var name = (doc.queryCommandValue('FontName')||this.defaultFont).toLowerCase();
+            if(name != this.fontSelect.dom.value){
+                this.fontSelect.dom.value = name;
+            }
+        }
+        if(this.enableFormat){
+            btns.bold.toggle(doc.queryCommandState('bold'));
+            btns.italic.toggle(doc.queryCommandState('italic'));
+            btns.underline.toggle(doc.queryCommandState('underline'));
+        }
+        if(this.enableAlignments){
+            btns.justifyleft.toggle(doc.queryCommandState('justifyleft'));
+            btns.justifycenter.toggle(doc.queryCommandState('justifycenter'));
+            btns.justifyright.toggle(doc.queryCommandState('justifyright'));
+        }
+        if(!Ext.isSafari2 && this.enableLists){
+            btns.insertorderedlist.toggle(doc.queryCommandState('insertorderedlist'));
+            btns.insertunorderedlist.toggle(doc.queryCommandState('insertunorderedlist'));
+        }
+
+        Ext.menu.MenuMgr.hideAll();
+
+        this.syncValue();
+    },
+
+    // private
+    relayBtnCmd : function(btn){
+        this.relayCmd(btn.getItemId());
+    },
+
+    /**
+     * Executes a Midas editor command on the editor document and performs necessary focus and
+     * toolbar updates. <b>This should only be called after the editor is initialized.</b>
+     * @param {String} cmd The Midas command
+     * @param {String/Boolean} value (optional) The value to pass to the command (defaults to null)
+     */
+    relayCmd : function(cmd, value){
+        (function(){
+            this.focus();
+            this.execCmd(cmd, value);
+            this.updateToolbar();
+        }).defer(10, this);
+    },
+
+    /**
+     * Executes a Midas editor command directly on the editor document.
+     * For visual commands, you should use {@link #relayCmd} instead.
+     * <b>This should only be called after the editor is initialized.</b>
+     * @param {String} cmd The Midas command
+     * @param {String/Boolean} value (optional) The value to pass to the command (defaults to null)
+     */
+    execCmd : function(cmd, value){
+        var doc = this.getDoc();
+        doc.execCommand(cmd, false, value === undefined ? null : value);
+        this.syncValue();
+    },
+
+    // private
+    applyCommand : function(e){
+        if(e.ctrlKey){
+            var c = e.getCharCode(), cmd;
+            if(c > 0){
+                c = String.fromCharCode(c);
+                switch(c){
+                    case 'b':
+                        cmd = 'bold';
+                    break;
+                    case 'i':
+                        cmd = 'italic';
+                    break;
+                    case 'u':
+                        cmd = 'underline';
+                    break;
+                }
+                if(cmd){
+                    this.win.focus();
+                    this.execCmd(cmd);
+                    this.deferFocus();
+                    e.preventDefault();
+                }
+            }
+        }
+    },
+
+    /**
+     * Inserts the passed text at the current cursor position. Note: the editor must be initialized and activated
+     * to insert text.
+     * @param {String} text
+     */
+    insertAtCursor : function(text){
+        if(!this.activated){
+            return;
+        }
+        if(Ext.isIE){
+            this.win.focus();
+            var doc = this.getDoc(),
+                r = doc.selection.createRange();
+            if(r){
+                r.pasteHTML(text);
+                this.syncValue();
+                this.deferFocus();
+            }
+        }else{
+            this.win.focus();
+            this.execCmd('InsertHTML', text);
+            this.deferFocus();
+        }
+    },
+
+    // private
+    fixKeys : function(){ // load time branching for fastest keydown performance
+        if(Ext.isIE){
+            return function(e){
+                var k = e.getKey(),
+                    doc = this.getDoc(),
+                        r;
+                if(k == e.TAB){
+                    e.stopEvent();
+                    r = doc.selection.createRange();
+                    if(r){
+                        r.collapse(true);
+                        r.pasteHTML('&nbsp;&nbsp;&nbsp;&nbsp;');
+                        this.deferFocus();
+                    }
+                }else if(k == e.ENTER){
+                    r = doc.selection.createRange();
+                    if(r){
+                        var target = r.parentElement();
+                        if(!target || target.tagName.toLowerCase() != 'li'){
+                            e.stopEvent();
+                            r.pasteHTML('<br />');
+                            r.collapse(false);
+                            r.select();
+                        }
+                    }
+                }
+            };
+        }else if(Ext.isOpera){
+            return function(e){
+                var k = e.getKey();
+                if(k == e.TAB){
+                    e.stopEvent();
+                    this.win.focus();
+                    this.execCmd('InsertHTML','&nbsp;&nbsp;&nbsp;&nbsp;');
+                    this.deferFocus();
+                }
+            };
+        }else if(Ext.isWebKit){
+            return function(e){
+                var k = e.getKey();
+                if(k == e.TAB){
+                    e.stopEvent();
+                    this.execCmd('InsertText','\t');
+                    this.deferFocus();
+                }else if(k == e.ENTER){
+                    e.stopEvent();
+                    this.execCmd('InsertHtml','<br /><br />');
+                    this.deferFocus();
+                }
+             };
+        }
+    }(),
+
+    /**
+     * Returns the editor's toolbar. <b>This is only available after the editor has been rendered.</b>
+     * @return {Ext.Toolbar}
+     */
+    getToolbar : function(){
+        return this.tb;
+    },
+
+    /**
+     * Object collection of toolbar tooltips for the buttons in the editor. The key
+     * is the command id associated with that button and the value is a valid QuickTips object.
+     * For example:
+<pre><code>
+{
+    bold : {
+        title: 'Bold (Ctrl+B)',
+        text: 'Make the selected text bold.',
+        cls: 'x-html-editor-tip'
+    },
+    italic : {
+        title: 'Italic (Ctrl+I)',
+        text: 'Make the selected text italic.',
+        cls: 'x-html-editor-tip'
+    },
+    ...
+</code></pre>
+    * @type Object
+     */
+    buttonTips : {
+        bold : {
+            title: 'Bold (Ctrl+B)',
+            text: 'Make the selected text bold.',
+            cls: 'x-html-editor-tip'
+        },
+        italic : {
+            title: 'Italic (Ctrl+I)',
+            text: 'Make the selected text italic.',
+            cls: 'x-html-editor-tip'
+        },
+        underline : {
+            title: 'Underline (Ctrl+U)',
+            text: 'Underline the selected text.',
+            cls: 'x-html-editor-tip'
+        },
+        increasefontsize : {
+            title: 'Grow Text',
+            text: 'Increase the font size.',
+            cls: 'x-html-editor-tip'
+        },
+        decreasefontsize : {
+            title: 'Shrink Text',
+            text: 'Decrease the font size.',
+            cls: 'x-html-editor-tip'
+        },
+        backcolor : {
+            title: 'Text Highlight Color',
+            text: 'Change the background color of the selected text.',
+            cls: 'x-html-editor-tip'
+        },
+        forecolor : {
+            title: 'Font Color',
+            text: 'Change the color of the selected text.',
+            cls: 'x-html-editor-tip'
+        },
+        justifyleft : {
+            title: 'Align Text Left',
+            text: 'Align text to the left.',
+            cls: 'x-html-editor-tip'
+        },
+        justifycenter : {
+            title: 'Center Text',
+            text: 'Center text in the editor.',
+            cls: 'x-html-editor-tip'
+        },
+        justifyright : {
+            title: 'Align Text Right',
+            text: 'Align text to the right.',
+            cls: 'x-html-editor-tip'
+        },
+        insertunorderedlist : {
+            title: 'Bullet List',
+            text: 'Start a bulleted list.',
+            cls: 'x-html-editor-tip'
+        },
+        insertorderedlist : {
+            title: 'Numbered List',
+            text: 'Start a numbered list.',
+            cls: 'x-html-editor-tip'
+        },
+        createlink : {
+            title: 'Hyperlink',
+            text: 'Make the selected text a hyperlink.',
+            cls: 'x-html-editor-tip'
+        },
+        sourceedit : {
+            title: 'Source Edit',
+            text: 'Switch to source editing mode.',
+            cls: 'x-html-editor-tip'
+        }
+    }
+
+    // hide stuff that is not compatible
+    /**
+     * @event blur
+     * @hide
+     */
+    /**
+     * @event change
+     * @hide
+     */
+    /**
+     * @event focus
+     * @hide
+     */
+    /**
+     * @event specialkey
+     * @hide
+     */
+    /**
+     * @cfg {String} fieldClass @hide
+     */
+    /**
+     * @cfg {String} focusClass @hide
+     */
+    /**
+     * @cfg {String} autoCreate @hide
+     */
+    /**
+     * @cfg {String} inputType @hide
+     */
+    /**
+     * @cfg {String} invalidClass @hide
+     */
+    /**
+     * @cfg {String} invalidText @hide
+     */
+    /**
+     * @cfg {String} msgFx @hide
+     */
+    /**
+     * @cfg {String} validateOnBlur @hide
+     */
+    /**
+     * @cfg {Boolean} allowDomMove  @hide
+     */
+    /**
+     * @cfg {String} applyTo @hide
+     */
+    /**
+     * @cfg {String} autoHeight  @hide
+     */
+    /**
+     * @cfg {String} autoWidth  @hide
+     */
+    /**
+     * @cfg {String} cls  @hide
+     */
+    /**
+     * @cfg {String} disabled  @hide
+     */
+    /**
+     * @cfg {String} disabledClass  @hide
+     */
+    /**
+     * @cfg {String} msgTarget  @hide
+     */
+    /**
+     * @cfg {String} readOnly  @hide
+     */
+    /**
+     * @cfg {String} style  @hide
+     */
+    /**
+     * @cfg {String} validationDelay  @hide
+     */
+    /**
+     * @cfg {String} validationEvent  @hide
+     */
+    /**
+     * @cfg {String} tabIndex  @hide
+     */
+    /**
+     * @property disabled
+     * @hide
+     */
+    /**
+     * @method applyToMarkup
+     * @hide
+     */
+    /**
+     * @method disable
+     * @hide
+     */
+    /**
+     * @method enable
+     * @hide
+     */
+    /**
+     * @method validate
+     * @hide
+     */
+    /**
+     * @event valid
+     * @hide
+     */
+    /**
+     * @method setDisabled
+     * @hide
+     */
+    /**
+     * @cfg keys
+     * @hide
+     */
+});
 Ext.reg('htmleditor', Ext.form.HtmlEditor);/**\r
  * @class Ext.form.TimeField\r
  * @extends Ext.form.ComboBox\r
@@ -60086,15 +62718,15 @@ Ext.form.TimeField = Ext.extend(Ext.form.ComboBox, {
     /**\r
      * @cfg {Date/String} minValue\r
      * The minimum allowed time. Can be either a Javascript date object with a valid time value or a string \r
-     * time in a valid format -- see {@link #format} and {@link #altFormats} (defaults to null).\r
+     * time in a valid format -- see {@link #format} and {@link #altFormats} (defaults to undefined).\r
      */\r
-    minValue : null,\r
+    minValue : undefined,\r
     /**\r
      * @cfg {Date/String} maxValue\r
      * The maximum allowed time. Can be either a Javascript date object with a valid time value or a string \r
-     * time in a valid format -- see {@link #format} and {@link #altFormats} (defaults to null).\r
+     * time in a valid format -- see {@link #format} and {@link #altFormats} (defaults to undefined).\r
      */\r
-    maxValue : null,\r
+    maxValue : undefined,\r
     /**\r
      * @cfg {String} minText\r
      * The error text to display when the date in the cell is before minValue (defaults to\r
@@ -60146,26 +62778,67 @@ Ext.form.TimeField = Ext.extend(Ext.form.ComboBox, {
 \r
     // private\r
     initComponent : function(){\r
-        if(typeof this.minValue == "string"){\r
-            this.minValue = this.parseDate(this.minValue);\r
+        if(Ext.isDefined(this.minValue)){\r
+            this.setMinValue(this.minValue, true);\r
         }\r
-        if(typeof this.maxValue == "string"){\r
-            this.maxValue = this.parseDate(this.maxValue);\r
+        if(Ext.isDefined(this.maxValue)){\r
+            this.setMaxValue(this.maxValue, true);\r
         }\r
-\r
         if(!this.store){\r
-            var min = this.parseDate(this.minValue) || new Date(this.initDate).clearTime();\r
-            var max = this.parseDate(this.maxValue) || new Date(this.initDate).clearTime().add('mi', (24 * 60) - 1);\r
-            var times = [];\r
-            while(min <= max){\r
-                times.push(min.dateFormat(this.format));\r
-                min = min.add('mi', this.increment);\r
-            }\r
-            this.store = times;\r
+            this.generateStore(true);\r
         }\r
         Ext.form.TimeField.superclass.initComponent.call(this);\r
     },\r
+    \r
+    /**\r
+     * Replaces any existing {@link #minValue} with the new time and refreshes the store.\r
+     * @param {Date/String} value The minimum time that can be selected\r
+     */\r
+    setMinValue: function(value, /* private */ initial){\r
+        this.setLimit(value, true, initial);\r
+        return this;\r
+    },\r
 \r
+    /**\r
+     * Replaces any existing {@link #maxValue} with the new time and refreshes the store.\r
+     * @param {Date/String} value The maximum time that can be selected\r
+     */\r
+    setMaxValue: function(value, /* private */ initial){\r
+        this.setLimit(value, false, initial);\r
+        return this;\r
+    },\r
+    \r
+    // private\r
+    generateStore: function(initial){\r
+        var min = this.minValue || new Date(this.initDate).clearTime(),\r
+            max = this.maxValue || new Date(this.initDate).clearTime().add('mi', (24 * 60) - 1),\r
+            times = [];\r
+            \r
+        while(min <= max){\r
+            times.push(min.dateFormat(this.format));\r
+            min = min.add('mi', this.increment);\r
+        }\r
+        this.bindStore(times, initial);\r
+    },\r
+\r
+    // private\r
+    setLimit: function(value, isMin, initial){\r
+        var d;\r
+        if(Ext.isString(value)){\r
+            d = this.parseDate(value);\r
+        }else if(Ext.isDate(value)){\r
+            d = value;\r
+        }\r
+        if(d){\r
+            var val = new Date(this.initDate).clearTime();\r
+            val.setHours(d.getHours(), d.getMinutes(), isMin ? 0 : 59, 0);\r
+            this[isMin ? 'minValue' : 'maxValue'] = val;\r
+            if(!initial){\r
+                this.generateStore();\r
+            }\r
+        }\r
+    },\r
+    \r
     // inherited docs\r
     getValue : function(){\r
         var v = Ext.form.TimeField.superclass.getValue.call(this);\r
@@ -60242,771 +62915,771 @@ Ext.form.Label = Ext.extend(Ext.BoxComponent, {
         }
         Ext.form.Label.superclass.onRender.call(this, ct, position);
     },
-
-    /**
-     * Updates the label's innerHTML with the specified string.
-     * @param {String} text The new label text
-     * @param {Boolean} encode (optional) False to skip HTML-encoding the text when rendering it
-     * to the label (defaults to true which encodes the value). This might be useful if you want to include
-     * tags in the label's innerHTML rather than rendering them as string literals per the default logic.
-     * @return {Label} this
-     */
-    setText : function(t, encode){
-        var e = encode === false;
-        this[!e ? 'text' : 'html'] = t;
-        delete this[e ? 'text' : 'html'];
-        if(this.rendered){
-            this.el.dom.innerHTML = encode !== false ? Ext.util.Format.htmlEncode(t) : t;
+
+    /**
+     * Updates the label's innerHTML with the specified string.
+     * @param {String} text The new label text
+     * @param {Boolean} encode (optional) False to skip HTML-encoding the text when rendering it
+     * to the label (defaults to true which encodes the value). This might be useful if you want to include
+     * tags in the label's innerHTML rather than rendering them as string literals per the default logic.
+     * @return {Label} this
+     */
+    setText : function(t, encode){
+        var e = encode === false;
+        this[!e ? 'text' : 'html'] = t;
+        delete this[e ? 'text' : 'html'];
+        if(this.rendered){
+            this.el.dom.innerHTML = encode !== false ? Ext.util.Format.htmlEncode(t) : t;
+        }
+        return this;
+    }
+});
+
+Ext.reg('label', Ext.form.Label);/**
+ * @class Ext.form.Action
+ * <p>The subclasses of this class provide actions to perform upon {@link Ext.form.BasicForm Form}s.</p>
+ * <p>Instances of this class are only created by a {@link Ext.form.BasicForm Form} when
+ * the Form needs to perform an action such as submit or load. The Configuration options
+ * listed for this class are set through the Form's action methods: {@link Ext.form.BasicForm#submit submit},
+ * {@link Ext.form.BasicForm#load load} and {@link Ext.form.BasicForm#doAction doAction}</p>
+ * <p>The instance of Action which performed the action is passed to the success
+ * and failure callbacks of the Form's action methods ({@link Ext.form.BasicForm#submit submit},
+ * {@link Ext.form.BasicForm#load load} and {@link Ext.form.BasicForm#doAction doAction}),
+ * and to the {@link Ext.form.BasicForm#actioncomplete actioncomplete} and
+ * {@link Ext.form.BasicForm#actionfailed actionfailed} event handlers.</p>
+ */
+Ext.form.Action = function(form, options){
+    this.form = form;
+    this.options = options || {};
+};
+
+/**
+ * Failure type returned when client side validation of the Form fails
+ * thus aborting a submit action. Client side validation is performed unless
+ * {@link #clientValidation} is explicitly set to <tt>false</tt>.
+ * @type {String}
+ * @static
+ */
+Ext.form.Action.CLIENT_INVALID = 'client';
+/**
+ * <p>Failure type returned when server side processing fails and the {@link #result}'s
+ * <tt style="font-weight:bold">success</tt> property is set to <tt>false</tt>.</p>
+ * <p>In the case of a form submission, field-specific error messages may be returned in the
+ * {@link #result}'s <tt style="font-weight:bold">errors</tt> property.</p>
+ * @type {String}
+ * @static
+ */
+Ext.form.Action.SERVER_INVALID = 'server';
+/**
+ * Failure type returned when a communication error happens when attempting
+ * to send a request to the remote server. The {@link #response} may be examined to
+ * provide further information.
+ * @type {String}
+ * @static
+ */
+Ext.form.Action.CONNECT_FAILURE = 'connect';
+/**
+ * Failure type returned when the response's <tt style="font-weight:bold">success</tt>
+ * property is set to <tt>false</tt>, or no field values are returned in the response's
+ * <tt style="font-weight:bold">data</tt> property.
+ * @type {String}
+ * @static
+ */
+Ext.form.Action.LOAD_FAILURE = 'load';
+
+Ext.form.Action.prototype = {
+/**
+ * @cfg {String} url The URL that the Action is to invoke.
+ */
+/**
+ * @cfg {Boolean} reset When set to <tt><b>true</b></tt>, causes the Form to be
+ * {@link Ext.form.BasicForm.reset reset} on Action success. If specified, this happens
+ * <b>before</b> the {@link #success} callback is called and before the Form's
+ * {@link Ext.form.BasicForm.actioncomplete actioncomplete} event fires.
+ */
+/**
+ * @cfg {String} method The HTTP method to use to access the requested URL. Defaults to the
+ * {@link Ext.form.BasicForm}'s method, or if that is not specified, the underlying DOM form's method.
+ */
+/**
+ * @cfg {Mixed} params <p>Extra parameter values to pass. These are added to the Form's
+ * {@link Ext.form.BasicForm#baseParams} and passed to the specified URL along with the Form's
+ * input fields.</p>
+ * <p>Parameters are encoded as standard HTTP parameters using {@link Ext#urlEncode}.</p>
+ */
+/**
+ * @cfg {Number} timeout The number of seconds to wait for a server response before
+ * failing with the {@link #failureType} as {@link #Action.CONNECT_FAILURE}. If not specified,
+ * defaults to the configured <tt>{@link Ext.form.BasicForm#timeout timeout}</tt> of the
+ * {@link Ext.form.BasicForm form}.
+ */
+/**
+ * @cfg {Function} success The function to call when a valid success return packet is recieved.
+ * The function is passed the following parameters:<ul class="mdetail-params">
+ * <li><b>form</b> : Ext.form.BasicForm<div class="sub-desc">The form that requested the action</div></li>
+ * <li><b>action</b> : Ext.form.Action<div class="sub-desc">The Action class. The {@link #result}
+ * property of this object may be examined to perform custom postprocessing.</div></li>
+ * </ul>
+ */
+/**
+ * @cfg {Function} failure The function to call when a failure packet was recieved, or when an
+ * error ocurred in the Ajax communication.
+ * The function is passed the following parameters:<ul class="mdetail-params">
+ * <li><b>form</b> : Ext.form.BasicForm<div class="sub-desc">The form that requested the action</div></li>
+ * <li><b>action</b> : Ext.form.Action<div class="sub-desc">The Action class. If an Ajax
+ * error ocurred, the failure type will be in {@link #failureType}. The {@link #result}
+ * property of this object may be examined to perform custom postprocessing.</div></li>
+ * </ul>
+ */
+/**
+ * @cfg {Object} scope The scope in which to call the callback functions (The <tt>this</tt> reference
+ * for the callback functions).
+ */
+/**
+ * @cfg {String} waitMsg The message to be displayed by a call to {@link Ext.MessageBox#wait}
+ * during the time the action is being processed.
+ */
+/**
+ * @cfg {String} waitTitle The title to be displayed by a call to {@link Ext.MessageBox#wait}
+ * during the time the action is being processed.
+ */
+
+/**
+ * The type of action this Action instance performs.
+ * Currently only "submit" and "load" are supported.
+ * @type {String}
+ */
+    type : 'default',
+/**
+ * The type of failure detected will be one of these: {@link #CLIENT_INVALID},
+ * {@link #SERVER_INVALID}, {@link #CONNECT_FAILURE}, or {@link #LOAD_FAILURE}.  Usage:
+ * <pre><code>
+var fp = new Ext.form.FormPanel({
+...
+buttons: [{
+    text: 'Save',
+    formBind: true,
+    handler: function(){
+        if(fp.getForm().isValid()){
+            fp.getForm().submit({
+                url: 'form-submit.php',
+                waitMsg: 'Submitting your data...',
+                success: function(form, action){
+                    // server responded with success = true
+                    var result = action.{@link #result};
+                },
+                failure: function(form, action){
+                    if (action.{@link #failureType} === Ext.form.Action.{@link #CONNECT_FAILURE}) {
+                        Ext.Msg.alert('Error',
+                            'Status:'+action.{@link #response}.status+': '+
+                            action.{@link #response}.statusText);
+                    }
+                    if (action.failureType === Ext.form.Action.{@link #SERVER_INVALID}){
+                        // server responded with success = false
+                        Ext.Msg.alert('Invalid', action.{@link #result}.errormsg);
+                    }
+                }
+            });
+        }
+    }
+},{
+    text: 'Reset',
+    handler: function(){
+        fp.getForm().reset();
+    }
+}]
+ * </code></pre>
+ * @property failureType
+ * @type {String}
+ */
+ /**
+ * The XMLHttpRequest object used to perform the action.
+ * @property response
+ * @type {Object}
+ */
+ /**
+ * The decoded response object containing a boolean <tt style="font-weight:bold">success</tt> property and
+ * other, action-specific properties.
+ * @property result
+ * @type {Object}
+ */
+
+    // interface method
+    run : function(options){
+
+    },
+
+    // interface method
+    success : function(response){
+
+    },
+
+    // interface method
+    handleResponse : function(response){
+
+    },
+
+    // default connection failure
+    failure : function(response){
+        this.response = response;
+        this.failureType = Ext.form.Action.CONNECT_FAILURE;
+        this.form.afterAction(this, false);
+    },
+
+    // private
+    // shared code among all Actions to validate that there was a response
+    // with either responseText or responseXml
+    processResponse : function(response){
+        this.response = response;
+        if(!response.responseText && !response.responseXML){
+            return true;
+        }
+        this.result = this.handleResponse(response);
+        return this.result;
+    },
+
+    // utility functions used internally
+    getUrl : function(appendParams){
+        var url = this.options.url || this.form.url || this.form.el.dom.action;
+        if(appendParams){
+            var p = this.getParams();
+            if(p){
+                url = Ext.urlAppend(url, p);
+            }
+        }
+        return url;
+    },
+
+    // private
+    getMethod : function(){
+        return (this.options.method || this.form.method || this.form.el.dom.method || 'POST').toUpperCase();
+    },
+
+    // private
+    getParams : function(){
+        var bp = this.form.baseParams;
+        var p = this.options.params;
+        if(p){
+            if(typeof p == "object"){
+                p = Ext.urlEncode(Ext.applyIf(p, bp));
+            }else if(typeof p == 'string' && bp){
+                p += '&' + Ext.urlEncode(bp);
+            }
+        }else if(bp){
+            p = Ext.urlEncode(bp);
+        }
+        return p;
+    },
+
+    // private
+    createCallback : function(opts){
+        var opts = opts || {};
+        return {
+            success: this.success,
+            failure: this.failure,
+            scope: this,
+            timeout: (opts.timeout*1000) || (this.form.timeout*1000),
+            upload: this.form.fileUpload ? this.success : undefined
+        };
+    }
+};
+
+/**
+ * @class Ext.form.Action.Submit
+ * @extends Ext.form.Action
+ * <p>A class which handles submission of data from {@link Ext.form.BasicForm Form}s
+ * and processes the returned response.</p>
+ * <p>Instances of this class are only created by a {@link Ext.form.BasicForm Form} when
+ * {@link Ext.form.BasicForm#submit submit}ting.</p>
+ * <p><u><b>Response Packet Criteria</b></u></p>
+ * <p>A response packet may contain:
+ * <div class="mdetail-params"><ul>
+ * <li><b><code>success</code></b> property : Boolean
+ * <div class="sub-desc">The <code>success</code> property is required.</div></li>
+ * <li><b><code>errors</code></b> property : Object
+ * <div class="sub-desc"><div class="sub-desc">The <code>errors</code> property,
+ * which is optional, contains error messages for invalid fields.</div></li>
+ * </ul></div>
+ * <p><u><b>JSON Packets</b></u></p>
+ * <p>By default, response packets are assumed to be JSON, so a typical response
+ * packet may look like this:</p><pre><code>
+{
+    success: false,
+    errors: {
+        clientCode: "Client not found",
+        portOfLoading: "This field must not be null"
+    }
+}</code></pre>
+ * <p>Other data may be placed into the response for processing by the {@link Ext.form.BasicForm}'s callback
+ * or event handler methods. The object decoded from this JSON is available in the
+ * {@link Ext.form.Action#result result} property.</p>
+ * <p>Alternatively, if an {@link #errorReader} is specified as an {@link Ext.data.XmlReader XmlReader}:</p><pre><code>
+    errorReader: new Ext.data.XmlReader({
+            record : 'field',
+            success: '@success'
+        }, [
+            'id', 'msg'
+        ]
+    )
+</code></pre>
+ * <p>then the results may be sent back in XML format:</p><pre><code>
+&lt;?xml version="1.0" encoding="UTF-8"?&gt;
+&lt;message success="false"&gt;
+&lt;errors&gt;
+    &lt;field&gt;
+        &lt;id&gt;clientCode&lt;/id&gt;
+        &lt;msg&gt;&lt;![CDATA[Code not found. &lt;br /&gt;&lt;i&gt;This is a test validation message from the server &lt;/i&gt;]]&gt;&lt;/msg&gt;
+    &lt;/field&gt;
+    &lt;field&gt;
+        &lt;id&gt;portOfLoading&lt;/id&gt;
+        &lt;msg&gt;&lt;![CDATA[Port not found. &lt;br /&gt;&lt;i&gt;This is a test validation message from the server &lt;/i&gt;]]&gt;&lt;/msg&gt;
+    &lt;/field&gt;
+&lt;/errors&gt;
+&lt;/message&gt;
+</code></pre>
+ * <p>Other elements may be placed into the response XML for processing by the {@link Ext.form.BasicForm}'s callback
+ * or event handler methods. The XML document is available in the {@link #errorReader}'s {@link Ext.data.XmlReader#xmlData xmlData} property.</p>
+ */
+Ext.form.Action.Submit = function(form, options){
+    Ext.form.Action.Submit.superclass.constructor.call(this, form, options);
+};
+
+Ext.extend(Ext.form.Action.Submit, Ext.form.Action, {
+    /**
+     * @cfg {Ext.data.DataReader} errorReader <p><b>Optional. JSON is interpreted with
+     * no need for an errorReader.</b></p>
+     * <p>A Reader which reads a single record from the returned data. The DataReader's
+     * <b>success</b> property specifies how submission success is determined. The Record's
+     * data provides the error messages to apply to any invalid form Fields.</p>
+     */
+    /**
+     * @cfg {boolean} clientValidation Determines whether a Form's fields are validated
+     * in a final call to {@link Ext.form.BasicForm#isValid isValid} prior to submission.
+     * Pass <tt>false</tt> in the Form's submit options to prevent this. If not defined, pre-submission field validation
+     * is performed.
+     */
+    type : 'submit',
+
+    // private
+    run : function(){
+        var o = this.options;
+        var method = this.getMethod();
+        var isGet = method == 'GET';
+        if(o.clientValidation === false || this.form.isValid()){
+            Ext.Ajax.request(Ext.apply(this.createCallback(o), {
+                form:this.form.el.dom,
+                url:this.getUrl(isGet),
+                method: method,
+                headers: o.headers,
+                params:!isGet ? this.getParams() : null,
+                isUpload: this.form.fileUpload
+            }));
+        }else if (o.clientValidation !== false){ // client validation failed
+            this.failureType = Ext.form.Action.CLIENT_INVALID;
+            this.form.afterAction(this, false);
+        }
+    },
+
+    // private
+    success : function(response){
+        var result = this.processResponse(response);
+        if(result === true || result.success){
+            this.form.afterAction(this, true);
+            return;
+        }
+        if(result.errors){
+            this.form.markInvalid(result.errors);
+        }
+        this.failureType = Ext.form.Action.SERVER_INVALID;
+        this.form.afterAction(this, false);
+    },
+
+    // private
+    handleResponse : function(response){
+        if(this.form.errorReader){
+            var rs = this.form.errorReader.read(response);
+            var errors = [];
+            if(rs.records){
+                for(var i = 0, len = rs.records.length; i < len; i++) {
+                    var r = rs.records[i];
+                    errors[i] = r.data;
+                }
+            }
+            if(errors.length < 1){
+                errors = null;
+            }
+            return {
+                success : rs.success,
+                errors : errors
+            };
+        }
+        return Ext.decode(response.responseText);
+    }
+});
+
+
+/**
+ * @class Ext.form.Action.Load
+ * @extends Ext.form.Action
+ * <p>A class which handles loading of data from a server into the Fields of an {@link Ext.form.BasicForm}.</p>
+ * <p>Instances of this class are only created by a {@link Ext.form.BasicForm Form} when
+ * {@link Ext.form.BasicForm#load load}ing.</p>
+ * <p><u><b>Response Packet Criteria</b></u></p>
+ * <p>A response packet <b>must</b> contain:
+ * <div class="mdetail-params"><ul>
+ * <li><b><code>success</code></b> property : Boolean</li>
+ * <li><b><code>data</code></b> property : Object</li>
+ * <div class="sub-desc">The <code>data</code> property contains the values of Fields to load.
+ * The individual value object for each Field is passed to the Field's
+ * {@link Ext.form.Field#setValue setValue} method.</div></li>
+ * </ul></div>
+ * <p><u><b>JSON Packets</b></u></p>
+ * <p>By default, response packets are assumed to be JSON, so for the following form load call:<pre><code>
+var myFormPanel = new Ext.form.FormPanel({
+    title: 'Client and routing info',
+    items: [{
+        fieldLabel: 'Client',
+        name: 'clientName'
+    }, {
+        fieldLabel: 'Port of loading',
+        name: 'portOfLoading'
+    }, {
+        fieldLabel: 'Port of discharge',
+        name: 'portOfDischarge'
+    }]
+});
+myFormPanel.{@link Ext.form.FormPanel#getForm getForm}().{@link Ext.form.BasicForm#load load}({
+    url: '/getRoutingInfo.php',
+    params: {
+        consignmentRef: myConsignmentRef
+    },
+    failure: function(form, action) {
+        Ext.Msg.alert("Load failed", action.result.errorMessage);
+    }
+});
+</code></pre>
+ * a <b>success response</b> packet may look like this:</p><pre><code>
+{
+    success: true,
+    data: {
+        clientName: "Fred. Olsen Lines",
+        portOfLoading: "FXT",
+        portOfDischarge: "OSL"
+    }
+}</code></pre>
+ * while a <b>failure response</b> packet may look like this:</p><pre><code>
+{
+    success: false,
+    errorMessage: "Consignment reference not found"
+}</code></pre>
+ * <p>Other data may be placed into the response for processing the {@link Ext.form.BasicForm Form}'s
+ * callback or event handler methods. The object decoded from this JSON is available in the
+ * {@link Ext.form.Action#result result} property.</p>
+ */
+Ext.form.Action.Load = function(form, options){
+    Ext.form.Action.Load.superclass.constructor.call(this, form, options);
+    this.reader = this.form.reader;
+};
+
+Ext.extend(Ext.form.Action.Load, Ext.form.Action, {
+    // private
+    type : 'load',
+
+    // private
+    run : function(){
+        Ext.Ajax.request(Ext.apply(
+                this.createCallback(this.options), {
+                    method:this.getMethod(),
+                    url:this.getUrl(false),
+                    headers: this.options.headers,
+                    params:this.getParams()
+        }));
+    },
+
+    // private
+    success : function(response){
+        var result = this.processResponse(response);
+        if(result === true || !result.success || !result.data){
+            this.failureType = Ext.form.Action.LOAD_FAILURE;
+            this.form.afterAction(this, false);
+            return;
+        }
+        this.form.clearInvalid();
+        this.form.setValues(result.data);
+        this.form.afterAction(this, true);
+    },
+
+    // private
+    handleResponse : function(response){
+        if(this.form.reader){
+            var rs = this.form.reader.read(response);
+            var data = rs.records && rs.records[0] ? rs.records[0].data : null;
+            return {
+                success : rs.success,
+                data : data
+            };
+        }
+        return Ext.decode(response.responseText);
+    }
+});
+
+
+
+/**
+ * @class Ext.form.Action.DirectLoad
+ * @extends Ext.form.Action.Load
+ * <p>Provides Ext.direct support for loading form data.</p>
+ * <p>This example illustrates usage of Ext.Direct to <b>load</b> a form through Ext.Direct.</p>
+ * <pre><code>
+var myFormPanel = new Ext.form.FormPanel({
+    // configs for FormPanel
+    title: 'Basic Information',
+    renderTo: document.body,
+    width: 300, height: 160,
+    padding: 10,
+
+    // configs apply to child items
+    defaults: {anchor: '100%'},
+    defaultType: 'textfield',
+    items: [{
+        fieldLabel: 'Name',
+        name: 'name'
+    },{
+        fieldLabel: 'Email',
+        name: 'email'
+    },{
+        fieldLabel: 'Company',
+        name: 'company'
+    }],
+
+    // configs for BasicForm
+    api: {
+        // The server-side method to call for load() requests
+        load: Profile.getBasicInfo,
+        // The server-side must mark the submit handler as a 'formHandler'
+        submit: Profile.updateBasicInfo
+    },
+    // specify the order for the passed params
+    paramOrder: ['uid', 'foo']
+});
+
+// load the form
+myFormPanel.getForm().load({
+    // pass 2 arguments to server side getBasicInfo method (len=2)
+    params: {
+        foo: 'bar',
+        uid: 34
+    }
+});
+ * </code></pre>
+ * The data packet sent to the server will resemble something like:
+ * <pre><code>
+[
+    {
+        "action":"Profile","method":"getBasicInfo","type":"rpc","tid":2,
+        "data":[34,"bar"] // note the order of the params
+    }
+]
+ * </code></pre>
+ * The form will process a data packet returned by the server that is similar
+ * to the following format:
+ * <pre><code>
+[
+    {
+        "action":"Profile","method":"getBasicInfo","type":"rpc","tid":2,
+        "result":{
+            "success":true,
+            "data":{
+                "name":"Fred Flintstone",
+                "company":"Slate Rock and Gravel",
+                "email":"fred.flintstone@slaterg.com"
+            }
+        }
+    }
+]
+ * </code></pre>
+ */
+Ext.form.Action.DirectLoad = Ext.extend(Ext.form.Action.Load, {
+    constructor: function(form, opts) {
+        Ext.form.Action.DirectLoad.superclass.constructor.call(this, form, opts);
+    },
+    type : 'directload',
+
+    run : function(){
+        var args = this.getParams();
+        args.push(this.success, this);
+        this.form.api.load.apply(window, args);
+    },
+
+    getParams : function() {
+        var buf = [], o = {};
+        var bp = this.form.baseParams;
+        var p = this.options.params;
+        Ext.apply(o, p, bp);
+        var paramOrder = this.form.paramOrder;
+        if(paramOrder){
+            for(var i = 0, len = paramOrder.length; i < len; i++){
+                buf.push(o[paramOrder[i]]);
+            }
+        }else if(this.form.paramsAsHash){
+            buf.push(o);
+        }
+        return buf;
+    },
+    // Direct actions have already been processed and therefore
+    // we can directly set the result; Direct Actions do not have
+    // a this.response property.
+    processResponse : function(result) {
+        this.result = result;
+        return result;
+    },
+    
+    success : function(response, trans){
+        if(trans.type == Ext.Direct.exceptions.SERVER){
+            response = {};
+        }
+        Ext.form.Action.DirectLoad.superclass.success.call(this, response);
+    }
+});
+
+/**
+ * @class Ext.form.Action.DirectSubmit
+ * @extends Ext.form.Action.Submit
+ * <p>Provides Ext.direct support for submitting form data.</p>
+ * <p>This example illustrates usage of Ext.Direct to <b>submit</b> a form through Ext.Direct.</p>
+ * <pre><code>
+var myFormPanel = new Ext.form.FormPanel({
+    // configs for FormPanel
+    title: 'Basic Information',
+    renderTo: document.body,
+    width: 300, height: 160,
+    padding: 10,
+    buttons:[{
+        text: 'Submit',
+        handler: function(){
+            myFormPanel.getForm().submit({
+                params: {
+                    foo: 'bar',
+                    uid: 34
+                }
+            });
+        }
+    }],
+
+    // configs apply to child items
+    defaults: {anchor: '100%'},
+    defaultType: 'textfield',
+    items: [{
+        fieldLabel: 'Name',
+        name: 'name'
+    },{
+        fieldLabel: 'Email',
+        name: 'email'
+    },{
+        fieldLabel: 'Company',
+        name: 'company'
+    }],
+
+    // configs for BasicForm
+    api: {
+        // The server-side method to call for load() requests
+        load: Profile.getBasicInfo,
+        // The server-side must mark the submit handler as a 'formHandler'
+        submit: Profile.updateBasicInfo
+    },
+    // specify the order for the passed params
+    paramOrder: ['uid', 'foo']
+});
+ * </code></pre>
+ * The data packet sent to the server will resemble something like:
+ * <pre><code>
+{
+    "action":"Profile","method":"updateBasicInfo","type":"rpc","tid":"6",
+    "result":{
+        "success":true,
+        "id":{
+            "extAction":"Profile","extMethod":"updateBasicInfo",
+            "extType":"rpc","extTID":"6","extUpload":"false",
+            "name":"Aaron Conran","email":"aaron@extjs.com","company":"Ext JS, LLC"
+        }
+    }
+}
+ * </code></pre>
+ * The form will process a data packet returned by the server that is similar
+ * to the following:
+ * <pre><code>
+// sample success packet (batched requests)
+[
+    {
+        "action":"Profile","method":"updateBasicInfo","type":"rpc","tid":3,
+        "result":{
+            "success":true
+        }
+    }
+]
+
+// sample failure packet (one request)
+{
+        "action":"Profile","method":"updateBasicInfo","type":"rpc","tid":"6",
+        "result":{
+            "errors":{
+                "email":"already taken"
+            },
+            "success":false,
+            "foo":"bar"
+        }
+}
+ * </code></pre>
+ * Also see the discussion in {@link Ext.form.Action.DirectLoad}.
+ */
+Ext.form.Action.DirectSubmit = Ext.extend(Ext.form.Action.Submit, {
+    constructor : function(form, opts) {
+        Ext.form.Action.DirectSubmit.superclass.constructor.call(this, form, opts);
+    },
+    type : 'directsubmit',
+    // override of Submit
+    run : function(){
+        var o = this.options;
+        if(o.clientValidation === false || this.form.isValid()){
+            // tag on any additional params to be posted in the
+            // form scope
+            this.success.params = this.getParams();
+            this.form.api.submit(this.form.el.dom, this.success, this);
+        }else if (o.clientValidation !== false){ // client validation failed
+            this.failureType = Ext.form.Action.CLIENT_INVALID;
+            this.form.afterAction(this, false);
+        }
+    },
+
+    getParams : function() {
+        var o = {};
+        var bp = this.form.baseParams;
+        var p = this.options.params;
+        Ext.apply(o, p, bp);
+        return o;
+    },
+    // Direct actions have already been processed and therefore
+    // we can directly set the result; Direct Actions do not have
+    // a this.response property.
+    processResponse : function(result) {
+        this.result = result;
+        return result;
+    },
+    
+    success : function(response, trans){
+        if(trans.type == Ext.Direct.exceptions.SERVER){
+            response = {};
         }
-        return this;
+        Ext.form.Action.DirectSubmit.superclass.success.call(this, response);
     }
 });
 
-Ext.reg('label', Ext.form.Label);/**\r
- * @class Ext.form.Action\r
- * <p>The subclasses of this class provide actions to perform upon {@link Ext.form.BasicForm Form}s.</p>\r
- * <p>Instances of this class are only created by a {@link Ext.form.BasicForm Form} when\r
- * the Form needs to perform an action such as submit or load. The Configuration options\r
- * listed for this class are set through the Form's action methods: {@link Ext.form.BasicForm#submit submit},\r
- * {@link Ext.form.BasicForm#load load} and {@link Ext.form.BasicForm#doAction doAction}</p>\r
- * <p>The instance of Action which performed the action is passed to the success\r
- * and failure callbacks of the Form's action methods ({@link Ext.form.BasicForm#submit submit},\r
- * {@link Ext.form.BasicForm#load load} and {@link Ext.form.BasicForm#doAction doAction}),\r
- * and to the {@link Ext.form.BasicForm#actioncomplete actioncomplete} and\r
- * {@link Ext.form.BasicForm#actionfailed actionfailed} event handlers.</p>\r
- */\r
-Ext.form.Action = function(form, options){\r
-    this.form = form;\r
-    this.options = options || {};\r
-};\r
-\r
-/**\r
- * Failure type returned when client side validation of the Form fails\r
- * thus aborting a submit action. Client side validation is performed unless\r
- * {@link #clientValidation} is explicitly set to <tt>false</tt>.\r
- * @type {String}\r
- * @static\r
- */\r
-Ext.form.Action.CLIENT_INVALID = 'client';\r
-/**\r
- * <p>Failure type returned when server side processing fails and the {@link #result}'s\r
- * <tt style="font-weight:bold">success</tt> property is set to <tt>false</tt>.</p>\r
- * <p>In the case of a form submission, field-specific error messages may be returned in the\r
- * {@link #result}'s <tt style="font-weight:bold">errors</tt> property.</p>\r
- * @type {String}\r
- * @static\r
- */\r
-Ext.form.Action.SERVER_INVALID = 'server';\r
-/**\r
- * Failure type returned when a communication error happens when attempting\r
- * to send a request to the remote server. The {@link #response} may be examined to\r
- * provide further information.\r
- * @type {String}\r
- * @static\r
- */\r
-Ext.form.Action.CONNECT_FAILURE = 'connect';\r
-/**\r
- * Failure type returned when the response's <tt style="font-weight:bold">success</tt>\r
- * property is set to <tt>false</tt>, or no field values are returned in the response's\r
- * <tt style="font-weight:bold">data</tt> property.\r
- * @type {String}\r
- * @static\r
- */\r
-Ext.form.Action.LOAD_FAILURE = 'load';\r
-\r
-Ext.form.Action.prototype = {\r
-/**\r
- * @cfg {String} url The URL that the Action is to invoke.\r
- */\r
-/**\r
- * @cfg {Boolean} reset When set to <tt><b>true</b></tt>, causes the Form to be\r
- * {@link Ext.form.BasicForm.reset reset} on Action success. If specified, this happens\r
- * <b>before</b> the {@link #success} callback is called and before the Form's\r
- * {@link Ext.form.BasicForm.actioncomplete actioncomplete} event fires.\r
- */\r
-/**\r
- * @cfg {String} method The HTTP method to use to access the requested URL. Defaults to the\r
- * {@link Ext.form.BasicForm}'s method, or if that is not specified, the underlying DOM form's method.\r
- */\r
-/**\r
- * @cfg {Mixed} params <p>Extra parameter values to pass. These are added to the Form's\r
- * {@link Ext.form.BasicForm#baseParams} and passed to the specified URL along with the Form's\r
- * input fields.</p>\r
- * <p>Parameters are encoded as standard HTTP parameters using {@link Ext#urlEncode}.</p>\r
- */\r
-/**\r
- * @cfg {Number} timeout The number of seconds to wait for a server response before\r
- * failing with the {@link #failureType} as {@link #Action.CONNECT_FAILURE}. If not specified,\r
- * defaults to the configured <tt>{@link Ext.form.BasicForm#timeout timeout}</tt> of the\r
- * {@link Ext.form.BasicForm form}.\r
- */\r
-/**\r
- * @cfg {Function} success The function to call when a valid success return packet is recieved.\r
- * The function is passed the following parameters:<ul class="mdetail-params">\r
- * <li><b>form</b> : Ext.form.BasicForm<div class="sub-desc">The form that requested the action</div></li>\r
- * <li><b>action</b> : Ext.form.Action<div class="sub-desc">The Action class. The {@link #result}\r
- * property of this object may be examined to perform custom postprocessing.</div></li>\r
- * </ul>\r
- */\r
-/**\r
- * @cfg {Function} failure The function to call when a failure packet was recieved, or when an\r
- * error ocurred in the Ajax communication.\r
- * The function is passed the following parameters:<ul class="mdetail-params">\r
- * <li><b>form</b> : Ext.form.BasicForm<div class="sub-desc">The form that requested the action</div></li>\r
- * <li><b>action</b> : Ext.form.Action<div class="sub-desc">The Action class. If an Ajax\r
- * error ocurred, the failure type will be in {@link #failureType}. The {@link #result}\r
- * property of this object may be examined to perform custom postprocessing.</div></li>\r
- * </ul>\r
- */\r
-/**\r
- * @cfg {Object} scope The scope in which to call the callback functions (The <tt>this</tt> reference\r
- * for the callback functions).\r
- */\r
-/**\r
- * @cfg {String} waitMsg The message to be displayed by a call to {@link Ext.MessageBox#wait}\r
- * during the time the action is being processed.\r
- */\r
-/**\r
- * @cfg {String} waitTitle The title to be displayed by a call to {@link Ext.MessageBox#wait}\r
- * during the time the action is being processed.\r
- */\r
-\r
-/**\r
- * The type of action this Action instance performs.\r
- * Currently only "submit" and "load" are supported.\r
- * @type {String}\r
- */\r
-    type : 'default',\r
-/**\r
- * The type of failure detected will be one of these: {@link #CLIENT_INVALID},\r
- * {@link #SERVER_INVALID}, {@link #CONNECT_FAILURE}, or {@link #LOAD_FAILURE}.  Usage:\r
- * <pre><code>\r
-var fp = new Ext.form.FormPanel({\r
-...\r
-buttons: [{\r
-    text: 'Save',\r
-    formBind: true,\r
-    handler: function(){\r
-        if(fp.getForm().isValid()){\r
-            fp.getForm().submit({\r
-                url: 'form-submit.php',\r
-                waitMsg: 'Submitting your data...',\r
-                success: function(form, action){\r
-                    // server responded with success = true\r
-                    var result = action.{@link #result};\r
-                },\r
-                failure: function(form, action){\r
-                    if (action.{@link #failureType} === Ext.form.Action.{@link #CONNECT_FAILURE}) {\r
-                        Ext.Msg.alert('Error',\r
-                            'Status:'+action.{@link #response}.status+': '+\r
-                            action.{@link #response}.statusText);\r
-                    }\r
-                    if (action.failureType === Ext.form.Action.{@link #SERVER_INVALID}){\r
-                        // server responded with success = false\r
-                        Ext.Msg.alert('Invalid', action.{@link #result}.errormsg);\r
-                    }\r
-                }\r
-            });\r
-        }\r
-    }\r
-},{\r
-    text: 'Reset',\r
-    handler: function(){\r
-        fp.getForm().reset();\r
-    }\r
-}]\r
- * </code></pre>\r
- * @property failureType\r
- * @type {String}\r
- */\r
- /**\r
- * The XMLHttpRequest object used to perform the action.\r
- * @property response\r
- * @type {Object}\r
- */\r
- /**\r
- * The decoded response object containing a boolean <tt style="font-weight:bold">success</tt> property and\r
- * other, action-specific properties.\r
- * @property result\r
- * @type {Object}\r
- */\r
-\r
-    // interface method\r
-    run : function(options){\r
-\r
-    },\r
-\r
-    // interface method\r
-    success : function(response){\r
-\r
-    },\r
-\r
-    // interface method\r
-    handleResponse : function(response){\r
-\r
-    },\r
-\r
-    // default connection failure\r
-    failure : function(response){\r
-        this.response = response;\r
-        this.failureType = Ext.form.Action.CONNECT_FAILURE;\r
-        this.form.afterAction(this, false);\r
-    },\r
-\r
-    // private\r
-    // shared code among all Actions to validate that there was a response\r
-    // with either responseText or responseXml\r
-    processResponse : function(response){\r
-        this.response = response;\r
-        if(!response.responseText && !response.responseXML){\r
-            return true;\r
-        }\r
-        this.result = this.handleResponse(response);\r
-        return this.result;\r
-    },\r
-\r
-    // utility functions used internally\r
-    getUrl : function(appendParams){\r
-        var url = this.options.url || this.form.url || this.form.el.dom.action;\r
-        if(appendParams){\r
-            var p = this.getParams();\r
-            if(p){\r
-                url = Ext.urlAppend(url, p);\r
-            }\r
-        }\r
-        return url;\r
-    },\r
-\r
-    // private\r
-    getMethod : function(){\r
-        return (this.options.method || this.form.method || this.form.el.dom.method || 'POST').toUpperCase();\r
-    },\r
-\r
-    // private\r
-    getParams : function(){\r
-        var bp = this.form.baseParams;\r
-        var p = this.options.params;\r
-        if(p){\r
-            if(typeof p == "object"){\r
-                p = Ext.urlEncode(Ext.applyIf(p, bp));\r
-            }else if(typeof p == 'string' && bp){\r
-                p += '&' + Ext.urlEncode(bp);\r
-            }\r
-        }else if(bp){\r
-            p = Ext.urlEncode(bp);\r
-        }\r
-        return p;\r
-    },\r
-\r
-    // private\r
-    createCallback : function(opts){\r
-        var opts = opts || {};\r
-        return {\r
-            success: this.success,\r
-            failure: this.failure,\r
-            scope: this,\r
-            timeout: (opts.timeout*1000) || (this.form.timeout*1000),\r
-            upload: this.form.fileUpload ? this.success : undefined\r
-        };\r
-    }\r
-};\r
-\r
-/**\r
- * @class Ext.form.Action.Submit\r
- * @extends Ext.form.Action\r
- * <p>A class which handles submission of data from {@link Ext.form.BasicForm Form}s\r
- * and processes the returned response.</p>\r
- * <p>Instances of this class are only created by a {@link Ext.form.BasicForm Form} when\r
- * {@link Ext.form.BasicForm#submit submit}ting.</p>\r
- * <p><u><b>Response Packet Criteria</b></u></p>\r
- * <p>A response packet may contain:\r
- * <div class="mdetail-params"><ul>\r
- * <li><b><code>success</code></b> property : Boolean\r
- * <div class="sub-desc">The <code>success</code> property is required.</div></li>\r
- * <li><b><code>errors</code></b> property : Object\r
- * <div class="sub-desc"><div class="sub-desc">The <code>errors</code> property,\r
- * which is optional, contains error messages for invalid fields.</div></li>\r
- * </ul></div>\r
- * <p><u><b>JSON Packets</b></u></p>\r
- * <p>By default, response packets are assumed to be JSON, so a typical response\r
- * packet may look like this:</p><pre><code>\r
-{\r
-    success: false,\r
-    errors: {\r
-        clientCode: "Client not found",\r
-        portOfLoading: "This field must not be null"\r
-    }\r
-}</code></pre>\r
- * <p>Other data may be placed into the response for processing by the {@link Ext.form.BasicForm}'s callback\r
- * or event handler methods. The object decoded from this JSON is available in the\r
- * {@link Ext.form.Action#result result} property.</p>\r
- * <p>Alternatively, if an {@link #errorReader} is specified as an {@link Ext.data.XmlReader XmlReader}:</p><pre><code>\r
-    errorReader: new Ext.data.XmlReader({\r
-            record : 'field',\r
-            success: '@success'\r
-        }, [\r
-            'id', 'msg'\r
-        ]\r
-    )\r
-</code></pre>\r
- * <p>then the results may be sent back in XML format:</p><pre><code>\r
-&lt;?xml version="1.0" encoding="UTF-8"?&gt;\r
-&lt;message success="false"&gt;\r
-&lt;errors&gt;\r
-    &lt;field&gt;\r
-        &lt;id&gt;clientCode&lt;/id&gt;\r
-        &lt;msg&gt;&lt;![CDATA[Code not found. &lt;br /&gt;&lt;i&gt;This is a test validation message from the server &lt;/i&gt;]]&gt;&lt;/msg&gt;\r
-    &lt;/field&gt;\r
-    &lt;field&gt;\r
-        &lt;id&gt;portOfLoading&lt;/id&gt;\r
-        &lt;msg&gt;&lt;![CDATA[Port not found. &lt;br /&gt;&lt;i&gt;This is a test validation message from the server &lt;/i&gt;]]&gt;&lt;/msg&gt;\r
-    &lt;/field&gt;\r
-&lt;/errors&gt;\r
-&lt;/message&gt;\r
-</code></pre>\r
- * <p>Other elements may be placed into the response XML for processing by the {@link Ext.form.BasicForm}'s callback\r
- * or event handler methods. The XML document is available in the {@link #errorReader}'s {@link Ext.data.XmlReader#xmlData xmlData} property.</p>\r
- */\r
-Ext.form.Action.Submit = function(form, options){\r
-    Ext.form.Action.Submit.superclass.constructor.call(this, form, options);\r
-};\r
-\r
-Ext.extend(Ext.form.Action.Submit, Ext.form.Action, {\r
-    /**\r
-     * @cfg {Ext.data.DataReader} errorReader <p><b>Optional. JSON is interpreted with\r
-     * no need for an errorReader.</b></p>\r
-     * <p>A Reader which reads a single record from the returned data. The DataReader's\r
-     * <b>success</b> property specifies how submission success is determined. The Record's\r
-     * data provides the error messages to apply to any invalid form Fields.</p>\r
-     */\r
-    /**\r
-     * @cfg {boolean} clientValidation Determines whether a Form's fields are validated\r
-     * in a final call to {@link Ext.form.BasicForm#isValid isValid} prior to submission.\r
-     * Pass <tt>false</tt> in the Form's submit options to prevent this. If not defined, pre-submission field validation\r
-     * is performed.\r
-     */\r
-    type : 'submit',\r
-\r
-    // private\r
-    run : function(){\r
-        var o = this.options;\r
-        var method = this.getMethod();\r
-        var isGet = method == 'GET';\r
-        if(o.clientValidation === false || this.form.isValid()){\r
-            Ext.Ajax.request(Ext.apply(this.createCallback(o), {\r
-                form:this.form.el.dom,\r
-                url:this.getUrl(isGet),\r
-                method: method,\r
-                headers: o.headers,\r
-                params:!isGet ? this.getParams() : null,\r
-                isUpload: this.form.fileUpload\r
-            }));\r
-        }else if (o.clientValidation !== false){ // client validation failed\r
-            this.failureType = Ext.form.Action.CLIENT_INVALID;\r
-            this.form.afterAction(this, false);\r
-        }\r
-    },\r
-\r
-    // private\r
-    success : function(response){\r
-        var result = this.processResponse(response);\r
-        if(result === true || result.success){\r
-            this.form.afterAction(this, true);\r
-            return;\r
-        }\r
-        if(result.errors){\r
-            this.form.markInvalid(result.errors);\r
-        }\r
-        this.failureType = Ext.form.Action.SERVER_INVALID;\r
-        this.form.afterAction(this, false);\r
-    },\r
-\r
-    // private\r
-    handleResponse : function(response){\r
-        if(this.form.errorReader){\r
-            var rs = this.form.errorReader.read(response);\r
-            var errors = [];\r
-            if(rs.records){\r
-                for(var i = 0, len = rs.records.length; i < len; i++) {\r
-                    var r = rs.records[i];\r
-                    errors[i] = r.data;\r
-                }\r
-            }\r
-            if(errors.length < 1){\r
-                errors = null;\r
-            }\r
-            return {\r
-                success : rs.success,\r
-                errors : errors\r
-            };\r
-        }\r
-        return Ext.decode(response.responseText);\r
-    }\r
-});\r
-\r
-\r
-/**\r
- * @class Ext.form.Action.Load\r
- * @extends Ext.form.Action\r
- * <p>A class which handles loading of data from a server into the Fields of an {@link Ext.form.BasicForm}.</p>\r
- * <p>Instances of this class are only created by a {@link Ext.form.BasicForm Form} when\r
- * {@link Ext.form.BasicForm#load load}ing.</p>\r
- * <p><u><b>Response Packet Criteria</b></u></p>\r
- * <p>A response packet <b>must</b> contain:\r
- * <div class="mdetail-params"><ul>\r
- * <li><b><code>success</code></b> property : Boolean</li>\r
- * <li><b><code>data</code></b> property : Object</li>\r
- * <div class="sub-desc">The <code>data</code> property contains the values of Fields to load.\r
- * The individual value object for each Field is passed to the Field's\r
- * {@link Ext.form.Field#setValue setValue} method.</div></li>\r
- * </ul></div>\r
- * <p><u><b>JSON Packets</b></u></p>\r
- * <p>By default, response packets are assumed to be JSON, so for the following form load call:<pre><code>\r
-var myFormPanel = new Ext.form.FormPanel({\r
-    title: 'Client and routing info',\r
-    items: [{\r
-        fieldLabel: 'Client',\r
-        name: 'clientName'\r
-    }, {\r
-        fieldLabel: 'Port of loading',\r
-        name: 'portOfLoading'\r
-    }, {\r
-        fieldLabel: 'Port of discharge',\r
-        name: 'portOfDischarge'\r
-    }]\r
-});\r
-myFormPanel.{@link Ext.form.FormPanel#getForm getForm}().{@link Ext.form.BasicForm#load load}({\r
-    url: '/getRoutingInfo.php',\r
-    params: {\r
-        consignmentRef: myConsignmentRef\r
-    },\r
-    failure: function(form, action) {\r
-        Ext.Msg.alert("Load failed", action.result.errorMessage);\r
-    }\r
-});\r
-</code></pre>\r
- * a <b>success response</b> packet may look like this:</p><pre><code>\r
-{\r
-    success: true,\r
-    data: {\r
-        clientName: "Fred. Olsen Lines",\r
-        portOfLoading: "FXT",\r
-        portOfDischarge: "OSL"\r
-    }\r
-}</code></pre>\r
- * while a <b>failure response</b> packet may look like this:</p><pre><code>\r
-{\r
-    success: false,\r
-    errorMessage: "Consignment reference not found"\r
-}</code></pre>\r
- * <p>Other data may be placed into the response for processing the {@link Ext.form.BasicForm Form}'s\r
- * callback or event handler methods. The object decoded from this JSON is available in the\r
- * {@link Ext.form.Action#result result} property.</p>\r
- */\r
-Ext.form.Action.Load = function(form, options){\r
-    Ext.form.Action.Load.superclass.constructor.call(this, form, options);\r
-    this.reader = this.form.reader;\r
-};\r
-\r
-Ext.extend(Ext.form.Action.Load, Ext.form.Action, {\r
-    // private\r
-    type : 'load',\r
-\r
-    // private\r
-    run : function(){\r
-        Ext.Ajax.request(Ext.apply(\r
-                this.createCallback(this.options), {\r
-                    method:this.getMethod(),\r
-                    url:this.getUrl(false),\r
-                    headers: this.options.headers,\r
-                    params:this.getParams()\r
-        }));\r
-    },\r
-\r
-    // private\r
-    success : function(response){\r
-        var result = this.processResponse(response);\r
-        if(result === true || !result.success || !result.data){\r
-            this.failureType = Ext.form.Action.LOAD_FAILURE;\r
-            this.form.afterAction(this, false);\r
-            return;\r
-        }\r
-        this.form.clearInvalid();\r
-        this.form.setValues(result.data);\r
-        this.form.afterAction(this, true);\r
-    },\r
-\r
-    // private\r
-    handleResponse : function(response){\r
-        if(this.form.reader){\r
-            var rs = this.form.reader.read(response);\r
-            var data = rs.records && rs.records[0] ? rs.records[0].data : null;\r
-            return {\r
-                success : rs.success,\r
-                data : data\r
-            };\r
-        }\r
-        return Ext.decode(response.responseText);\r
-    }\r
-});\r
-\r
-\r
-\r
-/**\r
- * @class Ext.form.Action.DirectLoad\r
- * @extends Ext.form.Action.Load\r
- * <p>Provides Ext.direct support for loading form data.</p>\r
- * <p>This example illustrates usage of Ext.Direct to <b>load</b> a form through Ext.Direct.</p>\r
- * <pre><code>\r
-var myFormPanel = new Ext.form.FormPanel({\r
-    // configs for FormPanel\r
-    title: 'Basic Information',\r
-    renderTo: document.body,\r
-    width: 300, height: 160,\r
-    padding: 10,\r
-\r
-    // configs apply to child items\r
-    defaults: {anchor: '100%'},\r
-    defaultType: 'textfield',\r
-    items: [{\r
-        fieldLabel: 'Name',\r
-        name: 'name'\r
-    },{\r
-        fieldLabel: 'Email',\r
-        name: 'email'\r
-    },{\r
-        fieldLabel: 'Company',\r
-        name: 'company'\r
-    }],\r
-\r
-    // configs for BasicForm\r
-    api: {\r
-        // The server-side method to call for load() requests\r
-        load: Profile.getBasicInfo,\r
-        // The server-side must mark the submit handler as a 'formHandler'\r
-        submit: Profile.updateBasicInfo\r
-    },\r
-    // specify the order for the passed params\r
-    paramOrder: ['uid', 'foo']\r
-});\r
-\r
-// load the form\r
-myFormPanel.getForm().load({\r
-    // pass 2 arguments to server side getBasicInfo method (len=2)\r
-    params: {\r
-        foo: 'bar',\r
-        uid: 34\r
-    }\r
-});\r
- * </code></pre>\r
- * The data packet sent to the server will resemble something like:\r
- * <pre><code>\r
-[\r
-    {\r
-        "action":"Profile","method":"getBasicInfo","type":"rpc","tid":2,\r
-        "data":[34,"bar"] // note the order of the params\r
-    }\r
-]\r
- * </code></pre>\r
- * The form will process a data packet returned by the server that is similar\r
- * to the following format:\r
- * <pre><code>\r
-[\r
-    {\r
-        "action":"Profile","method":"getBasicInfo","type":"rpc","tid":2,\r
-        "result":{\r
-            "success":true,\r
-            "data":{\r
-                "name":"Fred Flintstone",\r
-                "company":"Slate Rock and Gravel",\r
-                "email":"fred.flintstone@slaterg.com"\r
-            }\r
-        }\r
-    }\r
-]\r
- * </code></pre>\r
- */\r
-Ext.form.Action.DirectLoad = Ext.extend(Ext.form.Action.Load, {\r
-    constructor: function(form, opts) {\r
-        Ext.form.Action.DirectLoad.superclass.constructor.call(this, form, opts);\r
-    },\r
-    type : 'directload',\r
-\r
-    run : function(){\r
-        var args = this.getParams();\r
-        args.push(this.success, this);\r
-        this.form.api.load.apply(window, args);\r
-    },\r
-\r
-    getParams : function() {\r
-        var buf = [], o = {};\r
-        var bp = this.form.baseParams;\r
-        var p = this.options.params;\r
-        Ext.apply(o, p, bp);\r
-        var paramOrder = this.form.paramOrder;\r
-        if(paramOrder){\r
-            for(var i = 0, len = paramOrder.length; i < len; i++){\r
-                buf.push(o[paramOrder[i]]);\r
-            }\r
-        }else if(this.form.paramsAsHash){\r
-            buf.push(o);\r
-        }\r
-        return buf;\r
-    },\r
-    // Direct actions have already been processed and therefore\r
-    // we can directly set the result; Direct Actions do not have\r
-    // a this.response property.\r
-    processResponse : function(result) {\r
-        this.result = result;\r
-        return result;\r
-    },\r
-    \r
-    success : function(response, trans){\r
-        if(trans.type == Ext.Direct.exceptions.SERVER){\r
-            response = {};\r
-        }\r
-        Ext.form.Action.DirectLoad.superclass.success.call(this, response);\r
-    }\r
-});\r
-\r
-/**\r
- * @class Ext.form.Action.DirectSubmit\r
- * @extends Ext.form.Action.Submit\r
- * <p>Provides Ext.direct support for submitting form data.</p>\r
- * <p>This example illustrates usage of Ext.Direct to <b>submit</b> a form through Ext.Direct.</p>\r
- * <pre><code>\r
-var myFormPanel = new Ext.form.FormPanel({\r
-    // configs for FormPanel\r
-    title: 'Basic Information',\r
-    renderTo: document.body,\r
-    width: 300, height: 160,\r
-    padding: 10,\r
-    buttons:[{\r
-        text: 'Submit',\r
-        handler: function(){\r
-            myFormPanel.getForm().submit({\r
-                params: {\r
-                    foo: 'bar',\r
-                    uid: 34\r
-                }\r
-            });\r
-        }\r
-    }],\r
-\r
-    // configs apply to child items\r
-    defaults: {anchor: '100%'},\r
-    defaultType: 'textfield',\r
-    items: [{\r
-        fieldLabel: 'Name',\r
-        name: 'name'\r
-    },{\r
-        fieldLabel: 'Email',\r
-        name: 'email'\r
-    },{\r
-        fieldLabel: 'Company',\r
-        name: 'company'\r
-    }],\r
-\r
-    // configs for BasicForm\r
-    api: {\r
-        // The server-side method to call for load() requests\r
-        load: Profile.getBasicInfo,\r
-        // The server-side must mark the submit handler as a 'formHandler'\r
-        submit: Profile.updateBasicInfo\r
-    },\r
-    // specify the order for the passed params\r
-    paramOrder: ['uid', 'foo']\r
-});\r
- * </code></pre>\r
- * The data packet sent to the server will resemble something like:\r
- * <pre><code>\r
-{\r
-    "action":"Profile","method":"updateBasicInfo","type":"rpc","tid":"6",\r
-    "result":{\r
-        "success":true,\r
-        "id":{\r
-            "extAction":"Profile","extMethod":"updateBasicInfo",\r
-            "extType":"rpc","extTID":"6","extUpload":"false",\r
-            "name":"Aaron Conran","email":"aaron@extjs.com","company":"Ext JS, LLC"\r
-        }\r
-    }\r
-}\r
- * </code></pre>\r
- * The form will process a data packet returned by the server that is similar\r
- * to the following:\r
- * <pre><code>\r
-// sample success packet (batched requests)\r
-[\r
-    {\r
-        "action":"Profile","method":"updateBasicInfo","type":"rpc","tid":3,\r
-        "result":{\r
-            "success":true\r
-        }\r
-    }\r
-]\r
-\r
-// sample failure packet (one request)\r
-{\r
-        "action":"Profile","method":"updateBasicInfo","type":"rpc","tid":"6",\r
-        "result":{\r
-            "errors":{\r
-                "email":"already taken"\r
-            },\r
-            "success":false,\r
-            "foo":"bar"\r
-        }\r
-}\r
- * </code></pre>\r
- * Also see the discussion in {@link Ext.form.Action.DirectLoad}.\r
- */\r
-Ext.form.Action.DirectSubmit = Ext.extend(Ext.form.Action.Submit, {\r
-    constructor : function(form, opts) {\r
-        Ext.form.Action.DirectSubmit.superclass.constructor.call(this, form, opts);\r
-    },\r
-    type : 'directsubmit',\r
-    // override of Submit\r
-    run : function(){\r
-        var o = this.options;\r
-        if(o.clientValidation === false || this.form.isValid()){\r
-            // tag on any additional params to be posted in the\r
-            // form scope\r
-            this.success.params = this.getParams();\r
-            this.form.api.submit(this.form.el.dom, this.success, this);\r
-        }else if (o.clientValidation !== false){ // client validation failed\r
-            this.failureType = Ext.form.Action.CLIENT_INVALID;\r
-            this.form.afterAction(this, false);\r
-        }\r
-    },\r
-\r
-    getParams : function() {\r
-        var o = {};\r
-        var bp = this.form.baseParams;\r
-        var p = this.options.params;\r
-        Ext.apply(o, p, bp);\r
-        return o;\r
-    },\r
-    // Direct actions have already been processed and therefore\r
-    // we can directly set the result; Direct Actions do not have\r
-    // a this.response property.\r
-    processResponse : function(result) {\r
-        this.result = result;\r
-        return result;\r
-    },\r
-    \r
-    success : function(response, trans){\r
-        if(trans.type == Ext.Direct.exceptions.SERVER){\r
-            response = {};\r
-        }\r
-        Ext.form.Action.DirectSubmit.superclass.success.call(this, response);\r
-    }\r
-});\r
-\r
-Ext.form.Action.ACTION_TYPES = {\r
-    'load' : Ext.form.Action.Load,\r
-    'submit' : Ext.form.Action.Submit,\r
-    'directload' : Ext.form.Action.DirectLoad,\r
-    'directsubmit' : Ext.form.Action.DirectSubmit\r
-};\r
+Ext.form.Action.ACTION_TYPES = {
+    'load' : Ext.form.Action.Load,
+    'submit' : Ext.form.Action.Submit,
+    'directload' : Ext.form.Action.DirectLoad,
+    'directsubmit' : Ext.form.Action.DirectSubmit
+};
 /**
  * @class Ext.form.VTypes
  * <p>This is a singleton object which contains a set of commonly used field validation functions.
@@ -61045,7 +63718,7 @@ Ext.form.VTypes = function(){
     // closure these in so they are only created once.
     var alpha = /^[a-zA-Z_]+$/,
         alphanum = /^[a-zA-Z0-9_]+$/,
-        email = /^(\w+)([\-+.][\w]+)*@(\w[\-\w]*\.){1,5}([A-Za-z]){2,4}$/,
+        email = /^(\w+)([\-+.][\w]+)*@(\w[\-\w]*\.){1,5}([A-Za-z]){2,6}$/,
         url = /(((^https?)|(^ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
 
     // All these messages and functions are configurable
@@ -61348,14 +64021,14 @@ Ext.grid.GridPanel = Ext.extend(Ext.Panel, {
      * @cfg {Array} stateEvents\r
      * An array of events that, when fired, should trigger this component to save its state.\r
      * Defaults to:<pre><code>\r
-     * stateEvents: ['columnmove', 'columnresize', 'sortchange']\r
+     * stateEvents: ['columnmove', 'columnresize', 'sortchange', 'groupchange']\r
      * </code></pre>\r
      * <p>These can be any types of events supported by this component, including browser or\r
      * custom events (e.g., <tt>['click', 'customerchange']</tt>).</p>\r
      * <p>See {@link Ext.Component#stateful} for an explanation of saving and restoring\r
      * Component state.</p>\r
      */\r
-    stateEvents : ['columnmove', 'columnresize', 'sortchange'],\r
+    stateEvents : ['columnmove', 'columnresize', 'sortchange', 'groupchange'],\r
     /**\r
      * @cfg {Object} view The {@link Ext.grid.GridView} used by the grid. This can be set\r
      * before a call to {@link Ext.Component#render render()}.\r
@@ -61365,6 +64038,7 @@ Ext.grid.GridPanel = Ext.extend(Ext.Panel, {
     /**\r
      * @cfg {Array} bubbleEvents\r
      * <p>An array of events that, when fired, should be bubbled to any parent container.\r
+     * See {@link Ext.util.Observable#enableBubble}. \r
      * Defaults to <tt>[]</tt>.\r
      */\r
     bubbleEvents: [],\r
@@ -61495,6 +64169,33 @@ Ext.grid.GridPanel = Ext.extend(Ext.Panel, {
              * @param {Ext.EventObject} e\r
              */\r
             'headermousedown',\r
+            \r
+            /**\r
+             * @event groupmousedown\r
+             * Fires before a group header is clicked. <b>Only applies for grids with a {@link Ext.grid.GroupingView GroupingView}</b>.\r
+             * @param {Grid} this\r
+             * @param {String} groupField\r
+             * @param {String} groupValue\r
+             * @param {Ext.EventObject} e\r
+             */\r
+            'groupmousedown',\r
+            \r
+            /**\r
+             * @event rowbodymousedown\r
+             * Fires before the row body is clicked. <b>Only applies for grids with {@link Ext.grid.GridView#enableRowBody enableRowBody} configured.</b>\r
+             * @param {Grid} this\r
+             * @param {Number} rowIndex\r
+             * @param {Ext.EventObject} e\r
+             */\r
+            'rowbodymousedown',\r
+            \r
+            /**\r
+             * @event containermousedown\r
+             * Fires before the container is clicked. The container consists of any part of the grid body that is not covered by a row.\r
+             * @param {Grid} this\r
+             * @param {Ext.EventObject} e\r
+             */\r
+            'containermousedown',\r
 \r
             /**\r
              * @event cellclick\r
@@ -61556,6 +64257,56 @@ function(grid, rowIndex, columnIndex, e) {
              * @param {Ext.EventObject} e\r
              */\r
             'headerdblclick',\r
+            /**\r
+             * @event groupclick\r
+             * Fires when group header is clicked. <b>Only applies for grids with a {@link Ext.grid.GroupingView GroupingView}</b>.\r
+             * @param {Grid} this\r
+             * @param {String} groupField\r
+             * @param {String} groupValue\r
+             * @param {Ext.EventObject} e\r
+             */\r
+            'groupclick',\r
+            /**\r
+             * @event groupdblclick\r
+             * Fires when group header is double clicked. <b>Only applies for grids with a {@link Ext.grid.GroupingView GroupingView}</b>.\r
+             * @param {Grid} this\r
+             * @param {String} groupField\r
+             * @param {String} groupValue\r
+             * @param {Ext.EventObject} e\r
+             */\r
+            'groupdblclick',\r
+            /**\r
+             * @event containerclick\r
+             * Fires when the container is clicked. The container consists of any part of the grid body that is not covered by a row.\r
+             * @param {Grid} this\r
+             * @param {Ext.EventObject} e\r
+             */\r
+            'containerclick',\r
+            /**\r
+             * @event containerdblclick\r
+             * Fires when the container is double clicked. The container consists of any part of the grid body that is not covered by a row.\r
+             * @param {Grid} this\r
+             * @param {Ext.EventObject} e\r
+             */\r
+            'containerdblclick',\r
+            \r
+            /**\r
+             * @event rowbodyclick\r
+             * Fires when the row body is clicked. <b>Only applies for grids with {@link Ext.grid.GridView#enableRowBody enableRowBody} configured.</b>\r
+             * @param {Grid} this\r
+             * @param {Number} rowIndex\r
+             * @param {Ext.EventObject} e\r
+             */\r
+            'rowbodyclick',\r
+            /**\r
+             * @event rowbodydblclick\r
+             * Fires when the row body is double clicked. <b>Only applies for grids with {@link Ext.grid.GridView#enableRowBody enableRowBody} configured.</b>\r
+             * @param {Grid} this\r
+             * @param {Number} rowIndex\r
+             * @param {Ext.EventObject} e\r
+             */\r
+            'rowbodydblclick',\r
+            \r
             /**\r
              * @event rowcontextmenu\r
              * Fires when a row is right clicked\r
@@ -61581,6 +64332,30 @@ function(grid, rowIndex, columnIndex, e) {
              * @param {Ext.EventObject} e\r
              */\r
             'headercontextmenu',\r
+            /**\r
+             * @event groupcontextmenu\r
+             * Fires when group header is right clicked. <b>Only applies for grids with a {@link Ext.grid.GroupingView GroupingView}</b>.\r
+             * @param {Grid} this\r
+             * @param {String} groupField\r
+             * @param {String} groupValue\r
+             * @param {Ext.EventObject} e\r
+             */\r
+            'groupcontextmenu',\r
+            /**\r
+             * @event containercontextmenu\r
+             * Fires when the container is right clicked. The container consists of any part of the grid body that is not covered by a row.\r
+             * @param {Grid} this\r
+             * @param {Ext.EventObject} e\r
+             */\r
+            'containercontextmenu',\r
+            /**\r
+             * @event rowbodycontextmenu\r
+             * Fires when the row body is right clicked. <b>Only applies for grids with {@link Ext.grid.GridView#enableRowBody enableRowBody} configured.</b>\r
+             * @param {Grid} this\r
+             * @param {Number} rowIndex\r
+             * @param {Ext.EventObject} e\r
+             */\r
+            'rowbodycontextmenu',\r
             /**\r
              * @event bodyscroll\r
              * Fires when the body element is scrolled\r
@@ -61609,6 +64384,13 @@ function(grid, rowIndex, columnIndex, e) {
              * @param {Object} sortInfo An object with the keys field and direction\r
              */\r
             'sortchange',\r
+            /**\r
+             * @event groupchange\r
+             * Fires when the grid's grouping changes (only applies for grids with a {@link Ext.grid.GroupingView GroupingView})\r
+             * @param {Grid} this\r
+             * @param {String} groupField A string with the grouping field, null if the store is not grouped.\r
+             */\r
+            'groupchange',\r
             /**\r
              * @event reconfigure\r
              * Fires when the grid is reconfigured with a new store and/or column model.\r
@@ -61616,7 +64398,13 @@ function(grid, rowIndex, columnIndex, e) {
              * @param {Ext.data.Store} store The new store\r
              * @param {Ext.grid.ColumnModel} colModel The new column model\r
              */\r
-            'reconfigure'\r
+            'reconfigure',\r
+            /**\r
+             * @event viewready\r
+             * Fires when the grid view is available (use this for selecting a default row). \r
+             * @param {Grid} this\r
+             */\r
+            'viewready'\r
         );\r
     },\r
 \r
@@ -61661,23 +64449,40 @@ function(grid, rowIndex, columnIndex, e) {
 \r
     applyState : function(state){\r
         var cm = this.colModel,\r
-            cs = state.columns;\r
+            cs = state.columns,\r
+            store = this.store,\r
+            s,\r
+            c,\r
+            oldIndex;\r
+            \r
         if(cs){\r
             for(var i = 0, len = cs.length; i < len; i++){\r
-                var s = cs[i];\r
-                var c = cm.getColumnById(s.id);\r
+                s = cs[i];\r
+                c = cm.getColumnById(s.id);\r
                 if(c){\r
                     c.hidden = s.hidden;\r
                     c.width = s.width;\r
-                    var oldIndex = cm.getIndexById(s.id);\r
+                    oldIndex = cm.getIndexById(s.id);\r
                     if(oldIndex != i){\r
                         cm.moveColumn(oldIndex, i);\r
                     }\r
                 }\r
             }\r
         }\r
-        if(state.sort && this.store){\r
-            this.store[this.store.remoteSort ? 'setDefaultSort' : 'sort'](state.sort.field, state.sort.direction);\r
+        if(store){\r
+            s = state.sort;\r
+            if(s){\r
+                store[store.remoteSort ? 'setDefaultSort' : 'sort'](s.field, s.direction);\r
+            }\r
+            s = state.group;\r
+            if(store.groupBy){\r
+                if(s){\r
+                    store.groupBy(s);\r
+                }else{\r
+                    store.clearGrouping();\r
+                }\r
+            }\r
+\r
         }\r
         var o = Ext.apply({}, state);\r
         delete o.columns;\r
@@ -61686,7 +64491,11 @@ function(grid, rowIndex, columnIndex, e) {
     },\r
 \r
     getState : function(){\r
-        var o = {columns: []};\r
+        var o = {columns: []},\r
+            store = this.store,\r
+            ss,\r
+            gs;\r
+            \r
         for(var i = 0, c; (c = this.colModel.config[i]); i++){\r
             o.columns[i] = {\r
                 id: c.id,\r
@@ -61696,11 +64505,17 @@ function(grid, rowIndex, columnIndex, e) {
                 o.columns[i].hidden = true;\r
             }\r
         }\r
-        if(this.store){\r
-            var ss = this.store.getSortState();\r
+        if(store){\r
+            ss = store.getSortState();\r
             if(ss){\r
                 o.sort = ss;\r
             }\r
+            if(store.getGroupState){\r
+                gs = store.getGroupState();\r
+                if(gs){\r
+                    o.group = gs;\r
+                }\r
+            }\r
         }\r
         return o;\r
     },\r
@@ -61732,15 +64547,20 @@ function(grid, rowIndex, columnIndex, e) {
      * @param {Ext.grid.ColumnModel} colModel The new {@link Ext.grid.ColumnModel} object\r
      */\r
     reconfigure : function(store, colModel){\r
-        if(this.loadMask){\r
-            this.loadMask.destroy();\r
-            this.loadMask = new Ext.LoadMask(this.bwrap,\r
-                    Ext.apply({}, {store:store}, this.initialConfig.loadMask));\r
+        var rendered = this.rendered;\r
+        if(rendered){\r
+            if(this.loadMask){\r
+                this.loadMask.destroy();\r
+                this.loadMask = new Ext.LoadMask(this.bwrap,\r
+                        Ext.apply({}, {store:store}, this.initialConfig.loadMask));\r
+            }\r
+        }\r
+        if(this.view){\r
+            this.view.initData(store, colModel);\r
         }\r
-        this.view.initData(store, colModel);\r
         this.store = store;\r
         this.colModel = colModel;\r
-        if(this.rendered){\r
+        if(rendered){\r
             this.view.refresh(true);\r
         }\r
         this.fireEvent('reconfigure', this, store, colModel);\r
@@ -61749,9 +64569,6 @@ function(grid, rowIndex, columnIndex, e) {
     // private\r
     onDestroy : function(){\r
         if(this.rendered){\r
-            var c = this.body;\r
-            c.removeAllListeners();\r
-            c.update('');\r
             Ext.destroy(this.view, this.loadMask);\r
         }else if(this.store && this.store.autoDestroy){\r
             this.store.destroy();\r
@@ -61764,21 +64581,31 @@ function(grid, rowIndex, columnIndex, e) {
     // private\r
     processEvent : function(name, e){\r
         this.fireEvent(name, e);\r
-        var t = e.getTarget();\r
-        var v = this.view;\r
-        var header = v.findHeaderIndex(t);\r
+        var t = e.getTarget(),\r
+            v = this.view,\r
+            header = v.findHeaderIndex(t);\r
+            \r
         if(header !== false){\r
             this.fireEvent('header' + name, this, header, e);\r
         }else{\r
-            var row = v.findRowIndex(t);\r
-            var cell = v.findCellIndex(t);\r
+            var row = v.findRowIndex(t),\r
+                cell,\r
+                body;\r
             if(row !== false){\r
                 this.fireEvent('row' + name, this, row, e);\r
+                cell = v.findCellIndex(t);\r
+                body = v.findRowBody(t);\r
                 if(cell !== false){\r
                     this.fireEvent('cell' + name, this, row, cell, e);\r
                 }\r
+                if(body){\r
+                    this.fireEvent('rowbody' + name, this, row, e);\r
+                }\r
+            }else{\r
+                this.fireEvent('container' + name, this, e);\r
             }\r
         }\r
+        this.view.processEvent(name, e);\r
     },\r
 \r
     // private\r
@@ -61803,8 +64630,11 @@ function(grid, rowIndex, columnIndex, e) {
 \r
     // private\r
     walkCells : function(row, col, step, fn, scope){\r
-        var cm = this.colModel, clen = cm.getColumnCount();\r
-        var ds = this.store, rlen = ds.getCount(), first = true;\r
+        var cm = this.colModel, \r
+            clen = cm.getColumnCount(),\r
+            ds = this.store, \r
+            rlen = ds.getCount(), \r
+            first = true;\r
         if(step < 0){\r
             if(col < 0){\r
                 row--;\r
@@ -62022,7 +64852,7 @@ function(grid, rowIndex, columnIndex, e) {
      * @hide \r
      */\r
     /** \r
-     * @event afterLayout \r
+     * @event afterlayout \r
      * @hide \r
      */\r
     /** \r
@@ -62106,67 +64936,7 @@ Ext.reg('grid', Ext.grid.GridPanel);/**
  * @constructor
  * @param {Object} config
  */
-Ext.grid.GridView = function(config){
-    Ext.apply(this, config);
-    // These events are only used internally by the grid components
-    this.addEvents(
-        /**
-         * @event beforerowremoved
-         * Internal UI Event. Fired before a row is removed.
-         * @param {Ext.grid.GridView} view
-         * @param {Number} rowIndex The index of the row to be removed.
-         * @param {Ext.data.Record} record The Record to be removed
-         */
-        'beforerowremoved',
-        /**
-         * @event beforerowsinserted
-         * Internal UI Event. Fired before rows are inserted.
-         * @param {Ext.grid.GridView} view
-         * @param {Number} firstRow The index of the first row to be inserted.
-         * @param {Number} lastRow The index of the last row to be inserted.
-         */
-        'beforerowsinserted',
-        /**
-         * @event beforerefresh
-         * Internal UI Event. Fired before the view is refreshed.
-         * @param {Ext.grid.GridView} view
-         */
-        'beforerefresh',
-        /**
-         * @event rowremoved
-         * Internal UI Event. Fired after a row is removed.
-         * @param {Ext.grid.GridView} view
-         * @param {Number} rowIndex The index of the row that was removed.
-         * @param {Ext.data.Record} record The Record that was removed
-         */
-        'rowremoved',
-        /**
-         * @event rowsinserted
-         * Internal UI Event. Fired after rows are inserted.
-         * @param {Ext.grid.GridView} view
-         * @param {Number} firstRow The index of the first inserted.
-         * @param {Number} lastRow The index of the last row inserted.
-         */
-        'rowsinserted',
-        /**
-         * @event rowupdated
-         * Internal UI Event. Fired after a row has been updated.
-         * @param {Ext.grid.GridView} view
-         * @param {Number} firstRow The index of the row updated.
-         * @param {Ext.data.record} record The Record backing the row updated.
-         */
-        'rowupdated',
-        /**
-         * @event refresh
-         * Internal UI Event. Fired after the GridView's body has been refreshed.
-         * @param {Ext.grid.GridView} view
-         */
-        'refresh'
-    );
-    Ext.grid.GridView.superclass.constructor.call(this);
-};
-
-Ext.extend(Ext.grid.GridView, Ext.util.Observable, {
+Ext.grid.GridView = Ext.extend(Ext.util.Observable, {
     /**
      * Override this function to apply custom CSS classes to rows during rendering.  You can also supply custom
      * parameters to the row template for the current row to customize how it is rendered using the <b>rowParams</b>
@@ -62315,6 +65085,11 @@ viewConfig: {
      * @cfg {Number} rowSelectorDepth The number of levels to search for rows in event delegation (defaults to <tt>10</tt>)
      */
     rowSelectorDepth : 10,
+    
+    /**
+     * @cfg {Number} rowBodySelectorDepth The number of levels to search for row bodies in event delegation (defaults to <tt>10</tt>)
+     */
+    rowBodySelectorDepth : 10,
 
     /**
      * @cfg {String} cellSelector The selector used to find cells internally (defaults to <tt>'td.x-grid3-cell'</tt>)
@@ -62325,10 +65100,75 @@ viewConfig: {
      */
     rowSelector : 'div.x-grid3-row',
     
+    /**
+     * @cfg {String} rowBodySelector The selector used to find row bodies internally (defaults to <tt>'div.x-grid3-row'</tt>)
+     */
+    rowBodySelector : 'div.x-grid3-row-body',
+    
     // private
     firstRowCls: 'x-grid3-row-first',
     lastRowCls: 'x-grid3-row-last',
     rowClsRe: /(?:^|\s+)x-grid3-row-(first|last|alt)(?:\s+|$)/g,
+    
+    constructor : function(config){
+        Ext.apply(this, config);
+           // These events are only used internally by the grid components
+           this.addEvents(
+               /**
+                * @event beforerowremoved
+                * Internal UI Event. Fired before a row is removed.
+                * @param {Ext.grid.GridView} view
+                * @param {Number} rowIndex The index of the row to be removed.
+                * @param {Ext.data.Record} record The Record to be removed
+                */
+               'beforerowremoved',
+               /**
+                * @event beforerowsinserted
+                * Internal UI Event. Fired before rows are inserted.
+                * @param {Ext.grid.GridView} view
+                * @param {Number} firstRow The index of the first row to be inserted.
+                * @param {Number} lastRow The index of the last row to be inserted.
+                */
+               'beforerowsinserted',
+               /**
+                * @event beforerefresh
+                * Internal UI Event. Fired before the view is refreshed.
+                * @param {Ext.grid.GridView} view
+                */
+               'beforerefresh',
+               /**
+                * @event rowremoved
+                * Internal UI Event. Fired after a row is removed.
+                * @param {Ext.grid.GridView} view
+                * @param {Number} rowIndex The index of the row that was removed.
+                * @param {Ext.data.Record} record The Record that was removed
+                */
+               'rowremoved',
+               /**
+                * @event rowsinserted
+                * Internal UI Event. Fired after rows are inserted.
+                * @param {Ext.grid.GridView} view
+                * @param {Number} firstRow The index of the first inserted.
+                * @param {Number} lastRow The index of the last row inserted.
+                */
+               'rowsinserted',
+               /**
+                * @event rowupdated
+                * Internal UI Event. Fired after a row has been updated.
+                * @param {Ext.grid.GridView} view
+                * @param {Number} firstRow The index of the row updated.
+                * @param {Ext.data.record} record The Record backing the row updated.
+                */
+               'rowupdated',
+               /**
+                * @event refresh
+                * Internal UI Event. Fired after the GridView's body has been refreshed.
+                * @param {Ext.grid.GridView} view
+                */
+               'refresh'
+           );
+           Ext.grid.GridView.superclass.constructor.call(this);    
+    },
 
     /* -------------------------------- UI Specific ----------------------------- */
 
@@ -62387,7 +65227,7 @@ viewConfig: {
 
         for(var k in ts){
             var t = ts[k];
-            if(t && typeof t.compile == 'function' && !t.compiled){
+            if(t && Ext.isFunction(t.compile) && !t.compiled){
                 t.disableFormats = true;
                 t.compile();
             }
@@ -62520,6 +65360,18 @@ viewConfig: {
         var r = this.findRow(el);
         return r ? r.rowIndex : false;
     },
+    
+    /**
+     * Return the HtmlElement representing the grid row body which contains the passed element.
+     * @param {HTMLElement} el The target HTMLElement
+     * @return {HTMLElement} The row body element, or null if the target element is not within a row body of this GridView.
+     */
+    findRowBody : function(el){
+        if(!el){
+            return false;
+        }
+        return this.fly(el).findParent(this.rowBodySelector, this.rowBodySelectorDepth);
+    },
 
     // getter methods for fetching elements dynamically in the grid
 
@@ -62725,12 +65577,12 @@ viewConfig: {
                 p.id = c.id;
                 p.css = i === 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');
                 p.attr = p.cellAttr = '';
-                p.value = c.renderer(r.data[c.name], p, r, rowIndex, i, ds);
+                p.value = c.renderer.call(c.scope, r.data[c.name], p, r, rowIndex, i, ds);
                 p.style = c.style;
                 if(Ext.isEmpty(p.value)){
                     p.value = '&#160;';
                 }
-                if(this.markDirty && r.dirty && typeof r.modified[c.name] !== 'undefined'){
+                if(this.markDirty && r.dirty && Ext.isDefined(r.modified[c.name])){
                     p.css += ' x-grid3-dirty-cell';
                 }
                 cb[cb.length] = ct.apply(p);
@@ -62758,18 +65610,24 @@ viewConfig: {
         if(!this.ds || this.ds.getCount() < 1){
             return;
         }
-        var rows = this.getRows();
+        var rows = this.getRows(),
+            len = rows.length,
+            i, r;
+            
         skipStripe = skipStripe || !this.grid.stripeRows;
         startRow = startRow || 0;
-        Ext.each(rows, function(row, idx){
-            row.rowIndex = idx;
-            if(!skipStripe){
-                row.className = row.className.replace(this.rowClsRe, ' ');
-                if ((idx + 1) % 2 === 0){
-                    row.className += ' x-grid3-row-alt';
-                }
-            }
-        }, this);
+        for(i = 0; i<len; i++) {
+            r = rows[i];
+            if(r) {
+                r.rowIndex = i;
+                if(!skipStripe){
+                    r.className = r.className.replace(this.rowClsRe, ' ');
+                    if ((i + 1) % 2 === 0){
+                        r.className += ' x-grid3-row-alt';
+                    }
+                }   
+            }          
+        }
         // add first/last-row classes
         if(startRow === 0){
             Ext.fly(rows[0]).addClass(this.firstRowCls);
@@ -62787,6 +65645,7 @@ viewConfig: {
         if(this.deferEmptyText !== true){
             this.applyEmptyText();
         }
+        this.grid.fireEvent('viewready', this.grid);
     },
 
     // private
@@ -62869,6 +65728,9 @@ viewConfig: {
         this.updateHeaderSortState();
 
     },
+    
+    // private
+    processEvent: Ext.emptyFn,
 
     // private
     layout : function(){
@@ -63036,7 +65898,7 @@ viewConfig: {
     },
 
     resolveCell : function(row, col, hscroll){
-        if(typeof row != "number"){
+        if(!Ext.isNumber(row)){
             row = row.rowIndex;
         }
         if(!this.ds){
@@ -63129,7 +65991,9 @@ viewConfig: {
     insertRows : function(dm, firstRow, lastRow, isUpdate){
         var last = dm.getCount() - 1;
         if(!isUpdate && firstRow === 0 && lastRow >= last){
+           this.fireEvent('beforerowsinserted', this, firstRow, lastRow);
             this.refresh();
+           this.fireEvent('rowsinserted', this, firstRow, lastRow);
         }else{
             if(!isUpdate){
                 this.fireEvent('beforerowsinserted', this, firstRow, lastRow);
@@ -63190,7 +66054,7 @@ viewConfig: {
     // private
     getColumnWidth : function(col){
         var w = this.cm.getColumnWidth(col);
-        if(typeof w == 'number'){
+        if(Ext.isNumber(w)){
             return (Ext.isBorderBox || (Ext.isWebKit && !Ext.isSafari2) ? w : (w - this.borderWidth > 0 ? w - this.borderWidth : 0)) + 'px';
         }
         return w;
@@ -63217,7 +66081,7 @@ viewConfig: {
         }
 
         var vc = cm.getColumnCount(true);
-        var ac = vc-(typeof omitColumn == 'number' ? 1 : 0);
+        var ac = vc-(Ext.isNumber(omitColumn) ? 1 : 0);
         if(ac === 0){
             ac = 1;
             omitColumn = undefined;
@@ -63284,8 +66148,9 @@ viewConfig: {
         for(var i = 0; i < colCount; i++){
             var name = cm.getDataIndex(i);
             cs[i] = {
-                name : (typeof name == 'undefined' ? this.ds.fields.get(i).name : name),
+                name : (!Ext.isDefined(name) ? this.ds.fields.get(i).name : name),
                 renderer : cm.getRenderer(i),
+                scope: cm.getRendererScope(i),
                 id : cm.getColumnId(i),
                 style : this.getColumnStyle(i)
             };
@@ -63306,7 +66171,7 @@ viewConfig: {
         var cs = this.getColumnData();
 
         startRow = startRow || 0;
-        endRow = typeof endRow == "undefined"? ds.getCount()-1 : endRow;
+        endRow = !Ext.isDefined(endRow) ? ds.getCount()-1 : endRow;
 
         // records to render
         var rs = ds.getRange(startRow, endRow);
@@ -63323,7 +66188,7 @@ viewConfig: {
     // private
     refreshRow : function(record){
         var ds = this.ds, index;
-        if(typeof record == 'number'){
+        if(Ext.isNumber(record)){
             index = record;
             record = ds.getAt(index);
             if(!record){
@@ -63385,6 +66250,16 @@ viewConfig: {
         }
     },
 
+    // private
+    clearHeaderSortState : function(){
+        if(!this.sortState){
+            return;
+        }
+        this.grid.fireEvent('sortchange', this.grid, null);
+        this.mainHd.select('td').removeClass(this.sortClasses);
+        delete this.sortState;
+    },
+
     // private
     destroy : function(){
         if(this.colMenu){
@@ -63431,9 +66306,9 @@ viewConfig: {
             delete Ext.dd.DDM.ids[this.columnDrop.ddGroup];
         }
 
-        if (this.splitone){ // enableColumnResize
-            this.splitone.destroy();
-            delete this.splitone._domRef;
+        if (this.splitZone){ // enableColumnResize
+            this.splitZone.destroy();
+            delete this.splitZone._domRef;
             delete Ext.dd.DDM.ids["gridSplitters" + this.grid.getGridEl().id];
         }
 
@@ -63562,6 +66437,7 @@ viewConfig: {
 
     // private
     onAdd : function(ds, records, index){
+       
         this.insertRows(ds, index, index + (records.length-1));
     },
 
@@ -63858,11 +66734,15 @@ Ext.extend(Ext.grid.GridView.SplitDragZone, Ext.dd.DDProxy, {
         this.startPos = x;
         Ext.dd.DDProxy.prototype.b4StartDrag.call(this, x, y);
     },
+    
+    allowHeaderDrag : function(e){
+        return true;
+    },
 
 
     handleMouseDown : function(e){
         var t = this.view.findHeaderCell(e.getTarget());
-        if(t){
+        if(t && this.allowHeaderDrag(e)){
             var xy = this.view.fly(t).getXY(), x = xy[0], y = xy[1];
             var exy = e.getXY(), ex = exy[0];
             var w = t.offsetWidth, adjust = false;
@@ -63913,19 +66793,21 @@ Ext.extend(Ext.grid.GridView.SplitDragZone, Ext.dd.DDProxy, {
 });
 // private\r
 // This is a support class used internally by the Grid components\r
-Ext.grid.HeaderDragZone = function(grid, hd, hd2){\r
-    this.grid = grid;\r
-    this.view = grid.getView();\r
-    this.ddGroup = "gridHeader" + this.grid.getGridEl().id;\r
-    Ext.grid.HeaderDragZone.superclass.constructor.call(this, hd);\r
-    if(hd2){\r
-        this.setHandleElId(Ext.id(hd));\r
-        this.setOuterHandleElId(Ext.id(hd2));\r
-    }\r
-    this.scroll = false;\r
-};\r
-Ext.extend(Ext.grid.HeaderDragZone, Ext.dd.DragZone, {\r
+Ext.grid.HeaderDragZone = Ext.extend(Ext.dd.DragZone, {\r
     maxDragWidth: 120,\r
+    \r
+    constructor : function(grid, hd, hd2){\r
+        this.grid = grid;\r
+        this.view = grid.getView();\r
+        this.ddGroup = "gridHeader" + this.grid.getGridEl().id;\r
+        Ext.grid.HeaderDragZone.superclass.constructor.call(this, hd);\r
+        if(hd2){\r
+            this.setHandleElId(Ext.id(hd));\r
+            this.setOuterHandleElId(Ext.id(hd2));\r
+        }\r
+        this.scroll = false;\r
+    },\r
+    \r
     getDragData : function(e){\r
         var t = Ext.lib.Event.getTarget(e);\r
         var h = this.view.findHeaderCell(t);\r
@@ -63961,28 +66843,29 @@ Ext.extend(Ext.grid.HeaderDragZone, Ext.dd.DragZone, {
 \r
 // private\r
 // This is a support class used internally by the Grid components\r
-Ext.grid.HeaderDropZone = function(grid, hd, hd2){\r
-    this.grid = grid;\r
-    this.view = grid.getView();\r
-    // split the proxies so they don't interfere with mouse events\r
-    this.proxyTop = Ext.DomHelper.append(document.body, {\r
-        cls:"col-move-top", html:"&#160;"\r
-    }, true);\r
-    this.proxyBottom = Ext.DomHelper.append(document.body, {\r
-        cls:"col-move-bottom", html:"&#160;"\r
-    }, true);\r
-    this.proxyTop.hide = this.proxyBottom.hide = function(){\r
-        this.setLeftTop(-100,-100);\r
-        this.setStyle("visibility", "hidden");\r
-    };\r
-    this.ddGroup = "gridHeader" + this.grid.getGridEl().id;\r
-    // temporarily disabled\r
-    //Ext.dd.ScrollManager.register(this.view.scroller.dom);\r
-    Ext.grid.HeaderDropZone.superclass.constructor.call(this, grid.getGridEl().dom);\r
-};\r
-Ext.extend(Ext.grid.HeaderDropZone, Ext.dd.DropZone, {\r
+Ext.grid.HeaderDropZone = Ext.extend(Ext.dd.DropZone, {\r
     proxyOffsets : [-4, -9],\r
     fly: Ext.Element.fly,\r
+    \r
+    constructor : function(grid, hd, hd2){\r
+        this.grid = grid;\r
+        this.view = grid.getView();\r
+        // split the proxies so they don't interfere with mouse events\r
+        this.proxyTop = Ext.DomHelper.append(document.body, {\r
+            cls:"col-move-top", html:"&#160;"\r
+        }, true);\r
+        this.proxyBottom = Ext.DomHelper.append(document.body, {\r
+            cls:"col-move-bottom", html:"&#160;"\r
+        }, true);\r
+        this.proxyTop.hide = this.proxyBottom.hide = function(){\r
+            this.setLeftTop(-100,-100);\r
+            this.setStyle("visibility", "hidden");\r
+        };\r
+        this.ddGroup = "gridHeader" + this.grid.getGridEl().id;\r
+        // temporarily disabled\r
+        //Ext.dd.ScrollManager.register(this.view.scroller.dom);\r
+        Ext.grid.HeaderDropZone.superclass.constructor.call(this, grid.getGridEl().dom);\r
+    },\r
 \r
     getTargetFromEvent : function(e){\r
         var t = Ext.lib.Event.getTarget(e);\r
@@ -64088,15 +66971,14 @@ Ext.extend(Ext.grid.HeaderDropZone, Ext.dd.DropZone, {
     }\r
 });\r
 \r
-\r
-Ext.grid.GridView.ColumnDragZone = function(grid, hd){\r
-    Ext.grid.GridView.ColumnDragZone.superclass.constructor.call(this, grid, hd, null);\r
-    this.proxy.el.addClass('x-grid3-col-dd');\r
-};\r
-\r
-Ext.extend(Ext.grid.GridView.ColumnDragZone, Ext.grid.HeaderDragZone, {\r
+Ext.grid.GridView.ColumnDragZone = Ext.extend(Ext.grid.HeaderDragZone, {\r
+    \r
+    constructor : function(grid, hd){\r
+        Ext.grid.GridView.ColumnDragZone.superclass.constructor.call(this, grid, hd, null);\r
+        this.proxy.el.addClass('x-grid3-col-dd');\r
+    },\r
+    \r
     handleMouseDown : function(e){\r
-\r
     },\r
 \r
     callHandleMouseDown : function(e){\r
@@ -64104,20 +66986,21 @@ Ext.extend(Ext.grid.GridView.ColumnDragZone, Ext.grid.HeaderDragZone, {
     }\r
 });// private
 // This is a support class used internally by the Grid components
-Ext.grid.SplitDragZone = function(grid, hd, hd2){
-    this.grid = grid;
-    this.view = grid.getView();
-    this.proxy = this.view.resizeProxy;
-    Ext.grid.SplitDragZone.superclass.constructor.call(this, hd,
-        "gridSplitters" + this.grid.getGridEl().id, {
-        dragElId : Ext.id(this.proxy.dom), resizeFrame:false
-    });
-    this.setHandleElId(Ext.id(hd));
-    this.setOuterHandleElId(Ext.id(hd2));
-    this.scroll = false;
-};
-Ext.extend(Ext.grid.SplitDragZone, Ext.dd.DDProxy, {
+Ext.grid.SplitDragZone = Ext.extend(Ext.dd.DDProxy, {
     fly: Ext.Element.fly,
+    
+    constructor : function(grid, hd, hd2){
+        this.grid = grid;
+        this.view = grid.getView();
+        this.proxy = this.view.resizeProxy;
+        Ext.grid.SplitDragZone.superclass.constructor.call(this, hd,
+            "gridSplitters" + this.grid.getGridEl().id, {
+            dragElId : Ext.id(this.proxy.dom), resizeFrame:false
+        });
+        this.setHandleElId(Ext.id(hd));
+        this.setOuterHandleElId(Ext.id(hd2));
+        this.scroll = false;
+    },
 
     b4StartDrag : function(x, y){
         this.view.headersDisabled = true;
@@ -64330,66 +67213,7 @@ Ext.extend(Ext.grid.GridDragZone, Ext.dd.DragZone, {
  * @param {Mixed} config Specify either an Array of {@link Ext.grid.Column} configuration objects or specify
  * a configuration Object (see introductory section discussion utilizing Initialization Method 2 above).
  */
-Ext.grid.ColumnModel = function(config){
-    /**
-     * An Array of {@link Ext.grid.Column Column definition} objects representing the configuration
-     * of this ColumnModel.  See {@link Ext.grid.Column} for the configuration properties that may
-     * be specified.
-     * @property config
-     * @type Array
-     */
-    if(config.columns){
-        Ext.apply(this, config);
-        this.setConfig(config.columns, true);
-    }else{
-        this.setConfig(config, true);
-    }
-    this.addEvents(
-        /**
-         * @event widthchange
-         * Fires when the width of a column is programmaticially changed using
-         * <code>{@link #setColumnWidth}</code>.
-         * Note internal resizing suppresses the event from firing. See also
-         * {@link Ext.grid.GridPanel}.<code>{@link #columnresize}</code>.
-         * @param {ColumnModel} this
-         * @param {Number} columnIndex The column index
-         * @param {Number} newWidth The new width
-         */
-        "widthchange",
-        /**
-         * @event headerchange
-         * Fires when the text of a header changes.
-         * @param {ColumnModel} this
-         * @param {Number} columnIndex The column index
-         * @param {String} newText The new header text
-         */
-        "headerchange",
-        /**
-         * @event hiddenchange
-         * Fires when a column is hidden or "unhidden".
-         * @param {ColumnModel} this
-         * @param {Number} columnIndex The column index
-         * @param {Boolean} hidden true if hidden, false otherwise
-         */
-        "hiddenchange",
-        /**
-         * @event columnmoved
-         * Fires when a column is moved.
-         * @param {ColumnModel} this
-         * @param {Number} oldIndex
-         * @param {Number} newIndex
-         */
-        "columnmoved",
-        /**
-         * @event configchange
-         * Fires when the configuration is changed
-         * @param {ColumnModel} this
-         */
-        "configchange"
-    );
-    Ext.grid.ColumnModel.superclass.constructor.call(this);
-};
-Ext.extend(Ext.grid.ColumnModel, Ext.util.Observable, {
+Ext.grid.ColumnModel = Ext.extend(Ext.util.Observable, {
     /**
      * @cfg {Number} defaultWidth (optional) The width of columns which have no <tt>{@link #width}</tt>
      * specified (defaults to <tt>100</tt>).  This property shall preferably be configured through the
@@ -64412,6 +67236,66 @@ Ext.extend(Ext.grid.ColumnModel, Ext.util.Observable, {
      * configuration options to all <tt><b>{@link #columns}</b></tt>.  Configuration options specified with
      * individual {@link Ext.grid.Column column} configs will supersede these <tt><b>{@link #defaults}</b></tt>.
      */
+    
+    constructor : function(config){
+        /**
+            * An Array of {@link Ext.grid.Column Column definition} objects representing the configuration
+            * of this ColumnModel.  See {@link Ext.grid.Column} for the configuration properties that may
+            * be specified.
+            * @property config
+            * @type Array
+            */
+           if(config.columns){
+               Ext.apply(this, config);
+               this.setConfig(config.columns, true);
+           }else{
+               this.setConfig(config, true);
+           }
+           this.addEvents(
+               /**
+                * @event widthchange
+                * Fires when the width of a column is programmaticially changed using
+                * <code>{@link #setColumnWidth}</code>.
+                * Note internal resizing suppresses the event from firing. See also
+                * {@link Ext.grid.GridPanel}.<code>{@link #columnresize}</code>.
+                * @param {ColumnModel} this
+                * @param {Number} columnIndex The column index
+                * @param {Number} newWidth The new width
+                */
+               "widthchange",
+               /**
+                * @event headerchange
+                * Fires when the text of a header changes.
+                * @param {ColumnModel} this
+                * @param {Number} columnIndex The column index
+                * @param {String} newText The new header text
+                */
+               "headerchange",
+               /**
+                * @event hiddenchange
+                * Fires when a column is hidden or "unhidden".
+                * @param {ColumnModel} this
+                * @param {Number} columnIndex The column index
+                * @param {Boolean} hidden true if hidden, false otherwise
+                */
+               "hiddenchange",
+               /**
+                * @event columnmoved
+                * Fires when a column is moved.
+                * @param {ColumnModel} this
+                * @param {Number} oldIndex
+                * @param {Number} newIndex
+                */
+               "columnmoved",
+               /**
+                * @event configchange
+                * Fires when the configuration is changed
+                * @param {ColumnModel} this
+                */
+               "configchange"
+           );
+           Ext.grid.ColumnModel.superclass.constructor.call(this);
+    },
 
     /**
      * Returns the id of the column at the specified index.
@@ -64441,10 +67325,7 @@ Ext.extend(Ext.grid.ColumnModel, Ext.util.Observable, {
         if(!initial){ // cleanup
             delete this.totalWidth;
             for(i = 0, len = this.config.length; i < len; i++){
-                c = this.config[i];
-                if(c.editor){
-                    c.editor.destroy();
-                }
+                this.config[i].destroy();
             }
         }
 
@@ -64460,7 +67341,7 @@ Ext.extend(Ext.grid.ColumnModel, Ext.util.Observable, {
         for(i = 0, len = config.length; i < len; i++){
             c = Ext.applyIf(config[i], this.defaults);
             // if no id, create one using column's ordinal position
-            if(typeof c.id == 'undefined'){
+            if(Ext.isEmpty(c.id)){
                 c.id = i;
             }
             if(!c.isColumn){
@@ -64538,8 +67419,10 @@ var columns = grid.getColumnModel().getColumnsBy(function(c){
   return c.hidden;
 });
 </code></pre>
-     * @param {Function} fn
-     * @param {Object} scope (optional)
+     * @param {Function} fn A function which, when passed a {@link Ext.grid.Column Column} object, must
+     * return <code>true</code> if the column is to be included in the returned Array.
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function
+     * is executed. Defaults to this ColumnModel.
      * @return {Array} result
      */
     getColumnsBy : function(fn, scope){
@@ -64582,6 +67465,10 @@ var columns = grid.getColumnModel().getColumnsBy(function(c){
         }
         return this.config[col].renderer;
     },
+    
+    getRendererScope : function(col){
+        return this.config[col].scope;
+    },
 
     /**
      * Sets the rendering (formatting) function for a column.  See {@link Ext.util.Format} for some
@@ -64743,7 +67630,11 @@ var grid = new Ext.grid.GridPanel({
      * @return {Boolean}
      */
     isCellEditable : function(colIndex, rowIndex){
-        return (this.config[colIndex].editable || (typeof this.config[colIndex].editable == "undefined" && this.config[colIndex].editor)) ? true : false;
+        var c = this.config[colIndex],
+            ed = c.editable;
+            
+        //force boolean
+        return !!(ed || (!Ext.isDefined(ed) && c.editor));
     },
 
     /**
@@ -64816,16 +67707,15 @@ myGrid.getColumnModel().setHidden(0, true); // hide column 0 (0 = the first colu
      * @param {Object} editor The editor object
      */
     setEditor : function(col, editor){
-        Ext.destroy(this.config[col].editor);
-        this.config[col].editor = editor;
+        this.config[col].setEditor(editor);
     },
 
     /**
      * Destroys this column model by purging any event listeners, and removing any editors.
      */
     destroy : function(){
-        for(var i = 0, c = this.config, len = c.length; i < len; i++){
-            Ext.destroy(c[i].editor);
+        for(var i = 0, len = this.config.length; i < len; i++){
+            this.config[i].destroy();
         }
         this.purgeListeners();
     }
@@ -64844,17 +67734,17 @@ Ext.grid.ColumnModel.defaultRenderer = function(value){
  * implemented by descendant classes.  This class should not be directly instantiated.\r
  * @constructor\r
  */\r
-Ext.grid.AbstractSelectionModel = function(){\r
-    this.locked = false;\r
-    Ext.grid.AbstractSelectionModel.superclass.constructor.call(this);\r
-};\r
-\r
-Ext.extend(Ext.grid.AbstractSelectionModel, Ext.util.Observable,  {\r
+Ext.grid.AbstractSelectionModel = Ext.extend(Ext.util.Observable,  {\r
     /**\r
      * The GridPanel for which this SelectionModel is handling selection. Read-only.\r
      * @type Object\r
      * @property grid\r
      */\r
+    \r
+    constructor : function(){\r
+        this.locked = false;\r
+        Ext.grid.AbstractSelectionModel.superclass.constructor.call(this);\r
+    },\r
 \r
     /** @ignore Called by the grid automatically. Do not call directly. */\r
     init : function(grid){\r
@@ -64897,60 +67787,59 @@ Ext.extend(Ext.grid.AbstractSelectionModel, Ext.util.Observable,  {
  * @constructor
  * @param {Object} config
  */
-Ext.grid.RowSelectionModel = function(config){
-    Ext.apply(this, config);
-    this.selections = new Ext.util.MixedCollection(false, function(o){
-        return o.id;
-    });
-
-    this.last = false;
-    this.lastActive = false;
-
-    this.addEvents(
-        /**
-         * @event selectionchange
-         * Fires when the selection changes
-         * @param {SelectionModel} this
-         */
-        'selectionchange',
-        /**
-         * @event beforerowselect
-         * Fires before a row is selected, return false to cancel the selection.
-         * @param {SelectionModel} this
-         * @param {Number} rowIndex The index to be selected
-         * @param {Boolean} keepExisting False if other selections will be cleared
-         * @param {Record} record The record to be selected
-         */
-        'beforerowselect',
-        /**
-         * @event rowselect
-         * Fires when a row is selected.
-         * @param {SelectionModel} this
-         * @param {Number} rowIndex The selected index
-         * @param {Ext.data.Record} r The selected record
-         */
-        'rowselect',
-        /**
-         * @event rowdeselect
-         * Fires when a row is deselected.  To prevent deselection
-         * {@link Ext.grid.AbstractSelectionModel#lock lock the selections}. 
-         * @param {SelectionModel} this
-         * @param {Number} rowIndex
-         * @param {Record} record
-         */
-        'rowdeselect'
-    );
-
-    Ext.grid.RowSelectionModel.superclass.constructor.call(this);
-};
-
-Ext.extend(Ext.grid.RowSelectionModel, Ext.grid.AbstractSelectionModel,  {
+Ext.grid.RowSelectionModel = Ext.extend(Ext.grid.AbstractSelectionModel,  {
     /**
      * @cfg {Boolean} singleSelect
      * <tt>true</tt> to allow selection of only one row at a time (defaults to <tt>false</tt>
      * allowing multiple selections)
      */
     singleSelect : false,
+    
+    constructor : function(config){
+        Ext.apply(this, config);
+        this.selections = new Ext.util.MixedCollection(false, function(o){
+            return o.id;
+        });
+
+        this.last = false;
+        this.lastActive = false;
+
+        this.addEvents(
+               /**
+                * @event selectionchange
+                * Fires when the selection changes
+                * @param {SelectionModel} this
+                */
+               'selectionchange',
+               /**
+                * @event beforerowselect
+                * Fires before a row is selected, return false to cancel the selection.
+                * @param {SelectionModel} this
+                * @param {Number} rowIndex The index to be selected
+                * @param {Boolean} keepExisting False if other selections will be cleared
+                * @param {Record} record The record to be selected
+                */
+               'beforerowselect',
+               /**
+                * @event rowselect
+                * Fires when a row is selected.
+                * @param {SelectionModel} this
+                * @param {Number} rowIndex The selected index
+                * @param {Ext.data.Record} r The selected record
+                */
+               'rowselect',
+               /**
+                * @event rowdeselect
+                * Fires when a row is deselected.  To prevent deselection
+                * {@link Ext.grid.AbstractSelectionModel#lock lock the selections}. 
+                * @param {SelectionModel} this
+                * @param {Number} rowIndex
+                * @param {Record} record
+                */
+               'rowdeselect'
+        );
+        Ext.grid.RowSelectionModel.superclass.constructor.call(this);
+    },
 
     /**
      * @cfg {Boolean} moveEditorOnEnter
@@ -65137,8 +68026,8 @@ Ext.extend(Ext.grid.RowSelectionModel, Ext.grid.AbstractSelectionModel,  {
      * Calls the passed function with each selection. If the function returns
      * <tt>false</tt>, iteration is stopped and this function returns
      * <tt>false</tt>. Otherwise it returns <tt>true</tt>.
-     * @param {Function} fn
-     * @param {Object} scope (optional)
+     * @param {Function} fn The function to call upon each iteration. It is passed the selected {@link Ext.data.Record Record}.
+     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to this RowSelectionModel.
      * @return {Boolean} true if all selections were iterated
      */
     each : function(fn, scope){
@@ -65427,23 +68316,7 @@ Ext.extend(Ext.grid.RowSelectionModel, Ext.grid.AbstractSelectionModel,  {
  * <p>While subclasses are provided to render data in different ways, this class renders a passed\r
  * data field unchanged and is usually used for textual columns.</p>\r
  */\r
-Ext.grid.Column = function(config){\r
-    Ext.apply(this, config);\r
-\r
-    if(Ext.isString(this.renderer)){\r
-        this.renderer = Ext.util.Format[this.renderer];\r
-    } else if(Ext.isObject(this.renderer)){\r
-        this.scope = this.renderer.scope;\r
-        this.renderer = this.renderer.fn;\r
-    }\r
-    this.renderer = this.renderer.createDelegate(this.scope || config);\r
-\r
-    if(this.editor){\r
-        this.editor = Ext.create(this.editor, 'textfield');\r
-    }\r
-};\r
-\r
-Ext.grid.Column.prototype = {\r
+Ext.grid.Column = Ext.extend(Object, {\r
     /**\r
      * @cfg {Boolean} editable Optional. Defaults to <tt>true</tt>, enabling the configured\r
      * <tt>{@link #editor}</tt>.  Set to <tt>false</tt> to initially disable editing on this column.\r
@@ -65648,6 +68521,24 @@ var grid = new Ext.grid.GridPanel({
      * Defaults to true.\r
      */\r
     isColumn : true,\r
+    \r
+    constructor : function(config){\r
+        Ext.apply(this, config);\r
+        \r
+        if(Ext.isString(this.renderer)){\r
+            this.renderer = Ext.util.Format[this.renderer];\r
+        }else if(Ext.isObject(this.renderer)){\r
+            this.scope = this.renderer.scope;\r
+            this.renderer = this.renderer.fn;\r
+        }\r
+        if(!this.scope){\r
+            this.scope = this;\r
+        }\r
+        \r
+        var ed = this.editor;\r
+        delete this.editor;\r
+        this.setEditor(ed);\r
+    },\r
 \r
     /**\r
      * Optional. A function which returns displayable data when passed the following parameters:\r
@@ -65678,6 +68569,32 @@ var grid = new Ext.grid.GridPanel({
     getEditor: function(rowIndex){\r
         return this.editable !== false ? this.editor : null;\r
     },\r
+    \r
+    /**\r
+     * Sets a new editor for this column.\r
+     * @param {Ext.Editor/Ext.form.Field} editor The editor to set\r
+     */\r
+    setEditor : function(editor){\r
+        if(this.editor){\r
+            this.editor.destroy();\r
+        }\r
+        this.editor = null;\r
+        if(editor){\r
+            //not an instance, create it\r
+            if(!editor.isXType){\r
+                editor = Ext.create(editor, 'textfield');\r
+            }\r
+            //check if it's wrapped in an editor\r
+            if(!editor.startEdit){\r
+                editor = new Ext.grid.GridEditor(editor);\r
+            }\r
+            this.editor = editor;\r
+        }\r
+    },\r
+    \r
+    destroy : function(){\r
+        this.setEditor(null);\r
+    },\r
 \r
     /**\r
      * Returns the {@link Ext.Editor editor} defined for this column that was created to wrap the {@link Ext.form.Field Field}\r
@@ -65686,20 +68603,9 @@ var grid = new Ext.grid.GridPanel({
      * @return {Ext.Editor}\r
      */\r
     getCellEditor: function(rowIndex){\r
-        var editor = this.getEditor(rowIndex);\r
-        if(editor){\r
-            if(!editor.startEdit){\r
-                if(!editor.gridEditor){\r
-                    editor.gridEditor = new Ext.grid.GridEditor(editor);\r
-                }\r
-                return editor.gridEditor;\r
-            }else if(editor.startEdit){\r
-                return editor;\r
-            }\r
-        }\r
-        return null;\r
+        return this.getEditor(rowIndex);\r
     }\r
-};\r
+});\r
 \r
 /**\r
  * @class Ext.grid.BooleanColumn\r
@@ -65795,7 +68701,7 @@ Ext.grid.TemplateColumn = Ext.extend(Ext.grid.Column, {
      */\r
     constructor: function(cfg){\r
         Ext.grid.TemplateColumn.superclass.constructor.call(this, cfg);\r
-        var tpl = Ext.isObject(this.tpl) ? this.tpl : new Ext.XTemplate(this.tpl);\r
+        var tpl = (!Ext.isPrimitive(this.tpl) && this.tpl.compile) ? this.tpl : new Ext.XTemplate(this.tpl);\r
         this.renderer = function(value, p, r){\r
             return tpl.apply(r.data);\r
         };\r
@@ -65841,14 +68747,7 @@ Ext.grid.Column.types = {
  * @constructor
  * @param {Object} config The configuration options
  */
-Ext.grid.RowNumberer = function(config){
-    Ext.apply(this, config);
-    if(this.rowspan){
-        this.renderer = this.renderer.createDelegate(this);
-    }
-};
-
-Ext.grid.RowNumberer.prototype = {
+Ext.grid.RowNumberer = Ext.extend(Object, {
     /**
      * @cfg {String} header Any valid text or HTML fragment to display in the header cell for the row
      * number column (defaults to '').
@@ -65863,6 +68762,13 @@ Ext.grid.RowNumberer.prototype = {
      * @hide
      */
     sortable: false,
+    
+    constructor : function(config){
+        Ext.apply(this, config);
+        if(this.rowspan){
+            this.renderer = this.renderer.createDelegate(this);
+        }
+    },
 
     // private
     fixed:true,
@@ -65878,7 +68784,7 @@ Ext.grid.RowNumberer.prototype = {
         }
         return rowIndex+1;
     }
-};/**\r
+});/**\r
  * @class Ext.grid.CheckboxSelectionModel\r
  * @extends Ext.grid.RowSelectionModel\r
  * A custom selection model that renders a column of checkboxes that can be toggled to select or deselect rows.\r
@@ -65987,46 +68893,46 @@ Ext.grid.CheckboxSelectionModel = Ext.extend(Ext.grid.RowSelectionModel, {
  * @constructor
  * @param {Object} config The object containing the configuration of this model.
  */
-Ext.grid.CellSelectionModel = function(config){
-    Ext.apply(this, config);
-
-    this.selection = null;
-
-    this.addEvents(
-        /**
-            * @event beforecellselect
-            * Fires before a cell is selected, return false to cancel the selection.
-            * @param {SelectionModel} this
-            * @param {Number} rowIndex The selected row index
-            * @param {Number} colIndex The selected cell index
-            */
-           "beforecellselect",
-        /**
-            * @event cellselect
-            * Fires when a cell is selected.
-            * @param {SelectionModel} this
-            * @param {Number} rowIndex The selected row index
-            * @param {Number} colIndex The selected cell index
-            */
-           "cellselect",
-        /**
-            * @event selectionchange
-            * Fires when the active selection changes.
-            * @param {SelectionModel} this
-            * @param {Object} selection null for no selection or an object with two properties
-         * <div class="mdetail-params"><ul>
-         * <li><b>cell</b> : see {@link #getSelectedCell} 
-         * <li><b>record</b> : Ext.data.record<p class="sub-desc">The {@link Ext.data.Record Record}
-         * which provides the data for the row containing the selection</p></li>
-         * </ul></div>
-            */
-           "selectionchange"
-    );
-
-    Ext.grid.CellSelectionModel.superclass.constructor.call(this);
-};
+Ext.grid.CellSelectionModel = Ext.extend(Ext.grid.AbstractSelectionModel,  {
+    
+    constructor : function(config){
+        Ext.apply(this, config);
 
-Ext.extend(Ext.grid.CellSelectionModel, Ext.grid.AbstractSelectionModel,  {
+           this.selection = null;
+       
+           this.addEvents(
+               /**
+                * @event beforecellselect
+                * Fires before a cell is selected, return false to cancel the selection.
+                * @param {SelectionModel} this
+                * @param {Number} rowIndex The selected row index
+                * @param {Number} colIndex The selected cell index
+                */
+               "beforecellselect",
+               /**
+                * @event cellselect
+                * Fires when a cell is selected.
+                * @param {SelectionModel} this
+                * @param {Number} rowIndex The selected row index
+                * @param {Number} colIndex The selected cell index
+                */
+               "cellselect",
+               /**
+                * @event selectionchange
+                * Fires when the active selection changes.
+                * @param {SelectionModel} this
+                * @param {Object} selection null for no selection or an object with two properties
+                * <div class="mdetail-params"><ul>
+                * <li><b>cell</b> : see {@link #getSelectedCell} 
+                * <li><b>record</b> : Ext.data.record<p class="sub-desc">The {@link Ext.data.Record Record}
+                * which provides the data for the row containing the selection</p></li>
+                * </ul></div>
+                */
+               "selectionchange"
+           );
+       
+           Ext.grid.CellSelectionModel.superclass.constructor.call(this);
+    },
 
     /** @ignore */
     initEvents : function(){
@@ -66284,7 +69190,7 @@ Ext.grid.EditorGridPanel = Ext.extend(Ext.grid.GridPanel, {
      * editing that cell.</p>
      */
     clicksToEdit: 2,
-    
+
     /**
     * @cfg {Boolean} forceValidation
     * True to force validation even if the value is unmodified (defaults to false)
@@ -66296,15 +69202,15 @@ Ext.grid.EditorGridPanel = Ext.extend(Ext.grid.GridPanel, {
     // private
     detectEdit: false,
 
-       /**
-        * @cfg {Boolean} autoEncode
-        * True to automatically HTML encode and decode values pre and post edit (defaults to false)
-        */
-       autoEncode : false,
+    /**
+     * @cfg {Boolean} autoEncode
+     * True to automatically HTML encode and decode values pre and post edit (defaults to false)
+     */
+    autoEncode : false,
 
-       /**
-        * @cfg {Boolean} trackMouseOver @hide
-        */
+    /**
+     * @cfg {Boolean} trackMouseOver @hide
+     */
     // private
     trackMouseOver: false, // causes very odd FF errors
 
@@ -66322,7 +69228,7 @@ Ext.grid.EditorGridPanel = Ext.extend(Ext.grid.GridPanel, {
 
         this.activeEditor = null;
 
-           this.addEvents(
+        this.addEvents(
             /**
              * @event beforeedit
              * Fires before cell editing is triggered. The edit event object has the following properties <br />
@@ -66351,13 +69257,13 @@ Ext.grid.EditorGridPanel = Ext.extend(Ext.grid.GridPanel, {
              * <li>column - The grid column index</li>
              * </ul>
              *
-             * <pre><code> 
+             * <pre><code>
 grid.on('afteredit', afterEdit, this );
 
 function afterEdit(e) {
     // execute an XHR to send/commit data to the server, in callback do (if successful):
     e.record.commit();
-}; 
+};
              * </code></pre>
              * @param {Object} e An edit event (see above for description)
              */
@@ -66380,10 +69286,10 @@ function afterEdit(e) {
              * records (not all).  By observing the grid's validateedit event, it can be cancelled if
              * the edit occurs on a targeted row (for example) and then setting the field's new value
              * in the Record directly:
-             * <pre><code> 
+             * <pre><code>
 grid.on('validateedit', function(e) {
   var myTargetRow = 6;
+
   if (e.row == myTargetRow) {
     e.cancel = true;
     e.record.data[e.field] = e.value;
@@ -66414,6 +69320,14 @@ grid.on('validateedit', function(e) {
         }
     },
 
+    onResize : function(){
+        Ext.grid.EditorGridPanel.superclass.onResize.apply(this, arguments);
+        var ae = this.activeEditor;
+        if(this.editing && ae){
+            ae.realign(true);
+        }
+    },
+
     // private
     onCellDblClick : function(g, row, col){
         this.startEditing(row, col);
@@ -66424,8 +69338,8 @@ grid.on('validateedit', function(e) {
         if(e.button !== 0){
             return;
         }
-        var row = this.view.findRowIndex(t);
-        var col = this.view.findCellIndex(t);
+        var row = this.view.findRowIndex(t),
+            col = this.view.findCellIndex(t);
         if(row !== false && col !== false){
             this.stopEditing();
             if(this.selModel.getSelectedCell){ // cell sm
@@ -66445,9 +69359,9 @@ grid.on('validateedit', function(e) {
     onEditComplete : function(ed, value, startValue){
         this.editing = false;
         this.activeEditor = null;
-        
-               var r = ed.record;
-        var field = this.colModel.getDataIndex(ed.col);
+
+        var r = ed.record,
+            field = this.colModel.getDataIndex(ed.col);
         value = this.postEditValue(value, startValue, r, field);
         if(this.forceValidation === true || String(value) !== String(startValue)){
             var e = {
@@ -66478,17 +69392,17 @@ grid.on('validateedit', function(e) {
         this.stopEditing();
         if(this.colModel.isCellEditable(col, row)){
             this.view.ensureVisible(row, col, true);
-            var r = this.store.getAt(row);
-            var field = this.colModel.getDataIndex(col);
-            var e = {
-                grid: this,
-                record: r,
-                field: field,
-                value: r.data[field],
-                row: row,
-                column: col,
-                cancel:false
-            };
+            var r = this.store.getAt(row),
+                field = this.colModel.getDataIndex(col),
+                e = {
+                    grid: this,
+                    record: r,
+                    field: field,
+                    value: r.data[field],
+                    row: row,
+                    column: col,
+                    cancel:false
+                };
             if(this.fireEvent("beforeedit", e) !== false && !e.cancel){
                 this.editing = true;
                 var ed = this.colModel.getCellEditor(col, row);
@@ -66523,8 +69437,16 @@ grid.on('validateedit', function(e) {
                     col: col
                 };
                 this.activeEditor = ed;
+                // Set the selectSameEditor flag if we are reusing the same editor again and
+                // need to prevent the editor from firing onBlur on itself.
+                ed.selectSameEditor = (this.activeEditor == this.lastActiveEditor);
                 var v = this.preEditValue(r, field);
                 ed.startEdit(this.view.getCell(row, col).firstChild, Ext.isDefined(v) ? v : '');
+
+                // Clear the selectSameEditor flag
+                (function(){
+                    delete ed.selectSameEditor;
+                }).defer(50);
             }
         }
     },
@@ -66536,9 +69458,9 @@ grid.on('validateedit', function(e) {
     },
 
     // private
-       postEditValue : function(value, originalValue, r, field){
-               return this.autoEncode && Ext.isString(value) ? Ext.util.Format.htmlEncode(value) : value;
-       },
+    postEditValue : function(value, originalValue, r, field){
+        return this.autoEncode && Ext.isString(value) ? Ext.util.Format.htmlEncode(value) : value;
+    },
 
     /**
      * Stops any active editing
@@ -66546,7 +69468,8 @@ grid.on('validateedit', function(e) {
      */
     stopEditing : function(cancel){
         if(this.editing){
-            var ae = this.activeEditor;
+            // Store the lastActiveEditor to check if it is changing
+            var ae = this.lastActiveEditor = this.activeEditor;
             if(ae){
                 ae[cancel === true ? 'cancelEdit' : 'completeEdit']();
                 this.view.focusCell(ae.row, ae.col);
@@ -66604,18 +69527,20 @@ Ext.grid.PropertyRecord = Ext.data.Record.create([
  * @param {Ext.grid.Grid} grid The grid this store will be bound to
  * @param {Object} source The source data config object
  */
-Ext.grid.PropertyStore = function(grid, source){
-    this.grid = grid;
-    this.store = new Ext.data.Store({
-        recordType : Ext.grid.PropertyRecord
-    });
-    this.store.on('update', this.onUpdate,  this);
-    if(source){
-        this.setSource(source);
-    }
-    Ext.grid.PropertyStore.superclass.constructor.call(this);
-};
-Ext.extend(Ext.grid.PropertyStore, Ext.util.Observable, {
+Ext.grid.PropertyStore = Ext.extend(Ext.util.Observable, {
+    
+    constructor : function(grid, source){
+        this.grid = grid;
+        this.store = new Ext.data.Store({
+            recordType : Ext.grid.PropertyRecord
+        });
+        this.store.on('update', this.onUpdate,  this);
+        if(source){
+            this.setSource(source);
+        }
+        Ext.grid.PropertyStore.superclass.constructor.call(this);    
+    },
+    
     // protected - should only be called by the grid.  Use grid.setSource instead.
     setSource : function(o){
         this.source = o;
@@ -66651,16 +69576,36 @@ Ext.extend(Ext.grid.PropertyStore, Ext.util.Observable, {
 
     // private
     isEditableValue: function(val){
-        if(Ext.isDate(val)){
-            return true;
-        }
-        return !(Ext.isObject(val) || Ext.isFunction(val));
+        return Ext.isPrimitive(val) || Ext.isDate(val);
     },
 
     // private
-    setValue : function(prop, value){
-        this.source[prop] = value;
-        this.store.getById(prop).set('value', value);
+    setValue : function(prop, value, create){
+        var r = this.getRec(prop);
+        if(r){
+            r.set('value', value);
+            this.source[prop] = value;
+        }else if(create){
+            // only create if specified.
+            this.source[prop] = value;
+            r = new Ext.grid.PropertyRecord({name: prop, value: value}, prop);
+            this.store.add(r);
+
+        }
+    },
+    
+    // private
+    remove : function(prop){
+        var r = this.getRec(prop);
+        if(r){
+            this.store.remove(r);
+            delete this.source[prop];
+        }
+    },
+    
+    // private
+    getRec : function(prop){
+        return this.store.getById(prop);
     },
 
     // protected - should only be called by the grid.  Use grid.getSource instead.
@@ -66677,43 +69622,45 @@ Ext.extend(Ext.grid.PropertyStore, Ext.util.Observable, {
  * @param {Ext.grid.Grid} grid The grid this store will be bound to
  * @param {Object} source The source data config object
  */
-Ext.grid.PropertyColumnModel = function(grid, store){
-    var g = Ext.grid,
-        f = Ext.form;
-        
-    this.grid = grid;
-    g.PropertyColumnModel.superclass.constructor.call(this, [
-        {header: this.nameText, width:50, sortable: true, dataIndex:'name', id: 'name', menuDisabled:true},
-        {header: this.valueText, width:50, resizable:false, dataIndex: 'value', id: 'value', menuDisabled:true}
-    ]);
-    this.store = store;
-
-    var bfield = new f.Field({
-        autoCreate: {tag: 'select', children: [
-            {tag: 'option', value: 'true', html: 'true'},
-            {tag: 'option', value: 'false', html: 'false'}
-        ]},
-        getValue : function(){
-            return this.el.dom.value == 'true';
-        }
-    });
-    this.editors = {
-        'date' : new g.GridEditor(new f.DateField({selectOnFocus:true})),
-        'string' : new g.GridEditor(new f.TextField({selectOnFocus:true})),
-        'number' : new g.GridEditor(new f.NumberField({selectOnFocus:true, style:'text-align:left;'})),
-        'boolean' : new g.GridEditor(bfield, {
-            autoSize: 'both'
-        })
-    };
-    this.renderCellDelegate = this.renderCell.createDelegate(this);
-    this.renderPropDelegate = this.renderProp.createDelegate(this);
-};
-
-Ext.extend(Ext.grid.PropertyColumnModel, Ext.grid.ColumnModel, {
+Ext.grid.PropertyColumnModel = Ext.extend(Ext.grid.ColumnModel, {
     // private - strings used for locale support
     nameText : 'Name',
     valueText : 'Value',
     dateFormat : 'm/j/Y',
+    trueText: 'true',
+    falseText: 'false',
+    
+    constructor : function(grid, store){
+        var g = Ext.grid,
+               f = Ext.form;
+               
+           this.grid = grid;
+           g.PropertyColumnModel.superclass.constructor.call(this, [
+               {header: this.nameText, width:50, sortable: true, dataIndex:'name', id: 'name', menuDisabled:true},
+               {header: this.valueText, width:50, resizable:false, dataIndex: 'value', id: 'value', menuDisabled:true}
+           ]);
+           this.store = store;
+       
+           var bfield = new f.Field({
+               autoCreate: {tag: 'select', children: [
+                   {tag: 'option', value: 'true', html: this.trueText},
+                   {tag: 'option', value: 'false', html: this.falseText}
+               ]},
+               getValue : function(){
+                   return this.el.dom.value == 'true';
+               }
+           });
+           this.editors = {
+               'date' : new g.GridEditor(new f.DateField({selectOnFocus:true})),
+               'string' : new g.GridEditor(new f.TextField({selectOnFocus:true})),
+               'number' : new g.GridEditor(new f.NumberField({selectOnFocus:true, style:'text-align:left;'})),
+               'boolean' : new g.GridEditor(bfield, {
+                   autoSize: 'both'
+               })
+           };
+           this.renderCellDelegate = this.renderCell.createDelegate(this);
+           this.renderPropDelegate = this.renderProp.createDelegate(this);
+    },
 
     // private
     renderDate : function(dateVal){
@@ -66722,7 +69669,7 @@ Ext.extend(Ext.grid.PropertyColumnModel, Ext.grid.ColumnModel, {
 
     // private
     renderBool : function(bVal){
-        return bVal ? 'true' : 'false';
+        return this[bVal ? 'trueText' : 'falseText'];
     },
 
     // private
@@ -66742,7 +69689,11 @@ Ext.extend(Ext.grid.PropertyColumnModel, Ext.grid.ColumnModel, {
     },
 
     // private
-    renderCell : function(val){
+    renderCell : function(val, meta, rec){
+        var renderer = this.grid.customRenderers[rec.get('name')];
+        if(renderer){
+            return renderer.apply(this, arguments);
+        }
         var rv = val;
         if(Ext.isDate(val)){
             rv = this.renderDate(val);
@@ -66781,7 +69732,7 @@ Ext.extend(Ext.grid.PropertyColumnModel, Ext.grid.ColumnModel, {
     destroy : function(){
         Ext.grid.PropertyColumnModel.superclass.destroy.call(this);
         for(var ed in this.editors){
-            Ext.destroy(ed);
+            Ext.destroy(this.editors[ed]);
         }
     }
 });
@@ -66834,6 +69785,33 @@ var grid = new Ext.grid.PropertyGrid({
         'Start Time': '10:00 AM'
     }
 });
+</code></pre>
+    */
+    /**
+    * @cfg {Object} source A data object to use as the data source of the grid (see {@link #setSource} for details).
+    */
+    /**
+    * @cfg {Object} customRenderers An object containing name/value pairs of custom renderer type definitions that allow
+    * the grid to support custom rendering of fields.  By default, the grid supports strongly-typed rendering
+    * of strings, dates, numbers and booleans using built-in form editors, but any custom type can be supported and
+    * associated with the type of the value.  The name of the renderer type should correspond with the name of the property
+    * that it will render.  Example usage:
+    * <pre><code>
+var grid = new Ext.grid.PropertyGrid({
+    ...
+    customRenderers: {
+        Available: function(v){
+            if(v){
+                return '<span style="color: green;">Yes</span>';
+            }else{
+                return '<span style="color: red;">No</span>';
+            }
+        }
+    },
+    source: {
+        Available: true
+    }
+});
 </code></pre>
     */
 
@@ -66849,6 +69827,7 @@ var grid = new Ext.grid.PropertyGrid({
 
     // private
     initComponent : function(){
+        this.customRenderers = this.customRenderers || {};
         this.customEditors = this.customEditors || {};
         this.lastEditRow = null;
         var store = new Ext.grid.PropertyStore(this);
@@ -66933,7 +69912,42 @@ grid.setSource({
      */
     getSource : function(){
         return this.propStore.getSource();
+    },
+    
+    /**
+     * Sets the value of a property.
+     * @param {String} prop The name of the property to set
+     * @param {Mixed} value The value to test
+     * @param {Boolean} create (Optional) True to create the property if it doesn't already exist. Defaults to <tt>false</tt>.
+     */
+    setProperty : function(prop, value, create){
+        this.propStore.setValue(prop, value, create);    
+    },
+    
+    /**
+     * Removes a property from the grid.
+     * @param {String} prop The name of the property to remove
+     */
+    removeProperty : function(prop){
+        this.propStore.remove(prop);
     }
+
+    /**
+     * @cfg store
+     * @hide
+     */
+    /**
+     * @cfg colModel
+     * @hide
+     */
+    /**
+     * @cfg cm
+     * @hide
+     */
+    /**
+     * @cfg columns
+     * @hide
+     */
 });
 Ext.reg("propertygrid", Ext.grid.PropertyGrid);
 /**\r
@@ -67071,13 +70085,13 @@ var grid = new Ext.grid.GridPanel({
      * </code></pre>\r
      */\r
     groupTextTpl : '{text}',\r
-    \r
+\r
     /**\r
      * @cfg {String} groupMode Indicates how to construct the group identifier. <tt>'value'</tt> constructs the id using\r
      * raw value, <tt>'display'</tt> constructs the id using the rendered value. Defaults to <tt>'value'</tt>.\r
      */\r
     groupMode: 'value',\r
-    \r
+\r
     /**\r
      * @cfg {Function} groupRenderer This property must be configured in the {@link Ext.grid.Column} for\r
      * each column.\r
@@ -67103,6 +70117,10 @@ var grid = new Ext.grid.GridPanel({
             );\r
         }\r
         this.startGroup.compile();\r
+        if(!this.endGroup){\r
+            this.endGroup = '</div></div>';\r
+        }\r
+\r
         this.endGroup = '</div></div>';\r
     },\r
 \r
@@ -67118,11 +70136,11 @@ var grid = new Ext.grid.GridPanel({
 \r
     // private\r
     onAdd : function(){\r
-        if(this.enableGrouping && !this.ignoreAdd){\r
+        if(this.canGroup() && !this.ignoreAdd){\r
             var ss = this.getScrollState();\r
             this.refresh();\r
             this.restoreScroll(ss);\r
-        }else if(!this.enableGrouping){\r
+        }else if(!this.canGroup()){\r
             Ext.grid.GroupingView.superclass.onAdd.apply(this, arguments);\r
         }\r
     },\r
@@ -67156,7 +70174,7 @@ var grid = new Ext.grid.GridPanel({
         }\r
         if((item = items.get('showGroups'))){\r
             item.setDisabled(disabled);\r
-                   item.setChecked(!!this.getGroupField(), true);\r
+            item.setChecked(this.enableGrouping, true);\r
         }\r
     },\r
 \r
@@ -67186,18 +70204,55 @@ var grid = new Ext.grid.GridPanel({
         }\r
     },\r
 \r
+    processEvent: function(name, e){\r
+        var hd = e.getTarget('.x-grid-group-hd', this.mainBody);\r
+        if(hd){\r
+            // group value is at the end of the string\r
+            var field = this.getGroupField(),\r
+                prefix = this.getPrefix(field),\r
+                groupValue = hd.id.substring(prefix.length);\r
+\r
+            // remove trailing '-hd'\r
+            groupValue = groupValue.substr(0, groupValue.length - 3);\r
+            if(groupValue){\r
+                this.grid.fireEvent('group' + name, this.grid, field, groupValue, e);\r
+            }\r
+        }\r
+\r
+    },\r
+\r
     // private\r
     onGroupByClick : function(){\r
+        this.enableGrouping = true;\r
         this.grid.store.groupBy(this.cm.getDataIndex(this.hdCtxIndex));\r
+        this.grid.fireEvent('groupchange', this, this.grid.store.getGroupState());\r
         this.beforeMenuShow(); // Make sure the checkboxes get properly set when changing groups\r
+        this.refresh();\r
     },\r
 \r
     // private\r
     onShowGroupsClick : function(mi, checked){\r
+    this.enableGrouping = checked;\r
         if(checked){\r
             this.onGroupByClick();\r
         }else{\r
             this.grid.store.clearGrouping();\r
+            this.grid.fireEvent('groupchange', this, null);\r
+        }\r
+    },\r
+\r
+    /**\r
+     * Toggle the group that contains the specific row.\r
+     * @param {Number} rowIndex The row inside the group\r
+     * @param {Boolean} expanded (optional)\r
+     */\r
+    toggleRowIndex : function(rowIndex, expanded){\r
+        if(!this.canGroup()){\r
+            return;\r
+        }\r
+        var row = this.getRow(rowIndex);\r
+        if(row){\r
+            this.toggleGroup(this.findGroup(row), expanded);\r
         }\r
     },\r
 \r
@@ -67207,14 +70262,13 @@ var grid = new Ext.grid.GridPanel({
      * @param {Boolean} expanded (optional)\r
      */\r
     toggleGroup : function(group, expanded){\r
-        this.grid.stopEditing(true);\r
-        group = Ext.getDom(group);\r
-        var gel = Ext.fly(group);\r
-        expanded = expanded !== undefined ?\r
-                expanded : gel.hasClass('x-grid-group-collapsed');\r
-\r
-        this.state[gel.dom.id] = expanded;\r
-        gel[expanded ? 'removeClass' : 'addClass']('x-grid-group-collapsed');\r
+        var gel = Ext.get(group);\r
+        expanded = Ext.isDefined(expanded) ? expanded : gel.hasClass('x-grid-group-collapsed');\r
+        if(this.state[gel.id] !== expanded){\r
+            this.grid.stopEditing(true);\r
+            this.state[gel.id] = expanded;\r
+            gel[expanded ? 'removeClass' : 'addClass']('x-grid-group-collapsed');\r
+        }\r
     },\r
 \r
     /**\r
@@ -67264,9 +70318,12 @@ var grid = new Ext.grid.GridPanel({
     getGroupField : function(){\r
         return this.grid.store.getGroupState();\r
     },\r
-    \r
+\r
     // private\r
     afterRender : function(){\r
+        if(!this.ds || !this.cm){\r
+            return;\r
+        }\r
         Ext.grid.GroupingView.superclass.afterRender.call(this);\r
         if(this.grid.deferRowRender){\r
             this.updateGroupWidths();\r
@@ -67279,15 +70336,16 @@ var grid = new Ext.grid.GridPanel({
         var eg = !!groupField;\r
         // if they turned off grouping and the last grouped field is hidden\r
         if(this.hideGroupedColumn) {\r
-            var colIndex = this.cm.findColumnIndex(groupField);\r
-            if(!eg && this.lastGroupField !== undefined) {\r
+            var colIndex = this.cm.findColumnIndex(groupField),\r
+                hasLastGroupField = Ext.isDefined(this.lastGroupField);\r
+            if(!eg && hasLastGroupField){\r
                 this.mainBody.update('');\r
                 this.cm.setHidden(this.cm.findColumnIndex(this.lastGroupField), false);\r
                 delete this.lastGroupField;\r
-            }else if (eg && this.lastGroupField === undefined) {\r
+            }else if (eg && !hasLastGroupField){\r
                 this.lastGroupField = groupField;\r
                 this.cm.setHidden(colIndex, true);\r
-            }else if (eg && this.lastGroupField !== undefined && groupField !== this.lastGroupField) {\r
+            }else if (eg && hasLastGroupField && groupField !== this.lastGroupField) {\r
                 this.mainBody.update('');\r
                 var oldIndex = this.cm.findColumnIndex(this.lastGroupField);\r
                 this.cm.setHidden(oldIndex, false);\r
@@ -67304,18 +70362,16 @@ var grid = new Ext.grid.GridPanel({
         if(rs.length < 1){\r
             return '';\r
         }\r
-        var groupField = this.getGroupField(),\r
-            colIndex = this.cm.findColumnIndex(groupField),\r
-            g;\r
 \r
-        this.enableGrouping = !!groupField;\r
-\r
-        if(!this.enableGrouping || this.isUpdating){\r
+        if(!this.canGroup() || this.isUpdating){\r
             return Ext.grid.GroupingView.superclass.doRender.apply(\r
                     this, arguments);\r
         }\r
-        var gstyle = 'width:' + this.getTotalWidth() + ';',\r
-            gidPrefix = this.grid.getGridEl().id,\r
+\r
+        var groupField = this.getGroupField(),\r
+            colIndex = this.cm.findColumnIndex(groupField),\r
+            g,\r
+            gstyle = 'width:' + this.getTotalWidth() + ';',\r
             cfg = this.cm.config[colIndex],\r
             groupRenderer = cfg.groupRenderer || cfg.renderer,\r
             prefix = this.showGroupName ? (cfg.groupName || cfg.header)+': ' : '',\r
@@ -67326,14 +70382,13 @@ var grid = new Ext.grid.GridPanel({
             var rowIndex = startRow + i,\r
                 r = rs[i],\r
                 gvalue = r.data[groupField];\r
-                \r
+\r
                 g = this.getGroup(gvalue, r, groupRenderer, rowIndex, colIndex, ds);\r
             if(!curGroup || curGroup.group != g){\r
-                gid = this.constructId(gvalue, gidPrefix, groupField, colIndex);\r
-                       // if state is defined use it, however state is in terms of expanded\r
-                               // so negate it, otherwise use the default.\r
-                               var isCollapsed  = typeof this.state[gid] !== 'undefined' ? !this.state[gid] : this.startCollapsed;\r
-                               var gcls = isCollapsed ? 'x-grid-group-collapsed' : ''; \r
+                gid = this.constructId(gvalue, groupField, colIndex);\r
+                // if state is defined use it, however state is in terms of expanded\r
+                // so negate it, otherwise use the default.\r
+                this.state[gid] = !(Ext.isDefined(this.state[gid]) ? !this.state[gid] : this.startCollapsed);\r
                 curGroup = {\r
                     group: g,\r
                     gvalue: gvalue,\r
@@ -67341,7 +70396,7 @@ var grid = new Ext.grid.GridPanel({
                     groupId: gid,\r
                     startRow: rowIndex,\r
                     rs: [r],\r
-                    cls: gcls,\r
+                    cls: this.state[gid] ? '' : 'x-grid-group-collapsed',\r
                     style: gstyle\r
                 };\r
                 groups.push(curGroup);\r
@@ -67370,16 +70425,26 @@ var grid = new Ext.grid.GridPanel({
      */\r
     getGroupId : function(value){\r
         var field = this.getGroupField();\r
-        return this.constructId(value, this.grid.getGridEl().id, field, this.cm.findColumnIndex(field));\r
+        return this.constructId(value, field, this.cm.findColumnIndex(field));\r
     },\r
-    \r
+\r
     // private\r
-    constructId : function(value, prefix, field, idx){\r
+    constructId : function(value, field, idx){\r
         var cfg = this.cm.config[idx],\r
             groupRenderer = cfg.groupRenderer || cfg.renderer,\r
             val = (this.groupMode == 'value') ? value : this.getGroup(value, {data:{}}, groupRenderer, 0, idx, this.ds);\r
-            \r
-        return prefix + '-gp-' + field + '-' + Ext.util.Format.htmlEncode(val);\r
+\r
+        return this.getPrefix(field) + Ext.util.Format.htmlEncode(val);\r
+    },\r
+\r
+    // private\r
+    canGroup  : function(){\r
+        return this.enableGrouping && !!this.getGroupField();\r
+    },\r
+\r
+    // private\r
+    getPrefix: function(field){\r
+        return this.grid.getGridEl().id + '-gp-' + field + '-';\r
     },\r
 \r
     // private\r
@@ -67394,7 +70459,7 @@ var grid = new Ext.grid.GridPanel({
 \r
     // private\r
     getRows : function(){\r
-        if(!this.enableGrouping){\r
+        if(!this.canGroup()){\r
             return Ext.grid.GroupingView.superclass.getRows.call(this);\r
         }\r
         var r = [];\r
@@ -67410,7 +70475,7 @@ var grid = new Ext.grid.GridPanel({
 \r
     // private\r
     updateGroupWidths : function(){\r
-        if(!this.enableGrouping || !this.hasRows()){\r
+        if(!this.canGroup() || !this.hasRows()){\r
             return;\r
         }\r
         var tw = Math.max(this.cm.getTotalWidth(), this.el.dom.offsetWidth-this.getScrollOffset()) +'px';\r
@@ -67445,14 +70510,7 @@ var grid = new Ext.grid.GridPanel({
 \r
     // private\r
     onBeforeRowSelect : function(sm, rowIndex){\r
-        if(!this.enableGrouping){\r
-            return;\r
-        }\r
-        var row = this.getRow(rowIndex);\r
-        if(row && !row.offsetParent){\r
-            var g = this.findGroup(row);\r
-            this.toggleGroup(g, true);\r
-        }\r
+        this.toggleRowIndex(rowIndex, true);\r
     }\r
 });\r
 // private\r