roojs-all.js
[roojs1] / roojs-debug.js
index 3c396e1..0d6014c 100644 (file)
@@ -567,7 +567,23 @@ Roo.factory(conf, Roo.data);
          * you may want to set this to true.
          * @type Boolean
          */
-        useShims : ((isIE && !isIE7) || (isGecko && isMac))
+        useShims : ((isIE && !isIE7) || (isGecko && isMac)),
+        
+        
+                
+        /**
+         * Selects a single element as a Roo Element
+         * This is about as close as you can get to jQuery's $('do crazy stuff')
+         * @param {String} selector The selector/xpath query
+         * @param {Node} root (optional) The start of the query (defaults to document).
+         * @return {Roo.Element}
+         */
+        selectNode : function(selector, root) 
+        {
+            var node = Roo.DomQuery.selectNode(selector,root);
+            return node ? Roo.get(node) : new Roo.Element(false);
+        }
+        
     });
 
 
@@ -7805,7 +7821,9 @@ if(opt.anim.isAnimated()){
          * @param {Object}   options   (optional)An object with standard {@link Roo.EventManager#addListener} options
          */
         addListener : function(eventName, fn, scope, options){
-            Roo.EventManager.on(this.dom,  eventName, fn, scope || this, options);
+            if (this.dom) {
+                Roo.EventManager.on(this.dom,  eventName, fn, scope || this, options);
+            }
         },
 
         /**
@@ -12261,7 +12279,7 @@ Roo.extend(Roo.util.MixedCollection, Roo.util.Observable, {
         this.fireEvent("add", this.length-1, o, key);
         return o;
     },
-   
+       
 /**
   * MixedCollection has a generic way to fetch keys if you implement getKey.
 <pre><code>
@@ -12770,7 +12788,10 @@ Roo.util.JSON = new (function(){
      * @param {Mixed} o The variable to encode
      * @return {String} The JSON string
      */
-    this.encode = function(o){
+    this.encode = function(o)
+    {
+        // should this be extended to fully wrap stringify..
+        
         if(typeof o == "undefined" || o === null){
             return "null";
         }else if(o instanceof Array){
@@ -12815,19 +12836,19 @@ Roo.util.JSON = new (function(){
      */
     this.decode = function(json){
         
-        return /** eval:var:json */ eval("(" + json + ')');
+        return  /** eval:var:json */ eval("(" + json + ')');
     };
 })();
 /** 
  * Shorthand for {@link Roo.util.JSON#encode}
  * @member Roo encode 
  * @method */
-Roo.encode = Roo.util.JSON.encode;
+Roo.encode = typeof(JSON) != 'undefined' && JSON.stringify ? JSON.stringify : Roo.util.JSON.encode;
 /** 
  * Shorthand for {@link Roo.util.JSON#decode}
  * @member Roo decode 
  * @method */
-Roo.decode = Roo.util.JSON.decode;
+Roo.decode = typeof(JSON) != 'undefined' && JSON.parse ? JSON.parse : Roo.util.JSON.decode;
 /*
  * Based on:
  * Ext JS Library 1.1.1
@@ -12947,6 +12968,46 @@ Roo.util.Format = function(){
             }
         },
 
+       
+        /**
+         * safer version of Math.toFixed..??/
+         * @param {Number/String} value The numeric value to format
+         * @param {Number/String} value Decimal places 
+         * @return {String} The formatted currency string
+         */
+        toFixed : function(v, n)
+        {
+            // why not use to fixed - precision is buggered???
+            if (!n) {
+                return Math.round(v-0);
+            }
+            var fact = Math.pow(10,n+1);
+            v = (Math.round((v-0)*fact))/fact;
+            var z = (''+fact).substring(2);
+            if (v == Math.floor(v)) {
+                return Math.floor(v) + '.' + z;
+            }
+            
+            // now just padd decimals..
+            var ps = String(v).split('.');
+            var fd = (ps[1] + z);
+            var r = fd.substring(0,n); 
+            var rm = fd.substring(n); 
+            if (rm < 5) {
+                return ps[0] + '.' + r;
+            }
+            r*=1; // turn it into a number;
+            r++;
+            if (String(r).length != n) {
+                ps[0]*=1;
+                ps[0]++;
+                r = String(r).substring(1); // chop the end off.
+            }
+            
+            return ps[0] + '.' + r;
+             
+        },
+        
         /**
          * Format a number as US currency
          * @param {Number/String} value The numeric value to format
@@ -12965,7 +13026,7 @@ Roo.util.Format = function(){
             }
             return "$" + whole + sub ;
         },
-
+        
         /**
          * Parse a value into a formatted date using the specified format pattern.
          * @param {Mixed} value The value to format
@@ -14356,6 +14417,7 @@ var Dom=Roo.lib.Dom;
 
 /**
  * @class Roo.dd.DragDrop
+ * @extends Roo.util.Observable
  * Defines the interface and base operation of items that that can be
  * dragged or can be drop targets.  It was designed to be extended, overriding
  * the event handlers for startDrag, onDrag, onDragOver and onDragOut.
@@ -14402,9 +14464,10 @@ Roo.dd.DragDrop = function(id, sGroup, config) {
     if (id) {
         this.init(id, sGroup, config);
     }
+    
 };
 
-Roo.dd.DragDrop.prototype = {
+Roo.extend(Roo.dd.DragDrop, Roo.util.Observable , {
 
     /**
      * The id of the element associated with this object.  This is what we
@@ -15487,7 +15550,7 @@ Roo.dd.DragDrop.prototype = {
         return ("DragDrop " + this.id);
     }
 
-};
+});
 
 })();
 /*
@@ -17330,6 +17393,12 @@ Roo.dd.DDTarget = function(id, sGroup, config) {
     if (id) {
         this.initTarget(id, sGroup, config);
     }
+    if (config.listeners || config.events) { 
+       Roo.dd.DragDrop.superclass.constructor.call(this,  { 
+            listeners : config.listeners || {}, 
+            events : config.events || {} 
+        });    
+    }
 };
 
 // Roo.dd.DDTarget.prototype = new Roo.dd.DragDrop();
@@ -18214,14 +18283,87 @@ Roo.extend(Roo.dd.DragSource, Roo.dd.DDProxy, {
 Roo.dd.DropTarget = function(el, config){
     this.el = Roo.get(el);
     
+    var listeners = false; ;
+    if (config && config.listeners) {
+        listeners= config.listeners;
+        delete config.listeners;
+    }
     Roo.apply(this, config);
     
     if(this.containerScroll){
         Roo.dd.ScrollManager.register(this.el);
     }
-    
-    Roo.dd.DropTarget.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, 
-          {isTarget: true});
+    this.addEvents( {
+         /**
+         * @scope Roo.dd.DropTarget
+         */
+         
+         /**
+         * @event enter
+         * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the source is now over the
+         * target.  This default implementation adds the CSS class specified by overClass (if any) to the drop element
+         * and returns the dropAllowed config value.  This method should be overridden if drop validation is required.
+         * 
+         * IMPORTANT : it should set this.overClass and this.dropAllowed
+         * 
+         * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
+         * @param {Event} e The event
+         * @param {Object} data An object containing arbitrary data supplied by the drag source
+         */
+        "enter" : true,
+        
+         /**
+         * @event over
+         * The function a {@link Roo.dd.DragSource} calls continuously while it is being dragged over the target.
+         * This method will be called on every mouse movement while the drag source is over the drop target.
+         * This default implementation simply returns the dropAllowed config value.
+         * 
+         * IMPORTANT : it should set this.dropAllowed
+         * 
+         * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
+         * @param {Event} e The event
+         * @param {Object} data An object containing arbitrary data supplied by the drag source
+         
+         */
+        "over" : true,
+        /**
+         * @event out
+         * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the source has been dragged
+         * out of the target without dropping.  This default implementation simply removes the CSS class specified by
+         * overClass (if any) from the drop element.
+         * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
+         * @param {Event} e The event
+         * @param {Object} data An object containing arbitrary data supplied by the drag source
+         */
+         "out" : true,
+         
+        /**
+         * @event drop
+         * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the dragged item has
+         * been dropped on it.  This method has no default implementation and returns false, so you must provide an
+         * implementation that does something to process the drop event and returns true so that the drag source's
+         * repair action does not run.
+         * 
+         * IMPORTANT : it should set this.success
+         * 
+         * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
+         * @param {Event} e The event
+         * @param {Object} data An object containing arbitrary data supplied by the drag source
+        */
+         "drop" : true
+    });
+            
+     
+    Roo.dd.DropTarget.superclass.constructor.call(  this, 
+        this.el.dom, 
+        this.ddGroup || this.group,
+        {
+            isTarget: true,
+            listeners : listeners || {} 
+           
+        
+        }
+    );
 
 };
 
@@ -18230,6 +18372,11 @@ Roo.extend(Roo.dd.DropTarget, Roo.dd.DDTarget, {
      * @cfg {String} overClass
      * The CSS class applied to the drop target element while the drag source is over it (defaults to "").
      */
+     /**
+     * @cfg {String} ddGroup
+     * The drag drop group to handle drop events for
+     */
+     
     /**
      * @cfg {String} dropAllowed
      * The CSS class returned to the drag source when drop is allowed (defaults to "x-dd-drop-ok").
@@ -18240,70 +18387,68 @@ Roo.extend(Roo.dd.DropTarget, Roo.dd.DDTarget, {
      * The CSS class returned to the drag source when drop is not allowed (defaults to "x-dd-drop-nodrop").
      */
     dropNotAllowed : "x-dd-drop-nodrop",
-
+    /**
+     * @cfg {boolean} success
+     * set this after drop listener.. 
+     */
+    success : false,
+    /**
+     * @cfg {boolean|String} valid true/false or string (ok-add/ok-sub/ok/nodrop)
+     * if the drop point is valid for over/enter..
+     */
+    valid : false,
     // private
     isTarget : true,
 
     // private
     isNotifyTarget : true,
-
+    
     /**
-     * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the source is now over the
-     * target.  This default implementation adds the CSS class specified by overClass (if any) to the drop element
-     * and returns the dropAllowed config value.  This method should be overridden if drop validation is required.
-     * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
-     * @param {Event} e The event
-     * @param {Object} data An object containing arbitrary data supplied by the drag source
-     * @return {String} status The CSS class that communicates the drop status back to the source so that the
-     * underlying {@link Roo.dd.StatusProxy} can be updated
+     * @hide
      */
-    notifyEnter : function(dd, e, data){
+    notifyEnter : function(dd, e, data)
+    {
+        this.valid = true;
+        this.fireEvent('enter', dd, e, data);
         if(this.overClass){
             this.el.addClass(this.overClass);
         }
-        return this.dropAllowed;
+        return typeof(this.valid) == 'string' ? 'x-dd-drop-' + this.valid : (
+            this.valid ? this.dropAllowed : this.dropNotAllowed
+        );
     },
 
     /**
-     * The function a {@link Roo.dd.DragSource} calls continuously while it is being dragged over the target.
-     * This method will be called on every mouse movement while the drag source is over the drop target.
-     * This default implementation simply returns the dropAllowed config value.
-     * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
-     * @param {Event} e The event
-     * @param {Object} data An object containing arbitrary data supplied by the drag source
-     * @return {String} status The CSS class that communicates the drop status back to the source so that the
-     * underlying {@link Roo.dd.StatusProxy} can be updated
+     * @hide
      */
-    notifyOver : function(dd, e, data){
-        return this.dropAllowed;
+    notifyOver : function(dd, e, data)
+    {
+        this.valid = true;
+        this.fireEvent('over', dd, e, data);
+        return typeof(this.valid) == 'string' ? 'x-dd-drop-' + this.valid : (
+            this.valid ? this.dropAllowed : this.dropNotAllowed
+        );
     },
 
     /**
-     * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the source has been dragged
-     * out of the target without dropping.  This default implementation simply removes the CSS class specified by
-     * overClass (if any) from the drop element.
-     * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
-     * @param {Event} e The event
-     * @param {Object} data An object containing arbitrary data supplied by the drag source
+     * @hide
      */
-    notifyOut : function(dd, e, data){
+    notifyOut : function(dd, e, data)
+    {
+        this.fireEvent('out', dd, e, data);
         if(this.overClass){
             this.el.removeClass(this.overClass);
         }
     },
 
     /**
-     * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the dragged item has
-     * been dropped on it.  This method has no default implementation and returns false, so you must provide an
-     * implementation that does something to process the drop event and returns true so that the drag source's
-     * repair action does not run.
-     * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
-     * @param {Event} e The event
-     * @param {Object} data An object containing arbitrary data supplied by the drag source
-     * @return {Boolean} True if the drop was valid, else false
+     * @hide
      */
-    notifyDrop : function(dd, e, data){
-        return false;
+    notifyDrop : function(dd, e, data)
+    {
+        this.success = false;
+        this.fireEvent('drop', dd, e, data);
+        return this.success;
     }
 });/*
  * Based on:
@@ -22529,6 +22674,7 @@ Roo.Shadow.prototype = {
         s.left = (l+a.l)+"px";
         s.top = (t+a.t)+"px";
         var sw = (w+a.w), sh = (h+a.h), sws = sw +"px", shs = sh + "px";
         if(s.width != sws || s.height != shs){
             s.width = sws;
             s.height = shs;
@@ -25775,11 +25921,13 @@ Roo.Button = function(renderTo, config)
     if(this.menu){
         this.menu = Roo.menu.MenuMgr.get(this.menu);
     }
+    // register listeners first!!  - so render can be captured..
+    Roo.util.Observable.call(this);
     if(renderTo){
         this.render(renderTo);
     }
     
-    Roo.util.Observable.call(this);
+  
 };
 
 Roo.extend(Roo.Button, Roo.util.Observable, {
@@ -25955,6 +26103,7 @@ Roo.extend(Roo.Button, Roo.util.Observable, {
             );
             repeater.on("click", this.onClick,  this);
         }
+        
         this.fireEvent('render', this);
         
     },
@@ -27066,13 +27215,24 @@ Roo.PagingToolbar = function(el, ds, config)
         ds = el.dataSource;
         el = config.container;
     }
-    
+    var items = [];
+    if (config.items) {
+        items = config.items;
+        config.items = [];
+    }
     
     Roo.PagingToolbar.superclass.constructor.call(this, el, null, config);
     this.ds = ds;
     this.cursor = 0;
     this.renderButtons(this.el);
     this.bind(ds);
+    
+    // supprot items array.
+   
+    Roo.each(items, function(e) {
+        this.add(Roo.factory(e));
+    },this);
+    
 };
 
 Roo.extend(Roo.PagingToolbar, Roo.Toolbar, {
@@ -27154,7 +27314,7 @@ Roo.extend(Roo.PagingToolbar, Roo.Toolbar, {
             disabled: true,
             handler: this.onClick.createDelegate(this, ["prev"])
         });
-        this.addSeparator();
+        //this.addSeparator();
         this.add(this.beforePageText);
         this.field = Roo.get(this.addDom({
            tag: "input",
@@ -27167,7 +27327,7 @@ Roo.extend(Roo.PagingToolbar, Roo.Toolbar, {
         this.field.on("focus", function(){this.dom.select();});
         this.afterTextEl = this.addText(String.format(this.afterPageText, 1));
         this.field.setHeight(18);
-        this.addSeparator();
+        //this.addSeparator();
         this.next = this.addButton({
             tooltip: this.nextText,
             cls: "x-btn-icon x-grid-page-next",
@@ -27180,7 +27340,7 @@ Roo.extend(Roo.PagingToolbar, Roo.Toolbar, {
             disabled: true,
             handler: this.onClick.createDelegate(this, ["last"])
         });
-        this.addSeparator();
+        //this.addSeparator();
         this.loading = this.addButton({
             tooltip: this.refreshText,
             cls: "x-btn-icon x-grid-loading",
@@ -27364,6 +27524,7 @@ Value   Description
  'sw'    southwest
  'se'    southeast
  'ne'    northeast
+ 'hd'    horizontal drag
  'all'   all
 </pre>
  * <p>Here's an example showing the creation of a typical Resizable:</p>
@@ -27413,7 +27574,8 @@ resizer.on("resize", myHandler);
  * @param {String/HTMLElement/Roo.Element} el The id or element to resize
  * @param {Object} config configuration options
   */
-Roo.Resizable = function(el, config){
+Roo.Resizable = function(el, config)
+{
     this.el = Roo.get(el);
 
     if(config && config.wrap){
@@ -27466,8 +27628,9 @@ Roo.Resizable = function(el, config){
     }
     // legacy
     this.corner = this.southeast;
-
-    if(this.handles.indexOf("n") != -1 || this.handles.indexOf("w") != -1){
+    
+    // updateBox = the box can move..
+    if(this.handles.indexOf("n") != -1 || this.handles.indexOf("w") != -1 || this.handles.indexOf("hd") != -1) {
         this.updateBox = true;
     }
 
@@ -27480,7 +27643,7 @@ Roo.Resizable = function(el, config){
             this.resizeChild = Roo.get(this.resizeChild, true);
         }
     }
-
+    
     if(this.adjustments == "auto"){
         var rc = this.resizeChild;
         var hw = this.west, he = this.east, hn = this.north, hs = this.south;
@@ -27736,6 +27899,7 @@ Roo.extend(Roo.Resizable, Roo.util.Observable, {
                     w += diffX;
                     w = Math.min(Math.max(mw, w), mxw);
                     break;
+             
                 case "south":
                     h += diffY;
                     h = Math.min(Math.max(mh, h), mxh);
@@ -27751,6 +27915,21 @@ Roo.extend(Roo.Resizable, Roo.util.Observable, {
                     y += diffY;
                     h -= diffY;
                     break;
+                case "hdrag":
+                    
+                    if (wi) {
+                        var adiffX = Math.abs(diffX);
+                        var sub = (adiffX % wi); // how much 
+                        if (sub > (wi/2)) { // far enough to snap
+                            diffX = (diffX > 0) ? diffX-sub + wi : diffX+sub - wi;
+                        } else {
+                            // remove difference.. 
+                            diffX = (diffX > 0) ? diffX-sub : diffX+sub;
+                        }
+                    }
+                    x += diffX;
+                    x = Math.max(this.minX, x);
+                    break;
                 case "west":
                     diffX = this.constrain(w, diffX, mw, mxw);
                     x += diffX;
@@ -27853,11 +28032,14 @@ Roo.extend(Roo.Resizable, Roo.util.Observable, {
                         h = Math.min(Math.max(mh, h), mxh);
                         w = ow * (h/oh);
                         y += th - h;
-                         x += tw - w;
+                        x += tw - w;
                        break;
 
                 }
             }
+            if (pos == 'hdrag') {
+                w = ow;
+            }
             this.proxy.setBounds(x, y, w, h);
             if(this.dynamic){
                 this.resizeElement();
@@ -27925,7 +28107,8 @@ Roo.extend(Roo.Resizable, Roo.util.Observable, {
 // private
 // hash to map config positions to true positions
 Roo.Resizable.positions = {
-    n: "north", s: "south", e: "east", w: "west", se: "southeast", sw: "southwest", nw: "northwest", ne: "northeast"
+    n: "north", s: "south", e: "east", w: "west", se: "southeast", sw: "southwest", nw: "northwest", ne: "northeast", 
+    hd: "hdrag"
 };
 
 // private
@@ -27940,7 +28123,13 @@ Roo.Resizable.Handle = function(rz, pos, disableTrackOver, transparent){
     }
     this.position = pos;
     this.rz = rz;
-    this.el = this.tpl.append(rz.el.dom, [this.position], true);
+    // show north drag fro topdra
+    var handlepos = pos == 'hdrag' ? 'north' : pos;
+    
+    this.el = this.tpl.append(rz.el.dom, [handlepos], true);
+    if (pos == 'hdrag') {
+        this.el.setStyle('cursor', 'pointer');
+    }
     this.el.unselectable();
     if(transparent){
         this.el.setOpacity(0);
@@ -28122,16 +28311,24 @@ Roo.extend(Roo.Editor, Roo.Component, {
         }
     },
 
-    onSpecialKey : function(field, e){
+    onSpecialKey : function(field, e)
+    {
         //Roo.log('editor onSpecialKey');
         if(this.completeOnEnter && e.getKey() == e.ENTER){
             e.stopEvent();
             this.completeEdit();
-        }else if(this.cancelOnEsc && e.getKey() == e.ESC){
-            this.cancelEdit();
-        }else{
-            this.fireEvent('specialkey', field, e);
+            return;
         }
+        // do not fire special key otherwise it might hide close the editor...
+        if(e.getKey() == e.ENTER){    
+            return;
+        }
+        if(this.cancelOnEsc && e.getKey() == e.ESC){
+            this.cancelEdit();
+            return;
+        } 
+        this.fireEvent('specialkey', field, e);
+    
     },
 
     /**
@@ -28908,7 +29105,7 @@ Roo.extend(Roo.BasicDialog, Roo.util.Observable, {
 
     // private
     animShow : function(){
-        var b = Roo.get(this.animateTarget, true).getBox();
+        var b = Roo.get(this.animateTarget).getBox();
         this.proxy.setSize(b.width, b.height);
         this.proxy.setLocation(b.x, b.y);
         this.proxy.show();
@@ -28934,7 +29131,7 @@ Roo.extend(Roo.BasicDialog, Roo.util.Observable, {
         this.animateTarget = animateTarget || this.animateTarget;
         if(!this.el.isVisible()){
             this.beforeShow();
-            if(this.animateTarget){
+            if(this.animateTarget && Roo.get(this.animateTarget)){
                 this.animShow();
             }else{
                 this.showEl();
@@ -29238,7 +29435,9 @@ Roo.extend(Roo.BasicDialog, Roo.util.Observable, {
         if(this.shim) {
           this.shim.hide();
         }
-        if(this.animateTarget){
+        // sometimes animateTarget seems to get set.. causing problems...
+        // this just double checks..
+        if(this.animateTarget && Roo.get(this.animateTarget)) {
            this.animHide(callback);
         }else{
             this.el.hide();
@@ -29477,7 +29676,10 @@ Roo.LayoutDialog = function(el, cfg){
     var config=  cfg;
     if (typeof(cfg) == 'undefined') {
         config = Roo.apply({}, el);
-        el = Roo.get( document.documentElement || document.body).createChild();
+        // not sure why we use documentElement here.. - it should always be body.
+        // IE7 borks horribly if we use documentElement.
+        // webkit also does not like documentElement - it creates a body element...
+        el = Roo.get( document.body || document.documentElement ).createChild();
         //config.autoCreate = true;
     }
     
@@ -35145,7 +35347,14 @@ side          Add an error icon to the right of the field with a popup on hover
              * Fires after the field has been validated with no errors.
              * @param {Roo.form.Field} this
              */
-            valid : true
+            valid : true,
+             /**
+             * @event keyup
+             * Fires after the key up
+             * @param {Roo.form.Field} this
+             * @param {Roo.EventObject}  e The event Object
+             */
+            keyup : true
         });
     },
 
@@ -35247,6 +35456,7 @@ side          Add an error icon to the right of the field with a popup on hover
         this.el.on("keydown" , this.fireKey,  this);
         this.el.on("focus", this.onFocus,  this);
         this.el.on("blur", this.onBlur,  this);
+        this.el.relayEvent('keyup', this);
 
         // reference to original value for reset
         this.originalValue = this.getValue();
@@ -37026,14 +37236,18 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
      */
     valueNotFoundText : undefined,
     /**
-     * @cfg {bool} blockFocus Prevents all focus calls, so it can work with things like HTML edtor bar
+     * @cfg {Boolean} blockFocus Prevents all focus calls, so it can work with things like HTML edtor bar
      */
     blockFocus : false,
     
     /**
-     * @cfg {bool} disableClear Disable showing of clear button.
+     * @cfg {Boolean} disableClear Disable showing of clear button.
      */
     disableClear : false,
+    /**
+     * @cfg {Boolean} alwaysQuery  Disable caching of results, and always send query
+     */
+    alwaysQuery : false,
     
     //private
     addicon : false,
@@ -37426,7 +37640,7 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
             dv = !o || typeof(o[this.displayField]) == 'undefined' ? '' : o[this.displayField];
         } else {
             // this is an error condition!!!
-            console.log('no value field set for '+ this.name);
+            Roo.log('no  displayField value set for '+ (this.name ? this.name : this.id));
         }
         
         if(this.valueField){
@@ -37634,7 +37848,7 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
         q = qe.query;
         forceAll = qe.forceAll;
         if(forceAll === true || (q.length >= this.minChars)){
-            if(this.lastQuery != q){
+            if(this.lastQuery != q || this.alwaysQuery){
                 this.lastQuery = q;
                 if(this.mode == 'local'){
                     this.selectedIndex = -1;
@@ -37679,6 +37893,9 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
         this.list.hide();
         Roo.get(document).un('mousedown', this.collapseIf, this);
         Roo.get(document).un('mousewheel', this.collapseIf, this);
+        if (!this.editable) {
+            Roo.get(document).un('keydown', this.listKeyPress, this);
+        }
         this.fireEvent('collapse', this);
     },
 
@@ -37700,6 +37917,10 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
         this.list.show();
         Roo.get(document).on('mousedown', this.collapseIf, this);
         Roo.get(document).on('mousewheel', this.collapseIf, this);
+        if (!this.editable) {
+            Roo.get(document).on('keydown', this.listKeyPress, this);
+        }
+        
         this.fireEvent('expand', this);
     },
 
@@ -37726,6 +37947,50 @@ Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
                 this.el.focus();
             }
         }
+    },
+    listKeyPress : function(e)
+    {
+        //Roo.log('listkeypress');
+        // scroll to first matching element based on key pres..
+        if (e.isSpecialKey()) {
+            return false;
+        }
+        var k = String.fromCharCode(e.getKey()).toUpperCase();
+        //Roo.log(k);
+        var match  = false;
+        var csel = this.view.getSelectedNodes();
+        var cselitem = false;
+        if (csel.length) {
+            var ix = this.view.indexOf(csel[0]);
+            cselitem  = this.store.getAt(ix);
+            if (!cselitem.get(this.displayField) || cselitem.get(this.displayField).substring(0,1).toUpperCase() != k) {
+                cselitem = false;
+            }
+            
+        }
+        
+        this.store.each(function(v) { 
+            if (cselitem) {
+                // start at existing selection.
+                if (cselitem.id == v.id) {
+                    cselitem = false;
+                }
+                return;
+            }
+                
+            if (v.get(this.displayField) && v.get(this.displayField).substring(0,1).toUpperCase() == k) {
+                match = this.store.indexOf(v);
+                return false;
+            }
+        }, this);
+        
+        if (match === false) {
+            return true; // no more action?
+        }
+        // scroll to?
+        this.view.select(match);
+        var sn = Roo.get(this.view.getSelectedNodes()[0])
+        sn.scrollIntoView(sn.dom.parentNode, false);
     }
 
     /** 
@@ -37930,7 +38195,7 @@ Roo.extend(Roo.form.Checkbox, Roo.form.Field,  {
         }
         this.checked = state;
         if(suppressEvent !== true){
-            this.fireEvent('checkchange', this, state);
+            this.fireEvent('check', this, state);
         }
         this.inSetChecked = true;
         this.el.dom.value = state ? this.inputValue : this.valueOff;
@@ -38883,6 +39148,12 @@ Roo.form.HtmlEditor = Roo.extend(Roo.form.Field, {
             // clean up silly Windows -- stuff?
             return; 
         }
+        if (node.nodeName == "#comment") {
+            node.parentNode.removeChild(node);
+            // clean up silly Windows -- stuff?
+            return; 
+        }
+        
         if (Roo.form.HtmlEditor.black.indexOf(node.tagName.toLowerCase()) > -1) {
             // remove node.
             node.parentNode.removeChild(node);
@@ -38914,6 +39185,8 @@ Roo.form.HtmlEditor = Roo.extend(Roo.form.Field, {
                 node.removeAttribute(n);
                 return;
             }
+            
+            
             var parts = v.split(/;/);
             Roo.each(parts, function(p) {
                 p = p.replace(/\s+/g,'');
@@ -38947,7 +39220,12 @@ Roo.form.HtmlEditor = Roo.extend(Roo.form.Field, {
             if (a.name == 'style') {
                 cleanStyle(a.name,a.value);
             }
-            
+            /// clean up MS crap..
+            if (a.name == 'class') {
+                if (a.value.match(/^Mso/)) {
+                    node.className = '';
+                }
+            }
             
             // style cleanup!?
             // class cleanup?
@@ -39016,18 +39294,18 @@ Roo.form.HtmlEditor.white = [
        'caption', 'col', 'colgroup', 'tbody', 'td', 'tfoot', 'th', 
       'thead',   'tr', 
      
-      'dir', 'menu', 'ol', 'ul', 'dl'
+      'dir', 'menu', 'ol', 'ul', 'dl',
        
+      'embed',  'object'
 ];
 
 
 Roo.form.HtmlEditor.black = [
-        'embed',  'object', // eventually enable for flash?
+    //    'embed',  'object', // enable - backend responsiblity to clean thiese
         'applet', // 
         'base',   'basefont', 'bgsound', 'blink',  'body', 
         'frame',  'frameset', 'head',    'html',   'ilayer', 
-        'iframe', 'layer',  'link',     'meta',    'object', 
-        
+        'iframe', 'layer',  'link',     'meta',    'object',   
         'script', 'style' ,'title',  'xml' // clean later..
 ];
 Roo.form.HtmlEditor.clean = [
@@ -39853,6 +40131,7 @@ Roo.apply(Roo.form.HtmlEditor.ToolbarContext.prototype,  {
         this.toolbars = {};
            
         for (var i in  ty) {
+          
             this.toolbars[i] = this.buildToolbar(ty[i],i);
         }
         this.tb = this.toolbars.BODY;
@@ -40104,10 +40383,13 @@ Roo.extend(Roo.form.BasicForm, Roo.util.Observable, {
      * @cfg {Boolean} fileUpload
      * Set to true if this form is a file upload.
      */
+     
     /**
      * @cfg {Object} baseParams
      * Parameters to pass with all requests. e.g. baseParams: {id: '123', foo: 'bar'}.
      */
+     /**
+     
     /**
      * @cfg {Number} timeout Timeout for form actions in seconds (default is 30 seconds).
      */
@@ -40140,7 +40422,7 @@ Roo.extend(Roo.form.BasicForm, Roo.util.Observable, {
      * element by passing it or its id or mask the form itself by passing in true.
      * @type Mixed
      */
-    waitMsgTarget : undefined,
+    waitMsgTarget : false,
 
     // private
     initEl : function(el){
@@ -40263,42 +40545,50 @@ clientValidation  Boolean          Applies to submit only.  Pass true to call fo
     // 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 = Roo.get(this.waitMsgTarget);
-                this.waitMsgTarget.mask(o.waitMsg, 'x-mask-loading');
-            }else{
-                Roo.MessageBox.wait(o.waitMsg, o.waitTitle || this.waitTitle || 'Please Wait...');
-            }
+        
+       
+        if(this.waitMsgTarget === true){
+            this.el.mask(o.waitMsg || "Sending", 'x-mask-loading');
+        }else if(this.waitMsgTarget){
+            this.waitMsgTarget = Roo.get(this.waitMsgTarget);
+            this.waitMsgTarget.mask(o.waitMsg || "Sending", 'x-mask-loading');
+        }else {
+            Roo.MessageBox.wait(o.waitMsg || "Sending", o.waitTitle || this.waitTitle || 'Please Wait...');
         }
+         
     },
 
     // 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{
-                Roo.MessageBox.updateProgress(1);
-                Roo.MessageBox.hide();
-            }
+        
+        if(this.waitMsgTarget === true){
+            this.el.unmask();
+        }else if(this.waitMsgTarget){
+            this.waitMsgTarget.unmask();
+        }else{
+            Roo.MessageBox.updateProgress(1);
+            Roo.MessageBox.hide();
         }
+         
         if(success){
             if(o.reset){
                 this.reset();
             }
             Roo.callback(o.success, o.scope, [this, action]);
             this.fireEvent('actioncomplete', this, action);
+            
         }else{
             Roo.callback(o.failure, o.scope, [this, action]);
+            // show an error message if no failed handler is set..
+            if (!this.hasListener('actionfailed')) {
+                Roo.MessageBox.alert("Error", "Saving Failed, please check your entries");
+            }
+            
             this.fireEvent('actionfailed', this, action);
         }
+        
     },
 
     /**
@@ -40457,6 +40747,35 @@ clientValidation  Boolean          Applies to submit only.  Pass true to call fo
         }
         return Roo.urlDecode(fs);
     },
+    
+    /**
+     * Returns the fields in this form as an object with key/value pairs. 
+     * This differs from getValues as it calls getValue on each child item, rather than using dom data.
+     * @return {Object}
+     */
+    getFieldValues : function()
+    {
+        if (this.childForms) {
+            // copy values from the child forms
+            Roo.each(this.childForms, function (f) {
+                this.setValues(f.getValues());
+            }, this);
+        }
+        
+        var ret = {};
+        this.items.each(function(f){
+            if (!f.getName()) {
+                return;
+            }
+            var v = f.getValue();
+            if ((typeof(v) == 'object') && f.getRawValue) {
+                v = f.getRawValue() ; // dates..
+            }
+            ret[f.getName()] = v;
+        });
+        
+        return ret;
+    },
 
     /**
      * Clears all invalid messages in this form.
@@ -40611,6 +40930,16 @@ Roo.form.Form = function(config){
         rendered : true
     });
     
+    if (this.progressUrl) {
+            // push a hidden field onto the list of fields..
+            this.addxtype( {
+                    xns: Roo.form, 
+                    xtype : 'Hidden', 
+                    name : 'UPLOAD_IDENTIFIER' 
+            });
+        }
+        
+    
     Roo.each(xitems, this.addxtype, this);
     
     
@@ -40651,7 +40980,12 @@ Roo.extend(Roo.form.Form, Roo.form.BasicForm, {
      * @cfg {Number} monitorPoll The milliseconds to poll valid state, ignored if monitorValid is not true (defaults to 200)
      */
     monitorPoll : 200,
-
+    
+    /**
+     * @cfg {String} progressUrl - Url to return progress data 
+     */
+    
+    progressUrl : false,
   
     /**
      * Opens a new {@link Roo.form.Column} container in the layout stack. If fields are passed after the config, the
@@ -40796,7 +41130,11 @@ Roo.extend(Roo.form.Form, Roo.form.BasicForm, {
      * @param {String/HTMLElement/Element} container The element this component should be rendered into
      * @return {Form} this
      */
-    render : function(ct){
+    render : function(ct)
+    {
+        
+        
+        
         ct = Roo.get(ct);
         var o = this.autoCreate || {
             tag: 'form',
@@ -40806,7 +41144,9 @@ Roo.extend(Roo.form.Form, Roo.form.BasicForm, {
         this.initEl(ct.createChild(o));
 
         this.root.render(this.el);
-
+        
+       
+             
         this.items.each(function(f){
             f.render('x-form-el-'+f.id);
         });
@@ -41043,6 +41383,7 @@ Roo.form.Action.prototype = {
 
     // default connection failure
     failure : function(response){
+        
         this.response = response;
         this.failureType = Roo.form.Action.CONNECT_FAILURE;
         this.form.afterAction(this, false);
@@ -41106,6 +41447,75 @@ Roo.form.Action.Submit = function(form, options){
 Roo.extend(Roo.form.Action.Submit, Roo.form.Action, {
     type : 'submit',
 
+    haveProgress : false,
+    uploadComplete : false,
+    
+    // uploadProgress indicator.
+    uploadProgress : function()
+    {
+        if (!this.form.progressUrl) {
+            return;
+        }
+        
+        if (!this.haveProgress) {
+            Roo.MessageBox.progress("Uploading", "Uploading");
+        }
+        if (this.uploadComplete) {
+           Roo.MessageBox.hide();
+           return;
+        }
+        
+        this.haveProgress = true;
+   
+        var uid = this.form.findField('UPLOAD_IDENTIFIER').getValue();
+        
+        var c = new Roo.data.Connection();
+        c.request({
+            url : this.form.progressUrl,
+            params: {
+                id : uid
+            },
+            method: 'GET',
+            success : function(req){
+               //console.log(data);
+                var rdata = false;
+                var edata;
+                try  {
+                   rdata = Roo.decode(req.responseText)
+                } catch (e) {
+                    Roo.log("Invalid data from server..");
+                    Roo.log(edata);
+                    return;
+                }
+                if (!rdata || !rdata.success) {
+                    Roo.log(rdata);
+                    return;
+                }
+                var data = rdata.data;
+                
+                if (this.uploadComplete) {
+                   Roo.MessageBox.hide();
+                   return;
+                }
+                   
+                if (data){
+                    Roo.MessageBox.updateProgress(data.bytes_uploaded/data.bytes_total,
+                       Math.floor((data.bytes_total - data.bytes_uploaded)/1000) + 'k remaining'
+                    );
+                }
+                this.uploadProgress.defer(2000,this);
+            },
+       
+            failure: function(data) {
+                Roo.log('progress url failed ');
+                Roo.log(data);
+            },
+            scope : this
+        });
+           
+    },
+    
+    
     run : function()
     {
         // run get Values on the form, so it syncs any secondary forms.
@@ -41115,6 +41525,14 @@ Roo.extend(Roo.form.Action.Submit, Roo.form.Action, {
         var method = this.getMethod();
         var isPost = method == 'POST';
         if(o.clientValidation === false || this.form.isValid()){
+            
+            if (this.form.progressUrl) {
+                this.form.findField('UPLOAD_IDENTIFIER').setValue(
+                    (new Date() * 1) + '' + Math.random());
+                    
+            } 
+            
+            
             Roo.Ajax.request(Roo.apply(this.createCallback(), {
                 form:this.form.el.dom,
                 url:this.getUrl(!isPost),
@@ -41122,6 +41540,8 @@ Roo.extend(Roo.form.Action.Submit, Roo.form.Action, {
                 params:isPost ? this.getParams() : null,
                 isUpload: this.form.fileUpload
             }));
+            
+            this.uploadProgress();
 
         }else if (o.clientValidation !== false){ // client validation failed
             this.failureType = Roo.form.Action.CLIENT_INVALID;
@@ -41129,7 +41549,14 @@ Roo.extend(Roo.form.Action.Submit, Roo.form.Action, {
         }
     },
 
-    success : function(response){
+    success : function(response)
+    {
+        this.uploadComplete= true;
+        if (this.haveProgress) {
+            Roo.MessageBox.hide();
+        }
+        
+        
         var result = this.processResponse(response);
         if(result === true || result.success){
             this.form.afterAction(this, true);
@@ -41141,7 +41568,19 @@ Roo.extend(Roo.form.Action.Submit, Roo.form.Action, {
         }
         this.form.afterAction(this, false);
     },
-
+    failure : function(response)
+    {
+        this.uploadComplete= true;
+        if (this.haveProgress) {
+            Roo.MessageBox.hide();
+        }
+        
+        
+        this.response = response;
+        this.failureType = Roo.form.Action.CONNECT_FAILURE;
+        this.form.afterAction(this, false);
+    },
+    
     handleResponse : function(response){
         if(this.form.errorReader){
             var rs = this.form.errorReader.read(response);
@@ -41166,7 +41605,7 @@ Roo.extend(Roo.form.Action.Submit, Roo.form.Action, {
         } catch (e) {
             ret = {
                 success: false,
-                errorMsg: "Failed to read server message: " + response.responseText,
+                errorMsg: "Failed to read server message: " + (response ? response.responseText : ' - no message'),
                 errors : []
             };
         }
@@ -41185,6 +41624,7 @@ Roo.extend(Roo.form.Action.Load, Roo.form.Action, {
     type : 'load',
 
     run : function(){
+        
         Roo.Ajax.request(Roo.apply(
                 this.createCallback(), {
                     method:this.getMethod(),
@@ -41194,6 +41634,7 @@ Roo.extend(Roo.form.Action.Load, Roo.form.Action, {
     },
 
     success : function(response){
+        
         var result = this.processResponse(response);
         if(result === true || !result.success || !result.data){
             this.failureType = Roo.form.Action.LOAD_FAILURE;
@@ -41964,6 +42405,14 @@ function FCKeditor_OnComplete(editorInstance){
  * @extends Roo.form.Field
  * Embed a grid (or editable grid into a form)
  * STATUS ALPHA
+ * 
+ * This embeds a grid in a form, the value of the field should be the json encoded array of rows
+ * it needs 
+ * xgrid.store = Roo.data.Store
+ * xgrid.store.proxy = Roo.data.MemoryProxy (data = [] )
+ * xgrid.store.reader = Roo.data.JsonReader 
+ * 
+ * 
  * @constructor
  * Creates a new GridField
  * @param {Object} config Configuration options
@@ -41983,7 +42432,9 @@ Roo.extend(Roo.form.GridField, Roo.form.Field,  {
      */
     height : 50,
      /**
-     * @cfg {Object} xgrid (xtype'd description of grid) Grid or EditorGrid
+     * @cfg {Object} xgrid (xtype'd description of grid) { xtype : 'Grid', dataSource: .... }
+         * 
+         *}
      */
     xgrid : false, 
     /**
@@ -42023,7 +42474,7 @@ Roo.extend(Roo.form.GridField, Roo.form.Field,  {
         var style = this.style;
         delete this.style;
         
-        Roo.form.DisplayImage.superclass.onRender.call(this, ct, position);
+        Roo.form.GridField.superclass.onRender.call(this, ct, position);
         this.wrap = this.el.wrap({cls: ''}); // not sure why ive done thsi...
         this.viewEl = this.wrap.createChild({ tag: 'div' });
         if (style) {
@@ -44979,6 +45430,11 @@ Roo.ContentPanel = function(el, config, content){
     });
     if(this.autoScroll){
         this.resizeEl.setStyle("overflow", "auto");
+    } else {
+        // fix randome scrolling
+        this.el.on('scroll', function() {
+            this.scrollTo('top',0); 
+        });
     }
     content = content || this.content;
     if(content){
@@ -45345,6 +45801,7 @@ Roo.NestedLayoutPanel = function(layout, config)
     }
     */
     
+    
     Roo.NestedLayoutPanel.superclass.constructor.call(this, layout.getEl(), config);
     
     layout.monitorWindowResize = false; // turn off autosizing
@@ -45353,6 +45810,7 @@ Roo.NestedLayoutPanel = function(layout, config)
     
     
     
+    
 };
 
 Roo.extend(Roo.NestedLayoutPanel, Roo.ContentPanel, {
@@ -45773,123 +46231,123 @@ Roo.grid.Grid = function(container, config){
     }
     /** @private */
        this.addEvents({
-           // raw events
-           /**
-            * @event click
-            * The raw click event for the entire grid.
-            * @param {Roo.EventObject} e
-            */
-           "click" : true,
-           /**
-            * @event dblclick
-            * The raw dblclick event for the entire grid.
-            * @param {Roo.EventObject} e
-            */
-           "dblclick" : true,
-           /**
-            * @event contextmenu
-            * The raw contextmenu event for the entire grid.
-            * @param {Roo.EventObject} e
-            */
-           "contextmenu" : true,
-           /**
-            * @event mousedown
-            * The raw mousedown event for the entire grid.
-            * @param {Roo.EventObject} e
-            */
-           "mousedown" : true,
-           /**
-            * @event mouseup
-            * The raw mouseup event for the entire grid.
-            * @param {Roo.EventObject} e
-            */
-           "mouseup" : true,
-           /**
-            * @event mouseover
-            * The raw mouseover event for the entire grid.
-            * @param {Roo.EventObject} e
-            */
-           "mouseover" : true,
-           /**
-            * @event mouseout
-            * The raw mouseout event for the entire grid.
-            * @param {Roo.EventObject} e
-            */
-           "mouseout" : true,
-           /**
-            * @event keypress
-            * The raw keypress event for the entire grid.
-            * @param {Roo.EventObject} e
-            */
-           "keypress" : true,
-           /**
-            * @event keydown
-            * The raw keydown event for the entire grid.
-            * @param {Roo.EventObject} e
-            */
-           "keydown" : true,
+        // raw events
+        /**
+         * @event click
+         * The raw click event for the entire grid.
+         * @param {Roo.EventObject} e
+         */
+        "click" : true,
+        /**
+         * @event dblclick
+         * The raw dblclick event for the entire grid.
+         * @param {Roo.EventObject} e
+         */
+        "dblclick" : true,
+        /**
+         * @event contextmenu
+         * The raw contextmenu event for the entire grid.
+         * @param {Roo.EventObject} e
+         */
+        "contextmenu" : true,
+        /**
+         * @event mousedown
+         * The raw mousedown event for the entire grid.
+         * @param {Roo.EventObject} e
+         */
+        "mousedown" : true,
+        /**
+         * @event mouseup
+         * The raw mouseup event for the entire grid.
+         * @param {Roo.EventObject} e
+         */
+        "mouseup" : true,
+        /**
+         * @event mouseover
+         * The raw mouseover event for the entire grid.
+         * @param {Roo.EventObject} e
+         */
+        "mouseover" : true,
+        /**
+         * @event mouseout
+         * The raw mouseout event for the entire grid.
+         * @param {Roo.EventObject} e
+         */
+        "mouseout" : true,
+        /**
+         * @event keypress
+         * The raw keypress event for the entire grid.
+         * @param {Roo.EventObject} e
+         */
+        "keypress" : true,
+        /**
+         * @event keydown
+         * The raw keydown event for the entire grid.
+         * @param {Roo.EventObject} e
+         */
+        "keydown" : true,
 
-           // custom events
+        // custom events
 
-           /**
-            * @event cellclick
-            * Fires when a cell is clicked
-            * @param {Grid} this
-            * @param {Number} rowIndex
-            * @param {Number} columnIndex
-            * @param {Roo.EventObject} e
-            */
-           "cellclick" : true,
-           /**
-            * @event celldblclick
-            * Fires when a cell is double clicked
-            * @param {Grid} this
-            * @param {Number} rowIndex
-            * @param {Number} columnIndex
-            * @param {Roo.EventObject} e
-            */
-           "celldblclick" : true,
-           /**
-            * @event rowclick
-            * Fires when a row is clicked
-            * @param {Grid} this
-            * @param {Number} rowIndex
-            * @param {Roo.EventObject} e
-            */
-           "rowclick" : true,
-           /**
-            * @event rowdblclick
-            * Fires when a row is double clicked
-            * @param {Grid} this
-            * @param {Number} rowIndex
-            * @param {Roo.EventObject} e
-            */
-           "rowdblclick" : true,
-           /**
-            * @event headerclick
-            * Fires when a header is clicked
-            * @param {Grid} this
-            * @param {Number} columnIndex
-            * @param {Roo.EventObject} e
-            */
-           "headerclick" : true,
-           /**
-            * @event headerdblclick
-            * Fires when a header cell is double clicked
-            * @param {Grid} this
-            * @param {Number} columnIndex
-            * @param {Roo.EventObject} e
-            */
-           "headerdblclick" : true,
-           /**
-            * @event rowcontextmenu
-            * Fires when a row is right clicked
-            * @param {Grid} this
-            * @param {Number} rowIndex
-            * @param {Roo.EventObject} e
-            */
-           "rowcontextmenu" : true,
-           /**
+        /**
+         * @event cellclick
+         * Fires when a cell is clicked
+         * @param {Grid} this
+         * @param {Number} rowIndex
+         * @param {Number} columnIndex
+         * @param {Roo.EventObject} e
+         */
+        "cellclick" : true,
+        /**
+         * @event celldblclick
+         * Fires when a cell is double clicked
+         * @param {Grid} this
+         * @param {Number} rowIndex
+         * @param {Number} columnIndex
+         * @param {Roo.EventObject} e
+         */
+        "celldblclick" : true,
+        /**
+         * @event rowclick
+         * Fires when a row is clicked
+         * @param {Grid} this
+         * @param {Number} rowIndex
+         * @param {Roo.EventObject} e
+         */
+        "rowclick" : true,
+        /**
+         * @event rowdblclick
+         * Fires when a row is double clicked
+         * @param {Grid} this
+         * @param {Number} rowIndex
+         * @param {Roo.EventObject} e
+         */
+        "rowdblclick" : true,
+        /**
+         * @event headerclick
+         * Fires when a header is clicked
+         * @param {Grid} this
+         * @param {Number} columnIndex
+         * @param {Roo.EventObject} e
+         */
+        "headerclick" : true,
+        /**
+         * @event headerdblclick
+         * Fires when a header cell is double clicked
+         * @param {Grid} this
+         * @param {Number} columnIndex
+         * @param {Roo.EventObject} e
+         */
+        "headerdblclick" : true,
+        /**
+         * @event rowcontextmenu
+         * Fires when a row is right clicked
+         * @param {Grid} this
+         * @param {Number} rowIndex
+         * @param {Roo.EventObject} e
+         */
+        "rowcontextmenu" : true,
+        /**
          * @event cellcontextmenu
          * Fires when a cell is right clicked
          * @param {Grid} this
@@ -45898,93 +46356,101 @@ Roo.grid.Grid = function(container, config){
          * @param {Roo.EventObject} e
          */
          "cellcontextmenu" : true,
-           /**
-            * @event headercontextmenu
-            * Fires when a header is right clicked
-            * @param {Grid} this
-            * @param {Number} columnIndex
-            * @param {Roo.EventObject} e
-            */
-           "headercontextmenu" : true,
-           /**
-            * @event bodyscroll
-            * Fires when the body element is scrolled
-            * @param {Number} scrollLeft
-            * @param {Number} scrollTop
-            */
-           "bodyscroll" : true,
-           /**
-            * @event columnresize
-            * Fires when the user resizes a column
-            * @param {Number} columnIndex
-            * @param {Number} newSize
-            */
-           "columnresize" : true,
-           /**
-            * @event columnmove
-            * Fires when the user moves a column
-            * @param {Number} oldIndex
-            * @param {Number} newIndex
-            */
-           "columnmove" : true,
-           /**
-            * @event startdrag
-            * Fires when row(s) start being dragged
-            * @param {Grid} this
-            * @param {Roo.GridDD} dd The drag drop object
-            * @param {event} e The raw browser event
-            */
-           "startdrag" : true,
-           /**
-            * @event enddrag
-            * Fires when a drag operation is complete
-            * @param {Grid} this
-            * @param {Roo.GridDD} dd The drag drop object
-            * @param {event} e The raw browser event
-            */
-           "enddrag" : true,
-           /**
-            * @event dragdrop
-            * Fires when dragged row(s) are dropped on a valid DD target
-            * @param {Grid} this
-            * @param {Roo.GridDD} dd The drag drop object
-            * @param {String} targetId The target drag drop object
-            * @param {event} e The raw browser event
-            */
-           "dragdrop" : true,
-           /**
-            * @event dragover
-            * Fires while row(s) are being dragged. "targetId" is the id of the Yahoo.util.DD object the selected rows are being dragged over.
-            * @param {Grid} this
-            * @param {Roo.GridDD} dd The drag drop object
-            * @param {String} targetId The target drag drop object
-            * @param {event} e The raw browser event
-            */
-           "dragover" : true,
-           /**
-            * @event dragenter
-            *  Fires when the dragged row(s) first cross another DD target while being dragged
-            * @param {Grid} this
-            * @param {Roo.GridDD} dd The drag drop object
-            * @param {String} targetId The target drag drop object
-            * @param {event} e The raw browser event
-            */
-           "dragenter" : true,
-           /**
-            * @event dragout
-            * Fires when the dragged row(s) leave another DD target while being dragged
-            * @param {Grid} this
-            * @param {Roo.GridDD} dd The drag drop object
-            * @param {String} targetId The target drag drop object
-            * @param {event} e The raw browser event
-            */
-           "dragout" : true,
+        /**
+         * @event headercontextmenu
+         * Fires when a header is right clicked
+         * @param {Grid} this
+         * @param {Number} columnIndex
+         * @param {Roo.EventObject} e
+         */
+        "headercontextmenu" : true,
+        /**
+         * @event bodyscroll
+         * Fires when the body element is scrolled
+         * @param {Number} scrollLeft
+         * @param {Number} scrollTop
+         */
+        "bodyscroll" : true,
+        /**
+         * @event columnresize
+         * Fires when the user resizes a column
+         * @param {Number} columnIndex
+         * @param {Number} newSize
+         */
+        "columnresize" : true,
+        /**
+         * @event columnmove
+         * Fires when the user moves a column
+         * @param {Number} oldIndex
+         * @param {Number} newIndex
+         */
+        "columnmove" : true,
+        /**
+         * @event startdrag
+         * Fires when row(s) start being dragged
+         * @param {Grid} this
+         * @param {Roo.GridDD} dd The drag drop object
+         * @param {event} e The raw browser event
+         */
+        "startdrag" : true,
+        /**
+         * @event enddrag
+         * Fires when a drag operation is complete
+         * @param {Grid} this
+         * @param {Roo.GridDD} dd The drag drop object
+         * @param {event} e The raw browser event
+         */
+        "enddrag" : true,
+        /**
+         * @event dragdrop
+         * Fires when dragged row(s) are dropped on a valid DD target
+         * @param {Grid} this
+         * @param {Roo.GridDD} dd The drag drop object
+         * @param {String} targetId The target drag drop object
+         * @param {event} e The raw browser event
+         */
+        "dragdrop" : true,
+        /**
+         * @event dragover
+         * Fires while row(s) are being dragged. "targetId" is the id of the Yahoo.util.DD object the selected rows are being dragged over.
+         * @param {Grid} this
+         * @param {Roo.GridDD} dd The drag drop object
+         * @param {String} targetId The target drag drop object
+         * @param {event} e The raw browser event
+         */
+        "dragover" : true,
+        /**
+         * @event dragenter
+         *  Fires when the dragged row(s) first cross another DD target while being dragged
+         * @param {Grid} this
+         * @param {Roo.GridDD} dd The drag drop object
+         * @param {String} targetId The target drag drop object
+         * @param {event} e The raw browser event
+         */
+        "dragenter" : true,
+        /**
+         * @event dragout
+         * Fires when the dragged row(s) leave another DD target while being dragged
+         * @param {Grid} this
+         * @param {Roo.GridDD} dd The drag drop object
+         * @param {String} targetId The target drag drop object
+         * @param {event} e The raw browser event
+         */
+        "dragout" : true,
+        /**
+         * @event rowclass
+         * Fires when a row is rendered, so you can change add a style to it.
+         * @param {GridView} gridview The grid view
+         * @param {Object} rowcfg contains record, rowIndex and rowClass - set rowClass to add a style.
+         */
+        'rowclass' : true,
+
         /**
          * @event render
          * Fires when the grid is rendered
          * @param {Grid} grid
          */
-        render : true
+        'render' : true
     });
 
     Roo.grid.Grid.superclass.constructor.call(this);
@@ -46087,7 +46553,10 @@ Roo.extend(Roo.grid.Grid, Roo.util.Observable, {
      * @cfg {Object} loadMask An {@link Roo.LoadMask} config or true to mask the grid while loading. Default is false.
         */
        loadMask : false,
-
+    /**
+     * @cfg {Roo.dd.DropTarget} dragTarget An {@link Roo.dd.DragTarget} config
+        */
+       dropTarget: false,
     // private
     rendered : false,
 
@@ -46137,6 +46606,12 @@ Roo.extend(Roo.grid.Grid, Roo.util.Observable, {
             this.footer.container = this.getView().getFooterPanel(true);
             this.footer = Roo.factory(this.footer, Roo);
         }
+        if (this.dropTarget && this.dropTarget.xtype) {
+            delete this.dropTarget.xtype;
+            this.dropTarget =  new Ext.dd.DropTarget(this.getView().mainBody, this.dropTarget);
+        }
+        
+        
         this.rendered = true;
         this.fireEvent('render', this);
         return this;
@@ -46762,98 +47237,98 @@ Roo.extend(Roo.grid.GridView, Roo.grid.AbstractGridView, {
     },
 
     init: function(grid){
-               Roo.grid.GridView.superclass.init.call(this, grid);
+        Roo.grid.GridView.superclass.init.call(this, grid);
 
-               this.bind(grid.dataSource, grid.colModel);
+        this.bind(grid.dataSource, grid.colModel);
 
-           grid.on("headerclick", this.handleHeaderClick, this);
+        grid.on("headerclick", this.handleHeaderClick, this);
 
         if(grid.trackMouseOver){
             grid.on("mouseover", this.onRowOver, this);
-               grid.on("mouseout", this.onRowOut, this);
-           }
-           grid.cancelTextSelection = function(){};
-               this.gridId = grid.id;
-
-               var tpls = this.templates || {};
-
-               if(!tpls.master){
-                   tpls.master = new Roo.Template(
-                      '<div class="x-grid" hidefocus="true">',
-                         '<div class="x-grid-topbar"></div>',
-                         '<div class="x-grid-scroller"><div></div></div>',
-                         '<div class="x-grid-locked">',
-                             '<div class="x-grid-header">{lockedHeader}</div>',
-                             '<div class="x-grid-body">{lockedBody}</div>',
-                         "</div>",
-                         '<div class="x-grid-viewport">',
-                             '<div class="x-grid-header">{header}</div>',
-                             '<div class="x-grid-body">{body}</div>',
-                         "</div>",
-                         '<div class="x-grid-bottombar"></div>',
-                         '<a href="#" class="x-grid-focus" tabIndex="-1"></a>',
-                         '<div class="x-grid-resize-proxy">&#160;</div>',
-                      "</div>"
-                   );
-                   tpls.master.disableformats = true;
-               }
+            grid.on("mouseout", this.onRowOut, this);
+        }
+        grid.cancelTextSelection = function(){};
+        this.gridId = grid.id;
+
+        var tpls = this.templates || {};
+
+        if(!tpls.master){
+            tpls.master = new Roo.Template(
+               '<div class="x-grid" hidefocus="true">',
+                  '<div class="x-grid-topbar"></div>',
+                  '<div class="x-grid-scroller"><div></div></div>',
+                  '<div class="x-grid-locked">',
+                      '<div class="x-grid-header">{lockedHeader}</div>',
+                      '<div class="x-grid-body">{lockedBody}</div>',
+                  "</div>",
+                  '<div class="x-grid-viewport">',
+                      '<div class="x-grid-header">{header}</div>',
+                      '<div class="x-grid-body">{body}</div>',
+                  "</div>",
+                  '<div class="x-grid-bottombar"></div>',
+                  '<a href="#" class="x-grid-focus" tabIndex="-1"></a>',
+                  '<div class="x-grid-resize-proxy">&#160;</div>',
+               "</div>"
+            );
+            tpls.master.disableformats = true;
+        }
 
-               if(!tpls.header){
-                   tpls.header = new Roo.Template(
-                      '<table border="0" cellspacing="0" cellpadding="0">',
-                      '<tbody><tr class="x-grid-hd-row">{cells}</tr></tbody>',
-                      "</table>{splits}"
-                   );
-                   tpls.header.disableformats = true;
-               }
-               tpls.header.compile();
-
-               if(!tpls.hcell){
-                   tpls.hcell = new Roo.Template(
-                       '<td class="x-grid-hd x-grid-td-{id} {cellId}"><div title="{title}" class="x-grid-hd-inner x-grid-hd-{id}">',
-                       '<div class="x-grid-hd-text" unselectable="on">{value}<img class="x-grid-sort-icon" src="', Roo.BLANK_IMAGE_URL, '" /></div>',
-                       "</div></td>"
-                    );
-                    tpls.hcell.disableFormats = true;
-               }
-               tpls.hcell.compile();
+        if(!tpls.header){
+            tpls.header = new Roo.Template(
+               '<table border="0" cellspacing="0" cellpadding="0">',
+               '<tbody><tr class="x-grid-hd-row">{cells}</tr></tbody>',
+               "</table>{splits}"
+            );
+            tpls.header.disableformats = true;
+        }
+        tpls.header.compile();
 
-               if(!tpls.hsplit){
-                   tpls.hsplit = new Roo.Template('<div class="x-grid-split {splitId} x-grid-split-{id}" style="{style}" unselectable="on">&#160;</div>');
-                   tpls.hsplit.disableFormats = true;
-               }
-               tpls.hsplit.compile();
-
-               if(!tpls.body){
-                   tpls.body = new Roo.Template(
-                      '<table border="0" cellspacing="0" cellpadding="0">',
-                      "<tbody>{rows}</tbody>",
-                      "</table>"
-                   );
-                   tpls.body.disableFormats = true;
-               }
-               tpls.body.compile();
+        if(!tpls.hcell){
+            tpls.hcell = new Roo.Template(
+                '<td class="x-grid-hd x-grid-td-{id} {cellId}"><div title="{title}" class="x-grid-hd-inner x-grid-hd-{id}">',
+                '<div class="x-grid-hd-text" unselectable="on">{value}<img class="x-grid-sort-icon" src="', Roo.BLANK_IMAGE_URL, '" /></div>',
+                "</div></td>"
+             );
+             tpls.hcell.disableFormats = true;
+        }
+        tpls.hcell.compile();
 
-               if(!tpls.row){
-                   tpls.row = new Roo.Template('<tr class="x-grid-row {alt}">{cells}</tr>');
-                   tpls.row.disableFormats = true;
-               }
-               tpls.row.compile();
-
-               if(!tpls.cell){
-                   tpls.cell = new Roo.Template(
-                       '<td class="x-grid-col x-grid-td-{id} {cellId} {css}" tabIndex="0">',
-                       '<div class="x-grid-col-{id} x-grid-cell-inner"><div class="x-grid-cell-text" unselectable="on" {attr}>{value}</div></div>',
-                       "</td>"
-                   );
+        if(!tpls.hsplit){
+            tpls.hsplit = new Roo.Template('<div class="x-grid-split {splitId} x-grid-split-{id}" style="{style}" unselectable="on">&#160;</div>');
+            tpls.hsplit.disableFormats = true;
+        }
+        tpls.hsplit.compile();
+
+        if(!tpls.body){
+            tpls.body = new Roo.Template(
+               '<table border="0" cellspacing="0" cellpadding="0">',
+               "<tbody>{rows}</tbody>",
+               "</table>"
+            );
+            tpls.body.disableFormats = true;
+        }
+        tpls.body.compile();
+
+        if(!tpls.row){
+            tpls.row = new Roo.Template('<tr class="x-grid-row {alt}">{cells}</tr>');
+            tpls.row.disableFormats = true;
+        }
+        tpls.row.compile();
+
+        if(!tpls.cell){
+            tpls.cell = new Roo.Template(
+                '<td class="x-grid-col x-grid-td-{id} {cellId} {css}" tabIndex="0">',
+                '<div class="x-grid-col-{id} x-grid-cell-inner"><div class="x-grid-cell-text" unselectable="on" {attr}>{value}</div></div>',
+                "</td>"
+            );
             tpls.cell.disableFormats = true;
         }
-               tpls.cell.compile();
+        tpls.cell.compile();
 
-               this.templates = tpls;
-       },
+        this.templates = tpls;
+    },
 
-       // remap these for backwards compat
+    // remap these for backwards compat
     onColWidthChange : function(){
         this.updateColumns.apply(this, arguments);
     },
@@ -46875,11 +47350,11 @@ Roo.extend(Roo.grid.GridView, Roo.grid.AbstractGridView, {
         this.updateHeaderSortState();
     },
 
-       onClear : function(){
+    onClear : function(){
         this.refresh();
     },
 
-       onUpdate : function(ds, record){
+    onUpdate : function(ds, record){
         this.refreshRow(record);
     },
 
@@ -46947,9 +47422,9 @@ Roo.extend(Roo.grid.GridView, Roo.grid.AbstractGridView, {
             this.headerPanel.show();
         }
         return this.headerPanel;
-       },
+    },
 
-       /**
+    /**
      * Gets a panel in the footer of the grid that can be used for toolbars etc.
      * After modifying the contents of this panel a call to grid.autoSize() may be
      * required to register any changes in size.
@@ -46961,82 +47436,82 @@ Roo.extend(Roo.grid.GridView, Roo.grid.AbstractGridView, {
             this.footerPanel.show();
         }
         return this.footerPanel;
-       },
+    },
 
-       initElements : function(){
-           var E = Roo.Element;
-           var el = this.grid.getGridEl().dom.firstChild;
-           var cs = el.childNodes;
+    initElements : function(){
+        var E = Roo.Element;
+        var el = this.grid.getGridEl().dom.firstChild;
+        var cs = el.childNodes;
 
-           this.el = new E(el);
-           this.headerPanel = new E(el.firstChild);
-           this.headerPanel.enableDisplayMode("block");
+        this.el = new E(el);
+        this.headerPanel = new E(el.firstChild);
+        this.headerPanel.enableDisplayMode("block");
 
         this.scroller = new E(cs[1]);
-           this.scrollSizer = new E(this.scroller.dom.firstChild);
+        this.scrollSizer = new E(this.scroller.dom.firstChild);
 
-           this.lockedWrap = new E(cs[2]);
-           this.lockedHd = new E(this.lockedWrap.dom.firstChild);
-           this.lockedBody = new E(this.lockedWrap.dom.childNodes[1]);
+        this.lockedWrap = new E(cs[2]);
+        this.lockedHd = new E(this.lockedWrap.dom.firstChild);
+        this.lockedBody = new E(this.lockedWrap.dom.childNodes[1]);
 
-           this.mainWrap = new E(cs[3]);
-           this.mainHd = new E(this.mainWrap.dom.firstChild);
-           this.mainBody = new E(this.mainWrap.dom.childNodes[1]);
+        this.mainWrap = new E(cs[3]);
+        this.mainHd = new E(this.mainWrap.dom.firstChild);
+        this.mainBody = new E(this.mainWrap.dom.childNodes[1]);
 
-           this.footerPanel = new E(cs[4]);
-           this.footerPanel.enableDisplayMode("block");
+        this.footerPanel = new E(cs[4]);
+        this.footerPanel.enableDisplayMode("block");
 
         this.focusEl = new E(cs[5]);
         this.focusEl.swallowEvent("click", true);
         this.resizeProxy = new E(cs[6]);
 
-           this.headerSelector = String.format(
-              '#{0} td.x-grid-hd, #{1} td.x-grid-hd',
-              this.lockedHd.id, this.mainHd.id
-           );
+        this.headerSelector = String.format(
+           '#{0} td.x-grid-hd, #{1} td.x-grid-hd',
+           this.lockedHd.id, this.mainHd.id
+        );
 
-           this.splitterSelector = String.format(
-              '#{0} div.x-grid-split, #{1} div.x-grid-split',
-              this.idToCssName(this.lockedHd.id), this.idToCssName(this.mainHd.id)
-           );
+        this.splitterSelector = String.format(
+           '#{0} div.x-grid-split, #{1} div.x-grid-split',
+           this.idToCssName(this.lockedHd.id), this.idToCssName(this.mainHd.id)
+        );
     },
     idToCssName : function(s)
     {
         return s.replace(/[^a-z0-9]+/ig, '-');
     },
 
-       getHeaderCell : function(index){
-           return Roo.DomQuery.select(this.headerSelector)[index];
-       },
+    getHeaderCell : function(index){
+        return Roo.DomQuery.select(this.headerSelector)[index];
+    },
 
-       getHeaderCellMeasure : function(index){
-           return this.getHeaderCell(index).firstChild;
-       },
+    getHeaderCellMeasure : function(index){
+        return this.getHeaderCell(index).firstChild;
+    },
 
-       getHeaderCellText : function(index){
-           return this.getHeaderCell(index).firstChild.firstChild;
-       },
+    getHeaderCellText : function(index){
+        return this.getHeaderCell(index).firstChild.firstChild;
+    },
 
-       getLockedTable : function(){
-           return this.lockedBody.dom.firstChild;
-       },
+    getLockedTable : function(){
+        return this.lockedBody.dom.firstChild;
+    },
 
-       getBodyTable : function(){
-           return this.mainBody.dom.firstChild;
-       },
+    getBodyTable : function(){
+        return this.mainBody.dom.firstChild;
+    },
 
-       getLockedRow : function(index){
-           return this.getLockedTable().rows[index];
-       },
+    getLockedRow : function(index){
+        return this.getLockedTable().rows[index];
+    },
 
-       getRow : function(index){
-           return this.getBodyTable().rows[index];
-       },
+    getRow : function(index){
+        return this.getBodyTable().rows[index];
+    },
 
-       getRowComposite : function(index){
-           if(!this.rowEl){
-               this.rowEl = new Roo.CompositeElementLite();
-           }
+    getRowComposite : function(index){
+        if(!this.rowEl){
+            this.rowEl = new Roo.CompositeElementLite();
+        }
         var els = [], lrow, mrow;
         if(lrow = this.getLockedRow(index)){
             els.push(lrow);
@@ -47045,27 +47520,27 @@ Roo.extend(Roo.grid.GridView, Roo.grid.AbstractGridView, {
             els.push(mrow);
         }
         this.rowEl.elements = els;
-           return this.rowEl;
-       },
+        return this.rowEl;
+    },
 
-       getCell : function(rowIndex, colIndex){
-           var locked = this.cm.getLockedCount();
-           var source;
-           if(colIndex < locked){
-               source = this.lockedBody.dom.firstChild;
-           }else{
-               source = this.mainBody.dom.firstChild;
-               colIndex -= locked;
-           }
+    getCell : function(rowIndex, colIndex){
+        var locked = this.cm.getLockedCount();
+        var source;
+        if(colIndex < locked){
+            source = this.lockedBody.dom.firstChild;
+        }else{
+            source = this.mainBody.dom.firstChild;
+            colIndex -= locked;
+        }
         return source.rows[rowIndex].childNodes[colIndex];
-       },
+    },
 
-       getCellText : function(rowIndex, colIndex){
-           return this.getCell(rowIndex, colIndex).firstChild.firstChild;
-       },
+    getCellText : function(rowIndex, colIndex){
+        return this.getCell(rowIndex, colIndex).firstChild.firstChild;
+    },
 
-       getCellBox : function(cell){
-           var b = this.fly(cell).getBox();
+    getCellBox : function(cell){
+        var b = this.fly(cell).getBox();
         if(Roo.isOpera){ // opera fails to report the Y
             b.y = cell.offsetTop + this.mainBody.getY();
         }
@@ -47110,20 +47585,21 @@ Roo.extend(Roo.grid.GridView, Roo.grid.AbstractGridView, {
     },
 
     getColumnId : function(index){
-           return this.cm.getColumnId(index);
-       },
+        return this.cm.getColumnId(index);
+    },
 
-       getSplitters : function(){
-           if(this.splitterSelector){
-              return Roo.DomQuery.select(this.splitterSelector);
-           }else{
-               return null;
-           }
-       },
+    getSplitters : function()
+    {
+        if(this.splitterSelector){
+           return Roo.DomQuery.select(this.splitterSelector);
+        }else{
+            return null;
+      }
+    },
 
-       getSplitter : function(index){
-           return this.getSplitters()[index];
-       },
+    getSplitter : function(index){
+        return this.getSplitters()[index];
+    },
 
     onRowOver : function(e, t){
         var row;
@@ -47140,7 +47616,7 @@ Roo.extend(Roo.grid.GridView, Roo.grid.AbstractGridView, {
     },
 
     renderHeaders : function(){
-           var cm = this.cm;
+        var cm = this.cm;
         var ct = this.templates.hcell, ht = this.templates.header, st = this.templates.hsplit;
         var cb = [], lb = [], sb = [], lsb = [], p = {};
         for(var i = 0, len = cm.getColumnCount(); i < len; i++){
@@ -47160,9 +47636,9 @@ Roo.extend(Roo.grid.GridView, Roo.grid.AbstractGridView, {
         }
         return [ht.apply({cells: lb.join(""), splits:lsb.join("")}),
                 ht.apply({cells: cb.join(""), splits:sb.join("")})];
-       },
+    },
 
-       updateHeaders : function(){
+    updateHeaders : function(){
         var html = this.renderHeaders();
         this.lockedHd.update(html[0]);
         this.mainHd.update(html[1]);
@@ -47231,7 +47707,7 @@ Roo.extend(Roo.grid.GridView, Roo.grid.AbstractGridView, {
         var sright = sleft + c.clientWidth;
 
         if(ctop < stop){
-               c.scrollTop = ctop;
+            c.scrollTop = ctop;
         }else if(cbot > sbot){
             c.scrollTop = cbot-ch;
         }
@@ -47289,7 +47765,7 @@ Roo.extend(Roo.grid.GridView, Roo.grid.AbstractGridView, {
             var pos = 0, locked = true;
             for(var i = 0, len = cm.getColumnCount(); i < len; i++){
                 if(cm.isHidden(i)) continue;
-                var w = cm.getColumnWidth(i);
+                var w = cm.getColumnWidth(i); // make sure it's a number
                 if(!cm.isLocked(i) && locked){
                     pos = 0;
                     locked = false;
@@ -47503,6 +47979,9 @@ Roo.extend(Roo.grid.GridView, Roo.grid.AbstractGridView, {
                 var ts = this.templates, ct = ts.cell, rt = ts.row;
                 // buffers
                 var buf = "", lbuf = "", cb, lcb, c, p = {}, rp = {}, r, rowIndex;
+                
+                var hasListener = this.grid.hasListener('rowclass');
+                var rowcfg = {};
                 for(var j = 0, len = rs.length; j < len; j++){
                     r = rs[j]; cb = ""; lcb = ""; rowIndex = (j+startRow);
                     for(var i = 0; i < colCount; i++){
@@ -47524,14 +48003,24 @@ Roo.extend(Roo.grid.GridView, Roo.grid.AbstractGridView, {
                     }
                     var alt = [];
                     if(stripe && ((rowIndex+1) % 2 == 0)){
-                        alt[0] = "x-grid-row-alt";
+                        alt.push("x-grid-row-alt")
                     }
                     if(r.dirty){
-                        alt[1] = " x-grid-dirty-row";
+                        alt.push(  " x-grid-dirty-row");
                     }
                     rp.cells = lcb;
                     if(this.getRowClass){
-                        alt[2] = this.getRowClass(r, rowIndex);
+                        alt.push(this.getRowClass(r, rowIndex));
+                    }
+                    if (hasListener) {
+                        rowcfg = {
+                             
+                            record: r,
+                            rowIndex : rowIndex,
+                            rowClass : ''
+                        }
+                        this.grid.fireEvent('rowclass', this, rowcfg);
+                        alt.push(rowcfg.rowClass);
                     }
                     rp.alt = alt.join(" ");
                     lbuf+= rt.apply(rp);
@@ -47544,6 +48033,8 @@ Roo.extend(Roo.grid.GridView, Roo.grid.AbstractGridView, {
                 var ts = this.templates, ct = ts.cell, rt = ts.row;
                 // buffers
                 var buf = [], lbuf = [], cb, lcb, c, p = {}, rp = {}, r, rowIndex;
+                var hasListener = this.grid.hasListener('rowclass');
+                var rowcfg = {};
                 for(var j = 0, len = rs.length; j < len; j++){
                     r = rs[j]; cb = []; lcb = []; rowIndex = (j+startRow);
                     for(var i = 0; i < colCount; i++){
@@ -47565,14 +48056,24 @@ Roo.extend(Roo.grid.GridView, Roo.grid.AbstractGridView, {
                     }
                     var alt = [];
                     if(stripe && ((rowIndex+1) % 2 == 0)){
-                        alt[0] = "x-grid-row-alt";
+                        alt.push( "x-grid-row-alt");
                     }
                     if(r.dirty){
-                        alt[1] = " x-grid-dirty-row";
+                        alt.push(" x-grid-dirty-row");
                     }
                     rp.cells = lcb;
                     if(this.getRowClass){
-                        alt[2] = this.getRowClass(r, rowIndex);
+                        alt.push( this.getRowClass(r, rowIndex));
+                    }
+                    if (hasListener) {
+                        rowcfg = {
+                             
+                            record: r,
+                            rowIndex : rowIndex,
+                            rowClass : ''
+                        }
+                        this.grid.fireEvent('rowclass', this, rowcfg);
+                        alt.push(rowcfg.rowClass);
                     }
                     rp.alt = alt.join(" ");
                     rp.cells = lcb.join("");
@@ -47787,10 +48288,10 @@ Roo.extend(Roo.grid.GridView, Roo.grid.AbstractGridView, {
             return;
         }
         var dm = g.dataSource, cm = g.colModel;
-           if(!cm.isSortable(index)){
+        if(!cm.isSortable(index)){
             return;
         }
-           g.stopEditing();
+        g.stopEditing();
         dm.sort(cm.getDataIndex(index));
     },
 
@@ -47965,6 +48466,11 @@ Roo.extend(Roo.grid.GridView, Roo.grid.AbstractGridView, {
         this.grid.getGridEl().dom.innerHTML = html;
 
         this.initElements();
+        
+        // a kludge to fix the random scolling effect in webkit
+        this.el.on("scroll", function() {
+            this.el.dom.scrollTop=0; // hopefully not recursive..
+        },this);
 
         this.scroller.on("scroll", this.handleScroll, this);
         this.lockedBody.on("mousewheel", this.handleWheel, this);
@@ -48706,7 +49212,7 @@ Roo.extend(Roo.grid.ColumnModel, Roo.util.Observable, {
      * @return {Number}
      */
     getColumnWidth : function(col){
-        return this.config[col].width || this.defaultWidth;
+        return this.config[col].width * 1 || this.defaultWidth;
     },
 
     /**
@@ -49751,11 +50257,17 @@ Roo.extend(Roo.grid.EditorGrid, Roo.grid.Grid, {
             
             if(this.fireEvent("validateedit", e) !== false && !e.cancel){
                 r.set(field, e.value);
+                // if we are dealing with a combo box..
+                // then we also set the 'name' colum to be the displayField
+                if (ed.field.displayField && ed.field.name) {
+                    r.set(ed.field.name, ed.field.el.dom.value);
+                }
+                
                 delete e.cancel; //?? why!!!
                 this.fireEvent("afteredit", e);
             }
         } else {
-            this.fireEvent("afteredit", e); // always fir it!
+            this.fireEvent("afteredit", e); // always fire it!
         }
         this.view.focusCell(ed.row, ed.col);
     },
@@ -49800,6 +50312,12 @@ Roo.extend(Roo.grid.EditorGrid, Roo.grid.Grid, {
                     this.activeEditor = ed;
                     var v = r.data[field];
                     ed.startEdit(this.view.getCell(row, col), v);
+                    // combo's with 'displayField and name set
+                    if (ed.field.displayField && ed.field.name) {
+                        ed.field.el.dom.value = r.data[ed.field.name];
+                    }
+                    
+                    
                 }).defer(50, this);
             }
         }