Roo.form.DayPicker - final tweaks and documentation rebuild
[roojs1] / roojs-debug.js
index 76ba5e3..8ff0a7c 100644 (file)
@@ -336,16 +336,16 @@ Roo.factory(conf, Roo.data);
             }
             var buf = [];
             for(var key in o){
-                var ov = o[key], k = encodeURIComponent(key);
+                var ov = o[key], k = Roo.encodeURIComponent(key);
                 var type = typeof ov;
                 if(type == 'undefined'){
                     buf.push(k, "=&");
                 }else if(type != "function" && type != "object"){
-                    buf.push(k, "=", encodeURIComponent(ov), "&");
+                    buf.push(k, "=", Roo.encodeURIComponent(ov), "&");
                 }else if(ov instanceof Array){
                     if (ov.length) {
                            for(var i = 0, len = ov.length; i < len; i++) {
-                               buf.push(k, "=", encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&");
+                               buf.push(k, "=", Roo.encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&");
                            }
                        } else {
                            buf.push(k, "=&");
@@ -354,6 +354,60 @@ Roo.factory(conf, Roo.data);
             }
             buf.pop();
             return buf.join("");
+        },
+         /**
+         * Safe version of encodeURIComponent
+         * @param {String} data 
+         * @return {String} 
+         */
+        
+        encodeURIComponent : function (data)
+        {
+            try {
+                return encodeURIComponent(data);
+            } catch(e) {} // should be an uri encode error.
+            
+            if (data == '' || data == null){
+               return '';
+            }
+            // http://stackoverflow.com/questions/2596483/unicode-and-uri-encoding-decoding-and-escaping-in-javascript
+            function nibble_to_hex(nibble){
+                var chars = '0123456789ABCDEF';
+                return chars.charAt(nibble);
+            }
+            data = data.toString();
+            var buffer = '';
+            for(var i=0; i<data.length; i++){
+                var c = data.charCodeAt(i);
+                var bs = new Array();
+                if (c > 0x10000){
+                        // 4 bytes
+                    bs[0] = 0xF0 | ((c & 0x1C0000) >>> 18);
+                    bs[1] = 0x80 | ((c & 0x3F000) >>> 12);
+                    bs[2] = 0x80 | ((c & 0xFC0) >>> 6);
+                    bs[3] = 0x80 | (c & 0x3F);
+                }else if (c > 0x800){
+                         // 3 bytes
+                    bs[0] = 0xE0 | ((c & 0xF000) >>> 12);
+                    bs[1] = 0x80 | ((c & 0xFC0) >>> 6);
+                    bs[2] = 0x80 | (c & 0x3F);
+                }else if (c > 0x80){
+                       // 2 bytes
+                    bs[0] = 0xC0 | ((c & 0x7C0) >>> 6);
+                    bs[1] = 0x80 | (c & 0x3F);
+                }else{
+                        // 1 byte
+                    bs[0] = c;
+                }
+                for(var j=0; j<bs.length; j++){
+                    var b = bs[j];
+                    var hex = nibble_to_hex((b & 0xF0) >>> 4) 
+                            + nibble_to_hex(b &0x0F);
+                    buffer += '%'+hex;
+               }
+            }
+            return buffer;    
+             
         },
 
         /**
@@ -2432,10 +2486,10 @@ Roo.lib.Event = function() {
                             for (var j = 0; j < el.options.length; j++) {
                                 if (el.options[j].selected) {
                                     if (Roo.isIE) {
-                                        data += encodeURIComponent(name) + '=' + encodeURIComponent(el.options[j].attributes['value'].specified ? el.options[j].value : el.options[j].text) + '&';
+                                        data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(el.options[j].attributes['value'].specified ? el.options[j].value : el.options[j].text) + '&';
                                     }
                                     else {
-                                        data += encodeURIComponent(name) + '=' + encodeURIComponent(el.options[j].hasAttribute('value') ? el.options[j].value : el.options[j].text) + '&';
+                                        data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(el.options[j].hasAttribute('value') ? el.options[j].value : el.options[j].text) + '&';
                                     }
                                 }
                             }
@@ -2443,7 +2497,7 @@ Roo.lib.Event = function() {
                         case 'radio':
                         case 'checkbox':
                             if (el.checked) {
-                                data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
+                                data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
                             }
                             break;
                         case 'file':
@@ -2457,12 +2511,12 @@ Roo.lib.Event = function() {
                             break;
                         case 'submit':
                             if(hasSubmit == false) {
-                                data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
+                                data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
                                 hasSubmit = true;
                             }
                             break;
                         default:
-                            data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
+                            data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
                             break;
                     }
                 }
@@ -29678,7 +29732,8 @@ Roo.LayoutDialog = function(el, cfg){
         config = Roo.apply({}, el);
         // not sure why we use documentElement here.. - it should always be body.
         // IE7 borks horribly if we use documentElement.
-        el = Roo.get( Roo.isIE ? (document.body || document.documentElement) : (document.documentElement || document.body) ).createChild();
+        // webkit also does not like documentElement - it creates a body element...
+        el = Roo.get( document.body || document.documentElement ).createChild();
         //config.autoCreate = true;
     }
     
@@ -42646,6 +42701,189 @@ Roo.extend(Roo.form.DisplayField, Roo.form.TextField,  {
         Roo.form.DisplayField.superclass.setValue.call(this, v);
 
     }
+});/*
+ * 
+ * Licence- LGPL
+ * 
+ */
+
+/**
+ * @class Roo.form.DayPicker
+ * @extends Roo.form.Field
+ * A Day picker show [M] [T] [W] ....
+ * @constructor
+ * Creates a new Day Picker
+ * @param {Object} config Configuration options
+ */
+Roo.form.DayPicker= function(config){
+    Roo.form.DayPicker.superclass.constructor.call(this, config);
+     
+};
+
+Roo.extend(Roo.form.DayPicker, Roo.form.Field,  {
+    /**
+     * @cfg {String} focusClass The CSS class to use when the checkbox receives focus (defaults to undefined)
+     */
+    focusClass : undefined,
+    /**
+     * @cfg {String} fieldClass The default CSS class for the checkbox (defaults to "x-form-field")
+     */
+    fieldClass: "x-form-field",
+   
+    /**
+     * @cfg {String/Object} autoCreate A DomHelper element spec, or true for a default element spec (defaults to
+     * {tag: "input", type: "checkbox", autocomplete: "off"})
+     */
+    defaultAutoCreate : { tag: "input", type: 'hidden', autocomplete: "off"},
+    
+   
+    actionMode : 'viewEl', 
+    //
+    // private
+    inputType : 'hidden',
+    
+     
+    inputElement: false, // real input element?
+    basedOn: false, // ????
+    
+    isFormField: true, // not sure where this is needed!!!!
+
+    onResize : function(){
+        Roo.form.Checkbox.superclass.onResize.apply(this, arguments);
+        if(!this.boxLabel){
+            this.el.alignTo(this.wrap, 'c-c');
+        }
+    },
+
+    initEvents : function(){
+        Roo.form.Checkbox.superclass.initEvents.call(this);
+        this.el.on("click", this.onClick,  this);
+        this.el.on("change", this.onClick,  this);
+    },
+
+
+    getResizeEl : function(){
+        return this.wrap;
+    },
+
+    getPositionEl : function(){
+        return this.wrap;
+    },
+
+    
+    // private
+    onRender : function(ct, position){
+        Roo.form.Checkbox.superclass.onRender.call(this, ct, position);
+       
+        this.wrap = this.el.wrap({cls: 'x-form-daypick-item '});
+        
+        var r1 = '<table><tr>';
+        var r2 = '<tr class="x-form-daypick-icons">';
+        for (var i=0; i < 7; i++) {
+            r1+= '<td><div>' + Date.dayNames[i].substring(0,3) + '</div></td>';
+            r2+= '<td><img class="x-menu-item-icon" src="' + Roo.BLANK_IMAGE_URL  +'"></td>';
+        }
+        
+        var viewEl = this.wrap.createChild( r1 + '</tr>' + r2 + '</tr></table>');
+        viewEl.select('img').on('click', this.onClick, this);
+        this.viewEl = viewEl;   
+        
+        
+        // this will not work on Chrome!!!
+        this.el.on('DOMAttrModified', this.setFromHidden,  this); //ff
+        this.el.on('propertychange', this.setFromHidden,  this);  //ie
+        
+        
+          
+
+    },
+
+    // private
+    initValue : Roo.emptyFn,
+
+    /**
+     * Returns the checked state of the checkbox.
+     * @return {Boolean} True if checked, else false
+     */
+    getValue : function(){
+        return this.el.dom.value;
+        
+    },
+
+       // private
+    onClick : function(e){ 
+        //this.setChecked(!this.checked);
+        Roo.get(e.target).toggleClass('x-menu-item-checked');
+        this.refreshValue();
+        //if(this.el.dom.checked != this.checked){
+        //    this.setValue(this.el.dom.checked);
+       // }
+    },
+    
+    // private
+    refreshValue : function()
+    {
+        var val = '';
+        this.viewEl.select('img',true).each(function(e,i,n)  {
+            val += e.is(".x-menu-item-checked") ? String(n) : '';
+        });
+        this.setValue(val, true);
+    },
+
+    /**
+     * Sets the checked state of the checkbox.
+     * On is always based on a string comparison between inputValue and the param.
+     * @param {Boolean/String} value - the value to set 
+     * @param {Boolean/String} suppressEvent - whether to suppress the checkchange event.
+     */
+    setValue : function(v,suppressEvent){
+        if (!this.el.dom) {
+            return;
+        }
+        var old = this.el.dom.value ;
+        this.el.dom.value = v;
+        if (suppressEvent) {
+            return ;
+        }
+         
+        // update display..
+        this.viewEl.select('img',true).each(function(e,i,n)  {
+            
+            var on = e.is(".x-menu-item-checked");
+            var newv = v.indexOf(String(n)) > -1;
+            if (on != newv) {
+                e.toggleClass('x-menu-item-checked');
+            }
+            
+        });
+        
+        
+        this.fireEvent('change', this, v, old);
+        
+        
+    },
+   
+    // handle setting of hidden value by some other method!!?!?
+    setFromHidden: function()
+    {
+        if(!this.el){
+            return;
+        }
+        //console.log("SET FROM HIDDEN");
+        //alert('setFrom hidden');
+        this.setValue(this.el.dom.value);
+    },
+    
+    onDestroy : function()
+    {
+        if(this.viewEl){
+            Roo.get(this.viewEl).remove();
+        }
+         
+        Roo.form.DayPicker.superclass.onDestroy.call(this);
+    }
+
 });//<script type="text/javasscript">
  
 
@@ -45432,6 +45670,7 @@ Roo.ContentPanel = function(el, config, content){
     } else {
         // fix randome scrolling
         this.el.on('scroll', function() {
+            Roo.log('fix random scolling');
             this.scrollTo('top',0); 
         });
     }
@@ -46230,123 +46469,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
@@ -46355,93 +46594,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);
@@ -46450,74 +46697,74 @@ Roo.extend(Roo.grid.Grid, Roo.util.Observable, {
     
     /**
      * @cfg {String} ddGroup - drag drop group.
-        */
-    
+     */
+
     /**
      * @cfg {Number} minColumnWidth The minimum width a column can be resized to. Default is 25.
-        */
-       minColumnWidth : 25,
+     */
+    minColumnWidth : 25,
 
     /**
-        * @cfg {Boolean} autoSizeColumns True to automatically resize the columns to fit their content
-        * <b>on initial render.</b> It is more efficient to explicitly size the columns
-        * through the ColumnModel's {@link Roo.grid.ColumnModel#width} config option.  Default is false.
-        */
-       autoSizeColumns : false,
+     * @cfg {Boolean} autoSizeColumns True to automatically resize the columns to fit their content
+     * <b>on initial render.</b> It is more efficient to explicitly size the columns
+     * through the ColumnModel's {@link Roo.grid.ColumnModel#width} config option.  Default is false.
+     */
+    autoSizeColumns : false,
 
-       /**
-        * @cfg {Boolean} autoSizeHeaders True to measure headers with column data when auto sizing columns. Default is true.
-        */
-       autoSizeHeaders : true,
+    /**
+     * @cfg {Boolean} autoSizeHeaders True to measure headers with column data when auto sizing columns. Default is true.
+     */
+    autoSizeHeaders : true,
 
-       /**
-        * @cfg {Boolean} monitorWindowResize True to autoSize the grid when the window resizes. Default is true.
-        */
-       monitorWindowResize : true,
+    /**
+     * @cfg {Boolean} monitorWindowResize True to autoSize the grid when the window resizes. Default is true.
+     */
+    monitorWindowResize : true,
 
-       /**
-        * @cfg {Boolean} maxRowsToMeasure If autoSizeColumns is on, maxRowsToMeasure can be used to limit the number of
-        * rows measured to get a columns size. Default is 0 (all rows).
-        */
-       maxRowsToMeasure : 0,
+    /**
+     * @cfg {Boolean} maxRowsToMeasure If autoSizeColumns is on, maxRowsToMeasure can be used to limit the number of
+     * rows measured to get a columns size. Default is 0 (all rows).
+     */
+    maxRowsToMeasure : 0,
 
-       /**
-        * @cfg {Boolean} trackMouseOver True to highlight rows when the mouse is over. Default is true.
-        */
-       trackMouseOver : true,
+    /**
+     * @cfg {Boolean} trackMouseOver True to highlight rows when the mouse is over. Default is true.
+     */
+    trackMouseOver : true,
 
     /**
-        * @cfg {Boolean} enableDrag  True to enable drag of rows. Default is false. (double check if this is needed?)
-        */
+    * @cfg {Boolean} enableDrag  True to enable drag of rows. Default is false. (double check if this is needed?)
+    */
     
-       /**
-        * @cfg {Boolean} enableDragDrop True to enable drag and drop of rows. Default is false.
-        */
-       enableDragDrop : false,
-
-       /**
-        * @cfg {Boolean} enableColumnMove True to enable drag and drop reorder of columns. Default is true.
-        */
-       enableColumnMove : true,
-
-       /**
-        * @cfg {Boolean} enableColumnHide True to enable hiding of columns with the header context menu. Default is true.
-        */
-       enableColumnHide : true,
-
-       /**
-        * @cfg {Boolean} enableRowHeightSync True to manually sync row heights across locked and not locked rows. Default is false.
-        */
-       enableRowHeightSync : false,
-
-       /**
-        * @cfg {Boolean} stripeRows True to stripe the rows.  Default is true.
-        */
-       stripeRows : true,
-
-       /**
-        * @cfg {Boolean} autoHeight True to fit the height of the grid container to the height of the data. Default is false.
-        */
-       autoHeight : false,
+    /**
+    * @cfg {Boolean} enableDragDrop True to enable drag and drop of rows. Default is false.
+    */
+    enableDragDrop : false,
+    
+    /**
+    * @cfg {Boolean} enableColumnMove True to enable drag and drop reorder of columns. Default is true.
+    */
+    enableColumnMove : true,
+    
+    /**
+    * @cfg {Boolean} enableColumnHide True to enable hiding of columns with the header context menu. Default is true.
+    */
+    enableColumnHide : true,
+    
+    /**
+    * @cfg {Boolean} enableRowHeightSync True to manually sync row heights across locked and not locked rows. Default is false.
+    */
+    enableRowHeightSync : false,
+    
+    /**
+    * @cfg {Boolean} stripeRows True to stripe the rows.  Default is true.
+    */
+    stripeRows : true,
+    
+    /**
+    * @cfg {Boolean} autoHeight True to fit the height of the grid container to the height of the data. Default is false.
+    */
+    autoHeight : false,
 
     /**
      * @cfg {String} autoExpandColumn The id (or dataIndex) of a column in this grid that should expand to fill unused space. This id can not be 0. Default is false.
@@ -46536,18 +46783,19 @@ Roo.extend(Roo.grid.Grid, Roo.util.Observable, {
     autoExpandMax : 1000,
 
     /**
-        * @cfg {Object} view The {@link Roo.grid.GridView} used by the grid. This can be set before a call to render().
-        */
-       view : null,
+    * @cfg {Object} view The {@link Roo.grid.GridView} used by the grid. This can be set before a call to render().
+    */
+    view : null,
 
-       /**
-     * @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,
+    * @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,
 
@@ -46562,7 +46810,8 @@ Roo.extend(Roo.grid.Grid, Roo.util.Observable, {
      * Called once after all setup has been completed and the grid is ready to be rendered.
      * @return {Roo.grid.Grid} this
      */
-    render : function(){
+    render : function()
+    {
         var c = this.container;
         // try to detect autoHeight/width mode
         if((!c.dom.offsetHeight || c.dom.offsetHeight < 20) || c.getStyle("height") == "auto"){
@@ -47228,98 +47477,99 @@ 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">',
+                '<a href="#" class="x-grid-focus" tabIndex="-1"></a>',
+                  '<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>',
+                 
+                  '<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);
     },
@@ -47341,11 +47591,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);
     },
 
@@ -47413,9 +47663,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.
@@ -47427,82 +47677,84 @@ 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.focusEl = new E(el.firstChild);
+        this.focusEl.swallowEvent("click", true);
+        
+        this.headerPanel = new E(cs[1]);
+        this.headerPanel.enableDisplayMode("block");
 
-        this.scroller = new E(cs[1]);
-           this.scrollSizer = new E(this.scroller.dom.firstChild);
+        this.scroller = new E(cs[2]);
+        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[3]);
+        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[4]);
+        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[5]);
+        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);
@@ -47511,27 +47763,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();
         }
@@ -47576,20 +47828,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;
@@ -47606,7 +47859,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++){
@@ -47626,9 +47879,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]);
@@ -47638,7 +47891,9 @@ Roo.extend(Roo.grid.GridView, Roo.grid.AbstractGridView, {
      * Focuses the specified row.
      * @param {Number} row The row index
      */
-    focusRow : function(row){
+    focusRow : function(row)
+    {
+        //Roo.log('GridView.focusRow');
         var x = this.scroller.dom.scrollLeft;
         this.focusCell(row, 0, false);
         this.scroller.dom.scrollLeft = x;
@@ -47650,7 +47905,9 @@ Roo.extend(Roo.grid.GridView, Roo.grid.AbstractGridView, {
      * @param {Number} col The column index
      * @param {Boolean} hscroll false to disable horizontal scrolling
      */
-    focusCell : function(row, col, hscroll){
+    focusCell : function(row, col, hscroll)
+    {
+        //Roo.log('GridView.focusCell');
         var el = this.ensureVisible(row, col, hscroll);
         this.focusEl.alignTo(el, "tl-tl");
         if(Roo.isGecko){
@@ -47666,12 +47923,15 @@ Roo.extend(Roo.grid.GridView, Roo.grid.AbstractGridView, {
      * @param {Number} col The column index
      * @param {Boolean} hscroll false to disable horizontal scrolling
      */
-    ensureVisible : function(row, col, hscroll){
+    ensureVisible : function(row, col, hscroll)
+    {
+        //Roo.log('GridView.ensureVisible,' + row + ',' + col);
+        //return null; //disable for testing.
         if(typeof row != "number"){
             row = row.rowIndex;
         }
         if(row < 0 && row >= this.ds.getCount()){
-            return;
+            return  null;
         }
         col = (col !== undefined ? col : 0);
         var cm = this.grid.colModel;
@@ -47681,7 +47941,7 @@ Roo.extend(Roo.grid.GridView, Roo.grid.AbstractGridView, {
 
         var el = this.getCell(row, col);
         if(!el){
-            return;
+            return null;
         }
         var c = this.scroller.dom;
 
@@ -47689,19 +47949,31 @@ Roo.extend(Roo.grid.GridView, Roo.grid.AbstractGridView, {
         var cleft = parseInt(el.offsetLeft, 10);
         var cbot = ctop + el.offsetHeight;
         var cright = cleft + el.offsetWidth;
-
+        
         var ch = c.clientHeight - this.mainHd.dom.offsetHeight;
         var stop = parseInt(c.scrollTop, 10);
         var sleft = parseInt(c.scrollLeft, 10);
         var sbot = stop + ch;
         var sright = sleft + c.clientWidth;
-
+        /*
+        Roo.log('GridView.ensureVisible:' +
+                ' ctop:' + ctop +
+                ' c.clientHeight:' + c.clientHeight +
+                ' this.mainHd.dom.offsetHeight:' + this.mainHd.dom.offsetHeight +
+                ' stop:' + stop +
+                ' cbot:' + cbot +
+                ' sbot:' + sbot +
+                ' ch:' + ch  
+                );
+        */
         if(ctop < stop){
-               c.scrollTop = ctop;
+             c.scrollTop = ctop;
+            //Roo.log("set scrolltop to ctop DISABLE?");
         }else if(cbot > sbot){
+            //Roo.log("set scrolltop to cbot-ch");
             c.scrollTop = cbot-ch;
         }
-
+        
         if(hscroll !== false){
             if(cleft < sleft){
                 c.scrollLeft = cleft;
@@ -47709,6 +47981,7 @@ Roo.extend(Roo.grid.GridView, Roo.grid.AbstractGridView, {
                 c.scrollLeft = cright-c.clientWidth;
             }
         }
+         
         return el;
     },
 
@@ -47755,7 +48028,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;
@@ -47870,6 +48143,7 @@ Roo.extend(Roo.grid.GridView, Roo.grid.AbstractGridView, {
     },
 
     getScrollState : function(){
+        
         var sb = this.scroller.dom;
         return {left: sb.scrollLeft, top: sb.scrollTop};
     },
@@ -47901,6 +48175,7 @@ Roo.extend(Roo.grid.GridView, Roo.grid.AbstractGridView, {
     },
 
     restoreScroll : function(state){
+        //Roo.log('GridView.restoreScroll');
         var sb = this.scroller.dom;
         sb.scrollLeft = state.left;
         sb.scrollTop = state.top;
@@ -47908,6 +48183,7 @@ Roo.extend(Roo.grid.GridView, Roo.grid.AbstractGridView, {
     },
 
     syncScroll : function(){
+        //Roo.log('GridView.syncScroll');
         var sb = this.scroller.dom;
         var sh = this.mainHd.dom;
         var bs = this.mainBody.dom;
@@ -47969,6 +48245,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++){
@@ -47990,14 +48269,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);
@@ -48010,6 +48299,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++){
@@ -48031,14 +48322,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("");
@@ -48253,10 +48554,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));
     },
 
@@ -49177,7 +49478,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;
     },
 
     /**