| 
     
      
      
      From: <ken...@us...> - 2008-10-30 13:38:16
       
   | 
Revision: 817
          http://andro.svn.sourceforge.net/andro/?rev=817&view=rev
Author:   kendowns
Date:     2008-10-30 13:38:07 +0000 (Thu, 30 Oct 2008)
Log Message:
-----------
Two Major Contributions
1) Rudimentary HTML generation routines that mimic the PHP-side androHTML and its ilk.  Not intended for full-blown client-side HTML, intended for simple generation of HTML w/o using document.createElement() (slow) or having to build strings (error prone and ugly).
2) Created all browser-side code for an editable grid based on the "tabDiv" widget.
Modified Paths:
--------------
    trunk/andro/clib/x6.js
Modified: trunk/andro/clib/x6.js
===================================================================
--- trunk/andro/clib/x6.js	2008-10-28 20:59:30 UTC (rev 816)
+++ trunk/andro/clib/x6.js	2008-10-30 13:38:07 UTC (rev 817)
@@ -36,17 +36,8 @@
    on and off by commenting and uncommenting the relevant lines.
    
    # Beanshell: Turn logging off by commenting out lines
-   # NOTICE: THE FIRST AND SECOND LINES HAVE THE STRING LITERAL '* /'
-   #         YOU MUST REMOVE THAT SPACE WHEN YOU RUN THESE
-    SearchAndReplace.setSearchString("/*C* /");
-    SearchAndReplace.setReplaceString("/*C* / //");
-    SearchAndReplace.setBeanShellReplace(false);
-    SearchAndReplace.setIgnoreCase(true);
-    SearchAndReplace.setRegexp(false);
-    SearchAndReplace.setSearchFileSet(new CurrentBufferSet());
-    SearchAndReplace.replaceAll(view);
     SearchAndReplace.setSearchString("//console.");
-    SearchAndReplace.setReplaceString("////console.");
+    SearchAndReplace.setReplaceString("//console.");
     SearchAndReplace.setBeanShellReplace(false);
     SearchAndReplace.setIgnoreCase(true);
     SearchAndReplace.setRegexp(false);
@@ -54,16 +45,7 @@
     SearchAndReplace.replaceAll(view);
 
    # Beanshell: Turn logging on by uncommenting the lines.
-   # NOTICE: THE FIRST AND SECOND LINES HAVE THE STRING LITERAL '* /'
-   #         YOU MUST REMOVE THAT SPACE WHEN YOU RUN THESE
-    SearchAndReplace.setSearchString("/*C* / //");
-    SearchAndReplace.setReplaceString("/*C* /");
-    SearchAndReplace.setBeanShellReplace(false);
-    SearchAndReplace.setIgnoreCase(true);
-    SearchAndReplace.setRegexp(false);
-    SearchAndReplace.setSearchFileSet(new CurrentBufferSet());
-    SearchAndReplace.replaceAll(view);
-    SearchAndReplace.setSearchString("////console.");
+    SearchAndReplace.setSearchString("//console.");
     SearchAndReplace.setReplaceString("//console.");
     SearchAndReplace.setBeanShellReplace(false);
     SearchAndReplace.setIgnoreCase(true);
@@ -71,7 +53,162 @@
     SearchAndReplace.setSearchFileSet(new CurrentBufferSet());
     SearchAndReplace.replaceAll(view);
 \* ================================================================== */
+
+/****O* Javascript-API/jsHtml
+*
+* NAME
+*   Javascript-API.jsHtml
+*
+* FUNCTION
+*   The javascript function jsHtml is a constructor 
+*   function for a new HTML node.  It is considerably
+*   faster and easier than document.createElement() and
+*   node.appendChild.
+*
+*   This function works almost exactly the same way as the
+*   PHP function html(), except that it works in the
+*   browser.
+*
+*   The resulting object is considerably simpler than the
+*   HTML nodes you can create in PHP, and is designed
+*   only for basic tasks.  There are no shortcuts for 
+*   creating complex entities, those must be coded by
+*   hand.
+*
+*   You can pass the innerHTML in as the second parameter,
+*   or you can set it directly by assigning the innerHtml
+*   property of the object.
+*
+* INPUTS
+*   * string - a valid (x)html tag name like 'div' or 'span'
+*   * string - (optional) the value of innerHtml
+*
+* EXAMPLE
+*   Use the Javascript "new" operator with this function.
+*        <script>
+*        var div = new jsHtml('div','Hello, I am a div!');
+*        div.hp.style = 'width: 300px';
+*        var html = div.bufferedRender();
+*        $( -- some jquery selector -- ).append(html);
+*        </script>
+*
+******
+*/
+function jsHtml(tag,innerHtml) {
+    this.tag = tag;
+    this.children = [ ];
+    this.hp = { };
+
+    /****O* jsHtml.innerHtml
+    *
+    * NAME
+    *   jsHtml.innerHtml
+    *
+    * FUNCTION
+    *   The javascript property innerHtml holds the innerHTML
+    *   of an HTML node created by jsHtml().  You can pass in
+    *   the innerHtml as the second parameter to jsHtml, or
+    *   you can set this property directly.
+    *
+    * EXAMPLE
+    *   Use the Javascript "new" operator with this function.
+    *        <script>
+    *        var div = new jsHtml('div');
+    *        div.innerHtml = 'I set this on the 2nd line!';
+    *        var html = div.bufferedRender();
+    *        $( -- some jquery selector -- ).append(html);
+    *        </script>
+    *
+    ******
+    */
+    this.innerHtml = innerHtml ? innerHtml : '';
     
+    /****O* jsHtml.addChild
+    *
+    * NAME
+    *   jsHtml.addChild
+    *
+    * FUNCTION
+    *   The javascript method addChild adds one HTML node as
+    *   a child to another.  Both nodes must have been 
+    *   created by using the jsHtml() constructor function.
+    *
+    * EXAMPLE
+    *   Use the Javascript "new" operator with this function.
+    *        <script>
+    *        var div = new jsHtml('div');
+    *        var span = new jsHtml('span','A span in a div!');
+    *        div.addChild(span);
+    *        var html = div.bufferedRender();
+    *        $( -- some jquery selector -- ).append(html);
+    *        </script>
+    *
+    ******
+    */
+    this.addChild = function(child) {
+        this.children.push(child);
+    }
+    /******/
+
+    /****O* jsHtml.h
+    *
+    * NAME
+    *   jsHtml.h
+    *
+    * FUNCTION
+    *   The javascript method h creates a new HTML node and
+    *   makes it a child of the current node.  This is a 
+    *   shortcut for having to call jsHtml and then
+    *   addChild.
+    *
+    * EXAMPLE
+    *   Use the Javascript "new" operator with this function.
+    *        <script>
+    *        var div = new jsHtml('div');
+    *        var span = div.h('span','Hello!');
+    *        var html = div.bufferedRender();
+    *        $( -- some jquery selector -- ).append(html);
+    *        </script>
+    *
+    ******
+    */
+    this.h = function(tag,innerHtml) {
+        var newNode = new jsHtml(tag,innerHtml);
+        this.addChild(newNode);
+        return newNode;
+    }
+    /******/
+
+    /****O* jsHtml.bufferedRender
+    *
+    * NAME
+    *   jsHtml.bufferedRender
+    *
+    * FUNCTION
+    *   The javascript method bufferedRender returns a string
+    *   of HTML for a node created with jsHtml.  It sets all
+    *   properties, and recursively runs through all children.
+    *   The innerHtml, if it is present, goes out last.
+    *
+    * SOURCE
+    */
+    this.bufferedRender = function() {
+        var html = '<' + this.tag;
+        for(var attName in this.hp) {
+            html+=' '+attName+'="'+this.hp[attName]+'"';
+        }
+        html+=">";
+        for(var idx in this.children) {
+            html+=this.children[idx].bufferedRender();
+        }
+        html+=this.innerHtml;
+        html+='</'+this.tag+'>';
+        return html;
+    }
+    /******/
+
+}
+
     
 /****O* Javascript-API/x6events
 *
@@ -151,7 +288,7 @@
     * SOURCE
     */
     subscribeToEvent: function(eventName,id) {
-        /*C*/ // var ux=u.uniqueId(); //console.group("subscribeToEvent "+ux);
+        //console.group("subscribeToEvent "+eventName);
         //console.log("event name: ",eventName)
         //console.log("id subscbr: ",id);
         if(id=='undefined') {
@@ -173,7 +310,7 @@
             this.subscribers[eventName] = [ ];
         }
         this.subscribers[eventName].push(id);
-        /*C*/ // //console.groupEnd("subscribeToEvent "+ux);
+        //console.groupEnd();
     },
     /******/
         
@@ -229,7 +366,7 @@
     */
     retvals: { },
     fireEvent: function(eventName,arguments) {
-        /*C*/ // var ux=u.uniqueId(); //console.group("fireEvent "+eventName+' '+ux);
+        //console.group("fireEvent "+eventName);
         //console.log('arguments: ',arguments);
         // Find out if anybody is listening for this event
         var subscribers = this.getSubscribers(eventName);
@@ -261,7 +398,7 @@
             }
         }
         //console.log("RETURNING: ",this.retvals[eventName]);
-        /*C*/ // //console.groupEnd("fireEvent "+ux);
+        //console.groupEnd();
         return this.retvals[eventName];
     }
 }
@@ -284,7 +421,7 @@
     // DOM elements with property x6plugIn=xxx.  
     // Invoke the constructor for each one.
     init: function() {
-        //u.debugFlag = true;
+        u.debugFlag = true;
         
         // Job 1: Activate all of the plugins
         for(var plugInId in x6plugins) {
@@ -292,9 +429,8 @@
                     if(u.p(this,'id','')=='') {
                         this.id = u.uniqueId();
                     }
-                    u.debug(
-                        "Initializing object "+this.id+" as plugIn "+plugInId
-                    );
+                    s="Initializing object "+this.id+" as plugIn "+plugInId;
+                    //console.log(s);
                     this.zTable = u.p(this,'x6table');
                     x6plugins[plugInId](this,this.id,u.p(this,'x6table'));
             });
@@ -302,16 +438,19 @@
         
         // Job 2, activate a global keyboard handler
         $(document).keypress(function(e) {
-                u.debug("document.keypress (BEGIN)",1); 
+                //console.group("Document Keypress");
+                //console.log(e); 
                 var retval= x6.keyDispatcher(e);
-                u.debug("document.keypress (END)",-1); 
+                //console.groupEnd(); 
                 return retval;
         });
         
-        // Fade in anybody who has been asked to fade in,
-        // and when finished put focus onto whichever
-        // object has asked for it.
-        $('.fadein').fadeIn('slow',function() { x6.initFocus(); });
+        // We used to fade in here, but that was no good, because
+        // the fade in would occur before any page-specific code
+        // had run, and the user would see things jumping around.
+        // Now the index_hidden x6 dispatcher sends this command
+        // very last, so it is the last thing that happens.
+        //$('.fadein').fadeIn('slow',function() { x6.initFocus(); });
     },
     
     initFocus: function() {
@@ -392,21 +531,21 @@
         var stopThem = [ 'CtrlF5', 'F10' ];
         
         // Now we have a complete key label, fire the event
-        u.debug("In x6.keyDispatch, code and event follow");
-        u.debug(retval);
-        u.debug(e);
+        //console.log("In x6.keyDispatch, code and event follow");
+        //console.log(retval);
+        //console.log(e);
         if(stopThem.indexOf(retval)>0) {
-            u.debug("x6.keyDispatch: key is in force stop list, stopping propagation.");
+            //console.log("x6.keyDispatch: key is in force stop list, stopping propagation.");
             e.stopPropagation();
             return false;
         }
         else if (!x6events.fireEvent('key_'+retval,null)) {
-            u.debug("x6.keyDispatch: handler returned false, stopping propagation.");
+            //console.log("x6.keyDispatch: handler returned false, stopping propagation.");
             e.stopPropagation();
             return false;
         }
         else {
-            u.debug("x6.keyDispatch: handler returned true, continuing propagation.");
+            //console.log("x6.keyDispatch: handler returned true, continuing propagation.");
             return true;
         }
     }    
@@ -418,24 +557,46 @@
    
 \* **************************************************************** */
 var x6inputs = {
+    // This routine takes an input that has no x6 event
+    // handlers and adds all of the event handlers to it
+    initInput: function(input,tabIndex,mode) {
+        //console.group("Initializing Input");
+        //console.log(tabIndex,mode);
+        //console.log(input);
+        $(input)
+            .keyup(function(e)   { x6inputs.keyUp(e,this)   })
+            .keydown(function(e) { x6inputs.keyDown(e,this) })
+            .focus(function(e)   { x6inputs.focus(e,this)   })
+            .blur(function(e)    { x6inputs.blur(e,this)    });
+        input.tabIndex = tabIndex;
+        if(mode=='new') {
+            input.zNew = 1;
+            x6inputs.setClass(input);
+        }
+        //console.groupEnd();
+    },
+    
     // Key up is used to look for changed values because
     // you do not see an input's new value until the keyup 
     // event.  You do not see it in keypress or keydown.
     keyUp: function(e,inp) {
+        //console.group("Input keyUp");
+        //console.log(e);
+        //console.log(inp);
         x6inputs.setClass(inp);
+        //console.groupEnd("Input keyUp");
     },
     
     // Keydown is used only for tab or shift tab, to enforce
     // the concept of a "tab loop".  This function only does
     // anything if there are no enabled controls after the
-    // 
+    // current control
     //
     keyDown: function(e,inp) {
-        //u.debugPush();
-        ////console.log(e);
-        //u.debug(e);
-        //u.debug(inp);
         if(e.keyCode!=9) return true;
+        //console.group("input keyDown handler");
+        //console.log(e);
+        //console.log(inp);
         
         // work out which property to use.
         if(e.shiftKey) { 
@@ -446,8 +607,8 @@
             var prop = 'xNextTab';
             var jqf  = ':first';
         }
-        //u.debug(prop);
-        //u.debug(jqf);
+        //console.log(prop);
+        //console.log(jqf);
         
         // The loop breaks when we find a readable control
         // or get to the end of the list
@@ -458,20 +619,20 @@
             // at beginning
             if( u.p(xinp,prop,'X')=='X') {
                 jqx = '[tabindex]:not([disabled])'+jqf;
-                //u.debug("no control found, string to use: "+jqx);
+                //console.log("no control found, string to use: "+jqx);
                 break;
             }
             
             // Advance to next
             var tabCandidate = u.p(xinp,prop);
             jsq = '[tabindex='+tabCandidate+']';
-            //u.debug('advancing to '+jsq);
+            //console.log('advancing to '+jsq);
             xinp = $(jsq)[0];
             
             // and if the next is not disabled, return TRUE,
             // do NOTHING, and the browser will handle it
             if(u.p(xinp,'disabled',false)==false) {
-                //u.debug("next control is not read only, letting browse do it");
+                //console.log("next control is not read only, letting browse do it");
                 break;
             }
             
@@ -481,17 +642,21 @@
             if(xinp==inp) break;
         }
         if(jqx=='') {
-            //u.debug('not trying to pick focus');
+            //console.log('not trying to pick focus');
         }
         else {
-            //u.debug("trying to pick focus: "+jqx);
+            //console.log("trying to pick focus: "+jqx);
             $(jqx).focus();
         }
         //u.debugPop();
         if(jqx=='') {
+            //console.log("returning TRUE");
+            //console.groupEnd();
             return true;
         }
         else {
+            //console.log("PREVENTING DEFAULT AND RETURNING FALSE");
+            //console.groupEnd();
             e.preventDefault();
             return false;
         }
@@ -514,6 +679,9 @@
     },
     
     setClass: function(inp) {
+        ux = u.uniqueId();
+        //console.group("setClass for an input  "+ux);
+        //console.log(inp);
         if(u.p(inp,'zOriginalValue',null)==null) inp.zOriginalValue = '';
         if(inp.value==inp.zOriginalValue) {
             inp.zChanged = 0;
@@ -537,12 +705,15 @@
         else if(zNew)     css = 'changed';
         else if(zChanged) css = 'changed';
         else              css = '';
+        //console.log("initial class is "+css);
         
         // Now pick the selected version if required
         if(zSelected) css += 'Selected';
+        //console.log("Final class is "+css);
         
         // Now do some stuff if it is read only
         inp.disabled = zRO;
+        //console.log("Read Only Decision is",inp.disabled);
         
         // Flag to do the row
         doRow = u.p(inp,'xClassRow',0);
@@ -555,6 +726,7 @@
         if(doRow && !zSelected) {
             inp.parentNode.parentNode.className = '';
         }
+        //console.groupEnd();
     },
     
     clearOut: function(inp) {
@@ -564,7 +736,12 @@
         inp.value          = '';
         inp.zOriginalValue = '';
         x6inputs.setClass(inp);
+    },
+    
+    findFocus: function(obj) {
+        $(obj).find(":input:first").focus();
     }
+    
 }
 
 
@@ -1209,3 +1386,375 @@
         }
     }
 }
+
+
+/***im* x6plugins/tabDiv
+*
+* NAME
+*   x6plugins.tabDiv
+*
+* FUNCTION
+*   The Javascript method x6plugins.tabDiv implements
+*   all browser-side functionality for Andromeda's built-in
+*   plugIn tabDiv.  A "tabDiv" appears to the user to be an
+*   HTML TABLE but it is implemented with divs.
+*
+*   This routine is called automatically by x6.init, there
+*   is not usually any reason for calling this routine
+*   directly.
+*
+* INPUTS
+*   self - the DOM object to be activated.
+*   id - the ID of the object to be 'activated'.
+*   table - the database table that the tabDiv is handling.
+*
+* RESULTS
+*   no return value.
+*
+******
+*/
+x6plugins.x6tabDiv = function(self,id,table) {
+    // Start out by claiming not to be editing
+    // any particular key.
+    self.zSkey = -1;
+
+    // if grid select is 'inline', we subscribe to
+    // requests to edit rows
+    if(u.p(self,'xGridSelect','')=='inline') {
+        x6events.subscribeToEvent('reqEditRow_'+table,id);
+        self['receiveEvent_reqEditRow_'+table] = function(skey) {
+            /* Quiet return if the clicked the row already being edited */
+            if(skey==this.zSkey) return false;
+            
+            //console.group('reqEditRow',table);
+            var grid = this;
+            
+            /*
+            *   If editing a different row, try to save
+            *   and clear that row first
+            */
+            if(this.zSkey>-1) {
+                var oldSkey = this.zSkey;
+                if(!x6events.fireEvent('reqSaveRow_'+this.zTable)) { 
+                    //console.groupEnd();
+                    return false;
+                }
+                else {
+                    //console.log("removing inputs current row");
+                    this.removeInputs(oldSkey);
+                    this.zSkey==-1;
+                }
+            }
+            
+            // Make sure we have the row, otherwise it is
+            // kind of useless
+            if( $(this).find('#row_'+skey).length == 1) {
+                //console.log("We have the row, we can edit");
+                this.zSkey = skey;
+                this.buttonsOn();
+
+                //console.group("Putting inputs into div cells");                
+                $(this).find('.tbody #row_'+skey+' div').each(
+                    function() {
+                        // Work up to figuring out the name of the
+                        // id that holds the hidden input, then
+                        // grab the input and put it in.
+                        var colnum = u.p(this,'gColumn');
+                        var colid  = grid.zColsInfo[colnum].column_id;
+                        var id = 'wrapper_'+grid.zTable+'_'+colid;
+
+                        // Current Value
+                        var curval = this.innerHTML;
+                        //console.log(id,curval);
+                        
+                        this.innerHTML = u.byId(id).innerHTML;
+                        $(this).find(":input")[0].value=curval;
+                        //console.log(this.innerHTML);
+                    }
+                );
+                //console.groupEnd();
+            }
+            
+            //console.groupEnd();
+        }
+    }
+
+    // if grid is editable, xGridReqNew will be set to
+    // 'inline', which means new lines are added directly
+    // to the grid.
+    if(u.p(self,'xGridReqNew','')=='inline') {
+        x6events.subscribeToEvent('reqNewRow_'+table,id);
+        
+        self['receiveEvent_reqNewRow_'+table] = function(skey) {
+            //console.group("reqNewLine "+this.zTable);
+            //console.log('Table: '+this.zTable);
+            
+            /*
+            * If editing a new row, we will try to save it.
+            * If successful, quietly continue.  If it happens
+            * to be all empty, just focus on the row. 
+            */
+            if(this.zSkey>-1) {
+                if(!x6events.fireEvent('reqSaveRow_'+this.zTable)) {
+                    //console.log('Failed to save new row, no new new row');
+                    //console.groupEnd();
+                    x6inputs.findFocus( $(this).find("#row_0") );
+                    return true;
+                }
+            }
+
+            // We are going to make a new row.  Right now it will
+            // go at the top of div.thead, but later it has to
+            // be smarter and go in after the selected row, if any.
+            var newRow = new jsHtml('div');
+            newRow.hp.id = 'row_0';
+            newRow.hp.style = 'display: none;';
+            var numbers = [ 'int', 'numb', 'money' ];
+            //console.log(newRow);
+            for (var idx in this.zColsInfo) {
+                var colInfo = this.zColsInfo[idx];
+                if(colInfo.column_id == '') continue;
+                
+                var innerDiv = newRow.h('div');
+                innerDiv.hp.style= "width: "+colInfo.width+"px;";
+                if(numbers.indexOf(colInfo.type_id)>=0) {
+                    innerDiv.hp.style+="text-align: right";
+                }
+                var id = '#wrapper_'+this.zTable+'_'+colInfo.column_id;
+                var newInput = $(id).html();
+                //console.log("column: ",colInfo.column_id,newInput);
+                innerDiv.innerHtml = newInput;
+            }
+            //console.log(newRow);
+            // Add this new row into the visuals so it is real
+            $(this).find('.tbody').prepend(newRow.bufferedRender());
+            // Initialize all inputs to behave in x6 mode
+            tabIndex = 1000;
+            $(this).find(':input').each(
+                function() { x6inputs.initInput(this,tabIndex++,'new'); }
+            );
+            $(this).find('#row_0').fadeIn('fast'
+                ,function() { x6inputs.findFocus( this ) }
+            );
+            
+            // This warns downstream code that we are working
+            // on a new row.
+            this.zSkey = 0;
+            
+            // Turn on buttons
+            this.buttonsOn();
+            
+            // Send a message and get lost
+            //console.log('New row created, ready to edit');
+            //console.groupEnd();
+            return true;
+        }
+    }
+
+    // If grid allows either kind of inline row, it must
+    // must accept an abandon request and throw out the row
+    var xSelect = u.p(self,'xGridSelect','');
+    var xReqNew = u.p(self,'xGridReqNew','');
+    if(xSelect == 'inline' || xReqNew == 'inline') {
+        x6events.subscribeToEvent('cancelEdit_'+table,id);
+        
+        self['receiveEvent_cancelEdit_'+table] = function(skey) {
+            if(this.zSkey==-1) return false;
+
+            //console.group("Abandon: cancelEdit "+this.zTable);
+            if(this.zSkey==0) {
+                //console.log("Abandoning new row");
+                this.zSkey = -1;
+                this.buttonsOff();
+                $(this).find("#row_0").fadeOut('fast'
+                    ,function() { $(this).remove(); }
+                );
+            }
+            
+            if(this.zSkey>0) {
+                
+            }
+            
+            //console.groupEnd();
+        }
+    }
+
+    // An explicit flag set in the PHP side determines
+    // if we accept delete requests
+    if(u.p(self,'xGridReqDel','N')=='Y') {
+        x6events.subscribeToEvent('reqDelRow_'+table,id);
+        
+        self['receiveEvent_reqDelRow_'+table] = function() {
+            //console.group("reqDelRow "+table);
+            if(this.zSkey==-1) {
+                //console.log("No row, ignoring");
+                //console.groupEnd();
+                alert("Please select a row first");
+                return;
+            }
+            else if(this.zSkey==0) {
+                //console.log("on a new row, firing cancelEdit command");
+                x6events.fireEvent('cancelEdit_'+this.zTable);
+            }
+            else {
+                if(confirm("Delete the selected row?")) {
+                    //console.log("asking server to delete");
+                    ua.json.init('x6page',this.zTable);
+                    ua.json.addParm('x6action','delete');
+                    ua.json.addParm('skey',this.zSkey);
+                    if(!ua.json.execute()) {
+                        //console.log("server refused to delete");
+                    }
+                    else {
+                        //console.log("server did the delete");
+                        $(this).find('#row_'+this.zSkey).fadeOut(
+                            function() { $(this).remove(); }
+                        );
+                        this.zSkey = -1;
+                        this.buttonsOff();
+                    }
+                }
+            }
+            //console.groupEnd();
+        }
+    }
+    
+    // If grid allows either kind of inline row, it must
+    // must accept a save request as well
+    if(xSelect == 'inline' || xReqNew == 'inline') {
+        x6events.subscribeToEvent('reqSaveRow_'+table,id);
+        
+        self['receiveEvent_reqSaveRow_'+table] = function() {
+            /* never should get here if zskey=-1 */
+            if(this.zSkey==-1) return false;
+
+            //console.group("Request, Save Row "+this.zTable);
+            
+            var allInputs = '';
+            $(this).find("#row_"+this.zSkey+" :input").each(
+                function() {
+                    allInputs += this.value.trim();
+                }
+            );
+            if( allInputs=='') {
+                //console.log("Current row is empty, no save");
+                if(this.zSkey==0) {
+                    //console.log("New Row, firing cancelEdit, returning TRUE");
+                    x6events.fireEvent('cancelEdit_'+this.zTable);
+                    //console.groupEnd()
+                    return true;
+                }
+                else {
+                    //console.log("Must remain on row, returning FALSE");
+                    //console.groupEnd()
+                    return false;
+                }
+            }
+
+            /* Row is not empty, continue with save */            
+            ua.json.init('x6page',this.zTable);
+            ua.json.addParm('x6action','save');
+            ua.json.addParm('x4v_skey',this.zSkey);
+            ua.json.inputs(this);
+            if(!ua.json.execute()) {
+                //console.log("Errors on save, returning FALSE");
+                //console.groupEnd();
+                return false;
+            }
+            else {
+                // If returned ok, we have a new skey
+                //console.log("Row saved OK");
+                ua.json.process();
+                var row = $a.data.row;
+                var skey = row.skey; 
+
+                // Replace the input values with server returned values
+                $(this).find("#row_"+this.zSkey+" div").each(
+                    function() {
+                        col = u.p($(this).find(":input")[0],'xColumnId');
+                        //console.log(col,row[col]);
+                        this.innerHTML = row[col];
+                    }
+                );
+                
+                // If this was a new row, set it up 
+                if(this.zSkey==0) {
+                    $(this).find("#row_0").each(
+                        function() {
+                            this.id = 'row_'+$a.data.row.skey;
+                        }
+                    );
+                
+                    // PHP-JAVASCRIPT DUPLICATION ALERT!
+                    // This code also exists in androLib.php
+                    // addRow method of the tabDiv class
+                    var table = this.zTable;
+                    if (u.p(this,'xgridhilight')=='Y') {
+                        $(this).find('#row_'+$a.data.row.skey)
+                            .mouseover(
+                                function() {
+                                    $(this).addClass('hilight')
+                                }
+                            )
+                            .mouseout( 
+                                function() {
+                                    $(this).removeClass('hilight')
+                                }
+                            )
+                            .click(
+                                function() {
+                                    x6events.fireEvent(
+                                        'reqEditRow_'+table,this.id
+                                    );
+                                }
+                            );
+                    }
+                }
+               
+                
+                // Tell downstream code we are not editing a row
+                this.zSkey = -1;
+                this.buttonsOff();
+            }
+            //console.groupEnd();
+            return true;
+        }
+    }
+
+
+    /*
+    *   Routine to remove inputs from a given row and replace
+    *   them with the values of the inputs
+    */
+    self.removeInputs = function(skey) {
+        //console.group("Removing Inputs");
+        //console.log("Row sk...
 
[truncated message content] | 
| 
     
      
      
      From: <ken...@us...> - 2008-10-31 12:51:42
       
   | 
Revision: 831
          http://andro.svn.sourceforge.net/andro/?rev=831&view=rev
Author:   kendowns
Date:     2008-10-31 12:51:39 +0000 (Fri, 31 Oct 2008)
Log Message:
-----------
Modified Paths:
--------------
    trunk/andro/clib/x6.js
Modified: trunk/andro/clib/x6.js
===================================================================
--- trunk/andro/clib/x6.js	2008-10-31 12:48:30 UTC (rev 830)
+++ trunk/andro/clib/x6.js	2008-10-31 12:51:39 UTC (rev 831)
@@ -99,7 +99,7 @@
     this.children = [ ];
     this.hp = { };
 
-    /****O* jsHtml.innerHtml
+    /****O* jsHtml/innerHtml
     *
     * NAME
     *   jsHtml.innerHtml
@@ -123,7 +123,7 @@
     */
     this.innerHtml = innerHtml ? innerHtml : '';
     
-    /****O* jsHtml.addChild
+    /****O* jsHtml/addChild
     *
     * NAME
     *   jsHtml.addChild
@@ -150,7 +150,7 @@
     }
     /******/
 
-    /****O* jsHtml.h
+    /****O* jsHtml/h
     *
     * NAME
     *   jsHtml.h
@@ -179,7 +179,7 @@
     }
     /******/
 
-    /****O* jsHtml.bufferedRender
+    /****O* jsHtml/bufferedRender
     *
     * NAME
     *   jsHtml.bufferedRender
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
 | 
| 
     
      
      
      From: <ken...@us...> - 2008-10-31 18:12:39
       
   | 
Revision: 840
          http://andro.svn.sourceforge.net/andro/?rev=840&view=rev
Author:   kendowns
Date:     2008-10-31 18:12:36 +0000 (Fri, 31 Oct 2008)
Log Message:
-----------
Ongoing cleanup
Modified Paths:
--------------
    trunk/andro/clib/x6.js
Modified: trunk/andro/clib/x6.js
===================================================================
--- trunk/andro/clib/x6.js	2008-10-31 18:12:08 UTC (rev 839)
+++ trunk/andro/clib/x6.js	2008-10-31 18:12:36 UTC (rev 840)
@@ -565,9 +565,9 @@
         //console.log(input);
         $(input)
             .keyup(function(e)   { x6inputs.keyUp(e,this)   })
-            .keydown(function(e) { x6inputs.keyDown(e,this) })
             .focus(function(e)   { x6inputs.focus(e,this)   })
-            .blur(function(e)    { x6inputs.blur(e,this)    });
+            .blur(function(e)    { x6inputs.blur(e,this)    })
+            .keydown(function(e) { x6inputs.keyDown(e,this) });
         input.tabIndex = tabIndex;
         if(mode=='new') {
             input.zNew = 1;
@@ -598,68 +598,40 @@
         //console.log(e);
         //console.log(inp);
         
-        // work out which property to use.
+        var tg = u.p(inp,'xTabGroup','tgdefault');
+        //console.log("Tab Group",tg);
+        
         if(e.shiftKey) { 
-            var prop = 'xPrevTab';
-            var jqf  = ':last';
+            // hitting shift-tab on the first control means
+            // jump back to the last control
+            var first = $('[xTabGroup='+tg+']:not([disabled]):first')[0];
+            //console.log("The first is:");
+            //console.log(first);
+            //console.log("The input is:");
+            //console.log(inp);
+            if(first==inp) {
+                //console.log("This is first, jumping to last");
+                $('[xTabGroup='+tg+']:not([disabled]):last').focus();
+                e.preventDefault();
+            }
         }
         else {
-            var prop = 'xNextTab';
-            var jqf  = ':first';
-        }
-        //console.log(prop);
-        //console.log(jqf);
-        
-        // The loop breaks when we find a readable control
-        // or get to the end of the list
-        var xinp = inp;
-        var jqx  = '';
-        while(true) {
-            // Current control has no next tab, start over
-            // at beginning
-            if( u.p(xinp,prop,'X')=='X') {
-                jqx = '[tabindex]:not([disabled])'+jqf;
-                //console.log("no control found, string to use: "+jqx);
-                break;
+            // hitting tab on the last control is the only
+            // thing I care about.  If I'm not on the last
+            // control, let the browser do it, much faster.
+            var last = $('[xTabGroup='+tg+']:not([disabled]):last')[0];
+            //console.log("The last is:");
+            //console.log(last);
+            //console.log("The input is:");
+            //console.log(inp);
+            if(last==inp) {
+                //console.log("This is last, jumping to first");
+                $('[xTabGroup='+tg+']:not([disabled]):first').focus();
+                e.preventDefault();
             }
-            
-            // Advance to next
-            var tabCandidate = u.p(xinp,prop);
-            jsq = '[tabindex='+tabCandidate+']';
-            //console.log('advancing to '+jsq);
-            xinp = $(jsq)[0];
-            
-            // and if the next is not disabled, return TRUE,
-            // do NOTHING, and the browser will handle it
-            if(u.p(xinp,'disabled',false)==false) {
-                //console.log("next control is not read only, letting browse do it");
-                break;
-            }
-            
-            // if we get around to the original input, something
-            // is wrong, cancel also so we don't have an 
-            // infinite loop
-            if(xinp==inp) break;
         }
-        if(jqx=='') {
-            //console.log('not trying to pick focus');
-        }
-        else {
-            //console.log("trying to pick focus: "+jqx);
-            $(jqx).focus();
-        }
-        //u.debugPop();
-        if(jqx=='') {
-            //console.log("returning TRUE");
-            //console.groupEnd();
-            return true;
-        }
-        else {
-            //console.log("PREVENTING DEFAULT AND RETURNING FALSE");
-            //console.groupEnd();
-            e.preventDefault();
-            return false;
-        }
+        //console.groupEnd();
+        return;
     },
     
     focus: function(inp) {
@@ -1472,6 +1444,13 @@
                         //console.log(this.innerHTML);
                     }
                 );
+                tabIndex = 1000;
+                $(this).find('.tbody #row_'+skey+' :input').each(
+                    function() {
+                        x6inputs.initInput(this,tabIndex++,'new'); 
+                        this.setAttribute('xTabGroup','rowEdit');
+                    }
+                );
                 //console.groupEnd();
             }
             
@@ -1486,7 +1465,7 @@
         x6events.subscribeToEvent('reqNewRow_'+table,id);
         
         self['receiveEvent_reqNewRow_'+table] = function(skey) {
-            //console.group("reqNewLine "+this.zTable);
+            //console.group("reqNewRow "+this.zTable);
             //console.log('Table: '+this.zTable);
             
             /*
@@ -1495,6 +1474,10 @@
             * to be all empty, just focus on the row. 
             */
             if(this.zSkey>-1) {
+                /* special case, empty new row, just focus */
+                if(this.zSkey == 0) {
+                    
+                }
                 if(!x6events.fireEvent('reqSaveRow_'+this.zTable)) {
                     //console.log('Failed to save new row, no new new row');
                     //console.groupEnd();
@@ -1531,7 +1514,10 @@
             // Initialize all inputs to behave in x6 mode
             tabIndex = 1000;
             $(this).find(':input').each(
-                function() { x6inputs.initInput(this,tabIndex++,'new'); }
+                function() { 
+                    x6inputs.initInput(this,tabIndex++,'new'); 
+                    this.setAttribute('xTabGroup','rowEdit');
+                }
             );
             $(this).find('#row_0').fadeIn('fast'
                 ,function() { x6inputs.findFocus( this ) }
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
 | 
| 
     
      
      
      From: <ken...@us...> - 2008-11-03 15:54:16
       
   | 
Revision: 846
          http://andro.svn.sourceforge.net/andro/?rev=846&view=rev
Author:   kendowns
Date:     2008-11-03 15:54:14 +0000 (Mon, 03 Nov 2008)
Log Message:
-----------
Daily changes.
Modified Paths:
--------------
    trunk/andro/clib/x6.js
Modified: trunk/andro/clib/x6.js
===================================================================
--- trunk/andro/clib/x6.js	2008-11-03 15:53:28 UTC (rev 845)
+++ trunk/andro/clib/x6.js	2008-11-03 15:54:14 UTC (rev 846)
@@ -288,9 +288,9 @@
     * SOURCE
     */
     subscribeToEvent: function(eventName,id) {
-        //console.group("subscribeToEvent "+eventName);
-        //console.log("event name: ",eventName)
-        //console.log("id subscbr: ",id);
+        //c*onsole.group("subscribeToEvent "+eventName);
+        //c*onsole.log("event name: ",eventName)
+        //c*onsole.log("id subscbr: ",id);
         if(id=='undefined') {
             u.error('x6events.subscribeToEvent.  Second parameter '
                 +' undefined.  First parameter: '+eventName
@@ -310,7 +310,7 @@
             this.subscribers[eventName] = [ ];
         }
         this.subscribers[eventName].push(id);
-        //console.groupEnd();
+        //c*onsole.groupEnd();
     },
     /******/
         
@@ -397,7 +397,7 @@
                 break;
             }
         }
-        //console.log("RETURNING: ",this.retvals[eventName]);
+        //console.log("fireEvent RETURNING: ",this.retvals[eventName]);
         //console.groupEnd();
         return this.retvals[eventName];
     }
@@ -429,8 +429,8 @@
                     if(u.p(this,'id','')=='') {
                         this.id = u.uniqueId();
                     }
-                    s="Initializing object "+this.id+" as plugIn "+plugInId;
-                    //console.log(s);
+                    //s="Initializing object "+this.id+" as plugIn "+plugInId;
+                    //c*onsole.log(s);
                     this.zTable = u.p(this,'x6table');
                     x6plugins[plugInId](this,this.id,u.p(this,'x6table'));
             });
@@ -559,20 +559,36 @@
 var x6inputs = {
     // This routine takes an input that has no x6 event
     // handlers and adds all of the event handlers to it
-    initInput: function(input,tabIndex,mode) {
+    initInput: function(input,tabIndex,mode,tabGroup) {
         //console.group("Initializing Input");
-        //console.log(tabIndex,mode);
+        //console.log("tabindex, mode, tabgroup: ",tabIndex,mode,tabGroup);
         //console.log(input);
+        
+        // This is standard events and attributes
+        input.setAttribute('xTabGroup',tabGroup);
+        input.setAttribute('tabIndex' ,tabIndex);
+        input.zOriginalValue = input.value.trim();
         $(input)
             .keyup(function(e)   { x6inputs.keyUp(e,this)   })
             .focus(function(e)   { x6inputs.focus(e,this)   })
             .blur(function(e)    { x6inputs.blur(e,this)    })
             .keydown(function(e) { x6inputs.keyDown(e,this) });
-        input.tabIndex = tabIndex;
         if(mode=='new') {
             input.zNew = 1;
             x6inputs.setClass(input);
         }
+        
+        // KFD 11/1/08, EXPERIMENTAL use of jquery.maskedinput
+        //if(u.p(input,'xinputmask','')!='') {
+        //    $(input).mask(u.p(input,'xinputmask'));
+        //}
+
+        // This is important, it says that this is an 
+        // active input.  This distinguishes it from possible
+        // hidden inputs that were used as a clone source 
+        // that have many of the same properties.
+        input.zActive = 1;
+
         //console.groupEnd();
     },
     
@@ -711,9 +727,17 @@
     },
     
     findFocus: function(obj) {
-        $(obj).find(":input:first").focus();
+        if(typeof(obj)=='string') {
+            $(obj+" :input:first:not([disabled])").focus();
+        }
+        else {
+            $(obj).find(":input:first:not([disabled])").focus();
+        }
+    },
+    
+    jqFocusString: function() {
+        return ":input:not([disabled]):first";
     }
-    
 }
 
 
@@ -759,7 +783,7 @@
         x6plugins.buttonStandard(self,'abandon','CtrlT');
         self.main = function() {
             if(confirm("Abandon all changes?")) {
-                x6events.fireEvent('cancelEdit_'+this.zTable);
+                x6events.fireEvent('reqUndoRow_'+this.zTable);
             }
         }
     },
@@ -918,94 +942,229 @@
     */
     tableController: function(self,id,table) {
         // Initialize new properties
-        self.zSkey    = -1;
+        u.bb.vgfSet('skey_'+table,-1);
         self.zSortCol = false;
         self.zSortAsc = false;
         
-        // Table Controller will cache rows if offered
+        /*
+        *   Table controller will be happy to cache
+        *   rows for a table if they are offered. It
+        *   will also be happy to add a row to that
+        *   cache if offered.  There ought also to be
+        *   something here to remove a row, but that
+        *   seems to be missing?
+        *
+        *   Note: shouldn't that be cacheAddRow ?
+        *   Note: and then wouldn't we want cacheDelRow?
+        */
         x6events.subscribeToEvent('cacheRows_'+table,id);
         self['receiveEvent_cacheRows_'+table] = function(rows) {
             this.zRows = rows;
         }
-        // Table Controller will add a row to cache if offered
         x6events.subscribeToEvent('addRow_'+table,id);
         self['receiveEvent_addRow_'+table] = function(row) {
             this.zRows[row.skey] = row;
         }
+
+        /*
+        *   Table controller accepts the request to
+        *   save current changes.  First checks if this
+        *   makes sense.
+        *   
+        */
+        x6events.subscribeToEvent('reqSaveRow_'+table,id);
+        self['receiveEvent_reqSaveRow_'+table] = function(dupe) {
+            //console.group("tableController reqSaveRow "+this.zTable);
+            
+            var result = this.saveOk();
+            u.bb.vgfSet('lastSave_'+this.zTable,result);
+            if(result!='fail') {
+                if(result!='noaction') {
+                    x6events.fireEvent('uiRowSaved_'+table,$a.data.row);
+                }
+            }
+            //console.log('tableController reqSaveRow finished');
+            //console.groupEnd();
+        }
         
-        // Handle a new row by generating defaults and telling
-        // anybody who cares to display this row in this mode
+        
+        /*
+        *   Table controller accepts the request to
+        *   begin editing a new row.  It must first 
+        *   work out if any open rows being edited must
+        *   be saved.  If everything works out it 
+        *   broadcasts a UI notification that UI elements
+        *   should display their inputs in NEW mode.
+        *   
+        */
         x6events.subscribeToEvent('reqNewRow_'    +table,id);
-        self['receiveEvent_reqNewRow_'+table] = function(dupeCurrent) {
-            if( x6events.fireEvent('attemptChangeMode_'+u.p(this,'x6table'))) {
-                if(dupeCurrent && this.zSkey >0) {
-                    var row = this.zRows[this.zSkey];
+        self['receiveEvent_reqNewRow_'+table] = function(dupe) {
+            //console.group("tableController reqNewRow "+this.zTable);
+            
+            var result = this.saveOk();
+            u.bb.vgfSet('lastSave_'+this.zTable,result);
+            if(result!='fail') {
+                if(result!='noaction') {
+                    x6events.fireEvent('uiRowSaved_'+table,$a.data.row);
                 }
-                else {
-                    var row = { }
-                }
-                var argsObj = {
-                    mode: 'new',
-                    row: row
-                };
-                x6events.fireEvent('goMode_'+u.p(this,'x6table'),argsObj);
-                this.zSkey=0;
+                x6events.fireEvent('uiNewRow_'+table);
             }
+            //console.groupEnd();
         }
 
-        // table controller responds to request to edit a 
-        // particular row.
-        x6events.subscribeToEvent('reqEditRow_'   +table,id);
+        /*
+        *   Table controller accepts a request to edit a 
+        *   row.  It is smart enough that if we are already
+        *   editing that row it does nothing.  Otherwise
+        *   it tries to save any existing row before 
+        *   deciding whether to move on.
+        *   
+        */
+        x6events.subscribeToEvent('reqEditRow_'+table,id);
         self['receiveEvent_reqEditRow_'+table] = function(skey) {
-            if( x6events.fireEvent('attemptChangeMode_'+u.p(this,'x6table'))) {
-                var argsObj = {
-                    mode: 'edit',
-                    row: this.zRows[skey]
-                };
-                x6events.fireEvent('goMode_'+u.p(this,'x6table'),argsObj);
-                this.zSkey = skey;
+            //console.group("tableController reqEditRow "+this.zTable);
+            var skeynow = u.bb.vgfGet('skey_'+this.zTable);
+            if(skeynow == skey) {
+                //console.log("Request to edit same row, no action");
+            } 
+            else {
+                var result = this.saveOk();
+                u.bb.vgfSet('lastSave_'+this.zTable,result);
+                if(result!='fail') {
+                    if(result!='noaction') {
+                        x6events.fireEvent('uiRowSaved_'+table,$a.data.row);
+                    }
+                    x6events.fireEvent('uiEditRow_'+table,skey);
+                }
             }
+            //console.log("tableController reqEditRow finished");
+            //console.groupEnd();
+            return true;
         }
         
-        // table controller responds to an abandon event
-        x6events.subscribeToEvent('cancelEdit_'+table,id);
-        self['receiveEvent_cancelEdit_'+table] = function() {
-            // If we were on a new row, abandon it.  Otherwise
-            // take no action
-            if(this.zSkey==0) this.zSkey = -1;
+        /*
+        *   The saveOk figures out if it needs to save and
+        *   tries to do so.  If no active fields have changed,
+        *   it just returns 'noaction'.  If it needs to save,
+        *   it attempts to do so and returns 'success' or
+        *   'fail'.
+        */
+        self.saveOk = function() {
+            //console.group("tableController saveOK");
+            var inpAll = { };
+            var inpChg = { };
+            var cntChg = 0;
+            var jq = ':input[xtableid='+this.zTable+'][zActive]';
+            //console.log("Query string",jq);
+            $(this).find(jq).each(
+                function() {
+                    var col = u.p(this,'xcolumnid');
+                    inpAll[col] = this.value;
+                    var oval = u.p(this,'zOriginalValue','').trim();
+                    if(this.value.trim()!= oval) {
+                        inpChg[col] = this.value.trim();
+                        cntChg++;
+                    }
+                }
+            );
+            //console.log("All inputs: ",inpAll);
+            //console.log("Changed inputs: ",inpChg);
+            //console.log("Count of changes: ",cntChg);
+            
+            // Only attempt a save if something changed
+            if(cntChg == 0) {
+                //console.log("no changes, not trying to save");
+                var retval = 'noaction';
+            }
+            else {
+                //console.log("attempting database save");
+                //console.log("Sending x4v_skey ",this.zSkey);
+                ua.json.init('x6page',this.zTable);
+                ua.json.addParm('x6action','save');
+                ua.json.addParm('x4v_skey',u.bb.vgfGet('skey_'+this.zTable));
+                ua.json.inputs(jq);
+                if(ua.json.execute()) {
+                    var retval = 'success';
+                    ua.json.process();
+                }
+                else {
+                    var retval = 'fail';
+                    var errors = [ ];
+                    for(var idx in ua.json.jdata.error) {
+                        if(ua.json.jdata.error[idx].slice(0,8)!='(ADMIN):') {
+                            errors.push(ua.json.jdata.error[idx]);
+                        }
+                    }
+                    //console.log("save failed, here are errors");
+                    //console.log(errors);
+                    x6events.fireEvent('uiShowErrors_'+this.zTable,errors);
+                }
+            }
+            
+            //console.log("tableController saveOK RETURNING: ",retval);
+            //console.groupEnd();
+            return retval;
+        };
+
+
+        /*
+        *   The table controller accepts requests to undo
+        *   changes to a row.  It actually rolls back all
+        *   inputs and sets their classes, and then
+        *   fires of a uiUndoRow event so various other
+        *   elements can do their own thing.
+        */
+        x6events.subscribeToEvent('reqUndoRow_'+table,id);
+        self['receiveEvent_reqUndoRow_'+table] = function() {
+            //console.group("tableController reqUndoRow");
+            var skey = u.bb.vgfGet('skey_'+table);
+            if(skey>=0) {
+                //console.log("Skey is >= 0, continuing ",skey);
+                $(this).find(":input:not([disabled])[zActive]").each( 
+                    function() {
+                        this.value = this.zOriginalValue;
+                        this.zError = 0;
+                        x6inputs.setClass(this);
+                    }
+                );
+                x6events.fireEvent('uiUndoRow_'+this.zTable);
+            }
+            //console.log("tableController reqUndoRow Finished");
+            //console.groupEnd();
+            return true;
         }
         
 
+        /*
+        *   The table controller accepts delete request
+        *   and asks the database to do the delete.  If
+        *   this is successful, it tells any UI subscribers
+        *   to update their displays accordingly.
+        */
         x6events.subscribeToEvent('reqDelRow_'    +table,id);
         self['receiveEvent_reqDelRow_'+table] = function() {
-            if(this.zSkey==-1) {
-                alert("Please click on a row first, then click [DELETE]");
-                return false;
+            //console.group("tableController reqDelRow ",this.zTable);
+            var skey = u.bb.vgfGet('skey_'+this.zTable);
+            if(this.zSkey<1) {
+                //console.log("nothing being edited, quietly ignoring");
             }
-            var table = u.p(this,'x6table');
-            ua.json.init('x6page',table);
-            ua.json.addParm('x6action','delete');
-            ua.json.addParm('skey',this.zSkey);
-            ua.json.addParm('json',1);
-            if(ua.json.execute()) {
-                // Remove from cache
-                if(typeof(this.zRows[this.zSkey])!='undefined') {
-                    delete this.zRows[this.zSkey];
+            else {
+                if(confirm("Delete current row?")) {
+                    //console.log("sending delete to server");
+                    ua.json.init('x6page',this.zTable);
+                    ua.json.addParm('x6action','delete');
+                    ua.json.addParm('skey',skey);
+                    ua.json.addParm('json',1);
+                    if(ua.json.execute()) {
+                        x6events.fireEvent('uiDelRow_'+table,skey);
+                    }
                 }
-                
-                // Tell everybody else to get rid of it
-                x6events.fireEvent('delRow_'+table,this.zSkey);
-                this.skey = -1;
             }
-            return;
+            //console.log("tableController reqDelRow finished");
+            //console.groupEnd();
+            return true;
         }
         
-        x6events.subscribeToEvent('rowChanged_'+table,id);
-        self['receiveEvent_rowChanged_'+table] = function(row) {
-            var skey = row.skey;
-            this.zRows[skey] = row;
-        }
-
         // Sort requests are sorted out here.        
         x6events.subscribeToEvent('reqSort_'+table,id);
         self['receiveEvent_reqSort_'+table] = function(args) {
@@ -1386,345 +1545,326 @@
 ******
 */
 x6plugins.x6tabDiv = function(self,id,table) {
-    // Start out by claiming not to be editing
-    // any particular key.
-    self.zSkey = -1;
-
-    // if grid select is 'inline', we subscribe to
-    // requests to edit rows
-    if(u.p(self,'xGridSelect','')=='inline') {
-        x6events.subscribeToEvent('reqEditRow_'+table,id);
-        self['receiveEvent_reqEditRow_'+table] = function(skey) {
-            /* Quiet return if the clicked the row already being edited */
-            if(skey==this.zSkey) return false;
+    /*
+    *    These two will tell us down below if the grid
+    *    displays inputs for new rows and allows 
+    *    inline editing of rows
+    */
+    var uiNewRow  = u.p(self,'uiNewRow' ,'');
+    var uiEditRow = u.p(self,'uiEditRow','');
+    
+    /*
+    *   The grid is happy to display a new row for
+    *   editing if a certain flag has been set.
+    *   The event uiNewRow is unconditional, it means
+    *   all prerequisites have been met and the grid
+    *   should proceed forthwith.
+    */
+    if(uiNewRow=='inline') {
+        x6events.subscribeToEvent('uiNewRow_'+table,id);
+        
+        self['receiveEvent_uiNewRow_'+table] = function() {
+            //console.group("tabDiv uiNewRow "+this.zTable);
+            var skey = u.bb.vgfGet('skey_'+this.zTable,-1);
             
-            //console.group('reqEditRow',table);
-            var grid = this;
-            
             /*
-            *   If editing a different row, try to save
-            *   and clear that row first
+            *   If we are currently editing a new row, just
+            *   focus on it.
             */
-            if(this.zSkey>-1) {
-                var oldSkey = this.zSkey;
-                if(!x6events.fireEvent('reqSaveRow_'+this.zTable)) { 
-                    //console.groupEnd();
-                    return false;
-                }
-                else {
-                    //console.log("removing inputs current row");
-                    this.removeInputs(oldSkey);
-                    this.zSkey==-1;
-                }
-            }
-            
-            // Make sure we have the row, otherwise it is
-            // kind of useless
-            if( $(this).find('#row_'+skey).length == 1) {
-                //console.log("We have the row, we can edit");
-                this.zSkey = skey;
-                this.buttonsOn();
-
-                //console.group("Putting inputs into div cells");                
-                $(this).find('.tbody #row_'+skey+' div').each(
-                    function() {
-                        // Work up to figuring out the name of the
-                        // id that holds the hidden input, then
-                        // grab the input and put it in.
-                        var colnum = u.p(this,'gColumn');
-                        var colid  = grid.zColsInfo[colnum].column_id;
-                        var id = 'wrapper_'+grid.zTable+'_'+colid;
-
-                        // Current Value
-                        var curval = this.innerHTML;
-                        //console.log(id,curval);
-                        
-                        this.innerHTML = u.byId(id).innerHTML;
-                        $(this).find(":input")[0].value=curval;
-                        //console.log(this.innerHTML);
-                    }
-                );
-                tabIndex = 1000;
-                $(this).find('.tbody #row_'+skey+' :input').each(
-                    function() {
-                        x6inputs.initInput(this,tabIndex++,'new'); 
-                        this.setAttribute('xTabGroup','rowEdit');
-                    }
-                );
+            if(skey==0 && u.bb.vgfGet('lastSave_'+this.zTable)=='noaction') {
+                $(this).find("#row_0 :input:first:not([disabled])").focus();
+                //console.log("On an empty new row, setting focus");
                 //console.groupEnd();
+                return;
             }
             
-            //console.groupEnd();
-        }
-    }
-
-    // if grid is editable, xGridReqNew will be set to
-    // 'inline', which means new lines are added directly
-    // to the grid.
-    if(u.p(self,'xGridReqNew','')=='inline') {
-        x6events.subscribeToEvent('reqNewRow_'+table,id);
-        
-        self['receiveEvent_reqNewRow_'+table] = function(skey) {
-            //console.group("reqNewRow "+this.zTable);
-            //console.log('Table: '+this.zTable);
-            
             /*
-            * If editing a new row, we will try to save it.
-            * If successful, quietly continue.  If it happens
-            * to be all empty, just focus on the row. 
+            *   If editing some other row, we know it was saved
+            *   and is ok, convert it back to display
             */
-            if(this.zSkey>-1) {
-                /* special case, empty new row, just focus */
-                if(this.zSkey == 0) {
-                    
-                }
-                if(!x6events.fireEvent('reqSaveRow_'+this.zTable)) {
-                    //console.log('Failed to save new row, no new new row');
-                    //console.groupEnd();
-                    x6inputs.findFocus( $(this).find("#row_0") );
-                    return true;
-                }
+            if(skey>=0) {
+                this.removeInputs();
             }
 
-            // We are going to make a new row.  Right now it will
-            // go at the top of div.thead, but later it has to
-            // be smarter and go in after the selected row, if any.
+            /*
+            *   This is the major UI stuff.  We need to slip a
+            *   row into the grid, clone some of the invisible
+            *   inputs that have been provided by the PHP code,
+            *   and get them all initialized and ready to go.
+            */
             var newRow = new jsHtml('div');
             newRow.hp.id = 'row_0';
             newRow.hp.style = 'display: none;';
             var numbers = [ 'int', 'numb', 'money' ];
-            //console.log(newRow);
             for (var idx in this.zColsInfo) {
                 var colInfo = this.zColsInfo[idx];
                 if(colInfo.column_id == '') continue;
                 
                 var innerDiv = newRow.h('div');
                 innerDiv.hp.style= "width: "+colInfo.width+"px;";
+                innerDiv.hp.gColumn = idx;
                 if(numbers.indexOf(colInfo.type_id)>=0) {
                     innerDiv.hp.style+="text-align: right";
                 }
                 var id = '#wrapper_'+this.zTable+'_'+colInfo.column_id;
                 var newInput = $(id).html();
-                //console.log("column: ",colInfo.column_id,newInput);
+                //console.log("column: ",colInfo.column_id);
                 innerDiv.innerHtml = newInput;
             }
-            //console.log(newRow);
-            // Add this new row into the visuals so it is real
+            
+            /*
+            *   Now do everything required to make the 
+            *   row visible and editable
+            */
             $(this).find('.tbody').prepend(newRow.bufferedRender());
-            // Initialize all inputs to behave in x6 mode
             tabIndex = 1000;
             $(this).find(':input').each(
                 function() { 
-                    x6inputs.initInput(this,tabIndex++,'new'); 
+                    x6inputs.initInput(this,tabIndex++,'new','rowNew'); 
                     this.setAttribute('xTabGroup','rowEdit');
                 }
             );
+            var grid = this;
             $(this).find('#row_0').fadeIn('fast'
-                ,function() { x6inputs.findFocus( this ) }
+                ,function() {
+                    //grid.buttonsOn();
+                    x6inputs.findFocus( this );
+                }
             );
             
-            // This warns downstream code that we are working
-            // on a new row.
-            this.zSkey = 0;
-            
-            // Turn on buttons
+            // Send a message and get lost
+            u.bb.vgfSet('skey_'+this.zTable,0);
             this.buttonsOn();
-            
-            // Send a message and get lost
             //console.log('New row created, ready to edit');
             //console.groupEnd();
             return true;
         }
     }
-
-    // If grid allows either kind of inline row, it must
-    // must accept an abandon request and throw out the row
-    var xSelect = u.p(self,'xGridSelect','');
-    var xReqNew = u.p(self,'xGridReqNew','');
-    if(xSelect == 'inline' || xReqNew == 'inline') {
-        x6events.subscribeToEvent('cancelEdit_'+table,id);
+    
+    /*
+    *   The grid is happy to display an existing row
+    *   for editing if the flag has been set.  This
+    *   is an unconditional event, it assumes all is
+    *   well and nothing stands in the way of editing.
+    */
+    if(uiEditRow=='inline') {
+        x6events.subscribeToEvent('uiEditRow_'+table,id);
         
-        self['receiveEvent_cancelEdit_'+table] = function(skey) {
-            if(this.zSkey==-1) return false;
-
-            //console.group("Abandon: cancelEdit "+this.zTable);
-            if(this.zSkey==0) {
-                //console.log("Abandoning new row");
-                this.zSkey = -1;
-                this.buttonsOff();
-                $(this).find("#row_0").fadeOut('fast'
-                    ,function() { $(this).remove(); }
-                );
+        self['receiveEvent_uiEditRow_'+table] = function(skey) {
+            //console.group("tabDiv uiEditRow "+this.zTable);
+    
+            if( $(this).find('#row_'+skey).length == 0) {
+                //console.log("We don't have that row, cannot edit");
+                //console.groupEnd();
+                return;
             }
             
-            if(this.zSkey>0) {
-                
+            /*
+            *   If editing some other row, we know it was saved
+            *   and is ok, convert it back to display
+            */
+            if(u.bb.vgfGet('skey_'+this.zTable)>=0) {
+                this.removeInputs();
             }
-            
+    
+            //console.log("Putting inputs into div cells");
+            grid = this;
+            $(this).find('.tbody #row_'+skey+' div').each(
+                function() {
+                    // Work up to figuring out the name of the
+                    // id that holds the hidden input, then
+                    // grab the input and put it in.
+                    var colnum = u.p(this,'gColumn');
+                    var colid  = grid.zColsInfo[colnum].column_id;
+                    var id = 'wrapper_'+grid.zTable+'_'+colid;
+
+                    // Current Value
+                    var curval = this.innerHTML;
+                    //console.log(id,curval);
+                    
+                    this.innerHTML = u.byId(id).innerHTML;
+                    $(this).find(":input")[0].value=curval;
+                }
+            );
+            tabIndex = 1000;
+            $(this).find('.tbody #row_'+skey+' :input').each(
+                function() {
+                    x6inputs.initInput(this,tabIndex++,'new','rowEdit'); 
+                }
+            );
+            var string = x6inputs.jqFocusString();
+            $(this).find('.tbody #row_'+skey+' '+string).focus();
+            this.buttonsOn();
+            u.bb.vgfSet('skey_'+this.zTable,skey);
+            //console.log('uiEditRow Completed, returning true');
             //console.groupEnd();
+            return true;
         }
     }
+    
+    /*
+    *   A grid may need to convert inputs back into display
+    *   elements.  This routine is unconditionally created
+    *   and is only called by ui event handlers.
+    *
+    */
+    self.removeInputs = function() {
+        //console.group("tabDiv removeInputs");
 
-    // An explicit flag set in the PHP side determines
-    // if we accept delete requests
-    if(u.p(self,'xGridReqDel','N')=='Y') {
-        x6events.subscribeToEvent('reqDelRow_'+table,id);
-        
-        self['receiveEvent_reqDelRow_'+table] = function() {
-            //console.group("reqDelRow "+table);
-            if(this.zSkey==-1) {
-                //console.log("No row, ignoring");
-                //console.groupEnd();
-                alert("Please select a row first");
+        var skey = u.bb.vgfGet('skey_'+this.zTable);
+        //console.log("skey is ",skey);
+        $(this).find("#row_"+skey+" div").each(
+            function() {
+                var val = $(this).find(":input")[0].value; 
+                //console.log(val);
+                this.innerHTML = val;
+            }
+        );
+
+        // If we are removing inputs from the 0 row
+        // and the last save had no action, kill the row
+        if(skey==0) {
+            if(u.bb.vgfGet('lastSave_'+this.zTable)=='noaction') {
+                $(this).find("#row_0").fadeOut(
+                    function() { $(this).remove() }
+                );
                 return;
             }
-            else if(this.zSkey==0) {
-                //console.log("on a new row, firing cancelEdit command");
-                x6events.fireEvent('cancelEdit_'+this.zTable);
-            }
-            else {
-                if(confirm("Delete the selected row?")) {
-                    //console.log("asking server to delete");
-                    ua.json.init('x6page',this.zTable);
-                    ua.json.addParm('x6action','delete');
-                    ua.json.addParm('skey',this.zSkey);
-                    if(!ua.json.execute()) {
-                        //console.log("server refused to delete");
-                    }
-                    else {
-                        //console.log("server did the delete");
-                        $(this).find('#row_...
 
[truncated message content] | 
| 
     
      
      
      From: <ken...@us...> - 2008-11-03 19:36:51
       
   | 
Revision: 854
          http://andro.svn.sourceforge.net/andro/?rev=854&view=rev
Author:   kendowns
Date:     2008-11-03 19:36:48 +0000 (Mon, 03 Nov 2008)
Log Message:
-----------
Major changes to plugins so grid and twosides now work almost completely.
Modified Paths:
--------------
    trunk/andro/clib/x6.js
Modified: trunk/andro/clib/x6.js
===================================================================
--- trunk/andro/clib/x6.js	2008-11-03 19:36:09 UTC (rev 853)
+++ trunk/andro/clib/x6.js	2008-11-03 19:36:48 UTC (rev 854)
@@ -889,630 +889,508 @@
         $(self).click(function() { 
             if(!this.zDisabled) this.main(); 
         });
-    },
+    }
+}
+ 
+
+/****m* x6plugins/tableController
+*
+* NAME
+*   x6plugins.tableController
+*
+* FUNCTION
+*   The Javascript method x6plugins.tableController is
+*   a constructor function.  It accepts as a parameter the
+*   ID of a DOM element.  It adds functions to that DOM 
+*   element so that it will fully implement all browser-side
+*   features of our tableController object.
+*
+*   A tableController subscribes to all events in which a
+*   user requests to do something like add a row or delete
+*   a row.  The tableController executes whatever server-side
+*   requests are required, and then fires various events to
+*   notify other UI elements that they should display the
+*   results.
+* 
+*   Normally you do not invoke this method directly.  All 
+*   x6 plugins are detected and implmented automatically on
+*   page load.
+
+*   To turn any DOM element into a table controller, just set
+*   the properties x6plugIn and x6table, as in either
+*   of these:
+*
+*      <?php
+*      # here is one way to do it:
+*      echo "<div x6plugIn='tableController' x6table='users'>";
+*
+*      # another way to do it:
+*      $div = html('div');
+*      $div->hp['x6plugIn'] = 'tableController';
+*      $div->hp['x6table'] = 'users';
+*      $div->render();
+*      ?>
+*
+*   You should not have more than one table controller per 
+*   table on a page -- Andromeda will not trap for this!
+*
+* INPUTS
+*   id - the ID of the object to be 'activated'.
+*
+* RESULTS
+*   no return value.
+*
+******
+*/
+x6plugins.tableController = function(self,id,table) {
+    // Initialize new properties
+    u.bb.vgfSet('skey_'+table,-1);
+    self.zSortCol = false;
+    self.zSortAsc = false;
+    self.zCache   = u.p(self,'xCache')=='Y' ? true : false;
     
-    /****m* x6plugins/tableController
-    *
-    * NAME
-    *   x6plugins.tableController
-    *
-    * FUNCTION
-    *   The Javascript method x6plugins.tableController is
-    *   a constructor function.  It accepts as a parameter the
-    *   ID of a DOM element.  It adds functions to that DOM 
-    *   element so that it will fully implement all browser-side
-    *   features of our tableController object.
-    *
-    *   A tableController subscribes to all events in which a
-    *   user requests to do something like add a row or delete
-    *   a row.  The tableController executes whatever server-side
-    *   requests are required, and then fires various events to
-    *   notify other UI elements that they should display the
-    *   results.
-    * 
-    *   Normally you do not invoke this method directly.  All 
-    *   x6 plugins are detected and implmented automatically on
-    *   page load.
+    /*
+    *   Table controller accepts the request to
+    *   save current changes.  First checks if this
+    *   makes sense.
+    *   
+    */
+    x6events.subscribeToEvent('reqSaveRow_'+table,id);
+    self['receiveEvent_reqSaveRow_'+table] = function(dupe) {
+        //console.group("tableController reqSaveRow "+this.zTable);
+        
+        var result = this.saveOk();
+        u.bb.vgfSet('lastSave_'+this.zTable,result);
+        //console.log('tableController reqSaveRow finished');
+        //console.groupEnd();
+    }
     
-    *   To turn any DOM element into a table controller, just set
-    *   the properties x6plugIn and x6table, as in either
-    *   of these:
-    *
-    *      <?php
-    *      # here is one way to do it:
-    *      echo "<div x6plugIn='tableController' x6table='users'>";
-    *
-    *      # another way to do it:
-    *      $div = html('div');
-    *      $div->hp['x6plugIn'] = 'tableController';
-    *      $div->hp['x6table'] = 'users';
-    *      $div->render();
-    *      ?>
-    *
-    *   You should not have more than one table controller per 
-    *   table on a page -- Andromeda will not trap for this!
-    *
-    * INPUTS
-    *   id - the ID of the object to be 'activated'.
-    *
-    * RESULTS
-    *   no return value.
-    *
-    ******
+    
+    /*
+    *   Table controller accepts the request to
+    *   begin editing a new row.  It must first 
+    *   work out if any open rows being edited must
+    *   be saved.  If everything works out it 
+    *   broadcasts a UI notification that UI elements
+    *   should display their inputs in NEW mode.
+    *   
     */
-    tableController: function(self,id,table) {
-        // Initialize new properties
-        u.bb.vgfSet('skey_'+table,-1);
-        self.zSortCol = false;
-        self.zSortAsc = false;
+    x6events.subscribeToEvent('reqNewRow_'    +table,id);
+    self['receiveEvent_reqNewRow_'+table] = function(dupe) {
+        //console.group("tableController reqNewRow "+this.zTable);
         
-        /*
-        *   Table controller will be happy to cache
-        *   rows for a table if they are offered. It
-        *   will also be happy to add a row to that
-        *   cache if offered.  There ought also to be
-        *   something here to remove a row, but that
-        *   seems to be missing?
-        *
-        *   Note: shouldn't that be cacheAddRow ?
-        *   Note: and then wouldn't we want cacheDelRow?
-        */
-        x6events.subscribeToEvent('cacheRows_'+table,id);
-        self['receiveEvent_cacheRows_'+table] = function(rows) {
-            this.zRows = rows;
+        var result = this.saveOk();
+        u.bb.vgfSet('lastSave_'+this.zTable,result);
+        if(result!='fail') {
+            x6events.fireEvent('uiNewRow_'+table);
         }
-        x6events.subscribeToEvent('addRow_'+table,id);
-        self['receiveEvent_addRow_'+table] = function(row) {
-            this.zRows[row.skey] = row;
-        }
+        //console.groupEnd();
+    }
 
-        /*
-        *   Table controller accepts the request to
-        *   save current changes.  First checks if this
-        *   makes sense.
-        *   
-        */
-        x6events.subscribeToEvent('reqSaveRow_'+table,id);
-        self['receiveEvent_reqSaveRow_'+table] = function(dupe) {
-            //console.group("tableController reqSaveRow "+this.zTable);
-            
+    /*
+    *   Table controller accepts a request to edit a 
+    *   row.  It is smart enough that if we are already
+    *   editing that row it does nothing.  Otherwise
+    *   it tries to save any existing row before 
+    *   deciding whether to move on.
+    *   
+    */
+    x6events.subscribeToEvent('reqEditRow_'+table,id);
+    self['receiveEvent_reqEditRow_'+table] = function(skey) {
+        //console.group("tableController reqEditRow "+this.zTable);
+        var skeynow = u.bb.vgfGet('skey_'+this.zTable);
+        if(skeynow == skey) {
+            //console.log("Request to edit same row, no action");
+        } 
+        else {
             var result = this.saveOk();
             u.bb.vgfSet('lastSave_'+this.zTable,result);
             if(result!='fail') {
-                if(result!='noaction') {
-                    x6events.fireEvent('uiRowSaved_'+table,$a.data.row);
-                }
+                x6events.fireEvent('uiEditRow_'+table,skey);
             }
-            //console.log('tableController reqSaveRow finished');
-            //console.groupEnd();
         }
-        
-        
-        /*
-        *   Table controller accepts the request to
-        *   begin editing a new row.  It must first 
-        *   work out if any open rows being edited must
-        *   be saved.  If everything works out it 
-        *   broadcasts a UI notification that UI elements
-        *   should display their inputs in NEW mode.
-        *   
-        */
-        x6events.subscribeToEvent('reqNewRow_'    +table,id);
-        self['receiveEvent_reqNewRow_'+table] = function(dupe) {
-            //console.group("tableController reqNewRow "+this.zTable);
-            
-            var result = this.saveOk();
-            u.bb.vgfSet('lastSave_'+this.zTable,result);
-            if(result!='fail') {
-                if(result!='noaction') {
-                    x6events.fireEvent('uiRowSaved_'+table,$a.data.row);
+        //console.log("tableController reqEditRow finished");
+        //console.groupEnd();
+        return true;
+    }
+    
+    /*
+    *   The saveOk figures out if it needs to save and
+    *   tries to do so.  If no active fields have changed,
+    *   it just returns 'noaction'.  If it needs to save,
+    *   it attempts to do so and returns 'success' or
+    *   'fail'.
+    */
+    self.saveOk = function() {
+        //console.group("tableController saveOK");
+        var inpAll = { };
+        var inpChg = { };
+        var cntChg = 0;
+        var jq = ':input[xtableid='+this.zTable+'][zActive]';
+        //console.log("Query string",jq);
+        $(this).find(jq).each(
+            function() {
+                var col = u.p(this,'xcolumnid');
+                inpAll[col] = this.value;
+                var oval = u.p(this,'zOriginalValue','').trim();
+                if(this.value.trim()!= oval) {
+                    inpChg[col] = this.value.trim();
+                    cntChg++;
                 }
-                x6events.fireEvent('uiNewRow_'+table);
             }
-            //console.groupEnd();
+        );
+        //console.log("All inputs: ",inpAll);
+        //console.log("Changed inputs: ",inpChg);
+        //console.log("Count of changes: ",cntChg);
+        
+        // Only attempt a save if something changed
+        if(cntChg == 0) {
+            //console.log("no changes, not trying to save");
+            var retval = 'noaction';
         }
-
-        /*
-        *   Table controller accepts a request to edit a 
-        *   row.  It is smart enough that if we are already
-        *   editing that row it does nothing.  Otherwise
-        *   it tries to save any existing row before 
-        *   deciding whether to move on.
-        *   
-        */
-        x6events.subscribeToEvent('reqEditRow_'+table,id);
-        self['receiveEvent_reqEditRow_'+table] = function(skey) {
-            //console.group("tableController reqEditRow "+this.zTable);
-            var skeynow = u.bb.vgfGet('skey_'+this.zTable);
-            if(skeynow == skey) {
-                //console.log("Request to edit same row, no action");
-            } 
+        else {
+            //console.log("attempting database save");
+            //console.log("Sending x4v_skey ",this.zSkey);
+            ua.json.init('x6page',this.zTable);
+            ua.json.addParm('x6action','save');
+            ua.json.addParm('x4v_skey',u.bb.vgfGet('skey_'+this.zTable));
+            ua.json.inputs(jq);
+            if(ua.json.execute()) {
+                var retval = 'success';
+                ua.json.process();
+            }
             else {
-                var result = this.saveOk();
-                u.bb.vgfSet('lastSave_'+this.zTable,result);
-                if(result!='fail') {
-                    if(result!='noaction') {
-                        x6events.fireEvent('uiRowSaved_'+table,$a.data.row);
+                var retval = 'fail';
+                var errors = [ ];
+                for(var idx in ua.json.jdata.error) {
+                    if(ua.json.jdata.error[idx].slice(0,8)!='(ADMIN):') {
+                        errors.push(ua.json.jdata.error[idx]);
                     }
-                    x6events.fireEvent('uiEditRow_'+table,skey);
                 }
+                //console.log("save failed, here are errors");
+                //console.log(errors);
+                x6events.fireEvent('uiShowErrors_'+this.zTable,errors);
             }
-            //console.log("tableController reqEditRow finished");
-            //console.groupEnd();
-            return true;
         }
         
-        /*
-        *   The saveOk figures out if it needs to save and
-        *   tries to do so.  If no active fields have changed,
-        *   it just returns 'noaction'.  If it needs to save,
-        *   it attempts to do so and returns 'success' or
-        *   'fail'.
-        */
-        self.saveOk = function() {
-            //console.group("tableController saveOK");
-            var inpAll = { };
-            var inpChg = { };
-            var cntChg = 0;
-            var jq = ':input[xtableid='+this.zTable+'][zActive]';
-            //console.log("Query string",jq);
-            $(this).find(jq).each(
+        // If save went ok, notify any ui elements, then 
+        // fire off a cache save also if required.
+        if(retval=='success') {
+            //console.log(retval);
+            x6events.fireEvent('uiRowSaved_'+table,$a.data.row);
+            if(this.zCache) {
+                this.zRows[$a.data.row.skey] = $a.data.row;
+            }
+        }            
+        
+        //console.log("tableController saveOK RETURNING: ",retval);
+        //console.groupEnd();
+        return retval;
+    };
+
+
+    /*
+    *   The table controller accepts requests to undo
+    *   changes to a row.  It actually rolls back all
+    *   inputs and sets their classes, and then
+    *   fires of a uiUndoRow event so various other
+    *   elements can do their own thing.
+    */
+    x6events.subscribeToEvent('reqUndoRow_'+table,id);
+    self['receiveEvent_reqUndoRow_'+table] = function() {
+        //console.group("tableController reqUndoRow");
+        var skey = u.bb.vgfGet('skey_'+table);
+        if(skey>=0) {
+            //console.log("Skey is >= 0, continuing ",skey);
+            $(this).find(":input:not([disabled])[zActive]").each( 
                 function() {
-                    var col = u.p(this,'xcolumnid');
-                    inpAll[col] = this.value;
-                    var oval = u.p(this,'zOriginalValue','').trim();
-                    if(this.value.trim()!= oval) {
-                        inpChg[col] = this.value.trim();
-                        cntChg++;
-                    }
+                    this.value = this.zOriginalValue;
+                    this.zError = 0;
+                    x6inputs.setClass(this);
                 }
             );
-            //console.log("All inputs: ",inpAll);
-            //console.log("Changed inputs: ",inpChg);
-            //console.log("Count of changes: ",cntChg);
-            
-            // Only attempt a save if something changed
-            if(cntChg == 0) {
-                //console.log("no changes, not trying to save");
-                var retval = 'noaction';
-            }
-            else {
-                //console.log("attempting database save");
-                //console.log("Sending x4v_skey ",this.zSkey);
+            x6events.fireEvent('uiUndoRow_'+this.zTable);
+        }
+        //console.log("tableController reqUndoRow Finished");
+        //console.groupEnd();
+        return true;
+    }
+    
+
+    /*
+    *   The table controller accepts delete request
+    *   and asks the database to do the delete.  If
+    *   this is successful, it tells any UI subscribers
+    *   to update their displays accordingly.
+    */
+    x6events.subscribeToEvent('reqDelRow_'    +table,id);
+    self['receiveEvent_reqDelRow_'+table] = function() {
+        //console.group("tableController reqDelRow ",this.zTable);
+        var skey = u.bb.vgfGet('skey_'+this.zTable);
+        if(this.zSkey<1) {
+            //console.log("nothing being edited, quietly ignoring");
+        }
+        else {
+            if(confirm("Delete current row?")) {
+                //console.log("sending delete to server");
                 ua.json.init('x6page',this.zTable);
-                ua.json.addParm('x6action','save');
-                ua.json.addParm('x4v_skey',u.bb.vgfGet('skey_'+this.zTable));
-                ua.json.inputs(jq);
+                ua.json.addParm('x6action','delete');
+                ua.json.addParm('skey',skey);
+                ua.json.addParm('json',1);
                 if(ua.json.execute()) {
-                    var retval = 'success';
-                    ua.json.process();
+                    x6events.fireEvent('uiDelRow_'+table,skey);
                 }
-                else {
-                    var retval = 'fail';
-                    var errors = [ ];
-                    for(var idx in ua.json.jdata.error) {
-                        if(ua.json.jdata.error[idx].slice(0,8)!='(ADMIN):') {
-                            errors.push(ua.json.jdata.error[idx]);
-                        }
-                    }
-                    //console.log("save failed, here are errors");
-                    //console.log(errors);
-                    x6events.fireEvent('uiShowErrors_'+this.zTable,errors);
-                }
             }
-            
-            //console.log("tableController saveOK RETURNING: ",retval);
-            //console.groupEnd();
-            return retval;
-        };
-
-
-        /*
-        *   The table controller accepts requests to undo
-        *   changes to a row.  It actually rolls back all
-        *   inputs and sets their classes, and then
-        *   fires of a uiUndoRow event so various other
-        *   elements can do their own thing.
-        */
-        x6events.subscribeToEvent('reqUndoRow_'+table,id);
-        self['receiveEvent_reqUndoRow_'+table] = function() {
-            //console.group("tableController reqUndoRow");
-            var skey = u.bb.vgfGet('skey_'+table);
-            if(skey>=0) {
-                //console.log("Skey is >= 0, continuing ",skey);
-                $(this).find(":input:not([disabled])[zActive]").each( 
-                    function() {
-                        this.value = this.zOriginalValue;
-                        this.zError = 0;
-                        x6inputs.setClass(this);
-                    }
-                );
-                x6events.fireEvent('uiUndoRow_'+this.zTable);
-            }
-            //console.log("tableController reqUndoRow Finished");
-            //console.groupEnd();
-            return true;
         }
-        
-
-        /*
-        *   The table controller accepts delete request
-        *   and asks the database to do the delete.  If
-        *   this is successful, it tells any UI subscribers
-        *   to update their displays accordingly.
-        */
-        x6events.subscribeToEvent('reqDelRow_'    +table,id);
-        self['receiveEvent_reqDelRow_'+table] = function() {
-            //console.group("tableController reqDelRow ",this.zTable);
-            var skey = u.bb.vgfGet('skey_'+this.zTable);
-            if(this.zSkey<1) {
-                //console.log("nothing being edited, quietly ignoring");
-            }
-            else {
-                if(confirm("Delete current row?")) {
-                    //console.log("sending delete to server");
-                    ua.json.init('x6page',this.zTable);
-                    ua.json.addParm('x6action','delete');
-                    ua.json.addParm('skey',skey);
-                    ua.json.addParm('json',1);
-                    if(ua.json.execute()) {
-                        x6events.fireEvent('uiDelRow_'+table,skey);
-                    }
-                }
-            }
-            //console.log("tableController reqDelRow finished");
-            //console.groupEnd();
-            return true;
+        //console.log("tableController reqDelRow finished");
+        //console.groupEnd();
+        return true;
+    }
+    
+    // Sort requests are sorted out here.        
+    x6events.subscribeToEvent('reqSort_'+table,id);
+    self['receiveEvent_reqSort_'+table] = function(args) {
+        // Work out sort order
+        table = this.zTable
+        xColumn = args.xColumn;
+        xChGroup= args.xChGroup;
+        if(xColumn == this.zSortCol) {
+            this.zSortAsc = ! this.zSortAsc;
         }
-        
-        // Sort requests are sorted out here.        
-        x6events.subscribeToEvent('reqSort_'+table,id);
-        self['receiveEvent_reqSort_'+table] = function(args) {
-            // Work out sort order
-            table = this.zTable
-            xColumn = args.xColumn;
-            xChGroup= args.xChGroup;
-            if(xColumn == this.zSortCol) {
-                this.zSortAsc = ! this.zSortAsc;
-            }
-            else {
-                this.zSortCol = xColumn;
-                this.zSortAsc = true;
-            }
-            
-            // Flip all icons to both
-            $('[xChGroup='+xChGroup+']').html('↑&darr');
-            
-            // Flip just this icon to up or down
-            var icon = this.zSortAsc ? '↓' : '↑';
-            $('[xChGroup='+xChGroup+'][xColumn='+xColumn+']').html(icon);
-            
-            // Make the request to the server
-            var args2 = { sortCol: this.zSortCol, sortAsc: this.zSortAsc };
-            x6events.fireEvent('doSort_'+this.zTable,args2);
+        else {
+            this.zSortCol = xColumn;
+            this.zSortAsc = true;
         }
         
-
-    },
-    
-    /****m* x6plugins/grid 
-    * NAME
-    *   x6plugins.grid
-    *
-    ******/
-    grid: function(self,id,table) {
+        // Flip all icons to both
+        $('[xChGroup='+xChGroup+']').html('↑&darr');
         
-        // Subscribe to deletion event
-        x6events.subscribeToEvent('delRow_'+table,id);
-        self['receiveEvent_delRow_'+table] = function(skey) {
-            $(this).find('#row_'+skey).fadeOut(function() {
-                    $(this).remove();
-            });
-        }
+        // Flip just this icon to up or down
+        var icon = this.zSortAsc ? '↓' : '↑';
+        $('[xChGroup='+xChGroup+'][xColumn='+xColumn+']').html(icon);
         
-        // Grid accepts an addrow and requests some html from
-        // the server, then interprets it as a goMode
-        //
-        x6events.subscribeToEvent('addRow_'+table,id);
-        self['receiveEvent_addRow_'+table] = function(row) {
-            ua.json.init('x6page',this.zTable);
-            ua.json.addParm('x6plugIn',u.p(this,'x6plugIn'));
-            ua.json.addParm('x6action','onerow');
-            ua.json.addParm('skey',row.skey);
-            if(ua.json.execute()) {
-                var html = ua.json.jdata.html['*MAIN*'];
-                $(this).find('.tbody').prepend(html);
-                this['receiveEvent_goMode_'+table]({mode:'edit',row:row});
-            }
-        }
-        
-        // Grid accepts a notification that we are actually
-        // editing a row or reviewing a row
-        x6events.subscribeToEvent('goMode_'+table,id);
-        self['receiveEvent_goMode_'+table] = function(args) {
-            // In all cases, turn off any rows that are selected
-            $(this).find('.tbody .selected')
-                .removeClass('selected')
-                .removeClass('hilight');
-            
-            // If there is a new row, turn that one on
-            if(args.mode == 'edit') {
-                $(this).find('#row_'+args.row.skey)
-                    .removeClass('hilight')
-                    .addClass('selected');
-            }
-        }
+        // Make the request to the server
+        var args2 = { sortCol: this.zSortCol, sortAsc: this.zSortAsc };
+        x6events.fireEvent('doSort_'+this.zTable,args2);
+    }
+    
 
-        // Grid responds to request to sort in a particular order
-        x6events.subscribeToEvent('doSort_'+table,id);
-        self['receiveEvent_doSort_'+table] = function(args) {
-            ua.json.init('x6page',this.zTable);
-            ua.json.addParm('x6plugIn',u.p(this,'x6plugIn'));
-            ua.json.addParm('x6action','refresh');
-            ua.json.addParm('sortCol',args.sortCol);
-            ua.json.addParm('sortAsc',args.sortAsc);
-            u.dialogs.pleaseWait();
-            if(ua.json.execute(true)) {
-                var html = ua.json.jdata.html['*MAIN*'];
-                $(this).find('.tbody').replaceWith(html);
-            }
-            u.dialogs.clear();
-        }
+    /*
+    *   Table controller will be happy to cache
+    *   rows for a table if they are offered. It
+    *   will also be happy to add a row to that
+    *   cache if offered.  There ought also to be
+    *   something here to remove a row, but that
+    *   seems to be missing?
+    *
+    *   Note: shouldn't that be cacheAddRow ?
+    *   Note: and then wouldn't we want cacheDelRow?
+    */
+    this.zRows = { };
+    x6events.subscribeToEvent('cacheRows_'+table,id);
+    self['receiveEvent_cacheRows_'+table] = function(rows) {
+        this.zRows = rows;
+    }
+    x6events.subscribeToEvent('addRow_'+table,id);
+    self['receiveEvent_addRow_'+table] = function(row) {
+        this.zRows[row.skey] = row;
+    }
+    
+    /*
+    *    A request to put the current row onto
+    *    the bulletin board.
+    */
+    x6events.subscribeToEvent('dbFetchRow_'+table,id);
+    self['receiveEvent_dbFetchRow_'+table] = function(skey) {
         
-        // First keyboard event, keydown
-        x6events.subscribeToEvent('key_UpArrow',id);
-        self.receiveEvent_key_UpArrow = function(e) {
-            var jqRows = $(this).find('.hilight').prev();
-            if(jqRows.length==0) {
-                $(this).find('tbody tr:first').addClass('hilight');
-            }
-            else {
-                $(this).find('tbody tr.hilight').removeClass('hilight')
-                    .prev().addClass('hilight');
-            }
-            x6events.retvals['key_UpArrow'] =false;
+        if(typeof(this.zRows[skey])=='undefined') {
+            //console.log("tableController bbRow, no row found");
         }
-        x6events.subscribeToEvent('key_DownArrow',id);
-        self.receiveEvent_key_DownArrow = function(e) {
-            var jqRows = $(this).find('.hilight').next();
-            if(jqRows.length==0) {
-                $(this).find('tbody tr:first').addClass('hilight');
-            }
-            else {
-                $(this).find('.hilight').removeClass('hilight')
-                    .next().addClass('hilight');
-            }
-            x6events.retvals['key_UpArrow'] =false;
+        else {
+            //console.log("tableController bbRow, publishing row "+skey);
+            //console.log("putting onto bb as dbRow_"+this.zTable);
+            u.bb.vgfSet('dbRow_'+this.zTable,this.zRows[skey]);
         }
-        
-        
-    },
+    }
     
-    /****m* x6plugins/detailDisplay
-    *
-    * NAME
-    *   x6plugins.detailDisplay
-    *
-    * FUNCTION
-    *   The Javascript method x6plugins.detailDisplay implements
-    *   all browser-side functionality for Andromeda's built-in
-    *   plugIn detailDisplay.
-    *
-    *   A 'detailDisplay' plugIn displays user inputs to edit
-    *   the values for a particular row in a table.  
-    *
-    *   This plugin subscribes to the following events:
-    *   *  goMode_{table}
-    *
-    * INPUTS
-    *   self - the DOM object to be activated.
-    *   id - the ID of the object to be 'activated'.
-    *   table - the database table that the detailPane is handling.
-    *
-    * RESULTS
-    *   no return value.
-    *
-    ******
+    /*
+    *   Two requests, one to turn on editing-mode buttons,
+    *   another to turn them off.
     */
-    detailDisplay: function(self,id,table) {
-        self.zSkey = -1;
+    x6events.subscribeToEvent('buttonsOn_'+table,id);
+    self['receiveEvent_buttonsOn_'+table] = function() {
+        x6events.fireEvent('enable_save');
+        x6events.fireEvent('enable_abandon');
+        x6events.fireEvent('enable_remove');
+    }
+    x6events.subscribeToEvent('buttonsOff_'+table,id);
+    self['receiveEvent_buttonsOff_'+table] = function() {
+        x6events.fireEvent('disable_save');
+        x6events.fireEvent('disable_abandon');
+        x6events.fireEvent('disable_remove');
+    }
+}
+    
+    
+/****m* x6plugins/detailDisplay
+*
+* NAME
+*   x6plugins.detailDisplay
+*
+* FUNCTION
+*   The Javascript method x6plugins.detailDisplay implements
+*   all browser-side functionality for Andromeda's built-in
+*   plugIn detailDisplay.
+*
+*   A 'detailDisplay' plugIn displays user inputs to edit
+*   the values for a particular row in a table.  
+*
+*   This plugin subscribes to the following events:
+*   *  goMode_{table}
+*
+* INPUTS
+*   self - the DOM object to be activated.
+*   id - the ID of the object to be 'activated'.
+*   table - the database table that the detailPane is handling.
+*
+* RESULTS
+*   no return value.
+*
+******
+*/
+x6plugins.detailDisplay = function(self,id,table) {
+    // detail receives a request to go to a mode which
+    // is unconditional, it will do what it is told
+    x6events.subscribeToEvent('uiEditRow_'+table,id);
+    self['receiveEvent_uiEditRow_'+table] = function(skey) {
+        //console.group("detailDisplay uiEditRow",skey);
         
-        // detail receives a request to attempt to go into a 
-        // mode.  It checks to see if a save is required first.
-        x6events.subscribeToEvent('attemptChangeMode_'+table,id);
-        self['receiveEvent_attemptChangeMode_'+table] = function() {
-            // Check for existing row with changes
-            if(this.zSkey>=0) {
-                var ichg = $(this).find(":input[zChanged=1]");
-                if(ichg.length > 0) {
-                    alert("There are changed Values.  Must save first");
-                    return false;
-                }
-            }
-            return true;
-        }
+        // Ask somebody to publish the row
+        x6events.fireEvent('dbFetchRow_'+table,skey);
+        var row = u.bb.vgfGet('dbRow_'+table);
         
-        // Detail receives...
 
[truncated message content] | 
| 
     
      
      
      From: <ken...@us...> - 2008-11-04 20:17:05
       
   | 
Revision: 857
          http://andro.svn.sourceforge.net/andro/?rev=857&view=rev
Author:   kendowns
Date:     2008-11-04 20:17:04 +0000 (Tue, 04 Nov 2008)
Log Message:
-----------
Modified Paths:
--------------
    trunk/andro/clib/x6.js
Modified: trunk/andro/clib/x6.js
===================================================================
--- trunk/andro/clib/x6.js	2008-11-04 19:40:23 UTC (rev 856)
+++ trunk/andro/clib/x6.js	2008-11-04 20:17:04 UTC (rev 857)
@@ -564,19 +564,31 @@
         //console.log("tabindex, mode, tabgroup: ",tabIndex,mode,tabGroup);
         //console.log(input);
         
+        // Get the read-only decision
+        if(mode=='new') {
+            //console.log("hello, ro ins");
+            input.zRO = u.p(input,'xroins','N')=='Y' ? 1: 0;
+        }
+        else {
+            //console.log("hello, ro upd");
+            input.zRO = u.p(input,'xroupd','N')=='Y' ? 1: 0;
+        }
+        
         // This is standard events and attributes
         input.setAttribute('xTabGroup',tabGroup);
         input.setAttribute('tabIndex' ,tabIndex);
         input.zOriginalValue = input.value.trim();
-        $(input)
-            .keyup(function(e)   { x6inputs.keyUp(e,this)   })
-            .focus(function(e)   { x6inputs.focus(e,this)   })
-            .blur(function(e)    { x6inputs.blur(e,this)    })
-            .keydown(function(e) { x6inputs.keyDown(e,this) });
+        if(!input.zRO) {
+            $(input)
+                .keyup(function(e)   { x6inputs.keyUp(e,this)   })
+                .focus(function(e)   { x6inputs.focus(e,this)   })
+                .blur(function(e)    { x6inputs.blur(e,this)    })
+                .keydown(function(e) { x6inputs.keyDown(e,this) });
+        }
         if(mode=='new') {
             input.zNew = 1;
-            x6inputs.setClass(input);
         }
+        x6inputs.setClass(input);
         
         // KFD 11/1/08, EXPERIMENTAL use of jquery.maskedinput
         //if(u.p(input,'xinputmask','')!='') {
@@ -599,6 +611,27 @@
         //console.group("Input keyUp");
         //console.log(e);
         //console.log(inp);
+        
+        // if a numeric, filter out disallowed values
+        type = u.p(inp,'xtypeid');
+        //console.log(typeof(inp.value));
+        switch(type) {
+        case 'int':
+            //console.log("int, allowing only digits");
+            //console.log(inp);
+            //console.log(inp.value);
+            inp.value = inp.value.replace(/[^0-9]/g,'');
+            break;
+        case 'numb':
+        case 'money':
+            //console.log("numb or money, allowing only digits and period");
+            inp.value = inp.value.replace(/[^0-9\.]/g,'');
+            break;
+        case date:
+            //console.log("date, alowing digits, / and -");
+            inp.value = inp.value.replace(/[^0-9\/\-]/g,'');
+        }
+        
         x6inputs.setClass(inp);
         //console.groupEnd("Input keyUp");
     },
@@ -737,7 +770,8 @@
     
     jqFocusString: function() {
         return ":input:not([disabled]):first";
-    }
+    },
+
 }
 
 
@@ -1049,12 +1083,18 @@
             var retval = 'noaction';
         }
         else {
+            
             //console.log("attempting database save");
             //console.log("Sending x4v_skey ",this.zSkey);
             ua.json.init('x6page',this.zTable);
             ua.json.addParm('x6action','save');
             ua.json.addParm('x4v_skey',u.bb.vgfGet('skey_'+this.zTable));
             ua.json.inputs(jq);
+            // Look for an "skey after" to send back 
+            var skeyAfter = u.bb.vgfGet('skeyAfter_'+this.zTable,-1);
+            if(skeyAfter!=-1) {
+                ua.json.addParm('skeyAfter',skeyAfter);
+            }
             if(ua.json.execute()) {
                 var retval = 'success';
                 ua.json.process();
@@ -1072,6 +1112,7 @@
                 x6events.fireEvent('uiShowErrors_'+this.zTable,errors);
             }
         }
+        u.bb.vgfSet('lastSave_'+this.zTable,retval);
         
         // If save went ok, notify any ui elements, then 
         // fire off a cache save also if required.
@@ -1171,7 +1212,7 @@
         
         // Make the request to the server
         var args2 = { sortCol: this.zSortCol, sortAsc: this.zSortAsc };
-        x6events.fireEvent('doSort_'+this.zTable,args2);
+        x6events.fireEvent('uiSort_'+this.zTable,args2);
     }
     
 
@@ -1490,11 +1531,34 @@
                 innerDiv.innerHtml = newInput;
             }
             
+            /* 
+            *   Kind of a big deal.  If the grid has the
+            *   flag xInsertAfter set to "Y", we must slip the
+            *   new row in after the current, and trap the
+            *   skey value of the current
+            */
+            var iAfter = false;
+            if(u.p(this,'xInsertAfter','N')=='Y') {
+                if(skey>0) {
+                    iAfter = skey;
+                    u.bb.vgfSet('skeyAfter_'+this.zTable,skey);
+                }
+                else {
+                    u.bb.vgfSet('skeyAfter_'+this.zTable,0);
+                }
+            }
+            if(iAfter) {
+                $(this).find('#row_'+iAfter).after(newRow.bufferedRender());
+            }
+            else {
+                $(this).find('.tbody').prepend(newRow.bufferedRender());
+                u.bb.vgfSet('skeyAfter_'+this.zTable,-1);
+            }
+            
             /*
             *   Now do everything required to make the 
             *   row visible and editable
             */
-            $(this).find('.tbody').prepend(newRow.bufferedRender());
             tabIndex = 1000;
             $(this).find(':input').each(
                 function() { 
@@ -1566,7 +1630,7 @@
             tabIndex = 1000;
             $(this).find('.tbody #row_'+skey+' :input').each(
                 function() {
-                    x6inputs.initInput(this,tabIndex++,'new','rowEdit'); 
+                    x6inputs.initInput(this,tabIndex++,'edit','rowEdit'); 
                 }
             );
             var string = x6inputs.jqFocusString();
@@ -1882,4 +1946,25 @@
             }
         }
     }
+    
+    /*
+    *    Accept request to sort on a column.  The grid makes
+    *    the request because the grid is going to display it,
+    *    which keeps everything in one place.
+    */    
+    x6events.subscribeToEvent('uiSort_'+table,id);
+    self['receiveEvent_uiSort_'+table] = function(args) {
+        u.bb.vgfSet('skey_'+this.zTable,-1);
+        ua.json.init('x6page',this.zTable);
+        ua.json.addParm('x6plugIn','grid');
+        ua.json.addParm('x6action','refresh');
+        ua.json.addParm('sortCol',args.sortCol);
+        ua.json.addParm('sortAsc',args.sortAsc);
+        u.dialogs.pleaseWait();
+        if(ua.json.execute(true)) {
+            var html = ua.json.jdata.html['*MAIN*'];
+            $(this).find('.tbody').replaceWith(html);
+        }
+        u.dialogs.clear();
+    }
 }
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
 | 
| 
     
      
      
      From: <ken...@us...> - 2008-11-20 15:22:52
       
   | 
Revision: 895
          http://andro.svn.sourceforge.net/andro/?rev=895&view=rev
Author:   kendowns
Date:     2008-11-20 15:22:49 +0000 (Thu, 20 Nov 2008)
Log Message:
-----------
Daily x6 improvements.
Modified Paths:
--------------
    trunk/andro/clib/x6.js
Modified: trunk/andro/clib/x6.js
===================================================================
--- trunk/andro/clib/x6.js	2008-11-17 14:58:03 UTC (rev 894)
+++ trunk/andro/clib/x6.js	2008-11-20 15:22:49 UTC (rev 895)
@@ -1611,6 +1611,33 @@
     var uiEditRow = u.p(self,'uiEditRow','');
     
     /*
+    *  A grid may be set to receive a cacheRows event.
+    *  If so, it will replace its own data with the
+    *  data that has been provided.
+    */
+    if(u.p(self,'xCacheRows','')=='Y') {
+        x6events.subscribeToEvent('cacheRows_'+table,id);
+        
+        self['receiveEvent_cacheRows_'+table] = function(rows) {
+            // Clear current data
+            $(this).find('.tbody').html();
+            // Add new data
+            for(var x in rows) {
+                this.addRow(rows[x]);
+            }
+        }
+    }
+    
+    /*
+    *   Related to the above is a simple command to add a row
+    *
+    */
+    self.addRow = function(row) {
+        
+    }
+    
+    
+    /*
     *   The grid is happy to display a new row for
     *   editing if a certain flag has been set.
     *   The event uiNewRow is unconditional, it means
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
 | 
| 
     
      
      
      From: <ken...@us...> - 2008-12-01 12:32:41
       
   | 
Revision: 903
          http://andro.svn.sourceforge.net/andro/?rev=903&view=rev
Author:   kendowns
Date:     2008-12-01 12:32:38 +0000 (Mon, 01 Dec 2008)
Log Message:
-----------
Many major changes after a week of development.
Modified Paths:
--------------
    trunk/andro/clib/x6.js
Modified: trunk/andro/clib/x6.js
===================================================================
--- trunk/andro/clib/x6.js	2008-12-01 12:32:15 UTC (rev 902)
+++ trunk/andro/clib/x6.js	2008-12-01 12:32:38 UTC (rev 903)
@@ -309,10 +309,22 @@
         if( u.p(this.subscribers,eventName,null)==null) {
             this.subscribers[eventName] = [ ];
         }
-        this.subscribers[eventName].push(id);
+        if(this.subscribers[eventName].indexOf(id)==-1) {
+            this.subscribers[eventName].push(id);
+        }
         //console.groupEnd();
     },
     /******/
+    
+    unsubscribeToEvent: function(eventName,id) {
+        var subs = u.p(this.subscribers,eventName);
+        if( subs!=null) {
+            var i = this.subscribers[eventName].indexOf(id);
+            if(i >= 0) {
+                this.subscribers[eventName].splice(i,1);
+            }
+        }
+    },
         
     /****m* events/getSubscribers
     *
@@ -397,7 +409,7 @@
                 break;
             }
         }
-        //console.log("fireEvent RETURNING: ",this.retvals[eventName]);
+        //console.log("fireEvent ",eventName," RETURNING: ",this.retvals[eventName]);
         //console.groupEnd();
         return this.retvals[eventName];
     }
@@ -426,6 +438,8 @@
         case 'int':
         case 'numb':
         case 'money':
+            //console.log("I've got int, numb, or money", value);
+            if(value=='null') return '';
             //console.log("x6dd.display returning number");
             return Number(value);
             break;
@@ -446,19 +460,27 @@
     // DOM elements with property x6plugIn=xxx.  
     // Invoke the constructor for each one.
     init: function() {
-        u.debugFlag = true;
-        
+        // KFD 11/28/08.  Removed this and put initialization commands
+        //                into jqDocReady.  Turns out each plugin init
+        //                takes 5ms, but the jquery search for them
+        //                takes 350ms of a second, terrible.  So the
+        //                PHP code is generating commands to initialize
+        //                each plugin.
         // Job 1: Activate all of the plugins
+        /*
         for(var plugInId in x6plugins) {
             $('[x6plugIn='+plugInId+']').each(function() {
                     if(u.p(this,'id','')=='') {
                         this.id = u.uniqueId();
                     }
+                    //console.time("inititialing "+this.id);
                     this.zTable = u.p(this,'x6table');
                     //console.log("Initializing x6plugin  ",this);
                     x6plugins[plugInId](this,this.id,this.zTable);
+                    //console.timeEnd("inititialing "+this.id);
             });
         }
+        */
         
         // Job 2, activate a global keyboard handler
         $(document).keypress(function(e) {
@@ -481,7 +503,9 @@
     },
     
     initFocus: function() {
-        $('[x6firstFocus=Y]:last').focus();
+        var first = $('[x6firstFocus=Y]:last');
+        if(first.length>0) first.focus();
+        else $('.x6main').focus();
     },
     
     // Keyboard handler
@@ -493,9 +517,6 @@
         x4Keys['8']  = 'BackSpace';
         x4Keys['9']  = 'Tab';
         x4Keys['13'] = 'Enter';
-        //x4Keys['16'] = '';   // actually Shift, but prefix will take care of it
-        //x4Keys['17'] = '';   // actually Ctrl,  but prefix will take care of it
-        //x4Keys['18'] = '';   // actually Alt,   but prefix will take care of it
         x4Keys['16'] = 'Shift';
         x4Keys['17'] = 'Ctrl';
         x4Keys['18'] = 'Alt';
@@ -594,11 +615,11 @@
         // Get the read-only decision
         if(mode=='new') {
             //console.log("hello, ro ins");
-            input.zRO = u.p(input,'xroins','N')=='Y' ? 1: 0;
+            input.disabled = u.p(input,'xroins','N')=='Y';
         }
         else {
             //console.log("hello, ro upd");
-            input.zRO = u.p(input,'xroupd','N')=='Y' ? 1: 0;
+            input.disabled = u.p(input,'xroupd','N')=='Y';
         }
         
         // This is standard events and attributes
@@ -607,13 +628,14 @@
         /* IE Madness.  If no value assigned, the property 
            is not there, must use u.p                         */;
         //input.zOriginalValue = input.value.trim();
+        // KFD 11/27/08, this belongs in focus...
         input.zOriginalValue = u.p(input,'value','').trim();
         if(!input.zRO) {
             $(input)
                 .keyup(function(e)   { x6inputs.keyUp(e,this)   })
-                .focus(function(e)   { x6inputs.focus(e,this)   })
-                .blur(function(e)    { x6inputs.blur(e,this)    })
-                .keydown(function(e) { x6inputs.keyDown(e,this) });
+                .focus(function(e)   { x6inputs.focus(this)   })
+                .blur(function(e)    { x6inputs.blur(this)    })
+                .keydown(function(e) { return x6inputs.keyDown(e,this) });
         }
         if(mode=='new') {
             input.zNew = 1;
@@ -642,26 +664,6 @@
         //console.log(e);
         //console.log(inp);
         
-        // if a numeric, filter out disallowed values
-        type = u.p(inp,'xtypeid');
-        //console.log(typeof(inp.value));
-        switch(type) {
-        case 'int':
-            //console.log("int, allowing only digits");
-            //console.log(inp);
-            //console.log(inp.value);
-            inp.value = inp.value.replace(/[^0-9]/g,'');
-            break;
-        case 'numb':
-        case 'money':
-            //console.log("numb or money, allowing only digits and period");
-            inp.value = inp.value.replace(/[^0-9\.]/g,'');
-            break;
-        case 'date':
-            //console.log("date, alowing digits, / and -");
-            inp.value = inp.value.replace(/[^0-9\/\-]/g,'');
-        }
-        
         x6inputs.setClass(inp);
         //console.groupEnd("Input keyUp");
     },
@@ -672,64 +674,246 @@
     // current control
     //
     keyDown: function(e,inp) {
-        if(e.keyCode!=9) return true;
-        //console.group("input keyDown handler");
+        //console.group('Input keyDown ');
         //console.log(e);
         //console.log(inp);
+        var keyLabel=u.keyLabel(e);
+        var isTab   =keyLabel=='Tab'    || keyLabel=='ShiftTab';
+        var isEnter =keyLabel=='Enter'  || keyLabel=='ShiftEnter';  
+        var isMeta  =u.keyIsMeta(e);
+        var isNav   =isEnter || isTab;
+        //console.log("label ",keyLabel,' isTab ',isTab,' isEnter ',isEnter,' isMeta ',isMeta,' isNav ',isNav);
         
-        var tg = u.p(inp,'xTabGroup','tgdefault');
-        //console.log("Tab Group",tg);
+        // All meta keys return true immediately except TAB and ENTER
+        if(isMeta && !isNav) {
+            //console.log("meta key but not tab or enter, returning true");
+            //console.groupEnd();
+            return true;
+        }
         
-        if(e.shiftKey) { 
-            // hitting shift-tab on the first control means
-            // jump back to the last control
-            var first = $('[xTabGroup='+tg+']:not([disabled]):first')[0];
-            //console.log("The first is:");
-            //console.log(first);
-            //console.log("The input is:");
-            //console.log(inp);
-            if(first==inp) {
-                //console.log("This is first, jumping to last");
-                $('[xTabGroup='+tg+']:not([disabled]):last').focus();
-                e.preventDefault();
+        // Type validation for some types, only if not TAB or ENTER
+        if(!isNav) {
+            //console.log("Not nav key, doing type validation");
+            type = u.p(inp,'xtypeid');
+            switch(type) {
+            case 'int':
+                //console.log("type validation for int");
+                if(!u.keyIsNumeric(e)) return false;
+                break;
+            case 'numb':
+            case 'money':
+                //console.log("type validation for numb/money");
+                if(!u.keyIsNumeric(e) && u.keyLabel(e)!='.') return false;
+                break;
+            case 'date':
+                //console.log("type validation for date");
+                if(!u.keyIsNumeric(e)) {
+                    if(keyLabel!='-' && keyLabel!='/') return false;
+                }
             }
+            //console.log("Type validation complete, returning true");
+            //console.groupEnd();
+            return true;
         }
+        
+        
+        // This took a lot of experimentation to get right.
+        // Normally a BLUR would occur when an object loses focus
+        //  -> except if the user hits ENTER, we must force validation
+        //  -> except if validation enables new controls
+        //
+        // So we unconditionally fire the afterblurner to hit
+        // anything the control's special validation code might
+        // do.  Then we proceed normally.
+        //
+        // Also: returning false does NOT prevent losing focus,
+        // that's we don't check the return value.
+        x6inputs.afterBlurner(inp);
+        
+        // Get the first and last controls for easier
+        // logic immediately below
+        var tg       = u.p(inp,'xTabGroup','tgdefault');
+        var jqString = '[xTabGroup='+tg+']:not([disabled])';
+        var jqObj = $(jqString)
+        var inpCount = jqObj.length;
+        var first    = jqObj[0];
+        var last     = jqObj[inpCount-1];
+                
+        // If we are on first or last, Enter/Tab dichotomy does not matter,
+        // we just send focus where we want and return false to kill
+        // original behavior.
+        if(inp==first && e.shiftKey) {
+            $('[xTabGroup='+tg+']:not([disabled]):last').focus();
+            //console.log("First input, hit shift, going to last");
+            //console.groupEnd();
+            return false;
+        }
+        if(inp==last && !e.shiftKey) {
+            $('[xTabGroup='+tg+']:not([disabled]):first').focus();
+            //console.log("Last input, no shift, going to first");
+            //console.groupEnd();
+            return false;
+        }
+        
+        // If they hit the TAB key, we can quit now and return
+        // true to allow default behavior.  If they hit ENTER 
+        // we have to work out the next control to give focus
+        // to, either forward or backward
+        if(isTab) {
+            //console.log("Tab key hit, returning true");
+            //console.groupEnd();
+            return true;
+        }
+        if(!e.shiftKey) {
+            // no shift means look for next one
+            var focusTo = false;
+            var foundMe = false;
+            $('[xTabGroup='+tg+']:not([disabled])').each(
+                function() {
+                    //console.log(this.id);
+                    //console.log(focusTo,foundMe);
+                    if(focusTo) return;
+                    if(foundMe) {
+                        focusTo = this.id;
+                    }
+                    if(this == inp) foundMe = true;
+                }
+            );
+            if(focusTo) {
+                //console.log("Setting focus forward to ",focusTo);
+                $('#'+focusTo).focus().select();
+            }
+            
+        }
         else {
-            // hitting tab on the last control is the only
-            // thing I care about.  If I'm not on the last
-            // control, let the browser do it, much faster.
-            var last = $('[xTabGroup='+tg+']:not([disabled]):last')[0];
-            //console.log("The last is:");
-            //console.log(last);
-            //console.log("The input is:");
-            //console.log(inp);
-            if(last==inp) {
-                //console.log("This is last, jumping to first");
-                $('[xTabGroup='+tg+']:not([disabled]):first').focus();
-                e.preventDefault();
+            // shift means look for previous one.  Go forward 
+            // through inputs, assuming each one is the one that
+            // will get focus.  Once we find the input we are
+            // on stop doing that, and the last one assigned will
+            // be the one that gets focus.
+            var focusTo = false;
+            var foundMe = false;
+            $('[xTabGroup='+tg+']:not([disabled])').each(
+                function() {
+                    if(foundMe) return;
+                    if(this == inp) 
+                        foundMe = true;
+                    else
+                        focusTo = this.id;
+                }
+            );
+            if(focusTo) {
+                //console.log("Setting focus backward to ",focusTo);
+                $('#'+focusTo).focus().select();
             }
         }
+        //console.log("Returning True");
         //console.groupEnd();
-        return;
+        return true;
     },
     
     focus: function(inp) {
+        //console.group("Input focus ",inp.id);
+        //console.log("Input: ",inp);
         inp.zSelected = 1;
+        inp.zOriginalValue = u.p(inp,'zOriginalValue','').trim();
+        inp.lastBlurred    = '';
         x6inputs.setClass(inp);
+        //console.log("Input focus DONE");
+        //console.groupEnd();
+        return true;
     },
-    xFocus: function(anyObject) {
-        $(this).addClass('selected');
-    },
+    // KFD 11/29/08, not being called anywhere?
+    //xFocus: function(anyObject) {
+    //    $(this).addCla*ss('selected');
+    //},
     
     blur: function(inp) {
+        //console.group("Input blur ",inp.id);
         inp.zSelected = 0;
         x6inputs.setClass(inp);
+        x6inputs.afterBlurner(inp);
+        //console.log("Input Blur DONE");
+        //console.groupEnd();
+        return true;
     },
-    xBlur: function(anyObject) {
-        $(anyObject).removeClass('selected');
+    // KFD 11/29/08, not being called anywhere?
+    //xBlur: function(anyObject) {
+    //},
+    /*
+    *  We need to route through a wrapper to afterBlur 
+    *  mostly to keep it from firing multiple times.
+    *  Example: a blur calling alert() causes blur to fire again
+    *  
+    */
+    afterBlurner: function(inp) {
+        //console.group("afterBlurner");
+        //console.log(inp);
+        if(u.p(inp,'inblur',false)) {
+            //console.log("inblur flag set, no action");
+            //console.groupEnd();
+            return false;
+        }
+        inp.inblur = true;
+        // If method does not exist forget it
+        if(!inp.afterBlur) {
+            //console.log("No afterBlur(), leaving flag set and returning");
+            //console.groupEnd();
+            return true;
+        }
+        // If value has changed, fire it
+        if(inp.lastBlurred==u.p(inp,'value','').trim()) {
+            //console.log("Input lastBlurred is current value, no action");
+            //console.groupEnd();
+            inp.inblur = false;
+            return true;
+        }
+        else {
+            // Note that returning true only means the afterBlur() will
+            // not be fired again for this value.  It does not mean there
+            // is anything particularly "valid" or correct about the
+            // value.
+            if(inp.afterBlur()) {
+                //console.log("Afterblurner setting flag false, return true");
+                //console.groupEnd();
+                inp.inblur = false;
+                inp.lastBlurred = u.p(inp,'value','').trim();
+                return true;
+            }
+            else {
+                //console.log("Afterblurner setting flag false, return false");
+                //console.groupEnd();
+                inp.inblur = false;
+                return false;
+            }
+        }
     },
     
+    enable: function(inp) {
+        if(typeof(inp)=='string') inp = u.byId(inp);
+        //console.log("Enabling input ",inp.id);
+        inp.disabled = false;
+        inp.zOriginalValue = u.p(inp,'value','');
+        this.setClass(inp);
+    },
+    disable: function(inp) {
+        if(typeof(inp)=='string') inp = u.byId(inp);
+        //console.log("Disabling input ",inp.id);
+        inp.disabled = true;
+        this.setClass(inp);
+    },
+    
     setClass: function(inp) {
+        // Easiest is disabled controls, remove all classes
+        if(u.p(inp,'disabled',false)) {
+            inp.className='';
+            doRow = u.p(inp,'xClassRow',0);
+            if(doRow) {
+                inp.parentNode.parentNode.className = '';
+            }
+            return;
+        }
+        
         ux = u.uniqueId();
         //console.group("setClass for an input  "+ux);
         //console.log(inp);
@@ -746,13 +930,13 @@
         var zSelected = u.p(inp,'zSelected',0);
         var zChanged  = u.p(inp,'zChanged', 0);
         var zError    = u.p(inp,'zError'  , 0);
-        var zRO       = u.p(inp,'zRO'     , 0);
+        //var zRO       = u.p(inp,'zRO'     , 0);
         var zNew      = u.p(inp,'zNew'    , 0);
         
         // now pick them in order of preference,
         // we only pick one stem.
-        if     (zRO)      css = 'readOnly';
-        else if(zError)   css = 'error';
+        //if     (zRO)      css = 'readOnly';
+             if(zError)   css = 'error';
         else if(zNew)     css = 'changed';
         else if(zChanged) css = 'changed';
         else              css = '';
@@ -763,7 +947,7 @@
         //console.log("Final class is "+css);
         
         // Now do some stuff if it is read only
-        inp.disabled = zRO;
+        //inp.disabled = zRO;
         //console.log("Read Only Decision is",inp.disabled);
         
         // Flag to do the row
@@ -771,17 +955,24 @@
             
         // Now set the class name
         inp.className = css;
-        if(doRow && zSelected) {
-            inp.parentNode.parentNode.className = 'selected';
+        if(doRow!=0) {
+            //console.log('do row');
+            if(zSelected) {
+                inp.parentNode.parentNode.className = 'selected';
+            }
+            else {
+                inp.parentNode.parentNode.className = '';
+            }
         }
-        if(doRow && !zSelected) {
-            inp.parentNode.parentNode.className = '';
-        }
         //console.groupEnd();
     },
     
     clearOut: function(inp) {
-        inp.zRO            = 1;
+        if(inp.zSelected==1) {
+            //console.log("In clear out, blurring ",inp);
+            inp.blur();
+        }
+        inp.disabled       = true;
         inp.zNew           = 0;
         inp.zSelected      = 0;
         inp.value          = '';
@@ -800,6 +991,25 @@
     
     jqFocusString: function() {
         return ":input:not([disabled]):first";
+    },
+    
+    obj: function(table,column) {
+        if(table ==null) table='';
+        if(column==null) column='';
+        var selector = ':input'
+        if(table!='') {
+            selector += '[xtableid='+table+']';
+        }
+        if(column!='') {
+            selector += '[xcolumnid='+column+']';
+        }
+        var jq = $(selector);
+        if(jq.length>0) {
+            return jq[0];
+        }
+        else {
+            return false;
+        }
     }
 }
 
@@ -915,12 +1125,14 @@
             x6events.fireEvent('reqNewRow_'+this.zTable);   
         }
     },
+    /*
     buttonDuplicate: function(self,id,table) {
         x6plugins.buttonStandard(self,'duplicate','CtrlD');
         self.main = function() {
             x6events.fireEvent('reqNewRow_'+this.zTable,true);   
         }
     },
+    */
     buttonRemove: function(self,id,table) {
         x6plugins.buttonStandard(self,'remove','CtrlR');
         self.main = function() {
@@ -1037,6 +1249,18 @@
         $(self).click(function() { 
             if(!this.zDisabled) this.main(); 
         });
+        
+        // Make cute mouse effects on buttons
+        self.onmousedown = function() {
+            if(!this.zDisabled) {
+                $(this).addClass('button_mousedown');
+            }
+        }
+        self.onmouseup = self.onmouseout = function() {
+            if(!this.zDisabled) {
+                $(this).removeClass('button_mousedown');
+            }
+        }
     }
 }
  
@@ -1093,6 +1317,7 @@
 x6plugins.tableController = function(self,id,table) {
     // Initialize new properties
     u.bb.vgfSet('skey_'+table,-1);
+    self.zTable   = table;
     self.zSortCol = false;
     self.zSortAsc = false;
     self.zCache   = u.p(self,'xCache')=='Y' ? true : false;
@@ -1153,16 +1378,16 @@
     self['receiveEvent_reqEditRow_'+table] = function(skey) {
         //console.group("tableController reqEditRow "+this.zTable);
         var skeynow = u.bb.vgfGet('skey_'+this.zTable);
-        //if(skeynow == skey) {
-        //    //console.log("Request to edit same row, no action");
-        //} 
-        //else {
+        if(skeynow == skey) {
+            //console.log("Request to edit same row, no action");
+        } 
+        else {
             var result = this.saveOk();
             u.bb.vgfSet('lastSave_'+this.zTable,result);
             if(result!='fail') {
                 x6events.fireEvent('uiEditRow_'+table,skey);
             }
-        //}
+        }
         //console.log("tableController reqEditRow finished");
         //console.groupEnd();
         return true;
@@ -1209,7 +1434,7 @@
             //console.log("Sending x4v_skey ",this.zSkey);
             ua.json.init('x6page',this.zTable);
             ua.json.addParm('x6action','save');
-            ua.json.addParm('x4v_skey',u.bb.vgfGet('skey_'+this.zTable));
+            ua.json.addParm('x6v_skey',u.bb.vgfGet('skey_'+this.zTable));
             ua.json.inputs(jq);
             // Look for an "skey after" to send back 
             var skeyAfter = u.bb.vgfGet('skeyAfter_'+this.zTable,-1);
@@ -1271,7 +1496,7 @@
                     x6inputs.setClass(this);
                 }
             );
-            x6events.fireEvent('uiUndoRow_'+this.zTable);
+            x6events.fireEvent('uiUndoRow_'+this.zTable,skey);
         }
         //console.log("tableController reqUndoRow Finished");
         //console.groupEnd();
@@ -1369,7 +1594,7 @@
             //console.log("tableController bbRow, no row found, fetching");
             ua.json.init('x6page',this.zTable);
             ua.json.addParm('x6action','fetchRow');
-            ua.json.addParm('x4w_skey',skey);
+            ua.json.addParm('x6w_skey',skey);
             if(ua.json.execute(true)) {
                 u.bb.vgfSet('dbRow_'+this.zTable,a.data.row);
             }
@@ -1427,6 +1652,17 @@
 ******
 */
 x6plugins.detailDisplay = function(self,id,table) {
+    self.zTable = table;
+    
+    // If we are supposed to start out disabled, do it
+    if(u.p(self,'xInitDisabled','N')=='Y') {
+        $(self).find(":input").each(
+            function() {
+                x6inputs.disable(this);
+            }
+        );
+    }
+    
     // detail receives a request to go to a mode which
     // is unconditional, it will do what it is told
     x6events.subscribeToEvent('uiEditRow_'+table,id);
@@ -1465,6 +1701,22 @@
         //console.log("detailDisplay uiRowSaved FINISHED");
         //console.groupEnd();
     }
+    
+    /*
+    *   A detail always subscribes to uiUndoRow, and disables
+    *   and clears all controls.  
+    *
+    */
+    x6events.subscribeToEvent('uiUndoRow_'+table,id);
+    self['receiveEvent_uiUndoRow_'+table] = function(skey) {
+        $(this).find(":input").each(
+            function() {
+                x6inputs.clearOut(this);
+            }
+        );
+        u.bb.vgfSet('skey_'+this.zTable,-1);
+    }
+    
         
     /*
     *    A uiDelRow clears all inputs
@@ -1473,12 +1725,7 @@
     self['receiveEvent_uiDelRow_'+table] = function(skey) {
         //console.group("detailDisplay uiDelRow",skey);
         $(this).find(':input').each(function() {
-            this.value='';
-            this.zOriginalValue = '';
-            this.zChanged = 0;
-            this.zActive  = 0;
-            this.zRo      = 1;
-            x6inputs.setClass(this);
+                x6inputs.clearOut(this);
         });
         x6events.fireEvent('buttonsOff_'+this.zTable);
         //console.log("detailDisplay uiDelRow FINISHED");
@@ -1529,16 +1776,15 @@
                 var ro = u.p(this,'xroupd','N');
             }
             if(ro=='Y') {
-                this.zRO = 1;
                 this.disabled = true;
             }
             else {
-                this.zRO = 0;
                 this.disabled = false;
             }
             x6inputs.setClass(this);
         });
-        $(this).find(':input:not(.readOnly):first').focus();
+        var jqString = x6inputs.jqFocusString();
+        $(this).find(jqString).focus();
         
         // Now that all displays are done, if we have a tab
         // selector then select it
@@ -1602,6 +1848,10 @@
 ******
 */
 x6plugins.x6tabDiv = function(self,id,table) {
+    self.zTable    = table;
+    self.x6profile = u.p(self,'x6profile','none');
+    self.kbOnEdit  = ['x6tabDiv','twosides'].indexOf(self.x6profile)>=0;
+    
     /*
     *    These two will tell us down below if the grid
     *    displays inputs for new rows and allows 
@@ -1609,7 +1859,7 @@
     */
     var uiNewRow  = u.p(self,'uiNewRow' ,'');
     var uiEditRow = u.p(self,'uiEditRow','');
-    
+ 
     /*
     *  A grid may be set to receive a cacheRows event.
     *  If so, it will replace its own data with the
@@ -1622,32 +1872,28 @@
             // Clear current data
             $(this).find('.tbody').html();
             // Add new data
-            for(var x in rows) {
-                this.addRow(rows[x]);
-            }
+            //for(var x in rows) {
+            //    this.addRow(rows[x]);
+            //}
         }
     }
     
     /*
-    *   Related to the above is a simple command to add a row
-    *
-    */
-    self.addRow = function(row) {
-        
-    }
-    
-    
-    /*
     *   The grid is happy to display a new row for
     *   editing if a certain flag has been set.
     *   The event uiNewRow is unconditional, it means
     *   all prerequisites have been met and the grid
     *   should proceed forthwith.
     */
-    if(uiNewRow=='inline') {
-        x6events.subscribeToEvent('uiNewRow_'+table,id);
-        
+    x6events.subscribeToEvent('uiNewRow_'+table,id);
+    if(uiNewRow!='inline') {
+        // If not inline, it always stops responding on a new row
         self['receiveEvent_uiNewRow_'+table] = function() {
+            this.keyboardOff();
+        }
+    }
+    else {
+        self['receiveEvent_uiNewRow_'+table] = function() {
             //console.group("tabDiv uiNewRow "+this.zTable);
             var skey = u.bb.vgfGet('skey_'+this.zTable,-1);
             
@@ -1676,27 +1922,6 @@
             *   inputs that have been provided by the PHP code,
             *   and get them all initialized and ready to go.
             */
-            /*  Don't work in IE 
-            var newRow = new jsHtml('div');
-            newRow.hp.id = 'row_0';
-            newRow.hp.style = 'display: none;';
-            var numbers = [ 'int', 'numb', 'money' ];
-            for (var idx in this.zColsInfo) {
-                var colInfo = this.zColsInfo[idx];
-                if(colInfo.column_id == '') continue;
-                
-                var innerDiv = newRow.h('div');
-                innerDiv.hp.style= "width: "+colInfo.width+"px;";
-                innerDiv.hp.gColumn = idx;
-                if(numbers.indexOf(colInfo.type_id)>=0) {
-                    innerDiv.hp.style+="text-align: right";
-                }
-                var id = '#wrapper_'+this.zTable+'_'+colInfo.column_id;
-                var newInput = $(id).html();
-                //console.log("column: ",colInfo.column_id);
-                innerDiv.innerHtml = newInput;
-            }
-            */
             var newRow = "<div id='row_0' style='display:none'>";
             var numbers = [ 'int', 'numb', 'money' ];
             for (var idx in this.zColsInfo) {
@@ -1749,9 +1974,10 @@
             */
             tabIndex = 1000;
             $(this).find(':input').each(
-                function() { 
+                function() {
                     x6inputs.initInput(this,tabIndex++,'new','rowNew'); 
                     this.setAttribute('xTabGroup','rowEdit');
+                    this.setAttribute('xClassRow','0');
                 }
             );
             var grid = this;
@@ -1764,22 +1990,27 @@
             // Send a message and get lost
             u.bb.vgfSet('skey_'+this.zTable,0);
             x6events.fireEvent('buttonsOn_'+this.zTable);
+            this.keyboardOff();
             //console.log('New row created, ready to edit');
             //console.groupEnd();
             return true;
         }
     }
-    
+
+
     /*
-    *   The grid is happy to display an existing row
-    *   for editing if the flag has been set.  This
-    *   is an unconditional event, it assumes all is
-    *   well and nothing stands in the way of editing.
+    *   Always subscribe to an editrow command.  If in edit
+    *   mode the handler makes inputs and stuff.  If not,
+    *   it just turns off the keyboard.
     */
-    if(uiEditRow=='inline') {
-        x6events.subscribeToEvent('uiEditRow_'+table,id);
-        
+    x6events.subscribeToEvent('uiEditRow_'+table,id);
+    if(uiEditRow!='inline') {
         self['receiveEvent_uiEditRow_'+table] = function(skey) {
+            this.keyboardOff();
+        }
+    }
+    else {
+        self['receiveEvent_uiEditRow_'+table] = function(skey) {
             //console.group("tabDiv uiEditRow "+this.zTable);
     
             if( $(this).find('#row_'+skey).length == 0) {
@@ -1813,15 +2044,18 @@
                     var colnum = u.p(this,'gColumn');
                     var colid  = ...
 
[truncated message content] | 
| 
     
      
      
      From: <ken...@us...> - 2008-12-08 17:01:24
       
   | 
Revision: 917
          http://andro.svn.sourceforge.net/andro/?rev=917&view=rev
Author:   kendowns
Date:     2008-12-08 17:01:21 +0000 (Mon, 08 Dec 2008)
Log Message:
-----------
Many major changes after hack-a-thon
Modified Paths:
--------------
    trunk/andro/clib/x6.js
Modified: trunk/andro/clib/x6.js
===================================================================
--- trunk/andro/clib/x6.js	2008-12-08 17:00:56 UTC (rev 916)
+++ trunk/andro/clib/x6.js	2008-12-08 17:01:21 UTC (rev 917)
@@ -35,12 +35,12 @@
    Beanshell files show the jEdit commands for turning logging
    on and off by commenting and uncommenting the relevant lines.
    
-   If you want to do it manually, just replace all "console."
+   If you want to do it manually, just replace all "//console."
    with "//console." or vice-versa.
    
    # Beanshell: Turn logging off by commenting out lines
-    SearchAndReplace.setSearchString("console.");
-    SearchAndReplace.setReplaceString("console.");
+    SearchAndReplace.setSearchString("//console.");
+    SearchAndReplace.setReplaceString("//console.");
     SearchAndReplace.setBeanShellReplace(false);
     SearchAndReplace.setIgnoreCase(true);
     SearchAndReplace.setRegexp(false);
@@ -48,8 +48,8 @@
     SearchAndReplace.replaceAll(view);
 
    # Beanshell: Turn logging on by uncommenting the lines.
-    SearchAndReplace.setSearchString("console.");
-    SearchAndReplace.setReplaceString("console.");
+    SearchAndReplace.setSearchString("//console.");
+    SearchAndReplace.setReplaceString("//console.");
     SearchAndReplace.setBeanShellReplace(false);
     SearchAndReplace.setIgnoreCase(true);
     SearchAndReplace.setRegexp(false);
@@ -463,32 +463,13 @@
     // DOM elements with property x6plugIn=xxx.  
     // Invoke the constructor for each one.
     init: function() {
-        // KFD 11/28/08.  Removed this and put initialization commands
-        //                into jqDocReady.  Turns out each plugin init
-        //                takes 5ms, but the jquery search for them
-        //                takes 350ms of a second, terrible.  So the
-        //                PHP code is generating commands to initialize
-        //                each plugin.
-        // Job 1: Activate all of the plugins
-        /*
-        for(var plugInId in x6plugins) {
-            $('[x6plugIn='+plugInId+']').each(function() {
-                    if(u.p(this,'id','')=='') {
-                        this.id = u.uniqueId();
-                    }
-                    //console.time("inititialing "+this.id);
-                    this.zTable = u.p(this,'x6table');
-                    //console.log("Initializing x6plugin  ",this);
-                    x6plugins[plugInId](this,this.id,this.zTable);
-                    //console.timeEnd("inititialing "+this.id);
-            });
-        }
-        */
-        
-        // Job 2, activate a global keyboard handler
+        // Activate a global keyboard handler
+        // SEE ALSO: input.keyDown(), it must also pass some
+        //           events to keyDispatcher that don't go to
+        //           the document.keypress from an input 
         $(document).keypress(function(e) {
                 //console.group("Document Keypress");
-                //console.log(e); 
+                //console.log("keypress ",e);
                 var retval= x6.keyDispatcher(e);
                 //console.groupEnd(); 
                 return retval;
@@ -508,6 +489,7 @@
     initFocus: function() {
         //var str   = '[x6firstFocus=Y]:not([disabled]):reallyvisible:first';
         var str   = 'input:not([disabled]):reallyvisible:first';        
+        //var first = $('input:not([disabled])').isVisible().find(':first');
         var first = $(str);
         if(first.length>0) first.focus();
         else $('.x6main').focus();
@@ -515,73 +497,6 @@
     
     // Keyboard handler
     keyDispatcher: function(e) {
-        /*
-        var x = e.keyCode;
-        
-        // First make a big list of codes and look for the event
-        var x4Keys = { };
-        x4Keys['8']  = 'BackSpace';
-        x4Keys['9']  = 'Tab';
-        x4Keys['13'] = 'Enter';
-        x4Keys['16'] = 'Shift';
-        x4Keys['17'] = 'Ctrl';
-        x4Keys['18'] = 'Alt';
-        x4Keys['20'] = 'CapsLock';
-        x4Keys['27'] = 'Esc';
-        x4Keys['33'] = 'PageUp';
-        x4Keys['34'] = 'PageDown';
-        x4Keys['35'] = 'End';
-        x4Keys['36'] = 'Home';
-        x4Keys['37'] = 'LeftArrow';
-        x4Keys['38'] = 'UpArrow';
-        x4Keys['39'] = 'RightArrow';
-        x4Keys['40'] = 'DownArrow';
-        x4Keys['45'] = 'Insert';
-        x4Keys['46'] = 'Delete';
-        x4Keys['112']= 'F1' ;
-        x4Keys['113']= 'F2' ;
-        x4Keys['114']= 'F3' ;
-        x4Keys['115']= 'F4' ;
-        x4Keys['116']= 'F5' ;
-        x4Keys['117']= 'F6' ;
-        x4Keys['118']= 'F7' ;
-        x4Keys['119']= 'F8' ;
-        x4Keys['120']= 'F9' ;
-        x4Keys['121']= 'F10';
-        x4Keys['122']= 'F11';
-        x4Keys['123']= 'F12';
-    
-        // If they did not hit a control key of some sort, look
-        // next for letters
-        var retval = '';
-        if(typeof(x4Keys[x])!='undefined') {
-            retval = x4Keys[x];
-        }
-        else {
-            var letters = 
-                [ 'A', 'B', 'C', 'D', 'E', 'F', 'G',
-                  'H', 'I', 'J', 'K', 'L', 'M', 'N',
-                  'O', 'P', 'Q', 'R', 'S', 'T', 'U',
-                  'V', 'W', 'X', 'Y', 'Z' ];
-            var numbers = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ];
-            if(e.charCode >= 65 && e.charCode <= 90) {
-                retval = letters[e.charCode - 65];
-            }
-            else if(e.charCode >= 97 && e.charCode <= 121) {
-                retval = letters[e.charCode - 97];
-            }
-            else if(e.charCode >= 48 && e.charCode <= 57) {
-                retval = numbers[e.charCode - 48];
-            }
-        }
-    
-        // otherwise put on any prefixes and return
-        if(e.ctrlKey)  retval = 'Ctrl'  + retval;
-        // KFD 8/4/08, this never worked, removed.
-        if(e.altKey)   retval = 'Alt'   + retval;
-        if(e.shiftKey) retval = 'Shift' + retval;
-        */
-        
         var retval = u.keyLabel(e);
         
         // Make list of keys to stop no matter what
@@ -614,57 +529,6 @@
    
 \* **************************************************************** */
 var x6inputs = {
-    // This routine takes an input that has no x6 event
-    // handlers and adds all of the event handlers to it
-    initInput: function(input,tabIndex,mode,tabGroup) {
-        //console.group("Initializing Input");
-        //console.log("tabindex, mode, tabgroup: ",tabIndex,mode,tabGroup);
-        //console.log(input);
-        
-        // Get the read-only decision
-        if(mode=='new') {
-            //console.log("hello, ro ins");
-            input.disabled = u.p(input,'xroins','N')=='Y';
-        }
-        else {
-            //console.log("hello, ro upd");
-            input.disabled = u.p(input,'xroupd','N')=='Y';
-        }
-        
-        // This is standard events and attributes
-        input.setAttribute('xTabGroup',tabGroup);
-        input.setAttribute('tabIndex' ,tabIndex);
-        /* IE Madness.  If no value assigned, the property 
-           is not there, must use u.p                         */;
-        //input.zOriginalValue = input.value.trim();
-        // KFD 11/27/08, this belongs in focus...
-        input.zOriginalValue = u.p(input,'value','').trim();
-        if(!input.zRO) {
-            $(input)
-                .keyup(function(e)   { x6inputs.keyUp(e,this)   })
-                .focus(function(e)   { x6inputs.focus(this)   })
-                .blur(function(e)    { x6inputs.blur(this)    })
-                .keydown(function(e) { return x6inputs.keyDown(e,this) });
-        }
-        if(mode=='new') {
-            input.zNew = 1;
-        }
-        x6inputs.setClass(input);
-        
-        // KFD 11/1/08, EXPERIMENTAL use of jquery.maskedinput
-        //if(u.p(input,'xinputmask','')!='') {
-        //    $(input).mask(u.p(input,'xinputmask'));
-        //}
-
-        // This is important, it says that this is an 
-        // active input.  This distinguishes it from possible
-        // hidden inputs that were used as a clone source 
-        // that have many of the same properties.
-        input.zActive = 1;
-
-        //console.groupEnd();
-    },
-    
     // Key up is used to look for changed values because
     // you do not see an input's new value until the keyup 
     // event.  You do not see it in keypress or keydown.
@@ -684,7 +548,6 @@
     //
     keyDown: function(e,inp) {
         //console.group('Input keyDown ');
-        //console.log(e);
         //console.log(inp);
         var keyLabel=u.keyLabel(e);
         var isTab   =keyLabel=='Tab'    || keyLabel=='ShiftTab';
@@ -695,7 +558,35 @@
         
         // All meta keys return true immediately except TAB and ENTER
         if(isMeta && !isNav) {
-            //console.log("meta key but not tab or enter, returning true");
+            //console.log(keyLabel);
+            var handUpList = ['UpArrow','DownArrow','PageUp','PageDown'];
+            if(handUpList.indexOf(keyLabel)>=0) {
+                //console.log("Weird key that we pass up to doc-level keyPress");
+                var retval= x6.keyDispatcher(e);
+                //console.groupEnd(); 
+                return retval;
+            }
+            else if(keyLabel=='CtrlLeftArrow') {
+                this.firstInput(inp);
+            }
+            else if(keyLabel=='CtrlRightArrow') {
+                this.lastInput(inp);
+            }
+            else if(keyLabel=='Home') {
+                if(inp.selectionStart == 0 && inp.selectionEnd==0)
+                    this.firstInput(inp);
+            }
+            else if(keyLabel=='End') {
+                //console.log(inp);
+                var ss = inp.selectionStart;
+                var se = inp.selectionEnd;
+                var ln = inp.value.toString().trim().length;
+                //console.log(ss,se,ln);
+                if(ss == se && se == ln) this.lastInput(inp);
+            }
+            else {
+                //console.log("meta but not nav, ret true");
+            }
             //console.groupEnd();
             return true;
         }
@@ -998,6 +889,15 @@
         }
     },
     
+    firstInput: function(inp) {
+        var xtg = u.p(inp,'xTabGroup','tgdefault');
+        $(":input[xtabgroup="+xtg+"]:not([disabled]):first").focus();
+    },
+    lastInput: function(inp) {
+        var xtg = u.p(inp,'xTabGroup','tgdefault');
+        $(":input[xtabgroup="+xtg+"]:not([disabled]):last").focus();
+    },
+    
     jqFocusString: function() {
         return ":input:not([disabled]):first";
     },
@@ -1057,14 +957,14 @@
         }
     },
     */
-    buttonRemove: function(self,id,table) {
-        x6plugins.buttonStandard(self,'remove','CtrlR');
+    buttonDelete: function(self,id,table) {
+        x6plugins.buttonStandard(self,'delete','CtrlD');
         self.main = function() {
             x6events.fireEvent('reqDelRow_'+this.zTable);
         }
     },
-    buttonAbandon: function(self,id,table) {
-        x6plugins.buttonStandard(self,'abandon','CtrlT');
+    buttonCancel: function(self,id,table) {
+        x6plugins.buttonStandard(self,'cancel','Esc');
         self.main = function() {
             if(confirm("Abandon all changes?")) {
                 x6events.fireEvent('reqUndoRow_'+this.zTable);
@@ -1139,15 +1039,15 @@
         self.zKey      = key;
         
         // Respond to an enable event
-        x6events.subscribeToEvent('enable_'+action,self.id);
-        self['receiveEvent_enable_'+action] = function() {
+        x6events.subscribeToEvent('enable_'+action+'_'+self.zTable,self.id);
+        self['receiveEvent_enable_'+action+'_'+self.zTable] = function() {
             this.className = 'button';
             this.zDisabled = false;
         }
 
         // Respond to an disable event
-        x6events.subscribeToEvent('disable_'+action,self.id);
-        self['receiveEvent_disable_'+action] = function() {
+        x6events.subscribeToEvent('disable_'+action+'_'+self.zTable,self.id);
+        self['receiveEvent_disable_'+action+'_'+self.zTable] = function() {
             this.className = 'button_disabled';
             this.zDisabled = true;
         }
@@ -1536,15 +1436,15 @@
     */
     x6events.subscribeToEvent('buttonsOn_'+table,id);
     self['receiveEvent_buttonsOn_'+table] = function() {
-        x6events.fireEvent('enable_save');
-        x6events.fireEvent('enable_abandon');
-        x6events.fireEvent('enable_remove');
+        x6events.fireEvent('enable_save_'   +this.zTable);
+        x6events.fireEvent('enable_abandon_'+this.zTable);
+        x6events.fireEvent('enable_remove_' +this.zTable);
     }
     x6events.subscribeToEvent('buttonsOff_'+table,id);
     self['receiveEvent_buttonsOff_'+table] = function() {
-        x6events.fireEvent('disable_save');
-        x6events.fireEvent('disable_abandon');
-        x6events.fireEvent('disable_remove');
+        x6events.fireEvent('disable_save_'   +this.zTable);
+        x6events.fireEvent('disable_abandon_'+this.zTable);
+        x6events.fireEvent('disable_remove_' +this.zTable);
     }
 }
     
@@ -1810,7 +1710,7 @@
     *   should proceed forthwith.
     */
     x6events.subscribeToEvent('uiNewRow_'+table,id);
-    if(uiNewRow!='inline') {
+    if(uiNewRow!='Y') {
         // If not inline, it always stops responding on a new row
         self['receiveEvent_uiNewRow_'+table] = function() {
             this.keyboardOff();
@@ -1897,10 +1797,10 @@
             *   row visible and editable
             */
             tabIndex = 1000;
+            var grid = this;
             $(this).find(':input').each(
                 function() {
-                    x6inputs.initInput(this,tabIndex++,'new','rowNew'); 
-                    this.setAttribute('xTabGroup','rowEdit');
+                    grid.initInput(this,tabIndex++,'new','rowNew'); 
                     this.setAttribute('xClassRow','0');
                 }
             );
@@ -1920,6 +1820,39 @@
             return true;
         }
     }
+    
+   
+    self.initInput = function(input,tabIndex,mode,tabGroup) {
+        //console.group("Initializing Input");
+        //console.log("tabindex, mode, tabgroup: ",tabIndex,mode,tabGroup);
+        //console.log(input);
+        
+        // Get the read-only decision
+        if(mode=='new') {
+            //console.log("hello, ro ins");
+            input.disabled = u.p(input,'xroins','N')=='Y';
+        }
+        else {
+            //console.log("hello, ro upd");
+            input.disabled = u.p(input,'xroupd','N')=='Y';
+        }
+        
+        // This is standard events and attributes
+        input.setAttribute('xTabGroup',tabGroup);
+        input.setAttribute('tabIndex' ,tabIndex);
+        input.zOriginalValue = u.p(input,'value','').trim();
+        if(mode=='new') {
+            input.zNew = 1;
+        }
+        x6inputs.setClass(input);
+        
+        // This is important, it says that this is an 
+        // active input.  This distinguishes it from possible
+        // hidden inputs that were used as a clone source 
+        // that have many of the same properties.
+        input.zActive = 1;
+        //console.groupEnd();
+    }
 
 
     /*
@@ -1928,9 +1861,9 @@
     *   it just turns off the keyboard.
     */
     x6events.subscribeToEvent('uiEditRow_'+table,id);
-    if(uiEditRow!='inline') {
+    if(uiEditRow!='Y') {
         self['receiveEvent_uiEditRow_'+table] = function(skey) {
-            this.keyboardOff();
+            //this.keyboardOff();
         }
     }
     else {
@@ -1987,17 +1920,18 @@
                 }
             );
             tabIndex = 1000;
+            var grid = this;
             $(this).find('.tbody #row_'+skey+' :input').each(
                 function() {
+                    grid.initInput(this,tabIndex++,'edit','rowEdit');
                     this.setAttribute('xClassRow',0);
-                    x6inputs.initInput(this,tabIndex++,'edit','rowEdit');
                 }
             );
             var string = x6inputs.jqFocusString();
             $(this).find('.tbody #row_'+skey).addClass('selected');
             $(this).find('.tbody #row_'+skey+' '+string).focus();
             x6events.fireEvent('buttonsOn_'+this.zTable);
-            this.keyboardOff();
+            //this.keyboardOff();
             u.bb.vgfSet('skey_'+this.zTable,skey);
             //console.log('uiEditRow Completed, returning true');
             //console.groupEnd();
@@ -2061,9 +1995,10 @@
     *   Undo Row: the table controller has already reset
     *   any inputs, we will just remove them
     */
-    if(uiEditRow=='inline' || uiNewRow=='inline') {
+    if(uiEditRow=='Y' || uiNewRow=='Y') {
         x6events.subscribeToEvent('uiUndoRow_'+table,id);
         self['receiveEvent_uiUndoRow_'+table] = function(skey) {
+            x6events.fireEvent('buttonsOff_'+this.zTable);
             this.removeInputs();
             $(this).find("#row_"+skey).mouseover();
             u.bb.vgfSet('skey_'+this.zTable,-1);
@@ -2266,7 +2201,7 @@
     *    If a grid is displaying inputs, it may also have
     *    to display errors.
     */
-    if(uiEditRow=='inline' || uiNewRow=='inline') {
+    if(uiEditRow=='Y' || uiNewRow=='Y') {
         x6events.subscribeToEvent('uiShowErrors_'+table,id);
         self['receiveEvent_uiShowErrors_'+table] = function(errors) {
             //console.group("tabDiv uiShowErrors");
@@ -2290,33 +2225,18 @@
     }
     
     /*
-    *    Keyboard handling.  At very
-    *    least there are always 3 we accept: arrow keys and
-    *    ENTER key.  These are not automatically subscribed,
-    *    they must be turned on and off according to context.
+    *    Keyboard handling: row navigation
     */
-    // First keyboard event, keydown
     self.receiveEvent_key_UpArrow = function(e) {
         //console.group("tabDiv key_UpArrow");
-        var jqRows = $(this).find('.hilight').prev();
-        if(jqRows.length==0) {
-            //console.log("going for first row");
-            $(this).find('.tbody div:first').addClass('hilight');
+        var jqCurrent = this.jqCurrentRow();
+        var jqRowPrev = $(jqCurrent).prev();
+        if(jqCurrent.length==0) {
+            this.goRowTop();
         }
-        else {
-            // before doing anything, figure how many rows below
-            var rowsBelow = $(this).find('.hilight').nextAll().length;
-            var rowsLimit = Number(u.p(this,'xRowsVisible')) / 2;
-            
-            //console.log("Going for previous row");
-            $(this).find('.tbody div.hilight').removeClass('hilight')
-                .prev().addClass('hilight');
-            if(rowsBelow >= rowsLimit) {
-                var tbody = $(this).find('.tbody');
-                var shNow = tbody.scrollTop();
-                var shNew = Number(u.p(this,'cssLineHeight'));
-                tbody.scrollTop(shNow - (shNew-2));
-            }
+        else if(jqRowPrev.length!=0) {
+            this.goRowJq(jqRowPrev);
+            this.scrollMove(-1);
         }
         x6events.retvals['key_UpArrow'] =false;
         //console.log("tabDiv key_UpArrow finished");
@@ -2324,48 +2244,170 @@
     }
     self.receiveEvent_key_DownArrow = function(e) {
         //console.group("tabDiv key_DownArrow");
-        var jqRowNext = $(this).find('.hilight').next();
-        var jqRowPrev = $(this).find('.hilight').prev();
-        if(jqRowNext.length==0 && jqRowPrev.length==0) {
-            //console.log("going for first row");
-            $(this).find('.tbody div:first').addClass('hilight');
+        //console.log(e);
+        var jqCurrent = this.jqCurrentRow();
+        var jqRowNext = $(jqCurrent).next();
+        if(jqCurrent.length==0) {
+            this.goRowTop();
         }
         else if(jqRowNext.length!=0) {
+            this.goRowJq(jqRowNext);
+            this.scrollMove(1);
+        }
+        x6events.retvals['key_DownArrow'] =false;
+        //console.log("tabDiv key_DownArrow finished");
+        //console.groupEnd();
+    }
+    self.receiveEvent_key_PageUp = function(e) {
+        //console.group("tabDiv key_DownArrow");
+        var jqCurrent = this.jqCurrentRow();
+        var jqRowPrev = $(jqCurrent).prevAll();
+        if(jqCurrent.length==0) {
+            this.goRowTop();
+        }
+        else if(jqRowPrev.length!=0) {
+            var cntAbove  = jqRowPrev.length;
+            var cntJump   = Number(u.p(this,'xRowsVisible')) - 2;
+            
+            // Figure out how far to go up, then figure the row
+            var rowsChange = cntAbove < cntJump ? cntAbove : cntJump;
+            var newRow     = jqRowPrev[ rowsChange - 1 ];
+            this.goRowJq($(newRow));
+            this.scrollMove(-rowsChange);
+        }
+        x6events.retvals['key_PageUp'] =false;
+        //console.log("tabDiv key_DownArrow finished");
+        //console.groupEnd();
+    }
+    self.receiveEvent_key_PageDown = function(e) {
+        //console.group("tabDiv key_DownArrow");
+        var jqCurrent = this.jqCurrentRow();
+        var jqRowNext = $(jqCurrent).nextAll();
+        if(jqCurrent.length==0) {
+            this.goRowTop();
+        }
+        else if(jqRowNext.length!=0) {
             // before doing anything, figure how many rows above
-            var rowsAbove = $(this).find('.hilight').prevAll().length;
-            var rowsLimit = Number(u.p(this,'xRowsVisible')) / 2;
+            var cntBelow = jqRowNext.length;
+            var cntJump  = Number(u.p(this,'xRowsVisible')) - 2;
             
-            //console.log("going for next row");
-            $(this).find('.hilight').removeClass('hilight')
-                .next().addClass('hilight');
-            if(rowsAbove >= rowsLimit) {
-                var tbody = $(this).find('.tbody');
-                var shNow = tbody.scrollTop();
-                var shNew = Number(u.p(this,'cssLineHeight'));
-                tbody.scrollTop(shNow + (shNew -2 ));
-            }
+            // Figure out how far to go up, then figure the row
+            var rowsChange = cntBelow < cntJump ? cntBelow : cntJump;
+            var newRow     = jqRowNext[ rowsChange - 1 ];
+            this.goRowJq($(newRow));
+            this.scrollMove(rowsChange);
         }
-        x6events.retvals['key_DownArrow'] =false;
+        x6events.retvals['key_PageDown'] =false;
         //console.log("tabDiv key_DownArrow finished");
         //console.groupEnd();
     }
+    self.receiveEvent_key_CtrlHome = function(e) {
+        this.goRowTop();
+        x6events.retvals['key_CtrlHome'] =false;
+    }
+    self.receiveEvent_key_CtrlEnd = function(e) {
+        this.goRowJq( $(this).find('.tbody > div:last') ); 
+        var rowHeight = Number(u.p(this,'cssLineHeight'));
+        var rowCount  = $(this).find('.tbody > div').length;
+        $(this).find('.tbody').scrollTop(rowHeight * rowCount);
+    }
     self.receiveEvent_key_Enter = function(e) {
         //console.group("tabDiv key_Enter - clicking hilighted rows");
         $(this).find('.tbody div.hilight').click();
         //console.groupEnd();
     }
+    
+    /*
+    *    Routines to move pick a row and scroll
+    *
+    */
+    self.jqCurrentRow = function() {
+        var jq = $(this).find('.selected');
+        if(jq.length > 0) return jq;
+        var jq = $(this).find('.hilight');
+        if(jq.length > 0) return jq;
+        return $([]);
+        
+    }
+    self.goRowBySkey = function(skey) {
+        //console.log('goRowBySkey ',skey);
+        if( u.p(this,'uiEditRow','')=='Y') {
+            //console.log("We can edit, firing reqEditRow");
+            x6events.fireEvent('reqEditRow_'+this.zTable,skey);
+        }
+        else {
+            //console.log("We do not edit, hilighting");
+            $(this).find('.hilight').removeClass('.hilight');
+            $(this).find('#row_'+skey).addClass('.hilight');
+        }
+    }
+    self.goRow = function(ordinal) {
+        var row = $(this).find('.tbody > div')[ordinal];
+        var skey= row.id.slice(4);
+        //console.log("goRow for ",ordinal,' has picked skey ',skey);
+        this.goRowBySkey(skey);
+    }
+    self.goRowJq = function(jqRow) {
+        var skey = jqRow[0].id.slice(4);
+        //console.log("goRow by jQuery object ");
+        //console.log(jqRow);
+        //console.log(skey);
+        this.goRowBySkey(skey);
+    }
+    self.goRowTop = function() {
+        this.goRow(0);
+        $(this).find('.tbody').scrollTop(0);
+    }
+    self.scrollMove = function(change) {
+        // Get all of the numbers we need
+        var jqRow     = this.jqCurrentRow();
+        var cntAbove  = $(jqRow).prevAll().length;
+        var cntBelow  = $(jqRow).nextAll().length;
+        var cntAll    = $(this).find('.tbody > div').length;
+        var cntVisible= Number(u.p(this,'xRowsVisible'));
+        var cssHeight = Number(u.p(this,'cssLineHeight'));
+        //console.log(change,cntAbove,cntBelow,cntAll,cntVisible,cssHeight);
+        
+        var stAdjust = 0;
+        if(change > 0) {
+            if(cntAbove > (cntVisible/2)) {
+                var stAdjust = change * (cssHeight-2);
+            }
+        }
+        else {
+            if(cntBelow > (cntVisible/2)) {
+                var stAdjust = change * (cssHeight-2);
+            }
+        }
+        if(stAdjust!=0) {
+            //console.log(stAdjust);
+            var stNow     = $(this).find('.tbody').scrollTop();
+            $(this).find('.tbody').scrollTop(stNow + stAdjust);
+        }
+        
+    }
 
+    /*
+    *   This is the list of the keys that we wrote handlers
+    *   for above.  They have to sometimes be turned off
+    *   and on
+    */
+    self.keyList = [
+        'PageUp', 'PageDown', 'CtrlHome', 'CtrlEnd'
+        ,'UpArrow', 'DownArrow', 'Enter'
+    ];
     self.keyboardOn = function() {
-        //console.log("Turning on keyboard events ",this.id);
-        x6events.subscribeToEvent('key_UpArrow',id);
-        x6events.subscribeToEvent('key_DownArrow',id);
-        x6events.subscribeToEvent('key_Enter',id);
+        for(var key in this.keyList) {
+            var keyLabel = this.keyList[key];
+            x6events.subscribeToEvent('key_'+keyLabel,id);
+        }
         $(this).focus();
     }
     self.keyboardOff = function() {
-        x6events.unsubscribeToEvent('key_UpArrow',id);
-        x6events.unsubscribeToEvent('key_DownArrow',id);
-        x6events.unsubscribeToEvent('key_Enter',id);
+        for(var key in this.keyList) {
+            var keyLabel = this.keyList[key];
+            x6events.unsubscribeToEvent('key_'+keyLabel,id);
+        }
     }
     if(u.p(self,'xInitKeyboard','N')=='Y') self.keyboardOn();
 
@@ -2570,13 +2612,14 @@
     for(var x = offset; x<(offset+count); x++) {
         x6events.subscribeToEvent('key_Ctrl'+x.toString(),self.id);
         self['receiveEvent_key_Ctrl'+x.toString()] = function(key) {
-            console.time("tabs key");
-            console.time("checking for visible");
+            //console.time("tabs key");
+            //console.time("checking for visible");
             // Abort if he is not really visible, this is the
             // easiest way to do this, and we don't have to 
             // keep track of whether or not it is visible.
             if($(this).find(":reallyvisible").length==0) return;
-            console.timeEnd("checking for visible");
+            //if($(this).isVisible().length==0) return;            
+            //console.timeEnd("checking for visible");
             
             // get the offset, the keystroke, 
             // and calculate the index.
@@ -2585,7 +2628,7 @@
             var index  = (key - offset);
             var str = '#'+this.id+' > ul';
             $(str).tabs('select',index);
-            console.timeEnd("tabs key");
+            //console.timeEnd("tabs key");
         }
     }
 }
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
 | 
| 
     
      
      
      From: <ken...@us...> - 2009-01-23 19:09:20
       
   | 
Revision: 1135
          http://andro.svn.sourceforge.net/andro/?rev=1135&view=rev
Author:   kendowns
Date:     2009-01-23 19:09:10 +0000 (Fri, 23 Jan 2009)
Log Message:
-----------
removed some stray console.log commands, modified tableController.reqEditRow so that it always fires uiEditRow
Modified Paths:
--------------
    trunk/andro/clib/x6.js
Modified: trunk/andro/clib/x6.js
===================================================================
--- trunk/andro/clib/x6.js	2009-01-22 20:13:22 UTC (rev 1134)
+++ trunk/andro/clib/x6.js	2009-01-23 19:09:10 UTC (rev 1135)
@@ -4100,9 +4100,6 @@
         }
         x6events.subscribeToEvent('buttonsEdit_'+table,id);
         self['receiveEvent_buttonsEdit_'+table] = function(turnOn) {
-            console.log('buttonsedit ',table);
-            console.log(turnOn);
-            console.log($(this).prop('permupd','N'));
             if(turnOn) {
                 if($(this).prop('permupd','N')=='Y') {
                     this.className = 'button';
@@ -4310,17 +4307,22 @@
     self['receiveEvent_reqEditRow_'+table] = function(skey) {
         x6.console.group("tableController reqEditRow "+this.zTable+", "+skey);
         var skeynow = this.zSkey;
-        if(skeynow == skey) {
-            x6.console.log("Request to edit same row, no action");
-        } 
-        else {
+        // KFD 1/23/09.  Big change.  Table Controller must not 
+        //               decide what to do, must let the UI elements
+        //               decide, because they may have to change
+        //               tabs, set focus, etc.
+        //if(skeynow == skey) {
+        //    x6.console.log("Request to edit same row, no action");
+        //} 
+        //else {
             var result = this.saveOk();
             x6bb.fwSet('lastSave_'+this.zTable,result);
             if(result!='fail') {
                 x6events.fireEvent('uiEditRow_'+this.zTable,skey);
                 this.zSkey = skey;
             }
-        }
+        //}
+        // KFD 1/23/09 (END)
         x6.console.groupEnd();
         return true;
     }
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
 | 
| 
     
      
      
      From: <ken...@us...> - 2009-01-28 19:39:14
       
   | 
Revision: 1167
          http://andro.svn.sourceforge.net/andro/?rev=1167&view=rev
Author:   kendowns
Date:     2009-01-28 19:39:11 +0000 (Wed, 28 Jan 2009)
Log Message:
-----------
Several Changes:
1) When user hits ESC, if there is a widget id='x6exit' value 'Y', the window will close.  This is good for having custom buttons on detail screens that send the user to a custom screen.  When they are done they just hit ESC and they pop back to the original.
2) Fixed bug in conventional profile when editing children -- pk values of parents were not getting into the insert commands.
3) Cleaned up some event handling on tabShow to use the 'objectFocus' event.
Modified Paths:
--------------
    trunk/andro/clib/x6.js
Modified: trunk/andro/clib/x6.js
===================================================================
--- trunk/andro/clib/x6.js	2009-01-27 21:53:09 UTC (rev 1166)
+++ trunk/andro/clib/x6.js	2009-01-28 19:39:11 UTC (rev 1167)
@@ -722,18 +722,23 @@
                 var exitApproved = x6bb.fwGet('exitApproved',false);
                 x6.console.log("Key dispatch, ESC, exitapproved: ",exitApproved);
                 if(exitApproved) {
-                    x6.console.log("exit for ESC was approved, going to menu");
-                    setTimeout(
-                        function() {
-                            var x6page_prior=x6.p(x6.byId('x6page'),'value');
-                            var x6mod_prior =x6.p(x6.byId('x6module'),'value');
-                            var str = '?x6page=menu'
-                                +'&x6page_prior='+x6page_prior
-                                +'&x6mod_prior='+x6mod_prior;
-                            window.location.replace(str);
-                        }
-                        ,10
-                    );
+                    x6.console.log("exit for ESC was approved");
+                    if($('#x6exit').val()=='Y') {
+                        window.close();
+                    }
+                    else {
+                        setTimeout(
+                            function() {
+                                var x6page_prior=x6.p(x6.byId('x6page'),'value');
+                                var x6mod_prior =x6.p(x6.byId('x6module'),'value');
+                                var str = '?x6page=menu'
+                                    +'&x6page_prior='+x6page_prior
+                                    +'&x6mod_prior='+x6mod_prior;
+                                window.location.replace(str);
+                            }
+                            ,10
+                        );
+                    }
                 }
             }
             else {
@@ -4317,22 +4322,12 @@
     self['receiveEvent_reqEditRow_'+table] = function(skey) {
         x6.console.group("tableController reqEditRow "+this.zTable+", "+skey);
         var skeynow = this.zSkey;
-        // KFD 1/23/09.  Big change.  Table Controller must not 
-        //               decide what to do, must let the UI elements
-        //               decide, because they may have to change
-        //               tabs, set focus, etc.
-        //if(skeynow == skey) {
-        //    x6.console.log("Request to edit same row, no action");
-        //} 
-        //else {
-            var result = this.saveOk();
-            x6bb.fwSet('lastSave_'+this.zTable,result);
-            if(result!='fail') {
-                x6events.fireEvent('uiEditRow_'+this.zTable,skey);
-                this.zSkey = skey;
-            }
-        //}
-        // KFD 1/23/09 (END)
+        var result = this.saveOk();
+        x6bb.fwSet('lastSave_'+this.zTable,result);
+        if(result!='fail') {
+            x6events.fireEvent('uiEditRow_'+this.zTable,skey);
+            this.zSkey = skey;
+        }
         x6.console.groupEnd();
         return true;
     }
@@ -4432,6 +4427,16 @@
             x6.json.addParm('x6action','save');
             x6.json.addParm('x6v_skey',this.zSkey);
             x6.json.inputs(jq);
+            
+            // If we have a parent assigned, add that and the skey
+            var tp = $(this).prop('x6tablepar','');
+            if(tp != '') {
+                var skeypar = x6bb.fwGet('skey_'+tp+'_'+this.zTable);
+                x6.console.log("Setting parent table skey: "+tp+" "+skeypar);
+                x6.json.addParm('tableIdPar',tp);
+                x6.json.addParm('skeyPar',skeypar);
+            }
+            
             // Look for an "skey after" to send back 
             var queuepos  = x6bb.fwGet('queuepos_'+this.zTable,false);
             if(queuepos) {
@@ -4506,6 +4511,7 @@
                 x6.json.addParm('json',1);
                 if(x6.json.execute()) {
                     x6events.fireEvent('uiDelRow_'+table,skey);
+                    this.zSkey = -1;
                 }
             }
         }
@@ -5060,6 +5066,11 @@
         if(id!=this.id) {
             this.keyboardOff();
             x6inputs.objectFocusBlur(this.id);
+            
+            if(this.x6profile=='grid') {
+                x6events.fireEvent('buttonsNew_'+this.zTable,false);
+                x6events.fireEvent('buttonsEdit_'+this.zTable,false);
+            }
         }
         // If it IS us, turn everything on, and set
         // the bulletin board.  But if we already have
@@ -5069,10 +5080,12 @@
                 x6bb.fwSet('objectFocus',id);
 
                 this.keyboardOn();
-                x6events.fireEvent('buttonsNew_'+this.zTable,true);
                 
                 if(this.x6profile == 'grid') {
                     x6events.fireEvent('key_DownArrow','DownArrow');
+                    if($(this).prop('uiEditRow','N')=='Y') {
+                        x6events.fireEvent('buttonsNew_'+this.zTable,true);
+                    }
                 }
                 if(this.x6profile == 'conventional') {
                     x6inputs.objectFocusFocus(this.id,':input[id^=search]');
@@ -5201,7 +5214,7 @@
         
             // Send a message and get lost
             this.zSkey = 0;
-            x6events.fireEvent('buttonsOnEdit_'+this.zTable);
+            x6events.fireEvent('buttonsEdit_'+this.zTable,true);
             x6grid.removeHighlight(this.zTable);
             x6.console.log('New row created, ready to edit');
             x6.console.groupEnd();
@@ -5774,8 +5787,13 @@
     self.goRow = function(ordinal) {
         var row = $(this).find('.tbody > div')[ordinal];
         var skey= this.skeyForRow(row);
-        x6.console.log("goRow for ",ordinal,' has picked skey ',skey);
-        this.goRowBySkey(skey);
+        if(skey==undefined || skey=='') {
+            x6.console.log('goRow for '+ordinal+' found no skey, no action');
+        }
+        else {
+            x6.console.log("goRow for ",ordinal,' has picked skey ',skey);
+            this.goRowBySkey(skey);
+        }
     }
     self.goRowJq = function(jqRow) {
         var skey = this.skeyForRow(jqRow[0]);
@@ -5985,65 +6003,51 @@
     // IE/Firefox Event handling.  This event comes from 
     // jQuery so we can trust it is ok.
     tabsShow: function(tabsUl,event,ui) {
-        x6.console.group("x6tabs tabsShow");
+        x6.console.group("x6tabs tabsShow "+tabsUl.id+", "+ui.tab.text);
         var tabs = tabsUl;
         var profile = x6.p(tabs,'x6profile','');
         
-        // A "kids" profile must do slideup, and get busy turning
-        // buttons on and off for other tabs.
+        // A "kids" profile must do slideup, and get 
+        // busy setting object focus
         if(profile=='kids') {
             // disable all other tabs until we are finished, this is
             // the easiest way to prevent user from clicking on some
             // other tab while processing is going on.
             tabs.disableAll([ui.index]);
 
-            // First job for kids is to turn parent stuff on/off
+            // If we set objectfocus to '--null--', we turn off events
+            // for all objects, which is good, user can't go clicking
+            // things during animations.  But if they clicked 'hide'
+            // we turn the parent back on.
             var tablePar = x6.p(tabs,'x6parentTable');
             if(ui.index > 0) {
-                x6events.fireEvent('buttonsOff_'+tablePar,true);
+                x6events.fireEvent('objectFocus','--null--');
             }
             else {
-                x6events.fireEvent('buttonsOn_'+tablePar,true);
+                x6events.fireEvent('objectFocus','ddisp_'+tablePar);
             }
             
-            // Next job is to turn previous tab's buttons on/off.
-            // Find the first item with a tableid property and
-            // assume that is the culprit.
-            var previousTabId = x6.p(tabs,'zCurrentId','');
-            if(previousTabId != '') {
-                var jqTable = $('#'+previousTabId+' [xtableid]:first');
-                var oldTable = x6.p(jqTable[0],'xTableId','');
-                x6events.fireEvent('buttonsOff_'+oldTable,true);
-                $('#'+previousTabId+' div[x6plugin=x6grid]').each(
-                    function() { this.keyboardOff(); }
-                );
-            }
-            
             var topPane = x6.p(tabs,'x6slideUp');
             var tpi     = x6.p(tabs,'x6slideUpInner');
             x6tabs.slideUp(tabsUl,event,ui,topPane,tpi);
         }
         
-        /*
-        *   Nice little trick, always set focus to first item
-        *
-        */
-        var id = $(ui.panel).attr('x6ObjectFocusId');
-        if( id != '') {
-            x6events.fireEvent('objectFocus',id);
-        }
         else {
-            // this is a fallback thing, you should really
-            // assign an object in the tab to get focus.
-            var str = '#' + ui.panel.id;
-            str+=' :input:not([disabled]):first';
-            x6.jqSetFocus(str);
+            // Set focus to the first object if it has been named
+            var id = $(ui.panel).attr('x6ObjectFocusId');
+            if( id != '') {
+                x6events.fireEvent('objectFocus',id);
+            }
+            else {
+                // this is a fallback thing, you should really
+                // assign an object in the tab to get focus.
+                var str = '#' + ui.panel.id;
+                str+=' :input:not([disabled]):first';
+                x6.jqSetFocus(str);
+            }
         }
         
-        /*
-        *  Save the id and index of the newly shown tab
-        *
-        */
+        // Save some state information
         tabs.zCurrentId    = ui.panel.id;
         tabs.zCurrentIndex = ui.index;
         x6.console.groupEnd();
@@ -6055,7 +6059,7 @@
         var currentChild = obj.currentChild
         var newChild     = ui.panel.id;
         
-        // if UI.index = 0, they clicked hide.  Make the
+        // if UI.index = 0, they clicked hide.
         if(ui.index==0) {
             if(currentChild!='*') {
                 var newHeight = $('#'+topPane).height()+350;
@@ -6132,7 +6136,8 @@
         var skeyDid = x6bb.fwGet('skey_'+tablePar+'_'+table,0);
         if(skeyDid==skeyPar) {
             tabsUl.enableAll();
-            x6events.fireEvent('buttonsOn_'+table,true);
+            x6events.fireEvent('objectFocus','grid_'+table);
+            //x6events.fireEvent('buttonsOn_'+table,true);
         }
         else {
             var json = new x6JSON(   'x6page'    ,table        );
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
 | 
| 
     
      
      
      From: <ken...@us...> - 2009-02-20 13:28:31
       
   | 
Revision: 1276
          http://andro.svn.sourceforge.net/andro/?rev=1276&view=rev
Author:   kendowns
Date:     2009-02-20 13:28:30 +0000 (Fri, 20 Feb 2009)
Log Message:
-----------
Sourceforge Bug 2619913
Modified Paths:
--------------
    trunk/andro/clib/x6.js
Modified: trunk/andro/clib/x6.js
===================================================================
--- trunk/andro/clib/x6.js	2009-02-20 13:26:44 UTC (rev 1275)
+++ trunk/andro/clib/x6.js	2009-02-20 13:28:30 UTC (rev 1276)
@@ -4864,12 +4864,16 @@
             
             // Alternate method, find inputs with xdefsrc, which
             // tells us where to pull defaults from
+            console.log(row);
             $(this).find(':input[xdefsrc]').each(
                 function() {
                     var info = $(this).prop('xdefsrc').split('.');
                     var row  = x6bb.fwGet('dbRow_'+info[0]);
-                    var val  = row[info[1]];
-                    $(this).val(val);
+                    if(row) {
+                        console.log(row);
+                        var val  = row[info[1]];
+                        $(this).val(val);
+                    }
                 }
             );
         }
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
 | 
| 
     
      
      
      From: <ken...@us...> - 2009-03-06 15:58:08
       
   | 
Revision: 1304
          http://andro.svn.sourceforge.net/andro/?rev=1304&view=rev
Author:   kendowns
Date:     2009-03-06 15:58:06 +0000 (Fri, 06 Mar 2009)
Log Message:
-----------
Sourceforge 2668591, multiple child detail edits were stepping on each other.
Modified Paths:
--------------
    trunk/andro/clib/x6.js
Modified: trunk/andro/clib/x6.js
===================================================================
--- trunk/andro/clib/x6.js	2009-03-06 15:21:53 UTC (rev 1303)
+++ trunk/andro/clib/x6.js	2009-03-06 15:58:06 UTC (rev 1304)
@@ -6656,7 +6656,7 @@
         // start by making everybody inside the modal
         // invisible, then make the one we are interested
         // in visible later on
-        $('#x6modal div.x6modal').css('display:none');
+        $('#x6modal > div').css('display','none');
         
         // Turn scrolling off for the body
         $('body')
@@ -6678,6 +6678,10 @@
                         .css('display','block')
                         .css('width','')
                         .css('height','')
+                        
+                    // Now make the particular display visible
+                    $('#'+id).css('display','');
+                        
                     var mh = $('#x6modal').height();
                     var mw = $('#x6modal').width();
                     var ww = $(window).width();
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
 | 
| 
     
      
      
      From: <ken...@us...> - 2009-03-06 16:58:21
       
   | 
Revision: 1305
          http://andro.svn.sourceforge.net/andro/?rev=1305&view=rev
Author:   kendowns
Date:     2009-03-06 16:58:18 +0000 (Fri, 06 Mar 2009)
Log Message:
-----------
Sourceforge 2668122, auto-hide of children on new parent detail row was a little jumbled.
Modified Paths:
--------------
    trunk/andro/clib/x6.js
Modified: trunk/andro/clib/x6.js
===================================================================
--- trunk/andro/clib/x6.js	2009-03-06 15:58:06 UTC (rev 1304)
+++ trunk/andro/clib/x6.js	2009-03-06 16:58:18 UTC (rev 1305)
@@ -4845,13 +4845,11 @@
             
             // Alternate method, find inputs with xdefsrc, which
             // tells us where to pull defaults from
-            console.log(row);
             $(this).find(':input[xdefsrc]').each(
                 function() {
                     var info = $(this).prop('xdefsrc').split('.');
                     var row  = x6bb.fwGet('dbRow_'+info[0]);
                     if(row) {
-                        console.log(row);
                         var val  = row[info[1]];
                         $(this).val(val);
                     }
@@ -6086,48 +6084,50 @@
                 // Sliding tabs around works much better if we first 
                 // slide up the inner content, then slide everything
                 // else down.
-                var newHeight = $('#'+topPane).height()+350;
-                var newHeightI= $('#'+topPaneI).height()+350;
-                $('#'+currentChild).slideUp(200
-                    ,function() {
-                        // Wait 1/10 of a second and start slidin
-                        // the top-outer container down
-                        setTimeout(
-                            function() {
-                                $('#'+topPane).animate( 
-                                    {height: newHeight}
-                                    ,spd
-                                );
-                            }
-                            ,100
-                        );
-                        // Wait another 1/10 of a second and start sliding
-                        // the top-inner container down.  Do all wrap-up
-                        // when that is finished.
-                        setTimeout(
-                            function() {
-                                var pt
-                                    = 'ddisp_'
-                                    + $(tabsUl).prop('x6parenttable');
-                                $('#'+topPaneI).animate(
-                                    {height: newHeightI}
-                                    ,spd
-                                    ,null
-                                    ,function() {
-                                        $(this).css('overflow-y','scroll');
-                                        obj.currentChild = '*';
-                                        tabsUl.enableAll();
-                                        x6events.fireEvent(
-                                            'objectFocus'
-                                            ,pt
-                                        );
-                                    }
-                                );
-                            }
-                            ,200
-                        );
-                    }
-                );
+            	setTimeout(function() {
+	                var newHeight = $('#'+topPane).height()+350;
+	                var newHeightI= $('#'+topPaneI).height()+350;
+	                $('#'+currentChild).slideUp(200
+	                    ,function() {
+	                        // Wait 1/10 of a second and start slidin
+	                        // the top-outer container down
+	                        setTimeout(
+	                            function() {
+	                                $('#'+topPane).animate( 
+	                                    {height: newHeight}
+	                                    ,spd
+	                                );
+	                            }
+	                            ,100
+	                        );
+	                        // Wait another 1/10 of a second and start sliding
+	                        // the top-inner container down.  Do all wrap-up
+	                        // when that is finished.
+	                        setTimeout(
+	                            function() {
+	                                var pt
+	                                    = 'ddisp_'
+	                                    + $(tabsUl).prop('x6parenttable');
+	                                $('#'+topPaneI).animate(
+	                                    {height: newHeightI}
+	                                    ,spd
+	                                    ,null
+	                                    ,function() {
+	                                        $(this).css('overflow-y','scroll');
+	                                        obj.currentChild = '*';
+	                                        tabsUl.enableAll();
+	                                        x6events.fireEvent(
+	                                            'objectFocus'
+	                                            ,pt
+	                                        );
+	                                    }
+	                                );
+	                            }
+	                            ,200
+	                        );
+	                    }
+	                );
+            	},10);
                 return true;
             }
         }
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
 | 
| 
     
      
      
      From: <ken...@us...> - 2009-04-04 13:11:31
       
   | 
Revision: 1333
          http://andro.svn.sourceforge.net/andro/?rev=1333&view=rev
Author:   kendowns
Date:     2009-04-04 13:11:28 +0000 (Sat, 04 Apr 2009)
Log Message:
-----------
Sourceforge 2706256
Modified Paths:
--------------
    trunk/andro/clib/x6.js
Modified: trunk/andro/clib/x6.js
===================================================================
--- trunk/andro/clib/x6.js	2009-04-04 12:48:56 UTC (rev 1332)
+++ trunk/andro/clib/x6.js	2009-04-04 13:11:28 UTC (rev 1333)
@@ -6762,6 +6762,8 @@
                 $('#x6modalblock').animate({opacity:0},'fast',null
                     ,function() {
                         $(this).css('display','none');
+                        // KFD 4/4/09 Sourceforge 2706256
+                        $('body').css('overflow','auto');
                         x6events.priorFocus();
                     }
                 );
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
 | 
| 
     
      
      
      From: <ken...@us...> - 2008-12-09 13:44:06
       
   | 
Revision: 924
          http://andro.svn.sourceforge.net/andro/?rev=924&view=rev
Author:   kendowns
Date:     2008-12-09 13:44:04 +0000 (Tue, 09 Dec 2008)
Log Message:
-----------
Daily programming changes
Modified Paths:
--------------
    trunk/andro/clib/x6.js
Modified: trunk/andro/clib/x6.js
===================================================================
--- trunk/andro/clib/x6.js	2008-12-09 13:43:10 UTC (rev 923)
+++ trunk/andro/clib/x6.js	2008-12-09 13:44:04 UTC (rev 924)
@@ -649,6 +649,11 @@
             return false;
         }
         if(inp==last && !e.shiftKey) {
+            //if(u.p(inp,'inGrid',false)) {
+            //    x6events.fireEvent('key_DownArrow');
+            //    return;
+            //}
+            
             $('[xTabGroup='+tg+']:not([disabled]):first').focus();
             //console.log("Last input, no shift, going to first");
             //console.groupEnd();
@@ -949,14 +954,12 @@
             x6events.fireEvent('reqNewRow_'+this.zTable);   
         }
     },
-    /*
-    buttonDuplicate: function(self,id,table) {
-        x6plugins.buttonStandard(self,'duplicate','CtrlD');
+    buttonInsert: function(self,id,table) {
+        x6plugins.buttonStandard(self,'ins','CtrlI');
         self.main = function() {
             x6events.fireEvent('reqNewRow_'+this.zTable,true);   
         }
     },
-    */
     buttonDelete: function(self,id,table) {
         x6plugins.buttonStandard(self,'delete','CtrlD');
         self.main = function() {
@@ -1179,13 +1182,13 @@
     *   
     */
     x6events.subscribeToEvent('reqNewRow_'    +table,id);
-    self['receiveEvent_reqNewRow_'+table] = function(dupe) {
+    self['receiveEvent_reqNewRow_'+table] = function(tabDivBefore) {
         //console.group("tableController reqNewRow "+this.zTable);
         
         var result = this.saveOk();
         u.bb.vgfSet('lastSave_'+this.zTable,result);
         if(result!='fail') {
-            x6events.fireEvent('uiNewRow_'+table);
+            x6events.fireEvent('uiNewRow_'+table,tabDivBefore);
         }
         //console.groupEnd();
     }
@@ -1261,9 +1264,13 @@
             ua.json.addParm('x6v_skey',u.bb.vgfGet('skey_'+this.zTable));
             ua.json.inputs(jq);
             // Look for an "skey after" to send back 
-            var skeyAfter = u.bb.vgfGet('skeyAfter_'+this.zTable,-1);
-            if(skeyAfter!=-1) {
-                ua.json.addParm('skeyAfter',skeyAfter);
+            var queuepos  = u.bb.vgfGet('queuepos_'+this.zTable,false);
+            if(queuepos) {
+                var skeyAfter = u.bb.vgfGet('skeyAfter_' +this.zTable,-1);
+                var skeyBefore= u.bb.vgfGet('skeyBefore_'+this.zTable,-1);
+                ua.json.addParm('queuepos'  ,queuepos);
+                ua.json.addParm('skeyAfter' ,skeyAfter);
+                ua.json.addParm('skeyBefore',skeyBefore);
             }
             if(ua.json.execute()) {
                 var retval = 'success';
@@ -1437,14 +1444,14 @@
     x6events.subscribeToEvent('buttonsOn_'+table,id);
     self['receiveEvent_buttonsOn_'+table] = function() {
         x6events.fireEvent('enable_save_'   +this.zTable);
-        x6events.fireEvent('enable_abandon_'+this.zTable);
-        x6events.fireEvent('enable_remove_' +this.zTable);
+        x6events.fireEvent('enable_cancel_' +this.zTable);
+        x6events.fireEvent('enable_delete_' +this.zTable);
     }
     x6events.subscribeToEvent('buttonsOff_'+table,id);
     self['receiveEvent_buttonsOff_'+table] = function() {
         x6events.fireEvent('disable_save_'   +this.zTable);
-        x6events.fireEvent('disable_abandon_'+this.zTable);
-        x6events.fireEvent('disable_remove_' +this.zTable);
+        x6events.fireEvent('disable_cancel_' +this.zTable);
+        x6events.fireEvent('disable_delete_' +this.zTable);
     }
 }
     
@@ -1504,9 +1511,10 @@
     }
         
     // Detail receives an addRow event and interprets it
-    // as a goMode
+    // as a goMode.  The parameter is intended only for
+    // grids, a detail display ignores it.
     x6events.subscribeToEvent('uiNewRow_'+table,id);
-    self['receiveEvent_uiNewRow_'+table] = function(row) {
+    self['receiveEvent_uiNewRow_'+table] = function(tabDivBefore) {
         //console.group("detailDisplay uiNewRow");
         this.displayRow('new',{});
         //console.log("detailDisplay uiNewRow FINISHED");
@@ -1645,6 +1653,25 @@
     }
 }
 
+x6tabDiv = {
+    mouseEnabled: true,
+    
+    mouseDisable: function() {
+        this.mouseEnabled = false;
+        $('body').css('cursor','url(clib/mouseOff.png), default');
+        $(document).one('mousemove',function() {
+            x6tabDiv.mouseEnabled = true;
+            $('body').css('cursor','');
+        });
+    },
+    
+    mouseover: function(rowDiv) {
+        if(!this.mouseEnabled) return false;
+        
+        $(rowDiv).siblings('.hilight').removeClass('hilight');
+        $('#'+rowDiv.id+':not(.selected)').addClass('hilight');
+    }
+}
 
 /***im* x6plugins/tabDiv
 *
@@ -1711,13 +1738,15 @@
     */
     x6events.subscribeToEvent('uiNewRow_'+table,id);
     if(uiNewRow!='Y') {
-        // If not inline, it always stops responding on a new row
+        // If the grid itself does not display the row, then it
+        // stops responding to keyboard events while somebody
+        // else is displaying the new row.
         self['receiveEvent_uiNewRow_'+table] = function() {
             this.keyboardOff();
         }
     }
     else {
-        self['receiveEvent_uiNewRow_'+table] = function() {
+        self['receiveEvent_uiNewRow_'+table] = function(tabDivBefore) {
             //console.group("tabDiv uiNewRow "+this.zTable);
             var skey = u.bb.vgfGet('skey_'+this.zTable,-1);
             
@@ -1767,30 +1796,49 @@
             
             
             /* 
-            *   Kind of a big deal.  If the grid has the
-            *   flag xInsertAfter set to "Y", we must slip the
-            *   new row in after the current, and trap the
-            *   skey value of the current
+            *   Now figure out where to put the row.  [New] always
+            *   goes after current row, and [Insert] passes the 
+            *   tabDivBefore flag that says go before the current
+            *   row.  If there is no current row, [Insert] goes at
+            *   the top and [New] goes at the bottom.
             */
-            var iAfter = false;
-            if(u.p(this,'xInsertAfter','N')=='Y') {
-                if(skey>0) {
-                    iAfter = skey;
+            // First work out current row, if there is one
+            var iRelative = false;
+            if(skey!=0) {
+                iRelative = skey;
+                if(tabDivBefore) {
+                    u.bb.vgfSet('skeyBefore_'+this.zTable,skey);
+                }
+                else {
                     u.bb.vgfSet('skeyAfter_'+this.zTable,skey);
                 }
+                var jqRow = $('#row_'+skey);
+            }
+            else {
+                u.bb.vgfSet('skeyBefore_'+this.zTable,-1);
+                u.bb.vgfSet('skeyAfter_'+this.zTable, -1);
+                var jqRow = this.jqCurrentRow();
+            }
+            
+            // Now go either before or after the row we found, or at
+            // top or bottom as the case may be
+            if(jqRow.length==0) {
+                if(tabDivBefore) {
+                    $(this).find('.tbody').prepend(newRow);                    
+                }
                 else {
-                    u.bb.vgfSet('skeyAfter_'+this.zTable,0);
+                    $(this).find('.tbody').append(newRow);                    
                 }
             }
-            if(iAfter) {
-                //$(this).find('#row_'+iAfter).after(newRow.bufferedRender());
-                $(this).find('#row_'+iAfter).after(newRow);                
-            }
             else {
-                //$(this).find('.tbody').prepend(newRow.bufferedRender());
-                $(this).find('.tbody').prepend(newRow);
-                u.bb.vgfSet('skeyAfter_'+this.zTable,-1);
+                if(tabDivBefore) {
+                    $(jqRow).before(newRow);
+                }
+                else {
+                    $(jqRow).after(newRow);
+                }
             }
+
             
             /*
             *   Now do everything required to make the 
@@ -1815,6 +1863,8 @@
             u.bb.vgfSet('skey_'+this.zTable,0);
             x6events.fireEvent('buttonsOn_'+this.zTable);
             this.keyboardOff();
+            $(this).find('.tbody > div.hilight').removeClass('hilight');
+            x6tabDiv.mouseDisable();
             //console.log('New row created, ready to edit');
             //console.groupEnd();
             return true;
@@ -1916,7 +1966,10 @@
                     //console.log(id,curval);
                     
                     this.innerHTML = u.byId(id).innerHTML;
-                    $(this).find(":input")[0].value=curval;
+                    $(this).find(":input").each(function() {
+                            this.value=curval;
+                            this.inGrid = true;
+                    });
                 }
             );
             tabIndex = 1000;
@@ -1930,6 +1983,8 @@
             var string = x6inputs.jqFocusString();
             $(this).find('.tbody #row_'+skey).addClass('selected');
             $(this).find('.tbody #row_'+skey+' '+string).focus();
+            $(this).find('.tbody > div.hilight').removeClass('hilight');
+            x6tabDiv.mouseDisable();
             x6events.fireEvent('buttonsOn_'+this.zTable);
             //this.keyboardOff();
             u.bb.vgfSet('skey_'+this.zTable,skey);
@@ -1961,11 +2016,13 @@
         $(this).find("#row_"+skey+" div").each(
             function() {
                 var inp    = $(this).find(":input")[0];
-                var val    = inp.value;
-                var col    = u.p(inp,'xColumnId');
-                var typeid = grid.zColsById[col].type_id;
-                //console.log(val);
-                this.innerHTML = x6dd.display(typeid,val,' ');
+                if(inp != null) {
+                    var val    = inp.value;
+                    var col    = u.p(inp,'xColumnId');
+                    var typeid = grid.zColsById[col].type_id;
+                    //console.log(val);
+                    this.innerHTML = x6dd.display(typeid,val,' ');
+                }
             }
         );
 
@@ -2000,7 +2057,19 @@
         self['receiveEvent_uiUndoRow_'+table] = function(skey) {
             x6events.fireEvent('buttonsOff_'+this.zTable);
             this.removeInputs();
-            $(this).find("#row_"+skey).mouseover();
+            if(skey==0) {
+                var iBefore = u.bb.vgfGet('skeyBefore_'+this.zTable,-1);
+                var iAfter  = u.bb.vgfGet('skeyAfter_' +this.zTable,-1);
+                if(iBefore!=-1) {
+                    x6events.fireEvent('reqEditRow_'+this.zTable,iBefore);
+                }
+                else if(iAfter!=-1) {
+                    x6events.fireEvent('reqEditRow_'+this.zTable,iAfter);
+                }
+            }
+            else {
+                $(this).find("#row_"+skey).mouseover();
+            }
             u.bb.vgfSet('skey_'+this.zTable,-1);
         }
     }
@@ -2118,12 +2187,7 @@
         var table = this.zTable;
         $(this).find('#row_'+skey)
             .mouseover(
-                function() {
-                    $(this).siblings('.hilight').removeClass('hilight');
-                    if(!$(this).hasClass('selected')) {
-                        $(this).addClass('hilight');
-                    }
-                }
+                function() { x6tabDiv.mouseover(this) }
             )
             .click(
                 function() {
@@ -2238,6 +2302,12 @@
             this.goRowJq(jqRowPrev);
             this.scrollMove(-1);
         }
+        else {
+            // KFD 12/8/08, if new rows are inline, do it
+            if(u.p(this,'uiNewRow','N')=='Y') {
+                x6events.fireEvent('reqNewRow_'+this.zTable,true);
+            }
+        }
         x6events.retvals['key_UpArrow'] =false;
         //console.log("tabDiv key_UpArrow finished");
         //console.groupEnd();
@@ -2254,6 +2324,12 @@
             this.goRowJq(jqRowNext);
             this.scrollMove(1);
         }
+        else {
+            // KFD 12/8/08, if new rows are inline, do it
+            if(u.p(this,'uiNewRow','N')=='Y') {
+                x6events.fireEvent('reqNewRow_'+this.zTable);
+            }
+        }
         x6events.retvals['key_DownArrow'] =false;
         //console.log("tabDiv key_DownArrow finished");
         //console.groupEnd();
@@ -2309,7 +2385,9 @@
         this.goRowJq( $(this).find('.tbody > div:last') ); 
         var rowHeight = Number(u.p(this,'cssLineHeight'));
         var rowCount  = $(this).find('.tbody > div').length;
-        $(this).find('.tbody').scrollTop(rowHeight * rowCount);
+        //$(this).find('.tbody').scrollTop(rowHeight * rowCount);
+        var stNew = rowHeight * rowCount;
+        $(this).find('.tbody').animate({scrollTop:stNew},400);
     }
     self.receiveEvent_key_Enter = function(e) {
         //console.group("tabDiv key_Enter - clicking hilighted rows");
@@ -2356,7 +2434,8 @@
     }
     self.goRowTop = function() {
         this.goRow(0);
-        $(this).find('.tbody').scrollTop(0);
+        //$(this).find('.tbody').scrollTop(0);
+        $(this).find('.tbody').animate({scrollTop: 0},400);
     }
     self.scrollMove = function(change) {
         // Get all of the numbers we need
@@ -2382,7 +2461,9 @@
         if(stAdjust!=0) {
             //console.log(stAdjust);
             var stNow     = $(this).find('.tbody').scrollTop();
-            $(this).find('.tbody').scrollTop(stNow + stAdjust);
+            var stNew     = stNow + stAdjust;
+            //$(this).find('.tbody').scrollTop(stNow + stAdjust);
+            $(this).find('.tbody').animate({scrollTop:stNew},100);
         }
         
     }
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
 | 
| 
     
      
      
      From: <ken...@us...> - 2008-12-10 03:51:44
       
   | 
Revision: 930
          http://andro.svn.sourceforge.net/andro/?rev=930&view=rev
Author:   kendowns
Date:     2008-12-10 03:51:40 +0000 (Wed, 10 Dec 2008)
Log Message:
-----------
Many changes after hack-a-thon, all on the grid.
Modified Paths:
--------------
    trunk/andro/clib/x6.js
Modified: trunk/andro/clib/x6.js
===================================================================
--- trunk/andro/clib/x6.js	2008-12-10 02:29:59 UTC (rev 929)
+++ trunk/andro/clib/x6.js	2008-12-10 03:51:40 UTC (rev 930)
@@ -432,22 +432,17 @@
     // KFD 11/13/08.  Generic display routine
     display: function(typeid,value,nullDisplay) {
         if(nullDisplay==null) nullDisplay = '';
-        //console.log("x6dd.display parms: ",typeid,value,nullDisplay);
         if(value==null || value.toString().trim()=='') {
-            //console.log("x6dd.display returning empty string: ",nullDisplay);
             return nullDisplay;
         }
         switch(typeid) {
         case 'int':
         case 'numb':
         case 'money':
-            //console.log("I've got int, numb, or money", value);
             if(value=='null') return '';
-            //console.log("x6dd.display returning number");
             return Number(value);
             break;
         default:
-            //console.log("x6dd.display parms: ",typeid,value);
             return value;
         }
     }
@@ -813,7 +808,7 @@
         if(u.p(inp,'disabled',false)) {
             inp.className='';
             doRow = u.p(inp,'xClassRow',0);
-            if(doRow) {
+            if(doRow!=0) {
                 inp.parentNode.parentNode.className = '';
             }
             return;
@@ -1381,11 +1376,11 @@
         }
         
         // Flip all icons to both
-        $('[xChGroup='+xChGroup+']').html('⇔');
+        //$('[xChGroup='+xChGroup+']').html('⇔');
         
         // Flip just this icon to up or down
         var icon = this.zSortAsc ? '⇓' : '⇑';
-        $('[xChGroup='+xChGroup+'][xColumn='+xColumn+']').html(icon);
+        //$('[xChGroup='+xChGroup+'][xColumn='+xColumn+']').html(icon);
         
         // Make the request to the server
         var args2 = { sortCol: this.zSortCol, sortAsc: this.zSortAsc };
@@ -1665,11 +1660,27 @@
         });
     },
     
+    removeHighlight: function(table) {
+        var rowNow = u.bb.vgfGet('highlight_'+table,'');
+        if(rowNow!='') $('#'+rowNow).removeClass('hilight');
+        u.bb.vgfSet('highlight_'+table,'');
+        this.mouseDisable();
+    },
+    
     mouseover: function(rowDiv) {
         if(!this.mouseEnabled) return false;
+        var pieces = rowDiv.id.split('_');
         
-        $(rowDiv).siblings('.hilight').removeClass('hilight');
-        $('#'+rowDiv.id+':not(.selected)').addClass('hilight');
+        var rowNow = u.bb.vgfGet('highlight_'+pieces[0],'');
+        if(rowNow!='') u.byId(rowNow).className = '';
+        var row = u.byId(rowDiv.id);
+        if(row.id != 'selected') {
+            u.byId(rowDiv.id).className = 'hilight';
+            u.bb.vgfSet('highlight_'+pieces[0],rowDiv.id);
+        }
+        
+        //$(rowDiv).siblings('.hilight').removeClass('hilight');
+        //$('#'+rowDiv.id+':not(.selected)').addClass('hilight');
     }
 }
 
@@ -1716,6 +1727,7 @@
     *  If so, it will replace its own data with the
     *  data that has been provided.
     */
+    /* SUSPICIOUS, probably do not need this
     if(u.p(self,'xCacheRows','')=='Y') {
         x6events.subscribeToEvent('cacheRows_'+table,id);
         
@@ -1728,6 +1740,15 @@
             //}
         }
     }
+    */
+
+    self.rowId = function(skey,noPound) {
+        return (noPound==null ? '#' : '')+this.zTable+'_'+skey;
+    }
+    self.skeyForRow = function(row) {
+        var pieces = row.id.split('_');
+        return pieces[1];
+    }
     
     /*
     *   The grid is happy to display a new row for
@@ -1748,6 +1769,7 @@
     else {
         self['receiveEvent_uiNewRow_'+table] = function(tabDivBefore) {
             //console.group("tabDiv uiNewRow "+this.zTable);
+            //console.time("tabDiv uiNewRow");
             var skey = u.bb.vgfGet('skey_'+this.zTable,-1);
             
             /*
@@ -1755,7 +1777,7 @@
             *   focus on it.
             */
             if(skey==0 && u.bb.vgfGet('lastSave_'+this.zTable)=='noaction') {
-                $(this).find("#row_0 :input:first:not([disabled])").focus();
+                $(this.rowId(0)+" :input:first:not([disabled])").focus();
                 //console.log("On an empty new row, setting focus");
                 //console.groupEnd();
                 return;
@@ -1775,7 +1797,10 @@
             *   inputs that have been provided by the PHP code,
             *   and get them all initialized and ready to go.
             */
-            var newRow = "<div id='row_0' style='display:none'>";
+            var newRow = 
+                "<div id='"+this.zTable+"_0' "
+                +" class='selected' "
+                +" style='display:none'>";
             var numbers = [ 'int', 'numb', 'money' ];
             for (var idx in this.zColsInfo) {
                 var colInfo = this.zColsInfo[idx];
@@ -1808,11 +1833,14 @@
                 iRelative = skey;
                 if(tabDivBefore) {
                     u.bb.vgfSet('skeyBefore_'+this.zTable,skey);
+                    u.bb.vgfSet('skeyAfter_' +this.zTable,-1);
                 }
                 else {
-                    u.bb.vgfSet('skeyAfter_'+this.zTable,skey);
+                    u.bb.vgfSet('skeyAfter_' +this.zTable,skey);
+                    u.bb.vgfSet('skeyBefore_'+this.zTable,-1);
                 }
-                var jqRow = $('#row_'+skey);
+                //var jqRow = $('#row_'+skey);
+                var jqRow = $(this.rowId(skey));
             }
             else {
                 u.bb.vgfSet('skeyBefore_'+this.zTable,-1);
@@ -1824,17 +1852,21 @@
             // top or bottom as the case may be
             if(jqRow.length==0) {
                 if(tabDivBefore) {
+                    //console.log("body prepend");
                     $(this).find('.tbody').prepend(newRow);                    
                 }
                 else {
+                    //console.log("body append");
                     $(this).find('.tbody').append(newRow);                    
                 }
             }
             else {
                 if(tabDivBefore) {
+                    //console.log("before this row: ",jqRow);
                     $(jqRow).before(newRow);
                 }
                 else {
+                    //console.log("after this row: ",jqRow);
                     $(jqRow).after(newRow);
                 }
             }
@@ -1846,14 +1878,15 @@
             */
             tabIndex = 1000;
             var grid = this;
-            $(this).find(':input').each(
+            //$(this).find('#row_0 :input').each(
+            $(this.rowId(0)+' :input').each(            
                 function() {
+                    this.setAttribute('xClassRow','0');
                     grid.initInput(this,tabIndex++,'new','rowNew'); 
-                    this.setAttribute('xClassRow','0');
                 }
             );
-            var grid = this;
-            $(this).find('#row_0').fadeIn('fast'
+            //$(this).find('#row_0').fadeIn('fast'
+            $(this.rowId(0)).fadeIn('fast'
                 ,function() {
                     x6inputs.findFocus( this );
                 }
@@ -1862,10 +1895,12 @@
             // Send a message and get lost
             u.bb.vgfSet('skey_'+this.zTable,0);
             x6events.fireEvent('buttonsOn_'+this.zTable);
-            this.keyboardOff();
-            $(this).find('.tbody > div.hilight').removeClass('hilight');
-            x6tabDiv.mouseDisable();
+            //console.time("remove highlight");
+            //$(this).find('.tbody > div.hilight').removeClass('hilight');
+            x6tabDiv.removeHighlight(this.zTable);
+            //console.timeEnd('remove highlight');
             //console.log('New row created, ready to edit');
+            //console.timeEnd("tabDiv uiNewRow");
             //console.groupEnd();
             return true;
         }
@@ -1899,7 +1934,7 @@
         // This is important, it says that this is an 
         // active input.  This distinguishes it from possible
         // hidden inputs that were used as a clone source 
-        // that have many of the same properties.
+        // that have many or all of the same properties.
         input.zActive = 1;
         //console.groupEnd();
     }
@@ -1913,14 +1948,15 @@
     x6events.subscribeToEvent('uiEditRow_'+table,id);
     if(uiEditRow!='Y') {
         self['receiveEvent_uiEditRow_'+table] = function(skey) {
-            //this.keyboardOff();
+            this.keyboardOff();
         }
     }
     else {
         self['receiveEvent_uiEditRow_'+table] = function(skey) {
             //console.group("tabDiv uiEditRow "+this.zTable);
     
-            if( $(this).find('#row_'+skey).length == 0) {
+            if(u.byId(this.rowId(skey,false))==null) {
+            //if( $(this).find('#row_'+skey).length == 0) {
                 //console.log("We don't have that row, cannot edit");
                 //console.groupEnd();
                 return;
@@ -1940,51 +1976,50 @@
             if(u.bb.vgfGet('skey_'+this.zTable)>=0) {
                 this.removeInputs();
             }
-    
+
+            // Set this before adding inputs.  If you
+            // do it afterward we get "jumpies" as the
+            // border/padding/margin adjusts.
+            //$(this).find('.tbody #row_'+skey)[0].className='selected';
+            //console.log(this.rowId(skey));
+            var rowId = this.rowId(skey,true);
+            u.byId(rowId).className='selected';
+
             //console.log("Putting inputs into div cells");
-            grid = this;
-            $(this).find('.tbody #row_'+skey+' div').each(
+            var grid = this;
+            var tabIndex = 1000;
+            var focus=false;
+            //$(this).find('#row_'+skey+' div').each(
+            //console.log(this.rowId(skey)+' div');
+            $(this.rowId(skey)+' div').each(            
                 function() {
+                    var div = this;
                     // Work up to figuring out the name of the
                     // id that holds the hidden input, then
                     // grab the input and put it in.
-                    var colnum = u.p(this,'gColumn');
+                    var colnum = u.p(div,'gColumn');
                     var colid  = grid.zColsInfo[colnum].column_id;
                     var id = 'wrapper_'+grid.zTable+'_'+colid;
                     //console.log(id);
 
                     // Current Value
-                    // KFD 11/13/08, special exception for  
                     // KFD 11/29/08, use special html conversion
-                    var curval = this.innerHTML.htmlEdit();
-                    //if(this.innerHTML.trim()==' ') {
-                    //    var curval = '';
-                    //}
-                    //else {
-                    //    var curval = this.innerHTML;
-                    //}
-                    //console.log(id,curval);
+                    var curval = div.innerHTML.htmlEdit();
                     
-                    this.innerHTML = u.byId(id).innerHTML;
-                    $(this).find(":input").each(function() {
-                            this.value=curval;
-                            this.inGrid = true;
-                    });
+                    div.innerHTML = u.byId(id).innerHTML;
+                    var inp = div.lastChild;
+                    inp.value  = curval;
+                    inp.inGrid = true;
+                    inp.setAttribute('xClassRow',0);
+                    grid.initInput(inp,tabIndex++,'edit','rowEdit');
+                    if(!inp.disabled && !focus) {
+                        inp.focus();
+                        focus=true;
+                    }
                 }
             );
-            tabIndex = 1000;
-            var grid = this;
-            $(this).find('.tbody #row_'+skey+' :input').each(
-                function() {
-                    grid.initInput(this,tabIndex++,'edit','rowEdit');
-                    this.setAttribute('xClassRow',0);
-                }
-            );
-            var string = x6inputs.jqFocusString();
-            $(this).find('.tbody #row_'+skey).addClass('selected');
-            $(this).find('.tbody #row_'+skey+' '+string).focus();
-            $(this).find('.tbody > div.hilight').removeClass('hilight');
-            x6tabDiv.mouseDisable();
+            
+            x6tabDiv.removeHighlight(this.zTable);
             x6events.fireEvent('buttonsOn_'+this.zTable);
             //this.keyboardOff();
             u.bb.vgfSet('skey_'+this.zTable,skey);
@@ -1994,7 +2029,6 @@
         }
     }
     
-    
     /*
     *   A grid may need to convert inputs back into display
     *   elements.  This routine is unconditionally created
@@ -2003,19 +2037,28 @@
     */
     self.removeInputs = function() {
         //console.group("tabDiv removeInputs");
-        if( $(this).find(':input').length==0 ) {
+        var skey = u.bb.vgfGet('skey_'+this.zTable);
+
+        //if( $(this).find('#row_'+skey+' :input').length==0 ) {
+        if( $(this.rowId(skey)+' :input').length==0 ) {
             //console.log("no inputs, doing nothing");
             //console.groupEnd();
             return;
         }
+        
+        // Remove the "selected" class from the inputs row,
+        // it does not belong there anymore.
+        u.byId(this.rowId(skey,true)).className = '';
 
-        var skey = u.bb.vgfGet('skey_'+this.zTable);
         //console.log("skey is ",skey);
         var grid = this;
-        $(this).find("#row_"+skey).removeClass('selected');        
-        $(this).find("#row_"+skey+" div").each(
+        //$(this).find("#row_"+skey).removeClass('selected').find("div").each(
+        //if( $(this.rowId(skey)+' :input').length==0 ) {
+        //$(this).find("#row_"+skey+" div").each(
+        $(this.rowId(skey)+' div').each(
             function() {
-                var inp    = $(this).find(":input")[0];
+                var inp    = this.firstChild; 
+                //var inp    = $(this).find(":input")[0];
                 if(inp != null) {
                     var val    = inp.value;
                     var col    = u.p(inp,'xColumnId');
@@ -2031,7 +2074,7 @@
         if(skey==0) {
             if(u.bb.vgfGet('lastSave_'+this.zTable)=='noaction') {
                 //console.log("No action on last save, removing row ",skey);
-                $(this).find("#row_0").fadeOut(
+                $(this.rowId(0)).fadeOut(
                     function() { $(this).remove() }
                 );
             }
@@ -2046,8 +2089,6 @@
         return true;
     }
     
-    
-    
     /*
     *   Undo Row: the table controller has already reset
     *   any inputs, we will just remove them
@@ -2055,22 +2096,33 @@
     if(uiEditRow=='Y' || uiNewRow=='Y') {
         x6events.subscribeToEvent('uiUndoRow_'+table,id);
         self['receiveEvent_uiUndoRow_'+table] = function(skey) {
-            x6events.fireEvent('buttonsOff_'+this.zTable);
-            this.removeInputs();
-            if(skey==0) {
+            //console.group('tabDiv uiUndoRow ',skey);
+            if(skey!=0) {
+                //console.log("Skey is not zero, resetting values");
+                //$(this).find('#row_'+skey+' :input').each(
+                $(this.rowId(skey)+' :input').each(
+                    function() {
+                        this.value = this.zOriginalValue;
+                        x6inputs.setClass(this);
+                    }
+                );
+            }
+            else {
+                //console.log("Skey is zero, removing row");
+                this.removeInputs();
                 var iBefore = u.bb.vgfGet('skeyBefore_'+this.zTable,-1);
                 var iAfter  = u.bb.vgfGet('skeyAfter_' +this.zTable,-1);
-                if(iBefore!=-1) {
-                    x6events.fireEvent('reqEditRow_'+this.zTable,iBefore);
+                ////console.log(iBefore,iAfter);
+                if     (iBefore!=-1) skeyNew = iBefore;
+                else if(iAfter !=-1) skeyNew = iAfter;
+                else skeyNew = -1;
+                if(skeyNew!=-1){
+                    //console.log("Picked this row to edit: ",skeyNew);
+                    x6events.fireEvent('reqEditRow_'+this.zTable,skeyNew);
+                    //$(this).find('#row_'+skeyNew).mouseover();
                 }
-                else if(iAfter!=-1) {
-                    x6events.fireEvent('reqEditRow_'+this.zTable,iAfter);
-                }
             }
-            else {
-                $(this).find("#row_"+skey).mouseover();
-            }
-            u.bb.vgfSet('skey_'+this.zTable,-1);
+            //console.groupEnd();
         }
     }
     else if(self.kbOnEdit) {
@@ -2080,8 +2132,6 @@
         }
     }
     
-    
-    
     /*
     *   A grid must always have a facility to receive 
     *   new values from any source.  The code is smart
@@ -2094,10 +2144,13 @@
         //console.group("tabDiv uiRowSaved: "+this.zTable);
         // Replace the input values with server returned values
         skey = u.bb.vgfGet('skey_'+this.zTable);
-        if( $(this).find("#row_"+skey+" :input").length > 0) {
+        //if( $(this).find("#row_"+skey+" :input").length > 0) {
+        if( $(this.rowId(skey)+' :input').length > 0) {
             //console.log($(this).find("#row_"+skey+" :input"));
             //console.log("found inputs, going rowSavedEdit");
             this.uiRowSavedEdit(row);
+            var skeyNew = skey==0 ? row.skey : skey;
+            x6events.fireEvent('reqEditRow_'+this.zTable,skeyNew);
         }
         else {
             //console.log("no inputs, going rowSavedNoEdit");
@@ -2113,7 +2166,8 @@
     self.uiRowSavedEdit = function(row) {
         var skey = u.bb.vgfGet('skey_'+this.zTable);
         var grid = this;
-        $(this).find("#row_"+skey+" :input").each(
+        //$(this).find("#row_"+skey+" :input").each(
+        $(this.rowId(skey)+" :input").each(
             function() {
                 var col    = u.p(this,'xColumnId');
                 var typeid = grid.zColsById[col].type_id;
@@ -2123,22 +2177,24 @@
             }
         );
         this.removeInputs();
-        x6events.fireEvent('buttonsOff_'+this.zTable);
+        //x6events.fireEvent('buttonsOff_'+this.zTable);
         u.bb.vgfSet('skey_'+this.zTable,-1);
         
         // If this was a new row, set it up
         if(skey==0) {
             //console.log("Was new row, setting up the row for editing");
             table = this.zTable;
+            /*
             $(this).find("#row_0").each(
                 function() {
                     this.id = 'row_'+row.skey;
                 }
             );
+            */
+            u.byId(this.zTable+'_0').id = this.zTable+'_'+row.skey;
             this.initRow(row.skey);
+            
         }
-        $(this).find('#row_'+row.skey).mouseover();
-        
     }
         
     self.uiRowSavedNoEdit = function(row) {
@@ -2146,7 +2202,8 @@
         
         // If a new row has been saved and we don't 
         // have it, create it now
-        if($(this).find('.tbody #row_'+skey).length==0) {
+        //if($(this).find('.tbody #row_'+skey).length==0) {
+        if($(this.rowId(skey)).length==0) {        
             var newRow = new jsHtml('div');
             newRow.hp.id = 'row_'+skey;
             newRow.hp.style = 'display: none;';
@@ -2167,14 +2224,16 @@
             }
             $(this).find('.tbody').prepend(newRow.bufferedRender());
             this.initRow(skey);
-            $(this).find("#row_"+skey).fadeIn();
+            $(this.rowId(skey)).fadeIn();
         }
         else {
             for(var idx in this.zColsInfo) {
                 var col = this.zColsInfo[idx].column_id;
                 if(col!='') {
-                    var str="#row_"+skey+" div[gColumn="+idx+"]";
-                    $(this).find(str).html(row[col]);
+                    //var str="#row_"+skey+" div[gColumn="+idx+"]";
+                    var str=this.rowId(skey)+" div[gColumn="+idx+"]";
+                    //$(this).find(str).html(row[col]);
+                    $(str).html(row[col]);
                 }
             }
         }
@@ -2185,7 +2244,8 @@
         // This code also exists in androLib.php
         // addRow method of the tabDiv class
         var table = this.zTable;
-        $(this).find('#row_'+skey)
+        //$(this).find('#row_'+skey)
+        $(this.rowId(skey))
             .mouseover(
                 function() { x6tabDiv.mouseover(this) }
             )
@@ -2208,6 +2268,7 @@
     self['receiveEvent_uiDelRow_'+table] = function() {
         //console.group("tabDiv uiDelRow "+this.zTable);
         skey = u.bb.vgfGet('skey_'+this.zTable);
+        //console.log("current skey ",skey);
         
         if(this.kbOnEdit) {
             this.keyboardOn();
@@ -2221,12 +2282,12 @@
         if(skey!=-1) {
             var hilightRow = false;
             //console.log("Determining row to highlight afer removing");
-            var jqCandidate = $(this).find('#row_'+skey).next();
+            var jqCandidate = $(this.rowId(skey)).next();
             if(jqCandidate.length>0) {
                 var hilightRow = jqCandidate;
             }
             else {
-                var jqCandidate = $(this).find('#row_'+skey).prev();
+                var jqCandidate = $(this.rowId(skey)).prev();
                 if(jqCandidate.length>0) {
                     var hilightRow = jqCandidate;
                 }
@@ -2237,12 +2298,12 @@
             //console.log("No row, ignoring");
             return;
         }
-        else if(this.zSkey==0) {
+        else if(skey==0) {
             //console.log("on a new row, firing cancelEdit command");
             x6events.fireEvent('cancelEdit_'+this.zTable);
         }
         else {
-            $(this).find("#row_"+skey).fadeOut(
+            $(this.rowId(skey)).fadeOut(
                 function() {
                     $(this).remove();
                 }
@@ -2255,7 +2316,8 @@
         }
         else {
             //console.log("Will hilight this row: ",hilightRow);
-            $(hilightRow).mouseover();
+            var skey = this.skeyForRow(hilightRow[0]);
+            x6events.fireEvent('reqEditRow_'+this.zTable,skey);
         }
         //console.log("uiDelRow finished");
         //console.groupEnd();
@@ -2296,15 +2358,18 @@
         var jqCurrent = this.jqCurrentRow();
         var jqRowPrev = $(jqCurrent).prev();
         if(jqCurrent.length==0) {
+            //console.log("current is zero, going to top");
             this.goRowTop();
         }
         else if(jqRowPrev.length!=0) {
+            //console.log("there is a previous, going to that");
             this.goRowJq(jqRowPrev);
             this.scrollMove(-1);
         }
         else {
             // KFD 12/8/08, if new rows are inline, do it
             if(u.p(this,'uiNewRow','N')=='Y') {
+                //console.log("requesting new row, forcing insert before");
                 x6events.fireEvent('reqNewRow_'+this.zTable,true);
             }
         }
@@ -2385,13 +2450,15 @@
         this.goRowJq( $(this).find('.tbody > div:last') ); 
         var rowHeight = Number(u.p(this,'cssLineHeight'));
         var rowCount  = $(this).find('.tbody > div').length;
-        //$(this).find('.tbody').scrollTop(rowHeight * rowCount);
         var stNew = rowHeight * rowCount;
         $(this).find('.tbody').animate({scrollTop:stNew},400);
     }
     self.receiveEvent_key_Enter = function(e) {
         //console.group("tabDiv key_Enter - clicking hilighted rows");
         $(this).find('.tbody div.hilight').click();
+        //var jqRow = $(this).find('div.hilight')[0];
+        //var skey  = this.skeyForRow(jqRow);
+        //x6events.fireEvent('reqEditRow_'+this.zTable,skey);
         //console.groupEnd();
     }
     
@@ -2400,12 +2467,7 @@
     *
     */
     self.jqCurrentRow = function() {
-        var jq = $(this).find('.selected');
-        if(jq.length > 0) return jq;
-        var jq = $(this).find('.hilight');
-        if(jq.length > 0) return jq;
-        return $([]);
-        
+        return $(this).find('.selected');
     }
     self.goRowBySkey = function(skey) {
         //console.log('goRowBySkey ',skey);
@@ -2421,12 +2483,12 @@
     }
     self.goRow = function(ordinal) {
         var row = $(this).find('.tbody > div')[ordinal];
-        var skey= row.id.slice(4);
+        var skey= this.skeyForRow(row);
         //console.log("goRow for ",ordinal,' has picked skey ',skey);
         this.goRowBySkey(skey);
     }
     self.goRowJq = function(jqRow) {
-        var skey = jqRow[0].id.slice(4);
+        var skey = this.skeyForRow(jqRow[0]);
         //console.log("goRow by jQuery object ");
         //console.log(jqRow);
         //console.log(skey);
@@ -2442,30 +2504,40 @@
         var jqRow     = this.jqCurrentRow();
         var cntAbove  = $(jqRow).prevAll().length;
         var cntBelow  = $(jqRow).nextAll().length;
-        var cntAll    = $(this).find('.tbody > div').length;
+        var cntAll    = cntAbove + cntBelow + 1;
         var cntVisible= Number(u.p(this,'xRowsVisible'));
-        var cssHeight = Number(u.p(this,'cssLineHeight'));
-        //console.log(change,cntAbove,cntBelow,cntAll,cntVisible,cssHeight);
+        var cssHeight = Number(u.p(this,'cssLineHeight')) - 2;
+        var scrollNow = $(this).find('.tbody').scrollTop();
+        var limitBot  = cntVisible - 2;
+        var limitTop  = 3;
         
-        var stAdjust = 0;
+        // Work out where the last row was, by first working out
+        // where the current row is and then going backward.
+        var rowRaw = (cntAbove + 1);
+        var rowReal= rowRaw - (scrollNow / cssHeight);
+        
+        // Work out what we should adjust.
+        var stAdjust = false;
         if(change > 0) {
-            if(cntAbove > (cntVisible/2)) {
-                var stAdjust = change * (cssHeight-2);
+            // We are going down.  If the new position would be
+            // beyond
+            if(rowReal > limitBot) {
+                var rowsAdjust = rowReal - limitBot;
+                stAdjust = rowsAdjust * cssHeight;
             }
         }
         else {
-            if(cntBelow > (cntVisible/2)) {
-                var stAdjust = change * (cssHeight-2);
+            if(rowReal < limitTop) {
+                var rowsAdjust = rowReal - limitTop;
+                stAdjust = rowsAdjust * cssHeight;
             }
         }
         if(stAdjust!=0) {
             //console.log(stAdjust);
-            var stNow     = $(this).find('.tbody').scrollTop();
-            var stNew     = stNow + stAdjust;
+            var stNew     = scrollNow + stAdjust;
             //$(this).find('.tbody').scrollTop(stNow + stAdjust);
-            $(this).find('.tbody').animate({scrollTop:stNew},100);
+            $(this).find('.tbody').animate({scrollTop:stNew},200);
         }
-        
     }
 
     /*
@@ -2478,19 +2550,29 @@
         ,'UpArrow', 'DownArrow', 'Enter'
     ];
     self.keyboardOn = function() {
+        if(this.keyboardStatus=='On') return;
         for(var key in this.keyList) {
             var keyLabel = this.keyList[key];
             x6events.subscribeToEvent('key_'+keyLabel,id);
         }
+        this.keyboardStatus = 'On';
         $(this).focus();
     }
     self.keyboardOff = function() {
+        if(this.keyboardStatus=='Off') return;
         for(var key in this.keyList) {
             var keyLabel = this.keyList[key];
             x6events.unsubscribeToEvent('key_'+keyLabel,id);
         }
+        this.keyboardStatus = 'Off';
     }
-    if(u.p(self,'xInitKeyboard','N')=='Y') self.keyboardOn();
+    this.keyboardStatus = 'Off'
+    if(u.p(self,'xInitKeyboard','N')=='Y') {
+        self.keyboardOn();
+        if(uiEditRow=='Y') {
+            x6events.fireEvent('key_DownArrow'); 
+        }
+    }
 
 
     
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
 | 
| 
     
      
      
      From: <ken...@us...> - 2008-12-11 21:26:15
       
   | 
Revision: 944
          http://andro.svn.sourceforge.net/andro/?rev=944&view=rev
Author:   kendowns
Date:     2008-12-11 21:26:05 +0000 (Thu, 11 Dec 2008)
Log Message:
-----------
Created drop-down system.  
1) CBOOL and GENDER columns use the new drop-down w/fixed values
2) Put x6all="Y" onto a table.  Fk's to that table now display all rows w/o fetching from server.
3) Original x2/x4 "androSelect" now implemented to dynamically fetch rows as user types in values.
Modified Paths:
--------------
    trunk/andro/clib/x6.js
Modified: trunk/andro/clib/x6.js
===================================================================
--- trunk/andro/clib/x6.js	2008-12-11 21:23:55 UTC (rev 943)
+++ trunk/andro/clib/x6.js	2008-12-11 21:26:05 UTC (rev 944)
@@ -567,6 +567,16 @@
             else if(keyLabel=='CtrlRightArrow') {
                 this.lastInput(inp);
             }
+            else if(keyLabel=='ShiftDownArrow') {
+                if(u.p(inp,'x6select','N')=='Y') {
+                    x6inputs.x6select.display(inp,'Down');
+                }
+            }
+            else if(keyLabel=='ShiftUpArrow') {
+                if(u.p(inp,'x6select','N')=='Y') {
+                    x6inputs.x6select.display(inp,'Up');
+                }
+            }
             else if(keyLabel=='Home') {
                 if(inp.selectionStart == 0 && inp.selectionEnd==0)
                     this.firstInput(inp);
@@ -588,7 +598,7 @@
         
         // Type validation for some types, only if not TAB or ENTER
         if(!isNav) {
-            //console.log("Not nav key, doing type validation");
+            console.log("Not nav key, doing type validation");
             type = u.p(inp,'xtypeid');
             switch(type) {
             case 'int':
@@ -605,26 +615,68 @@
                 if(!u.keyIsNumeric(e)) {
                     if(keyLabel!='-' && keyLabel!='/') return false;
                 }
+                break;
+            case 'gender':
+                if(['M','F','U','H'].indexOf(keyLabel.toUpperCase())==-1) {
+                    return false;
+                }
+                break;
+            case 'cbool':
+                if(['Y','N'].indexOf(keyLabel.toUpperCase())==-1) {
+                    return false;
+                }
+                break;
             }
+            
+            // Next possibility is a lookup that requires a
+            // fetch from the server.
+            if(u.p(inp,'x6select','N')=='Y' && u.p(inp,'xValues',null)==null) {
+                // Generate the value to send back
+                var val = inp.value;
+                var val = val.slice(0,inp.selectionStart)
+                    +keyLabel
+                    +val.slice(inp.selectionEnd);
+                //console.log("current value: ",inp.value)
+                //console.log("sel start: ",inp.selectionStart)
+                //console.log("sel end: ",inp.selectionEnd)
+                //console.log("computed value:",val);
+                json = new androJSON('x6page',u.p(inp,'x6seltab'));
+                json.addParm('x6select','Y');
+                json.addParm('gpletters',val);
+                json.execute(true);
+                x6inputs.x6select.display(inp);
+                x6inputs.x6select.displayDynamic(inp,ua.data.x6select);
+            }
+            
             //console.log("Type validation complete, returning true");
             //console.groupEnd();
             return true;
         }
         
+        // If this input has an open x6select (SELECT replacement)
+        // then ask it for the value.
+        //
+        // Do this *before* the afterBlurner command below, so that
+        // the value is set when afterBlurner fires.
+        if(u.p(inp,'x6select','N')=='Y') {
+            x6inputs.x6select.assignToMe(inp);
+        }
         
         // This took a lot of experimentation to get right.
         // Normally a BLUR would occur when an object loses focus
-        //  -> except if the user hits ENTER, we must force validation
-        //  -> except if validation enables new controls
+        //  -> except if the user hits ENTER, we must force processing
+        //  -> except if processing enables new inputs
         //
         // So we unconditionally fire the afterblurner to hit
-        // anything the control's special validation code might
+        // anything the control's special processing code might
         // do.  Then we proceed normally.
         //
         // Also: returning false does NOT prevent losing focus,
-        // that's we don't check the return value.
+        // that's we don't check the return value.  We are not
+        // *validating*, we are *processing*.
         x6inputs.afterBlurner(inp);
         
+        
         // Get the first and last controls for easier
         // logic immediately below
         var tg       = u.p(inp,'xTabGroup','tgdefault');
@@ -733,6 +785,7 @@
         inp.zSelected = 0;
         x6inputs.setClass(inp);
         x6inputs.afterBlurner(inp);
+        x6inputs.x6select.hide();
         //console.log("Input Blur DONE");
         //console.groupEnd();
         return true;
@@ -919,6 +972,232 @@
         else {
             return false;
         }
+    },
+    
+    ddClick: function(button) {
+        var id = u.p(button,'xInputId');
+        var inp = $('[zActive]#'+id)[0];
+        this.x6select.display(inp);
+    },
+    
+    x6select: {
+        dynRowCount: 15,
+        div: false,
+        
+        hide: function() {
+            $(".x6select").remove();
+            this.tbody=false;
+            this.div = false;
+        },
+        
+        assignToMe: function(inp) {
+            if(this.div) {
+                var row = $('.x6select tr.hilight');
+                if(row.length > 0) {
+                    inp.value = row[0].firstChild.innerHTML;
+                }
+            }
+        },
+        
+        display: function(input,fromKeyboard) {
+            if(fromKeyboard!=null) {
+                if(this.div && this.div.style.display=='block') {
+                    return this.moveUpOrDown(fromKeyboard);
+                }
+            }
+            
+            if(!this.div) {
+                this.div = document.createElement('DIV');
+                this.div.style.display    = 'none';
+                this.div.style.position   = 'absolute';
+                this.div.style.backgroundColor = 'white';
+                this.div.style.overflow   = 'hidden';
+                this.div.style.border     ="1px solid black";
+                var lineHeight            = $(input).height();
+                this.lineHeight           = lineHeight;
+                this.div.style.lineHeight = lineHeight+"px";
+                this.div.style.cursor     = 'pointer';
+                this.div.style.zIndex     = 1000;
+                this.div.className        = 'x6select';
+
+                // Work out minimum width as the input plus the button
+                var jqButton = $('[xInputId='+input.id+']');
+                if(jqButton.length==0) {
+                    var minwidth = 10;
+                }
+                else {
+                    var minwidth 
+                        = ($(jqButton).offset().left - $(input).offset().left)
+                        + $(jqButton).width();
+                }
+                this.div.style.minWidth = minwidth + "px";
+                
+                // Put in the titles.  This is also where we
+                // work out the height of the drop-down
+                this.div.innerHTML = this.displayTitles(input);
+                
+                // Put in the div, and do the mouse events
+                document.body.appendChild(this.div);
+
+                // This is for optimization, allows us to avoid
+                // repeatedly making jquery calls for this object
+                this.tbody = $('.x6select tbody')[0];
+                
+                // special routine to populate with fixed
+                // values on a pre-populated attribute.  If none
+                // are there it does nothing.
+                this.displayFixed(input);
+                
+            }
+            // If it is invisible, position it and then make it visible
+            if(this.div.style.display=='none') {
+                var position = $(input).offset();
+                var postop = position.top -1;
+                var poslft = position.left;
+                this.div.style.top  = (postop + input.offsetHeight +1) + "px";
+                this.div.style.left = poslft + "px";
+                this.div.style.display = 'block';
+                this.mouseEvents(input);
+            }
+            
+            if(fromKeyboard != null) {
+                this.moveUpOrDown(fromKeyboard);
+            }
+        },
+        
+        displayTitles: function(input) {
+            // If still here, we have values and descriptions
+            var retval = '<table><thead><tr>';
+            var descs  = u.p(input,'xTitles').split('|');
+            for(var idx in descs) {
+                retval+='<th>'+descs[idx]+'</th>';
+            }
+            retval+='<th>    ';
+
+            // Now work out the height.  If static, go by
+            // the number of rows, otherwise set it to 16, which
+            // is 15 for data and one for titles.
+            if(u.p(input,'x6rowCount',null)!=null) {
+                var rowCount = Number(u.p(input,'x6rowCount'));
+            }
+            else {
+                var rowCount = this.dynRowCount;
+            }
+            this.div.style.height = ((this.lineHeight+3)*(rowCount+1))+"px";
+            // ...and the height of the body
+            var h = (this.lineHeight + 3)*rowCount;
+            
+            // Now put out an empty body
+            retval+='</thead>'
+                +'<tbody style="height: '+h+'px; max-height: '+h+'px; '
+                +' overflow-y:scroll">'
+                +'</tbody></table>';
+            return retval;
+        },
+        
+        displayFixed: function(input) {
+            var svals = u.p(input,'xValues','');
+            if(svals.trim()=='') return;
+
+            console.log(svals);
+            retval = '';
+            var rows   = svals.split('||');
+            for(var idx in rows) {
+                retval += '<tr>';
+                var values = rows[idx].split('|');
+                for(var idx2 in values) {
+                    retval+= '<td>'+values[idx2];
+                }
+            }
+            console.log(retval);
+            this.tbody.innerHTML = retval;
+        },
+        
+        displayDynamic: function(input,rows) {
+            retval = ''
+            if(rows.length==0) {
+                this.tbody.innerHTML = '';
+                return;
+            }
+            for(var idx in rows) {
+                retval += '<tr>';
+                var values = rows[idx];
+                for(var idx2 in values) {
+                    retval+= '<td>'+values[idx2];
+                }
+            }
+            var lh = this.lineHeight + 3;
+            if(rows.length < this.dynRowCount) {
+                this.div.style.height = lh*(rows.length+1) + "px";
+                this.tbody.style.height = lh*rows.length  + "px";
+            }
+            else {
+                this.div.style.height = lh*(this.dynRowCount+1) + "px";
+                this.tbody.style.height = lh*this.dynRowCount + "px";
+            }
+            this.tbody.innerHTML = retval;
+            this.mouseEvents(input);
+        },
+        
+        mouseEvents: function(input) {
+            $('.x6select td')
+            .each(
+                function() {
+                    this.input = input;
+                }
+            )
+            .mouseover(
+                function() {
+                    var rowNow = $('.x6select tr.hilight');
+                    if(rowNow.length > 0) {
+                        if(rowNow[0] == this.parentNode) return;
+                    }
+                    $('.x6select tr.hilight').removeClass('hilight');
+                    $(this.parentNode).addClass('hilight');
+                }
+            )
+            .mousedown(
+                function(e) {
+                    this.input.value = this.parentNode.firstChild.innerHTML;
+                    x6inputs.x6select.hide();
+                    setTimeout(function() {$(this.input).focus();},100);
+                    e.stopPropagation();
+                    return false;
+                }
+            );
+        },
+        
+        moveUpOrDown: function(direction) {
+            // get current row
+            var rowNow = $('.x6select tr.hilight:visible');
+            var jqBody = $('.x6select tbody');
+            if(rowNow.length==0) {
+                $(jqBody[0].firstChild).addClass('hilight');
+            }
+            else {
+                if(direction == 'Up') {
+                    var candidate = $(rowNow).prev();
+                    console.log("Up candidate ",candidate);
+                    var rowsBelow = $(rowNow).nextAll().length;
+                    if(rowsBelow > 5) {
+                        var stNow = $('.x6select tbody').scrollTop();
+                        $(jqBody).scrollTop(stNow - ( this.lineHeight + 3));                        
+                    }
+                }
+                else {
+                    var candidate = $(rowNow).next();
+                    console.log("Down candidate ",candidate);
+                    var rowsAbove = $(rowNow).prevAll().length;
+                    if(rowsAbove > 5) {
+                        var stNow = $('.x6select tbody').scrollTop();
+                        $(jqBody).scrollTop(stNow + this.lineHeight + 3);                        
+                    }
+                }
+                console.log("row now ",rowNow);
+                console.log(direction);
+                if (candidate.length > 0) $(candidate[0].firstChild).mouseover();
+            }
+        }
     }
 }
 
@@ -1669,6 +1948,8 @@
     
     mouseover: function(rowDiv) {
         if(!this.mouseEnabled) return false;
+        if(!rowDiv.id) return false;
+        if(rowDiv.className=='selected') return false;
         var pieces = rowDiv.id.split('_');
         
         var rowNow = u.bb.vgfGet('highlight_'+pieces[0],'');
@@ -1931,6 +2212,20 @@
         }
         x6inputs.setClass(input);
         
+        // An 'x6select' control replaces HTML Select.  We add
+        // a little button off to the right of the input.
+        if(u.p(input,'x6select','N')=='Y') {
+            var str= '<span '
+                + 'class="button" '
+                + 'xInputId="'+input.id+'" '
+                + 'onmousedown = "this.className = '+"'button_mousedown'"+'" '
+                + 'onmouseup   = "this.className = '+"'button'"+'" '
+                + 'onmouseout  = "this.className = '+"'button'"+'" '
+                + 'onclick="x6inputs.ddClick(this)">'
+                + ' ↓ </span>';
+            $(input).after(str);
+        }
+        
         // This is important, it says that this is an 
         // active input.  This distinguishes it from possible
         // hidden inputs that were used as a clone source 
@@ -2046,6 +2341,9 @@
             return;
         }
         
+        // KFD 12/10/08, hide any dropdowns
+        x6inputs.x6select.hide();
+        
         // Remove the "selected" class from the inputs row,
         // it does not belong there anymore.
         u.byId(this.rowId(skey,true)).className = '';
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
 | 
| 
     
      
      
      From: <ken...@us...> - 2008-12-19 14:41:50
       
   | 
Revision: 957
          http://andro.svn.sourceforge.net/andro/?rev=957&view=rev
Author:   kendowns
Date:     2008-12-19 14:41:46 +0000 (Fri, 19 Dec 2008)
Log Message:
-----------
Release 1 Candidate!!!  
Modified Paths:
--------------
    trunk/andro/clib/x6.js
Modified: trunk/andro/clib/x6.js
===================================================================
--- trunk/andro/clib/x6.js	2008-12-19 14:41:11 UTC (rev 956)
+++ trunk/andro/clib/x6.js	2008-12-19 14:41:46 UTC (rev 957)
@@ -57,162 +57,7 @@
     SearchAndReplace.replaceAll(view);
 \* ================================================================== */
 
-/****O* Javascript-API/jsHtml
-*
-* NAME
-*   Javascript-API.jsHtml
-*
-* FUNCTION
-*   The javascript function jsHtml is a constructor 
-*   function for a new HTML node.  It is considerably
-*   faster and easier than document.createElement() and
-*   node.appendChild.
-*
-*   This function works almost exactly the same way as the
-*   PHP function html(), except that it works in the
-*   browser.
-*
-*   The resulting object is considerably simpler than the
-*   HTML nodes you can create in PHP, and is designed
-*   only for basic tasks.  There are no shortcuts for 
-*   creating complex entities, those must be coded by
-*   hand.
-*
-*   You can pass the innerHTML in as the second parameter,
-*   or you can set it directly by assigning the innerHtml
-*   property of the object.
-*
-* INPUTS
-*   * string - a valid (x)html tag name like 'div' or 'span'
-*   * string - (optional) the value of innerHtml
-*
-* EXAMPLE
-*   Use the Javascript "new" operator with this function.
-*        <script>
-*        var div = new jsHtml('div','Hello, I am a div!');
-*        div.hp.style = 'width: 300px';
-*        var html = div.bufferedRender();
-*        $( -- some jquery selector -- ).append(html);
-*        </script>
-*
-******
-*/
-function jsHtml(tag,innerHtml) {
-    this.tag = tag;
-    this.children = [ ];
-    this.hp = { };
-
-    /****O* jsHtml/innerHtml
-    *
-    * NAME
-    *   jsHtml.innerHtml
-    *
-    * FUNCTION
-    *   The javascript property innerHtml holds the innerHTML
-    *   of an HTML node created by jsHtml().  You can pass in
-    *   the innerHtml as the second parameter to jsHtml, or
-    *   you can set this property directly.
-    *
-    * EXAMPLE
-    *   Use the Javascript "new" operator with this function.
-    *        <script>
-    *        var div = new jsHtml('div');
-    *        div.innerHtml = 'I set this on the 2nd line!';
-    *        var html = div.bufferedRender();
-    *        $( -- some jquery selector -- ).append(html);
-    *        </script>
-    *
-    ******
-    */
-    this.innerHtml = innerHtml ? innerHtml : '';
-    
-    /****O* jsHtml/addChild
-    *
-    * NAME
-    *   jsHtml.addChild
-    *
-    * FUNCTION
-    *   The javascript method addChild adds one HTML node as
-    *   a child to another.  Both nodes must have been 
-    *   created by using the jsHtml() constructor function.
-    *
-    * EXAMPLE
-    *   Use the Javascript "new" operator with this function.
-    *        <script>
-    *        var div = new jsHtml('div');
-    *        var span = new jsHtml('span','A span in a div!');
-    *        div.addChild(span);
-    *        var html = div.bufferedRender();
-    *        $( -- some jquery selector -- ).append(html);
-    *        </script>
-    *
-    ******
-    */
-    this.addChild = function(child) {
-        this.children.push(child);
-    }
-    /******/
-
-    /****O* jsHtml/h
-    *
-    * NAME
-    *   jsHtml.h
-    *
-    * FUNCTION
-    *   The javascript method h creates a new HTML node and
-    *   makes it a child of the current node.  This is a 
-    *   shortcut for having to call jsHtml and then
-    *   addChild.
-    *
-    * EXAMPLE
-    *   Use the Javascript "new" operator with this function.
-    *        <script>
-    *        var div = new jsHtml('div');
-    *        var span = div.h('span','Hello!');
-    *        var html = div.bufferedRender();
-    *        $( -- some jquery selector -- ).append(html);
-    *        </script>
-    *
-    ******
-    */
-    this.h = function(tag,innerHtml) {
-        var newNode = new jsHtml(tag,innerHtml);
-        this.addChild(newNode);
-        return newNode;
-    }
-    /******/
-
-    /****O* jsHtml/bufferedRender
-    *
-    * NAME
-    *   jsHtml.bufferedRender
-    *
-    * FUNCTION
-    *   The javascript method bufferedRender returns a string
-    *   of HTML for a node created with jsHtml.  It sets all
-    *   properties, and recursively runs through all children.
-    *   The innerHtml, if it is present, goes out last.
-    *
-    * SOURCE
-    */
-    this.bufferedRender = function() {
-        var html = '<' + this.tag;
-        for(var attName in this.hp) {
-            html+=' '+attName+'="'+this.hp[attName]+'"';
-        }
-        html+=">";
-        for(var idx in this.children) {
-            html+=this.children[idx].bufferedRender();
-        }
-        html+=this.innerHtml;
-        html+='</'+this.tag+'>';
-        return html;
-    }
-    /******/
-
-}
-
-    
+   
 /****O* Javascript-API/x6events
 *
 * NAME
@@ -398,16 +243,18 @@
                 continue;
             }
             
-            // First possibility is a generic nofity handler
+            // Look for the method to receive the event
             var retval = false;
             var method = 'receiveEvent_'+eventName;
             if(typeof(subscriber[method])=='function') {
                 retval = subscriber[method](arguments);
+                //console.log(id,eventName,retval);
             }
             else {
                 u.error("Subscriber has no method: ",method); 
             }
             if(retval==false) {
+                //console.log('id returned false, setting false');
                 this.retvals[eventName] = false;
                 break;
             }
@@ -469,6 +316,9 @@
                 //console.groupEnd(); 
                 return retval;
         });
+        
+        // Put little buttons next to stuff
+        $(':input').each(function() { x6inputs.x6select.addButton(this); });
     },
     
     // Initialize an object that has been sent from the server
@@ -497,6 +347,21 @@
         // Make list of keys to stop no matter what
         var stopThem = [ 'CtrlF5', 'F10' ];
         
+        var noPropagate = [
+            'CtrlS', 'CtrlN', 'CtrlI', 'CtrlD',
+            'CtrlL', 'CtrlO', 'CtrlW', 'CtrlP',
+            'CtrlQ', 'CtrlR', 'CtrlU', 'CtrlK',
+            'CtrlY'
+        ];
+        
+        // Set a flag now.  If user hit ESC, we are trying
+        // to exit the screen, unless somebody tells us we
+        // cannot do so.
+        if(retval=='Esc') {
+            //console.log("Esc key pressed, pre-seting exitApproved=true");
+            u.bb.vgfSet('exitApproved',true);
+        }
+        
         // Now we have a complete key label, fire the event
         //console.log("In x6.keyDispatch, code and event follow");
         //console.log(retval);
@@ -506,14 +371,40 @@
             e.stopPropagation();
             return false;
         }
-        else if (!x6events.fireEvent('key_'+retval,retval)) {
-            //console.log("x6.keyDispatch: handler returned false, stopping propagation.");
-            e.stopPropagation();
-            return false;
-        }
         else {
-            //console.log("x6.keyDispatch: handler returned true, continuing propagation.");
-            return true;
+            var eventRetVal = x6events.fireEvent('key_'+retval,retval);
+            // ESC key is special, we need to know the retval
+            // for that, because if it came back true we will exit,
+            // but otherwise we cannot.
+            if(retval=='Esc') {
+                var exitApproved = u.bb.vgfGet('exitApproved',false);
+                //console.log("Key dispatch, ESC, exitapproved: ",exitApproved);
+                if(exitApproved) {
+                    //console.log("exit for ESC was approved, going to menu");
+                    setTimeout(
+                        function() {
+                            var x6page_prior=u.p(u.byId('x6page'),'value');
+                            var x6mod_prior =u.p(u.byId('x6module'),'value');
+                            var str = '?x6page=menu'
+                                +'&x6page_prior='+x6page_prior
+                                +'&x6mod_prior='+x6mod_prior;
+                            window.location.replace(str);
+                        }
+                        ,10
+                    );
+                }
+            }
+            else {
+                // All othere keys in the no-propagate list are
+                // stopped here.
+                if(noPropagate.indexOf(retval)>=0) {
+                    e.stopPropagation();
+                    return false;
+                }
+                else {
+                    return true;
+                }
+            }
         }
     }    
 }
@@ -553,11 +444,25 @@
         
         // All meta keys return true immediately except TAB and ENTER
         if(isMeta && !isNav) {
-            //console.log(keyLabel);
+            //console.log("input keydown key: ",keyLabel);
             var handUpList = ['UpArrow','DownArrow','PageUp','PageDown'];
             if(handUpList.indexOf(keyLabel)>=0) {
-                //console.log("Weird key that we pass up to doc-level keyPress");
-                var retval= x6.keyDispatcher(e);
+                // An explicit flag can prevent handing events up
+                if(u.p(inp,'xNoPassup','N')=='N') {
+                    // If there is an open x6select, do not hand up
+                    if(x6inputs.x6select.div) {
+                        if(keyLabel == 'DownArrow') {
+                            x6inputs.x6select.display(inp,'Down');
+                        }
+                        if(keyLabel == 'UpArrow'  ) {
+                            x6inputs.x6select.display(inp,'Up');
+                        }
+                    }
+                    else {
+                    //console.log("Weird key that we pass up to doc-level keyPress");
+                        var retval= x6.keyDispatcher(e);
+                    }
+                }
                 //console.groupEnd(); 
                 return retval;
             }
@@ -598,7 +503,7 @@
         
         // Type validation for some types, only if not TAB or ENTER
         if(!isNav) {
-            console.log("Not nav key, doing type validation");
+            //console.log("Not nav key, doing type validation");
             type = u.p(inp,'xtypeid');
             switch(type) {
             case 'int':
@@ -644,7 +549,7 @@
                 json.addParm('x6select','Y');
                 json.addParm('gpletters',val);
                 json.execute(true);
-                x6inputs.x6select.display(inp);
+                //x6inputs.x6select.display(inp);
                 x6inputs.x6select.displayDynamic(inp,ua.data.x6select);
             }
             
@@ -660,6 +565,7 @@
         // the value is set when afterBlurner fires.
         if(u.p(inp,'x6select','N')=='Y') {
             x6inputs.x6select.assignToMe(inp);
+            x6inputs.x6select.hide();
         }
         
         // This took a lot of experimentation to get right.
@@ -681,26 +587,24 @@
         // logic immediately below
         var tg       = u.p(inp,'xTabGroup','tgdefault');
         var jqString = '[xTabGroup='+tg+']:not([disabled])';
-        var jqObj = $(jqString)
+        var jqObj = $(jqString);
         var inpCount = jqObj.length;
         var first    = jqObj[0];
         var last     = jqObj[inpCount-1];
+
                 
         // If we are on first or last, Enter/Tab dichotomy does not matter,
         // we just send focus where we want and return false to kill
         // original behavior.
         if(inp==first && e.shiftKey) {
-            $('[xTabGroup='+tg+']:not([disabled]):last').focus();
+            var str ='[xTabGroup='+tg+']:not([disabled]):last';
+            //console.log(str);
+            $(str).focus();
             //console.log("First input, hit shift, going to last");
             //console.groupEnd();
             return false;
         }
         if(inp==last && !e.shiftKey) {
-            //if(u.p(inp,'inGrid',false)) {
-            //    x6events.fireEvent('key_DownArrow');
-            //    return;
-            //}
-            
             $('[xTabGroup='+tg+']:not([disabled]):first').focus();
             //console.log("Last input, no shift, going to first");
             //console.groupEnd();
@@ -733,7 +637,7 @@
             );
             if(focusTo) {
                 //console.log("Setting focus forward to ",focusTo);
-                $('#'+focusTo).focus().select();
+                $('[zActive]#'+focusTo).focus().select();
             }
             
         }
@@ -756,7 +660,7 @@
             );
             if(focusTo) {
                 //console.log("Setting focus backward to ",focusTo);
-                $('#'+focusTo).focus().select();
+                $('[zActive]#'+focusTo).focus().select();
             }
         }
         //console.log("Returning True");
@@ -767,10 +671,14 @@
     focus: function(inp) {
         //console.group("Input focus ",inp.id);
         //console.log("Input: ",inp);
+        this.x6select.checkForMe(inp);
         inp.zSelected = 1;
         inp.zOriginalValue = u.p(inp,'zOriginalValue','').trim();
         inp.lastBlurred    = '';
         x6inputs.setClass(inp);
+        if(u.p(inp,'zNew',0)==0) {
+            u.bb.vgfSet('lastFocus_'+u.p(inp,'xTableId'),inp.id);
+        }
         //console.log("Input focus DONE");
         //console.groupEnd();
         return true;
@@ -976,18 +884,38 @@
     
     ddClick: function(button) {
         var id = u.p(button,'xInputId');
-        var inp = $('[zActive]#'+id)[0];
+        var inp = $('#'+id)[0];
         this.x6select.display(inp);
     },
     
     x6select: {
+        input:       false,
         dynRowCount: 15,
-        div: false,
+        div:         false,
         
+        addButton: function(input) {
+            if(u.p(input,'x6select','N')=='Y') {
+                var str= '<span '
+                    + 'class="button" '
+                    + 'xInputId="'+input.id+'" '
+                    + 'onmousedown = "this.className = '+"'button_mousedown'"+'" '
+                    + 'onmouseup   = "this.className = '+"'button'"+'" '
+                    + 'onmouseout  = "this.className = '+"'button'"+'" '
+                    + 'onclick="x6inputs.ddClick(this)">'
+                    + ' ↓ </span>';
+                $(input).after(str);
+            }
+        },
+        
+        checkForMe: function(input) {
+            if(this.input != input) this.hide();
+        },
+        
         hide: function() {
             $(".x6select").remove();
             this.tbody=false;
-            this.div = false;
+            this.div  =false;
+            this.input=false;
         },
         
         assignToMe: function(inp) {
@@ -1007,6 +935,7 @@
             }
             
             if(!this.div) {
+                this.input = input;
                 this.div = document.createElement('DIV');
                 this.div.style.display    = 'none';
                 this.div.style.position   = 'absolute';
@@ -1063,6 +992,9 @@
             if(fromKeyboard != null) {
                 this.moveUpOrDown(fromKeyboard);
             }
+            else {
+                $(input).focus();
+            }
         },
         
         displayTitles: function(input) {
@@ -1099,7 +1031,7 @@
             var svals = u.p(input,'xValues','');
             if(svals.trim()=='') return;
 
-            console.log(svals);
+            //console.log(svals);
             retval = '';
             var rows   = svals.split('||');
             for(var idx in rows) {
@@ -1109,16 +1041,27 @@
                     retval+= '<td>'+values[idx2];
                 }
             }
-            console.log(retval);
+            //console.log(retval);
             this.tbody.innerHTML = retval;
         },
         
         displayDynamic: function(input,rows) {
+            // Begin by determining if we will show or hide
             retval = ''
             if(rows.length==0) {
-                this.tbody.innerHTML = '';
+                this.hide();
+                //this.tbody.innerHTML = '';
                 return;
             }
+            this.display(input);  
+            
+            // Find out if there is a currently selected row
+            var curVal = '';
+            var jqCandidate = $(this.tbody).find("tr.hilight td:first");
+            if(jqCandidate.length > 0 ) {
+                curVal = jqCandidate[0].innerHTML;
+            }
+            
             for(var idx in rows) {
                 retval += '<tr>';
                 var values = rows[idx];
@@ -1135,8 +1078,23 @@
                 this.div.style.height = lh*(this.dynRowCount+1) + "px";
                 this.tbody.style.height = lh*this.dynRowCount + "px";
             }
+            
             this.tbody.innerHTML = retval;
             this.mouseEvents(input);
+
+            // Now determine if we will highlight a row
+            var doFirst = true;
+            if(curVal!='') {
+                var jqCandidate = $(this.tbody).find('td:contains('+curVal+')');
+                if(jqCandidate.length > 0) {
+                    $(jqCandidate).mouseover();
+                    doFirst = false;
+                }
+            }
+            if(doFirst) {
+                window.x = this.tbody;
+                $(this.tbody).find('td:first').mouseover();
+            }
         },
         
         mouseEvents: function(input) {
@@ -1177,7 +1135,7 @@
             else {
                 if(direction == 'Up') {
                     var candidate = $(rowNow).prev();
-                    console.log("Up candidate ",candidate);
+                    //console.log("Up candidate ",candidate);
                     var rowsBelow = $(rowNow).nextAll().length;
                     if(rowsBelow > 5) {
                         var stNow = $('.x6select tbody').scrollTop();
@@ -1186,15 +1144,15 @@
                 }
                 else {
                     var candidate = $(rowNow).next();
-                    console.log("Down candidate ",candidate);
+                    //console.log("Down candidate ",candidate);
                     var rowsAbove = $(rowNow).prevAll().length;
                     if(rowsAbove > 5) {
                         var stNow = $('.x6select tbody').scrollTop();
                         $(jqBody).scrollTop(stNow + this.lineHeight + 3);                        
                     }
                 }
-                console.log("row now ",rowNow);
-                console.log(direction);
+                //console.log("row now ",rowNow);
+                //console.log(direction);
                 if (candidate.length > 0) $(candidate[0].firstChild).mouseover();
             }
         }
@@ -1225,33 +1183,31 @@
     buttonNew: function(self,id,table) {
         x6plugins.buttonStandard(self,'new','CtrlN');
         self.main = function() {
-            x6events.fireEvent('reqNewRow_'+this.zTable);   
+            return x6events.fireEvent('reqNewRow_'+this.zTable);   
         }
     },
     buttonInsert: function(self,id,table) {
         x6plugins.buttonStandard(self,'ins','CtrlI');
         self.main = function() {
-            x6events.fireEvent('reqNewRow_'+this.zTable,true);   
+            return x6events.fireEvent('reqNewRow_'+this.zTable,true);   
         }
     },
     buttonDelete: function(self,id,table) {
         x6plugins.buttonStandard(self,'delete','CtrlD');
         self.main = function() {
-            x6events.fireEvent('reqDelRow_'+this.zTable);
+            return x6events.fireEvent('reqDelRow_'+this.zTable);
         }
     },
     buttonCancel: function(self,id,table) {
         x6plugins.buttonStandard(self,'cancel','Esc');
         self.main = function() {
-            if(confirm("Abandon all changes?")) {
-                x6events.fireEvent('reqUndoRow_'+this.zTable);
-            }
+            x6events.fireEvent('reqUndoRow_'+this.zTable);
         }
     },
     buttonSave: function(self,id,table) {
         x6plugins.buttonStandard(self,'save','CtrlS');
         self.main = function() {
-            x6events.fireEvent('reqSaveRow_'+this.zTable);
+            return x6events.fireEvent('reqSaveRow_'+this.zTable);
         }
     },
     /****m* x6plugins/buttonStandard
@@ -1343,7 +1299,9 @@
             if(!this.zDisabled) this.main();
             // if a key event is received, we *always* stop 
             // propagation
-            x6events.retvals['key_'+this.zKey] = false;
+            // KFD 12/15/08, EXPERIMENTAL.  Do not do this here,
+            //               handle it in the top-level controller
+            //x6events.retvals['key_'+this.zKey] = false;
         }
         
         // finally of course set the onclick method
@@ -1462,7 +1420,7 @@
         var result = this.saveOk();
         u.bb.vgfSet('lastSave_'+this.zTable,result);
         if(result!='fail') {
-            x6events.fireEvent('uiNewRow_'+table,tabDivBefore);
+            x6events.fireEvent('uiNewRow_'+this.zTable,tabDivBefore);
         }
         //console.groupEnd();
     }
@@ -1486,7 +1444,7 @@
             var result = this.saveOk();
             u.bb.vgfSet('lastSave_'+this.zTable,result);
             if(result!='fail') {
-                x6events.fireEvent('uiEditRow_'+table,skey);
+                x6events.fireEvent('uiEditRow_'+this.zTable,skey);
             }
         }
         //console.log("tableController reqEditRow finished");
@@ -1526,10 +1484,16 @@
         
         // Only attempt a save if something changed
         if(cntChg == 0) {
-            //console.log("no changes, not trying to save");
             var retval = 'noaction';
+            var skeynow=u.bb.vgfGet('skey_'+this.zTable)
+            if(skeynow==0) {
+                //console.log(" ---- was editing new row, exit denied ---- ");
+                u.bb.vgfSet('exitApproved',false);
+            }
         }
         else {
+            //console.log(" ---- There were changes, not approving exit ----");
+            u.bb.vgfSet('exitApproved',false);
             
             //console.log("attempting database save");
             //console.log("Sending x4v_skey ",this.zSkey);
@@ -1713,20 +1677,46 @@
     
     /*
     *   Two requests, one to turn on editing-mode buttons,
-    *   another to turn them off.
+    *   another to turn them off.  Third to turn on just new/ins
     */
     x6events.subscribeToEvent('buttonsOn_'+table,id);
-    self['receiveEvent_buttonsOn_'+table] = function() {
-        x6events.fireEvent('enable_save_'   +this.zTable);
-        x6events.fireEvent('enable_cancel_' +this.zTable);
-        x6events.fireEvent('enable_delete_' +this.zTable);
+    self['receiveEvent_buttonsOn_'+table] = function(forceAll) {
+        /*
+        *   If another table has its buttons on, they
+        *   must be turned off. 
+        */
+        var buttonsTable = u.bb.vgfGet('buttonsTable','');
+        if(buttonsTable!='' && buttonsTable != this.zTable) {
+            x6events.fireEvent('buttonsOff_'+buttonsTable);
+        }
+        
+        // Now only turn buttons on if we have an skey
+        var skey = u.bb.vgfGet('skey_'+this.zTable);
+        //console.log("current skey is ",skey);
+        x6events.fireEvent('enable_new_' +this.zTable);
+        x6events.fireEvent('enable_ins_' +this.zTable);
+        if(skey >= 0) {
+            x6events.fireEvent('enable_save_'   +this.zTable);
+            x6events.fireEvent('enable_cancel_' +this.zTable);
+            x6events.fireEvent('enable_delete_' +this.zTable);
+        }
+        u.bb.vgfSet('buttonsTable',this.zTable);
     }
     x6events.subscribeToEvent('buttonsOff_'+table,id);
-    self['receiveEvent_buttonsOff_'+table] = function() {
+    self['receiveEvent_buttonsOff_'+table] = function(forceAll) {
+        if(forceAll) {
+            x6events.fireEvent('disable_new_' +this.zTable);
+            x6events.fireEvent('disable_ins_' +this.zTable);
+        }
         x6events.fireEvent('disable_save_'   +this.zTable);
         x6events.fireEvent('disable_cancel_' +this.zTable);
         x6events.fireEvent('disable_delete_' +this.zTable);
     }
+    x6events.subscribeToEvent('buttonsNew_'+table,id);
+    self['receiveEvent_buttonsNew_'+table] = function() {
+        x6events.fireEvent('enable_new_' +this.zTable);
+        x6events.fireEvent('enable_ins_' +this.zTable);
+    }
 }
     
     
@@ -1780,6 +1770,9 @@
         
         // Branch out to display in edit mode
         this.displayRow('edit',row);
+        x6events.fireEvent('uiHideKids_'+this.zTable,this.zTable);
+        x6events.fireEvent('uiEnableKids_'+this.zTable,this.zTable);
+        
         //console.log("detailDisplay uiEditRow FINISHED");
         //console.groupEnd();
     }
@@ -1791,6 +1784,11 @@
     self['receiveEvent_uiNewRow_'+table] = function(tabDivBefore) {
         //console.group("detailDisplay uiNewRow");
         this.displayRow('new',{});
+        
+        // KFD 12/18/08. Fire an event to disable kid tabs
+        x6events.fireEvent('uiHideKids_'+this.zTable,this.zTable);
+        x6events.fireEvent('uiDisableKids_'+this.zTable,this.zTable);
+        
         //console.log("detailDisplay uiNewRow FINISHED");
         //console.groupEnd();
     }
@@ -1821,6 +1819,8 @@
             }
         );
         u.bb.vgfSet('skey_'+this.zTable,-1);
+        x6events.fireEvent('uiHideKids_'+this.zTable,this.zTable);
+        x6events.fireEvent('uiDisableKids_'+this.zTable,this.zTable);
     }
     
         
@@ -1834,6 +1834,8 @@
                 x6inputs.clearOut(this);
         });
         x6events.fireEvent('buttonsOff_'+this.zTable);
+        x6events.fireEvent('uiHideKids_'+this.zTable,this.zTable);
+        x6events.fireEvent('uiDisableKids_'+this.zTable,this.zTable);
         //console.log("detailDisplay uiDelRow FINISHED");
         //console.groupEnd();
     }
@@ -1953,7 +1955,7 @@
         var pieces = rowDiv.id.split('_');
         
         var rowNow = u.bb.vgfGet('highlight_'+pieces[0],'');
-        if(rowNow!='') u.byId(rowNow).className = '';
+        if(rowNow!='' && u.byId(rowNow)!=null) u.byId(rowNow).className = '';
         var row = u.byId(rowDiv.id);
         if(row.id != 'selected') {
             u.byId(rowDiv.id).className = 'hilight';
@@ -1995,6 +1997,7 @@
     self.x6profile = u.p(self,'x6profile','none');
     self.kbOnEdit  = ['x6tabDiv','twosides'].indexOf(self.x6profile)>=0;
     
+    
     /*
     *    These two will tell us down below if the grid
     *    displays inputs for new rows and allows 
@@ -2027,8 +2030,10 @@
         return (noPound==null ? '#' : '')+this.zTable+'_'+skey;
     }
     self.skeyForRow = function(row) {
-        var pieces = row.id.split('_');
-        return pieces[1];
+        if(typeof(row)!='undefined') {
+            var pieces = row.id.split('_');
+            return pieces[1];
+        }
     }
     
     /*
@@ -2063,7 +2068,7 @@
                 //console.groupEnd();
                 return;
             }
-            
+                                                                                         
             /*
             *   If editing some other row, we know it was saved
             *   and is ok, convert it back to display
@@ -2073,32 +2078,14 @@
             }
 
             /*
-            *   This is the major UI stuff.  We need to slip a
-            *   row into the grid, clone some of the invisible
-            *   inputs that have been provided by the PHP code,
-            *   and get them all initialized and ready to go.
+            *   Pull the empty row and replace all of the values.
             */
-            var newRow = 
-                "<div id='"+this.zTable+"_0' "
-                +" class='selected' "
-                +" style='display:none'>";
-            var numbers = [ 'int', 'numb', 'money' ];
-            for (var idx in this.zColsInfo) {
-                var colInfo = this.zColsInfo[idx];
-                if(colInfo.column_id == '') continue;
-
-                newRow+= "<div gColumn = '"+idx+"'" 
-                    +" style='width: "+colInfo.width+"px;";
-                if(numbers.indexOf(colInfo.type_id)>=0) {
-                    newRow+="text-align: right;";
-                }
-                newRow+="'>";
-                var id = '#wrapper_'+this.zTable+'_'+colInfo.column_id;
-                var newInput = $(id).html();
-                //console.log("column: ",colInfo.column_id);
-                newRow+=newInput+"</div>";
+            var html = "<div id='"+this.zTable+"_0' style='display:none'>"
+                + this.zRowEditHtml
+                + "</div>";
+            for(var idx in this.zColsById) {
+                html = html.replace('*VALUE_'+idx+'*','');
             }
-            newRow+="</div>";
             
             
             /* 
@@ -2134,38 +2121,30 @@
             if(jqRow.length==0) {
                 if(tabDivBefore) {
                     //console.log("body prepend");
-                    $(this).find('.tbody').prepend(newRow);                    
+                    $(this).find('.tbody').prepend(html);                    
                 }
                 else {
                     //console.log("body append");
-                    $(this).find('.tbody').append(newRow);                    
+                    $(this).find('.tbody').append(html);                    
                 }
             }
             else {
                 if(tabDivBefore) {
                     //console.log("before this row: ",jqRow);
-                    $(jqRow).before(newRow);
+                    $(jqRow).before(html);
                 }
                 else {
                     //console.log("after this row: ",jqRow);
-                    $(jqRow).after(newRow);
+                    $(jqRow).after(html);
                 }
  ...
 
[truncated message content] | 
| 
     
      
      
      From: <ken...@us...> - 2008-12-21 02:09:49
       
   | 
Revision: 977
          http://andro.svn.sourceforge.net/andro/?rev=977&view=rev
Author:   kendowns
Date:     2008-12-21 02:09:46 +0000 (Sun, 21 Dec 2008)
Log Message:
-----------
Accept notifications to turn off keyboard events for modal dialogs.  Experimental, not sure how this is going to play out yet.
Modified Paths:
--------------
    trunk/andro/clib/x6.js
Modified: trunk/andro/clib/x6.js
===================================================================
--- trunk/andro/clib/x6.js	2008-12-21 02:08:47 UTC (rev 976)
+++ trunk/andro/clib/x6.js	2008-12-21 02:09:46 UTC (rev 977)
@@ -106,6 +106,14 @@
     ******
     */
     subscribers: { },
+    
+    eventsDisabled: false,
+    disableEvents: function() {
+        this.eventsDisabled = true;
+    },
+    enableEvents: function() {
+        this.eventsDisabled = false;
+    },
 
     /****m* x6events/subscribeToEvent
     *
@@ -226,6 +234,8 @@
     */
     retvals: { },
     fireEvent: function(eventName,arguments) {
+        if(this.eventsDisabled) return;
+        
         //console.group("fireEvent "+eventName);
         //console.log('arguments: ',arguments);
         // Find out if anybody is listening for this event
@@ -301,6 +311,11 @@
    
 \* **************************************************************** */
 var x6 = {
+    // A list of keyboard events that is allowed when a modal
+    // dialog is up.  False means allow all, an array would list
+    // what is allowed, and an empty array allows none.
+    dialogsAllow: false,
+    
     // Find all plugins in the x6plugins object.  Find all
     // DOM elements with property x6plugIn=xxx.  
     // Invoke the constructor for each one.
@@ -333,7 +348,7 @@
     
     initFocus: function() {
         //var str   = '[x6firstFocus=Y]:not([disabled]):reallyvisible:first';
-        var str   = 'input:not([disabled]):reallyvisible:first';        
+        var str   = 'input:not([disabled]):first';        
         //var first = $('input:not([disabled])').isVisible().find(':first');
         var first = $(str);
         if(first.length>0) first.focus();
@@ -344,6 +359,15 @@
     keyDispatcher: function(e) {
         var retval = u.keyLabel(e);
         
+        // Possible trapping because of modal dialogs
+        if(typeof(x6.dialogsAllow)=='object') {
+            if(x6.dialogsAllow.indexOf(retval) == -1) {
+                e.stopPropagation();
+                return false;
+            }
+        }
+        
+        
         // Make list of keys to stop no matter what
         var stopThem = [ 'CtrlF5', 'F10' ];
         
@@ -2912,6 +2936,7 @@
                 // even if the server does not return anything,
                 // because we initialized to an empty object.
                 $(this).find(".tbody").replaceWith(html);
+                $(this).find('.tbody div:first').mouseover();
             }
         }
         delete json;
@@ -3187,7 +3212,7 @@
         self['receiveEvent_key_Ctrl'+x.toString()] = function(key) {
             //return;
             //console.time("tabs key");
-            console.time("checking for visible");
+            //console.time("checking for visible");
             // Abort if he is not really visible, this is the
             // easiest way to do this, and we don't have to 
             // keep track of whether or not it is visible.
@@ -3207,7 +3232,7 @@
                     return;
                 }
             }
-            console.timeEnd("checking for visible");
+            //console.timeEnd("checking for visible");
             
             // get the offset, the keystroke, 
             // and calculate the index.
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
 | 
| 
     
      
      
      From: <ken...@us...> - 2008-12-24 04:01:38
       
   | 
Revision: 992
          http://andro.svn.sourceforge.net/andro/?rev=992&view=rev
Author:   kendowns
Date:     2008-12-24 04:01:30 +0000 (Wed, 24 Dec 2008)
Log Message:
-----------
Bunch of changes for logging and support for androPage
Modified Paths:
--------------
    trunk/andro/clib/x6.js
Modified: trunk/andro/clib/x6.js
===================================================================
--- trunk/andro/clib/x6.js	2008-12-24 04:01:09 UTC (rev 991)
+++ trunk/andro/clib/x6.js	2008-12-24 04:01:30 UTC (rev 992)
@@ -19,45 +19,7 @@
    or visit http://www.gnu.org/licenses/gpl.html
 \* ================================================================== */
 
-/* ================================================================== *\
- 
-   Debugging using Firebug.
-   
-   This file is full of commands that make use of firebugs 
-   very nice console facilities.  The up-side is that we get very
-   thorough event tracing when needed.  The down-side is that they
-   do not work at all on Internet Explorer and severely slow you 
-   down while running.
-   
-   Therefore, it is desirable to be able to turn them off andon
-   from time to time.  The best thing to do is comment them all
-   out completely, but that can be tedious.  The following two
-   Beanshell files show the jEdit commands for turning logging
-   on and off by commenting and uncommenting the relevant lines.
-   
-   If you want to do it manually, just replace all "//console."
-   with "//console." or vice-versa.
-   
-   # Beanshell: Turn logging off by commenting out lines
-    SearchAndReplace.setSearchString("//console.");
-    SearchAndReplace.setReplaceString("//console.");
-    SearchAndReplace.setBeanShellReplace(false);
-    SearchAndReplace.setIgnoreCase(true);
-    SearchAndReplace.setRegexp(false);
-    SearchAndReplace.setSearchFileSet(new CurrentBufferSet());
-    SearchAndReplace.replaceAll(view);
-
-   # Beanshell: Turn logging on by uncommenting the lines.
-    SearchAndReplace.setSearchString("//console.");
-    SearchAndReplace.setReplaceString("//console.");
-    SearchAndReplace.setBeanShellReplace(false);
-    SearchAndReplace.setIgnoreCase(true);
-    SearchAndReplace.setRegexp(false);
-    SearchAndReplace.setSearchFileSet(new CurrentBufferSet());
-    SearchAndReplace.replaceAll(view);
-\* ================================================================== */
-
-   
+  
 /****O* Javascript-API/x6events
 *
 * NAME
@@ -144,9 +106,9 @@
     * SOURCE
     */
     subscribeToEvent: function(eventName,id) {
-        //console.group("subscribeToEvent "+eventName);
-        //console.log("event name: ",eventName)
-        //console.log("id subscbr: ",id);
+        x6.console.group("subscribeToEvent "+eventName);
+        x6.console.log("event name: ",eventName)
+        x6.console.log("id subscbr: ",id);
         if(id=='undefined') {
             u.error('x6events.subscribeToEvent.  Second parameter '
                 +' undefined.  First parameter: '+eventName
@@ -168,7 +130,7 @@
         if(this.subscribers[eventName].indexOf(id)==-1) {
             this.subscribers[eventName].push(id);
         }
-        //console.groupEnd();
+        x6.console.groupEnd();
     },
     /******/
     
@@ -236,8 +198,8 @@
     fireEvent: function(eventName,arguments) {
         if(this.eventsDisabled) return;
         
-        //console.group("fireEvent "+eventName);
-        //console.log('arguments: ',arguments);
+        x6.console.group("fireEvent "+eventName);
+        x6.console.log('arguments: ',arguments);
         // Find out if anybody is listening for this event
         var subscribers = this.getSubscribers(eventName);
         
@@ -246,7 +208,7 @@
         this.retvals[eventName] = true;
         for(var x in subscribers) {
             var id = subscribers[x];
-            //console.log("subscriber: ",id);
+            x6.console.log("subscriber: ",id);
             var subscriber = u.byId(id);
             if(subscriber==null) {
                 u.error("There is no object with that ID, cannot dispatch");
@@ -258,19 +220,19 @@
             var method = 'receiveEvent_'+eventName;
             if(typeof(subscriber[method])=='function') {
                 retval = subscriber[method](arguments);
-                //console.log(id,eventName,retval);
+                x6.console.log(id,eventName,retval);
             }
             else {
                 u.error("Subscriber has no method: ",method); 
             }
             if(retval==false) {
-                //console.log('id returned false, setting false');
+                x6.console.log('id returned false, setting false');
                 this.retvals[eventName] = false;
                 break;
             }
         }
-        //console.log("fireEvent ",eventName," RETURNING: ",this.retvals[eventName]);
-        //console.groupEnd();
+        x6.console.log("fireEvent ",eventName," RETURNING: ",this.retvals[eventName]);
+        x6.console.groupEnd();
         return this.retvals[eventName];
     }
 }
@@ -325,10 +287,10 @@
         //           events to keyDispatcher that don't go to
         //           the document.keypress from an input 
         $(document).keypress(function(e) {
-                //console.group("Document Keypress");
-                //console.log("keypress ",e);
+                x6.console.group("Document Keypress");
+                x6.console.log("keypress ",e);
                 var retval= x6.keyDispatcher(e);
-                //console.groupEnd(); 
+                x6.console.groupEnd(); 
                 return retval;
         });
         
@@ -341,14 +303,14 @@
         var obj = u.byId(id);
         var pin = u.p(obj,'x6plugin');
         obj.zTable = u.p(obj,'x6table');
-        //console.log(pin,obj.zTable);
-        //console.log(obj);
+        x6.console.log(pin,obj.zTable);
+        x6.console.log(obj);
         x6plugins[pin](obj,obj.id,obj.zTable);
     },
     
     initFocus: function() {
         //var str   = '[x6firstFocus=Y]:not([disabled]):reallyvisible:first';
-        var str   = 'input:not([disabled]):first';        
+        var str   = ':input:not([disabled]):first';
         //var first = $('input:not([disabled])').isVisible().find(':first');
         var first = $(str);
         if(first.length>0) first.focus();
@@ -358,6 +320,7 @@
     // Keyboard handler
     keyDispatcher: function(e) {
         var retval = u.keyLabel(e);
+        x6.console.log(retval);
         
         // Possible trapping because of modal dialogs
         if(typeof(x6.dialogsAllow)=='object') {
@@ -382,16 +345,16 @@
         // to exit the screen, unless somebody tells us we
         // cannot do so.
         if(retval=='Esc') {
-            //console.log("Esc key pressed, pre-seting exitApproved=true");
+            x6.console.log("Esc key pressed, pre-seting exitApproved=true");
             u.bb.vgfSet('exitApproved',true);
         }
         
         // Now we have a complete key label, fire the event
-        //console.log("In x6.keyDispatch, code and event follow");
-        //console.log(retval);
-        //console.log(e);
+        x6.console.log("In x6.keyDispatch, code and event follow");
+        x6.console.log(retval);
+        x6.console.log(e);
         if(stopThem.indexOf(retval)>0) {
-            //console.log("x6.keyDispatch: key is in force stop list, stopping propagation.");
+            x6.console.log("x6.keyDispatch: key is in force stop list, stopping propagation.");
             e.stopPropagation();
             return false;
         }
@@ -402,9 +365,9 @@
             // but otherwise we cannot.
             if(retval=='Esc') {
                 var exitApproved = u.bb.vgfGet('exitApproved',false);
-                //console.log("Key dispatch, ESC, exitapproved: ",exitApproved);
+                x6.console.log("Key dispatch, ESC, exitapproved: ",exitApproved);
                 if(exitApproved) {
-                    //console.log("exit for ESC was approved, going to menu");
+                    x6.console.log("exit for ESC was approved, going to menu");
                     setTimeout(
                         function() {
                             var x6page_prior=u.p(u.byId('x6page'),'value');
@@ -430,11 +393,168 @@
                 }
             }
         }
-    }    
+    },
+    
+    /*
+    *  The console object starts out with do-nothing functions.
+    *  These are replaced if the console object exists.
+    */
+    console: {
+        enabled:       false, 
+        enableLog:     false,
+        enableWarn:    false,
+        enableInfo:    false,
+        enableError:   false,
+        enableTime:    false,
+        enableGroup:   false,
+        enableProfile: false,
+        enableOutline: function() {
+            this.enableTime  = true;
+            this.enableGroup = true;
+            this.enableProfile=true;
+        },
+        enableAll: function() {
+            this.enableLog   = true;
+            this.enableWarn  = true;
+            this.enableInfo  = true;
+            this.enableError = true;
+            this.enableTime  = true;
+            this.enableGroup = true;
+            this.enableProfile=true;
+        },
+        disableAll: function() {
+            this.enableLog   = false;
+            this.enableWarn  = false;
+            this.enableInfo  = false;
+            this.enableError = false;
+            this.enableTime  = false;
+            this.enableGroup = false;
+            this.enableProfile=false;
+        },
+        indent:  '',
+        log:     function(args) { },
+        warn:    function(args) { },   
+        info:    function(args) { },   
+        error:   function(args) { },
+        time:    function(args) { },
+        timeEnd: function(args) { },
+        group:   function(args) { },
+        groupEnd:function(args) { },
+        _log:     function(x1,x2,x3,x4,x5,x6,x7) {
+            if(typeof(x2)=='undefined') 
+                console.log(x1);
+            else if (typeof(x3)=='undefined')
+                console.log(x1,x2);
+            else if (typeof(x4)=='undefined')
+                console.log(x1,x2,x3);
+            else if (typeof(x5)=='undefined')
+                console.log(x1,x2,x3,x4);
+            else if (typeof(x6)=='undefined')
+                console.log(x1,x2,x3,x4,x5);
+            else if (typeof(x7)=='undefined')
+                console.log(x1,x2,x3,x4,x5,x6);
+            else
+                console.log(x1,x2,x3,x4,x5,x6,x7);
+        },   
+    }
 }
 
 /* **************************************************************** *\
 
+   Run-time creation of specialized functions on
+   the x6.console object.  These are cross-compatible between
+   firebug and 
+   
+\* **************************************************************** */
+if(typeof(console)!='undefined') {
+    
+    // Firebug defines "x6.console.group", but blackbird does
+    // not.  So if we cannot find x6.console.group we create
+    // functions that do indenting instead.
+    //
+    if(typeof(x6.console.group)=='undefined') {
+        x6.console.group = function(x) {
+            if(!this.groupEnable) return;
+            this._log(x);
+            this.indent+='  ';   
+        }
+        x6.console.groupEnd = function(x) {
+            if(!this.groupEnable) return;
+            this._log(x);
+            if(this.indent.length > 0) {
+                if(this.indent.length==2) {
+                    this.indent = '';
+                }
+                else {
+                    this.indent = this.indent.slice(0,this.indent.length-2);
+                }
+            }
+        }
+        
+    
+        
+    }
+    
+    if(true) {
+        x6.console.log = function(x1,x2,x3,x4,x5,x6,x7) {
+            if(this.enableLog) {
+                this._log(this.indent+x1,x2,x3,x4,x5,x6,x7);    
+            }
+        }
+        x6.console.warn = function(x) {
+            if(this.enableWarn) console.warn(this.indent+x);   
+        }
+        x6.console.info = function(x) {
+            if(this.enableInfo) console.info(this.indent+x);   
+        }
+        x6.console.error = function(x) {
+            if(this.enableError) console.error(this.indent+x);   
+        }
+        
+
+        if(typeof(console.time)!='undefined') {
+            x6.console.time = function(x) {
+                if(this.enableTime) console.time(this.indent+x);
+            }
+            x6.console.timeEnd = function(str) {
+                if(this.enableTime) console.timeEnd(this.indent+x);
+            }
+        }
+    }
+    else {
+        x6.console.log = function(x) {
+            if(this.enableLog) console.log(x);   
+        }
+        x6.console.warn = function(x) {
+            if(this.enableWarn) console.warn(x);   
+        }
+        x6.console.info = function(x) {
+            if(this.enableInfo) console.info(x);   
+        }
+        x6.console.error = function(x) {
+            if(this.enableError) console.error(x);   
+        }
+        x6.console.group = function(x) {
+            if(this.enableGroup) console.group(x);
+        }
+        x6.console.groupEnd = function(x) {
+            if(this.enableGroup) console.groupEnd(x);
+        }
+        if(typeof(console.time)!='undefined') {
+            x6.console.time = function(x) {
+                if(this.enableTime) console.time(x);
+            }
+            x6.console.timeEnd = function(str) {
+                if(this.enableTime) console.timeEnd(x);
+            }
+        }
+    }
+}
+x6.console.enableAll();
+
+
+/* **************************************************************** *\
+
    Universal x6 input keyup handler
    
 \* **************************************************************** */
@@ -443,12 +563,12 @@
     // you do not see an input's new value until the keyup 
     // event.  You do not see it in keypress or keydown.
     keyUp: function(e,inp) {
-        //console.group("Input keyUp");
-        //console.log(e);
-        //console.log(inp);
+        x6.x6.console.group("Input keyUp");
+        x6.console.log(e);
+        x6.console.log(inp);
         
         x6inputs.setClass(inp);
-        //console.groupEnd("Input keyUp");
+        x6.console.groupEnd("Input keyUp");
     },
     
     // Keydown is used only for tab or shift tab, to enforce
@@ -457,18 +577,18 @@
     // current control
     //
     keyDown: function(e,inp) {
-        //console.group('Input keyDown ');
-        //console.log(inp);
+        x6.console.group('Input keyDown ');
+        x6.console.log(inp);
         var keyLabel=u.keyLabel(e);
         var isTab   =keyLabel=='Tab'    || keyLabel=='ShiftTab';
         var isEnter =keyLabel=='Enter'  || keyLabel=='ShiftEnter';  
         var isMeta  =u.keyIsMeta(e);
         var isNav   =isEnter || isTab;
-        //console.log("label ",keyLabel,' isTab ',isTab,' isEnter ',isEnter,' isMeta ',isMeta,' isNav ',isNav);
+        x6.console.log("label ",keyLabel,' isTab ',isTab,' isEnter ',isEnter,' isMeta ',isMeta,' isNav ',isNav);
         
         // All meta keys return true immediately except TAB and ENTER
         if(isMeta && !isNav) {
-            //console.log("input keydown key: ",keyLabel);
+            x6.console.log("input keydown key: ",keyLabel);
             var handUpList = ['UpArrow','DownArrow','PageUp','PageDown'];
             if(handUpList.indexOf(keyLabel)>=0) {
                 // An explicit flag can prevent handing events up
@@ -483,11 +603,11 @@
                         }
                     }
                     else {
-                    //console.log("Weird key that we pass up to doc-level keyPress");
+                    x6.console.log("Weird key that we pass up to doc-level keyPress");
                         var retval= x6.keyDispatcher(e);
                     }
                 }
-                //console.groupEnd(); 
+                x6.console.groupEnd(); 
                 return retval;
             }
             else if(keyLabel=='CtrlLeftArrow') {
@@ -511,36 +631,36 @@
                     this.firstInput(inp);
             }
             else if(keyLabel=='End') {
-                //console.log(inp);
+                x6.console.log(inp);
                 var ss = inp.selectionStart;
                 var se = inp.selectionEnd;
                 var ln = inp.value.toString().trim().length;
-                //console.log(ss,se,ln);
+                x6.console.log(ss,se,ln);
                 if(ss == se && se == ln) this.lastInput(inp);
             }
             else {
-                //console.log("meta but not nav, ret true");
+                x6.console.log("meta but not nav, ret true");
             }
-            //console.groupEnd();
+            x6.console.groupEnd();
             return true;
         }
         
         // Type validation for some types, only if not TAB or ENTER
         if(!isNav) {
-            //console.log("Not nav key, doing type validation");
+            x6.console.log("Not nav key, doing type validation");
             type = u.p(inp,'xtypeid');
             switch(type) {
             case 'int':
-                //console.log("type validation for int");
+                x6.console.log("type validation for int");
                 if(!u.keyIsNumeric(e)) return false;
                 break;
             case 'numb':
             case 'money':
-                //console.log("type validation for numb/money");
+                x6.console.log("type validation for numb/money");
                 if(!u.keyIsNumeric(e) && u.keyLabel(e)!='.') return false;
                 break;
             case 'date':
-                //console.log("type validation for date");
+                x6.console.log("type validation for date");
                 if(!u.keyIsNumeric(e)) {
                     if(keyLabel!='-' && keyLabel!='/') return false;
                 }
@@ -565,10 +685,10 @@
                 var val = val.slice(0,inp.selectionStart)
                     +keyLabel
                     +val.slice(inp.selectionEnd);
-                //console.log("current value: ",inp.value)
-                //console.log("sel start: ",inp.selectionStart)
-                //console.log("sel end: ",inp.selectionEnd)
-                //console.log("computed value:",val);
+                x6.console.log("current value: ",inp.value)
+                x6.console.log("sel start: ",inp.selectionStart)
+                x6.console.log("sel end: ",inp.selectionEnd)
+                x6.console.log("computed value:",val);
                 json = new androJSON('x6page',u.p(inp,'x6seltab'));
                 json.addParm('x6select','Y');
                 json.addParm('gpletters',val);
@@ -577,8 +697,8 @@
                 x6inputs.x6select.displayDynamic(inp,ua.data.x6select);
             }
             
-            //console.log("Type validation complete, returning true");
-            //console.groupEnd();
+            x6.console.log("Type validation complete, returning true");
+            x6.console.groupEnd();
             return true;
         }
         
@@ -622,16 +742,16 @@
         // original behavior.
         if(inp==first && e.shiftKey) {
             var str ='[xTabGroup='+tg+']:not([disabled]):last';
-            //console.log(str);
+            x6.console.log(str);
             $(str).focus();
-            //console.log("First input, hit shift, going to last");
-            //console.groupEnd();
+            x6.console.log("First input, hit shift, going to last");
+            x6.console.groupEnd();
             return false;
         }
         if(inp==last && !e.shiftKey) {
             $('[xTabGroup='+tg+']:not([disabled]):first').focus();
-            //console.log("Last input, no shift, going to first");
-            //console.groupEnd();
+            x6.console.log("Last input, no shift, going to first");
+            x6.console.groupEnd();
             return false;
         }
         
@@ -640,8 +760,8 @@
         // we have to work out the next control to give focus
         // to, either forward or backward
         if(isTab) {
-            //console.log("Tab key hit, returning true");
-            //console.groupEnd();
+            x6.console.log("Tab key hit, returning true");
+            x6.console.groupEnd();
             return true;
         }
         if(!e.shiftKey) {
@@ -650,8 +770,8 @@
             var foundMe = false;
             $('[xTabGroup='+tg+']:not([disabled])').each(
                 function() {
-                    //console.log(this.id);
-                    //console.log(focusTo,foundMe);
+                    x6.console.log(this.id);
+                    x6.console.log(focusTo,foundMe);
                     if(focusTo) return;
                     if(foundMe) {
                         focusTo = this.id;
@@ -660,7 +780,7 @@
                 }
             );
             if(focusTo) {
-                //console.log("Setting focus forward to ",focusTo);
+                x6.console.log("Setting focus forward to ",focusTo);
                 $('[zActive]#'+focusTo).focus().select();
             }
             
@@ -683,18 +803,18 @@
                 }
             );
             if(focusTo) {
-                //console.log("Setting focus backward to ",focusTo);
+                x6.console.log("Setting focus backward to ",focusTo);
                 $('[zActive]#'+focusTo).focus().select();
             }
         }
-        //console.log("Returning True");
-        //console.groupEnd();
+        x6.console.log("Returning True");
+        x6.console.groupEnd();
         return true;
     },
     
     focus: function(inp) {
-        //console.group("Input focus ",inp.id);
-        //console.log("Input: ",inp);
+        x6.console.group("Input focus ",inp.id);
+        x6.console.log("Input: ",inp);
         this.x6select.checkForMe(inp);
         inp.zSelected = 1;
         inp.zOriginalValue = u.p(inp,'zOriginalValue','').trim();
@@ -703,8 +823,8 @@
         if(u.p(inp,'zNew',0)==0) {
             u.bb.vgfSet('lastFocus_'+u.p(inp,'xTableId'),inp.id);
         }
-        //console.log("Input focus DONE");
-        //console.groupEnd();
+        x6.console.log("Input focus DONE");
+        x6.console.groupEnd();
         return true;
     },
     // KFD 11/29/08, not being called anywhere?
@@ -713,13 +833,13 @@
     //},
     
     blur: function(inp) {
-        //console.group("Input blur ",inp.id);
+        x6.console.group("Input blur ",inp.id);
         inp.zSelected = 0;
         x6inputs.setClass(inp);
         x6inputs.afterBlurner(inp);
         x6inputs.x6select.hide();
-        //console.log("Input Blur DONE");
-        //console.groupEnd();
+        x6.console.log("Input Blur DONE");
+        x6.console.groupEnd();
         return true;
     },
     // KFD 11/29/08, not being called anywhere?
@@ -732,24 +852,24 @@
     *  
     */
     afterBlurner: function(inp) {
-        //console.group("afterBlurner");
-        //console.log(inp);
+        x6.console.group("afterBlurner");
+        x6.console.log(inp);
         if(u.p(inp,'inblur',false)) {
-            //console.log("inblur flag set, no action");
-            //console.groupEnd();
+            x6.console.log("inblur flag set, no action");
+            x6.console.groupEnd();
             return false;
         }
         inp.inblur = true;
         // If method does not exist forget it
         if(!inp.afterBlur) {
-            //console.log("No afterBlur(), leaving flag set and returning");
-            //console.groupEnd();
+            x6.console.log("No afterBlur(), leaving flag set and returning");
+            x6.console.groupEnd();
             return true;
         }
         // If value has changed, fire it
         if(inp.lastBlurred==u.p(inp,'value','').trim()) {
-            //console.log("Input lastBlurred is current value, no action");
-            //console.groupEnd();
+            x6.console.log("Input lastBlurred is current value, no action");
+            x6.console.groupEnd();
             inp.inblur = false;
             return true;
         }
@@ -759,15 +879,15 @@
             // is anything particularly "valid" or correct about the
             // value.
             if(inp.afterBlur()) {
-                //console.log("Afterblurner setting flag false, return true");
-                //console.groupEnd();
+                x6.console.log("Afterblurner setting flag false, return true");
+                x6.console.groupEnd();
                 inp.inblur = false;
                 inp.lastBlurred = u.p(inp,'value','').trim();
                 return true;
             }
             else {
-                //console.log("Afterblurner setting flag false, return false");
-                //console.groupEnd();
+                x6.console.log("Afterblurner setting flag false, return false");
+                x6.console.groupEnd();
                 inp.inblur = false;
                 return false;
             }
@@ -776,14 +896,14 @@
     
     enable: function(inp) {
         if(typeof(inp)=='string') inp = u.byId(inp);
-        //console.log("Enabling input ",inp.id);
+        x6.console.log("Enabling input ",inp.id);
         inp.disabled = false;
         inp.zOriginalValue = u.p(inp,'value','');
         this.setClass(inp);
     },
     disable: function(inp) {
         if(typeof(inp)=='string') inp = u.byId(inp);
-        //console.log("Disabling input ",inp.id);
+        x6.console.log("Disabling input ",inp.id);
         inp.disabled = true;
         this.setClass(inp);
     },
@@ -806,8 +926,8 @@
         }
         
         ux = u.uniqueId();
-        //console.group("setClass for an input  "+ux);
-        //console.log(inp);
+        x6.console.group("setClass for an input  "+ux);
+        x6.console.log(inp);
         if(u.p(inp,'zOriginalValue',null)==null) inp.zOriginalValue = '';
         if(inp.value==inp.zOriginalValue) {
             inp.zChanged = 0;
@@ -831,15 +951,15 @@
         else if(zNew)     css = 'changed';
         else if(zChanged) css = 'changed';
         else              css = '';
-        //console.log("initial class is "+css);
+        x6.console.log("initial class is "+css);
         
         // Now pick the selected version if required
         if(zSelected) css += 'Selected';
-        //console.log("Final class is "+css);
+        x6.console.log("Final class is "+css);
         
         // Now do some stuff if it is read only
         //inp.disabled = zRO;
-        //console.log("Read Only Decision is",inp.disabled);
+        x6.console.log("Read Only Decision is",inp.disabled);
         
         // Flag to do the row
         doRow = u.p(inp,'xClassRow',0);
@@ -847,7 +967,7 @@
         // Now set the class name
         inp.className = css;
         if(doRow!=0) {
-            //console.log('do row');
+            x6.console.log('do row');
             if(zSelected) {
                 inp.parentNode.parentNode.className = 'selected';
             }
@@ -855,12 +975,12 @@
                 inp.parentNode.parentNode.className = '';
             }
         }
-        //console.groupEnd();
+        x6.console.groupEnd();
     },
     
     clearOut: function(inp) {
         if(inp.zSelected==1) {
-            //console.log("In clear out, blurring ",inp);
+            x6.console.log("In clear out, blurring ",inp);
             inp.blur();
         }
         inp.disabled       = true;
@@ -920,7 +1040,7 @@
             var skey = u.bb.vgfGet('skey_'+table,-1);
         }
         if(skey==-1) return;
-        console.log(table,skey);
+        x6.console.log(table,skey);
         
         ua.json.init('x6page',table);
         ua.json.addParm('x6action','viewClob');
@@ -1079,7 +1199,7 @@
             var svals = u.p(input,'xValues','');
             if(svals.trim()=='') return;
 
-            //console.log(svals);
+            x6.console.log(svals);
             retval = '';
             var rows   = svals.split('||');
             for(var idx in rows) {
@@ -1089,7 +1209,7 @@
                     retval+= '<td>'+values[idx2];
                 }
             }
-            //console.log(retval);
+            x6.console.log(retval);
             this.tbody.innerHTML = retval;
         },
         
@@ -1183,7 +1303,7 @@
             else {
                 if(direction == 'Up') {
                     var candidate = $(rowNow).prev();
-                    //console.log("Up candidate ",candidate);
+                    x6.console.log("Up candidate ",candidate);
                     var rowsBelow = $(rowNow).nextAll().length;
                     if(rowsBelow > 5) {
                         var stNow = $('.x6select tbody').scrollTop();
@@ -1192,15 +1312,15 @@
                 }
                 else {
                     var candidate = $(rowNow).next();
-                    //console.log("Down candidate ",candidate);
+                    x6.console.log("Down candidate ",candidate);
                     var rowsAbove = $(rowNow).prevAll().length;
                     if(rowsAbove > 5) {
                         var stNow = $('.x6select tbody').scrollTop();
                         $(jqBody).scrollTop(stNow + this.lineHeight + 3);                        
                     }
                 }
-                //console.log("row now ",rowNow);
-                //console.log(direction);
+                x6.console.log("row now ",rowNow);
+                x6.console.log(direction);
                 if (candidate.length > 0) $(candidate[0].firstChild).mouseover();
             }
         }
@@ -1258,6 +1378,36 @@
             return x6events.fireEvent('reqSaveRow_'+this.zTable);
         }
     },
+    buttonCustom: function(self,id,table) {
+        self.zTable = table;
+        // This is sort of the same as the predefined buttons
+        x6plugins.buttonStandard(self,id,u.p(self,'buttonKey'));
+        
+        // This is special for custom buttons
+        x6events.subscribeToEvent('buttonsOn_'+table,id);
+        self['receiveEvent_buttonsOn_'+table] = function() {
+            var skey = u.bb.vgfGet('skey_'+this.zTable);
+            var doit = false;
+            if(skey==0) {
+                doit = u.p(this,'permins','N')=='Y';
+            }
+            else {
+                doit = u.p(this,'permupd','N')=='Y';
+            }
+            if(doit...
 
[truncated message content] | 
| 
     
      
      
      From: <ken...@us...> - 2008-12-26 17:58:06
       
   | 
Revision: 1008
          http://andro.svn.sourceforge.net/andro/?rev=1008&view=rev
Author:   kendowns
Date:     2008-12-26 17:58:03 +0000 (Fri, 26 Dec 2008)
Log Message:
-----------
Three bug fixes
Modified Paths:
--------------
    trunk/andro/clib/x6.js
Modified: trunk/andro/clib/x6.js
===================================================================
--- trunk/andro/clib/x6.js	2008-12-24 17:04:00 UTC (rev 1007)
+++ trunk/andro/clib/x6.js	2008-12-26 17:58:03 UTC (rev 1008)
@@ -612,7 +612,7 @@
     // you do not see an input's new value until the keyup 
     // event.  You do not see it in keypress or keydown.
     keyUp: function(e,inp) {
-        x6.x6.console.group("Input keyUp");
+        x6.console.group("Input keyUp");
         x6.console.log(e);
         x6.console.log(inp);
         
@@ -2190,6 +2190,10 @@
             }
         }
     }
+    
+    if(u.p(self,'x6profile')=='twosides') {
+        x6events.fireEvent('buttonsNew_'+table);
+    }
 }
 
 x6tabDiv = {
@@ -3515,7 +3519,7 @@
                 var pieces = kids[kid].split(':');
                 var table_chd = pieces[0];
                 var display   = pieces[1];  // assume 'checkbox'
-                var json = new androJSON('x6table',this.zTable);
+                var json = new androJSON('x6page',this.zTable);
                 json.addParm('skey',u.bb.vgfGet('skey_'+this.zTable));
                 json.addParm('table_chd',pieces[0]);
                 json.addParm('x6action' ,'child_checkbox');
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
 | 
| 
     
      
      
      From: <ken...@us...> - 2008-12-26 22:33:01
       
   | 
Revision: 1018
          http://andro.svn.sourceforge.net/andro/?rev=1018&view=rev
Author:   kendowns
Date:     2008-12-26 22:32:58 +0000 (Fri, 26 Dec 2008)
Log Message:
-----------
In select drop-downs, null values are made spaces.
Modified Paths:
--------------
    trunk/andro/clib/x6.js
Modified: trunk/andro/clib/x6.js
===================================================================
--- trunk/andro/clib/x6.js	2008-12-26 20:32:17 UTC (rev 1017)
+++ trunk/andro/clib/x6.js	2008-12-26 22:32:58 UTC (rev 1018)
@@ -1287,7 +1287,12 @@
                 retval += '<tr>';
                 var values = rows[idx];
                 for(var idx2 in values) {
-                    retval+= '<td>'+values[idx2];
+                    if(values[idx2] == null) {
+                        retval+= '<td> ';
+                    }
+                    else {
+                        retval+= '<td>'+values[idx2];
+                    }
                 }
             }
             var lh = this.lineHeight + 3;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
 | 
| 
     
      
      
      From: <ken...@us...> - 2008-12-29 16:07:05
       
   | 
Revision: 1026
          http://andro.svn.sourceforge.net/andro/?rev=1026&view=rev
Author:   kendowns
Date:     2008-12-29 16:07:01 +0000 (Mon, 29 Dec 2008)
Log Message:
-----------
IE Compatibility: removed stray comma that messes up IE.
Modified Paths:
--------------
    trunk/andro/clib/x6.js
Modified: trunk/andro/clib/x6.js
===================================================================
--- trunk/andro/clib/x6.js	2008-12-29 16:06:07 UTC (rev 1025)
+++ trunk/andro/clib/x6.js	2008-12-29 16:07:01 UTC (rev 1026)
@@ -242,7 +242,7 @@
                 console[fnname](x1,x2,x3,x4,x5,x6);
             else
                 console[fnname](x1,x2,x3,x4,x5,x6,x7);
-        },   
+        }   
     }
 }
 
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
 | 
| 
     
      
      
      From: <ken...@us...> - 2008-12-30 17:10:22
       
   | 
Revision: 1034
          http://andro.svn.sourceforge.net/andro/?rev=1034&view=rev
Author:   kendowns
Date:     2008-12-30 17:10:19 +0000 (Tue, 30 Dec 2008)
Log Message:
-----------
Small fix to IE-compatibility for event handling.
Modified Paths:
--------------
    trunk/andro/clib/x6.js
Modified: trunk/andro/clib/x6.js
===================================================================
--- trunk/andro/clib/x6.js	2008-12-30 16:38:31 UTC (rev 1033)
+++ trunk/andro/clib/x6.js	2008-12-30 17:10:19 UTC (rev 1034)
@@ -75,7 +75,7 @@
         $(document).keypress(function(e) {
                 //e = e ? e : window.event;
                 x6.console.group("Document Keypress");
-                x6.console.log("keypress ",e);
+                x6.console.log("Here is keypress event: ",e);
                 var retval= x6.keyDispatcher(e);
                 x6.console.groupEnd(); 
                 return retval;
@@ -444,7 +444,7 @@
     subscribeToEvent: function(eventName,id) {
         x6.console.group("subscribeToEvent "+eventName);
         x6.console.log("event name: ",eventName)
-        x6.console.log("id subscbr: ",id);
+        x6.console.log("id subscriber: ",id);
         if(id=='undefined') {
             u.error('x6events.subscribeToEvent.  Second parameter '
                 +' undefined.  First parameter: '+eventName
@@ -538,11 +538,16 @@
         x6.console.log('arguments: ',arguments);
         // Find out if anybody is listening for this event
         var subscribers = this.getSubscribers(eventName);
+        if(subscribers.length==0) {
+            x6.console.log("No subscribers to this event, no action");
+            x6.console.groupEnd();
+            return;
+        }
         
         // loop through subscribers.  Note at the bottom of the list
         // that if an event handler returns false we must stop.
         this.retvals[eventName] = true;
-        for(var x=0; x<(subscribers.length-1);x++) {
+        for(var x=0; x<subscribers.length;x++) {
             var id = subscribers[x];
             x6.console.log("type of id: ",typeof(id));
             x6.console.log("subscriber: ",id);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
 |