dojox/grid/_FocusManager.js

  • Provides:

    • dojox.grid._FocusManager
  • Requires:

    • dojox.grid.util in common
  • dojox.grid._FocusManager

    • type
      Function
    • summary
      Controls grid cell focus. Owned by grid and used internally for focusing.
      Note: grid cell actually receives keyboard input only when cell is being edited.
    • parameters:
      • inGrid: (typeof )
    • source: [view]
        this.grid = inGrid;
        this.cell = null;
        this.rowIndex = -1;
        this._connects = [];
        this._headerConnects = [];
        this.headerMenu = this.grid.headerMenu;
        this._connects.push(dojo.connect(this.grid.domNode, "onfocus", this, "doFocus"));
        this._connects.push(dojo.connect(this.grid.domNode, "onblur", this, "doBlur"));
        this._connects.push(dojo.connect(this.grid.domNode, "oncontextmenu", this, "doContextMenu"));
        this._connects.push(dojo.connect(this.grid.lastFocusNode, "onfocus", this, "doLastNodeFocus"));
        this._connects.push(dojo.connect(this.grid.lastFocusNode, "onblur", this, "doLastNodeBlur"));
        this._connects.push(dojo.connect(this.grid,"_onFetchComplete", this, "_delayedCellFocus"));
        this._connects.push(dojo.connect(this.grid,"postrender", this, "_delayedHeaderFocus"));
  • dojox.grid._FocusManager.destroy

    • type
      Function
    • source: [view]
        dojo.forEach(this._connects, dojo.disconnect);
        dojo.forEach(this._headerConnects, dojo.disconnect);
        delete this.grid;
        delete this.cell;
    • summary
  • dojox.grid._FocusManager._colHeadNode

    • summary
  • dojox.grid._FocusManager._colHeadFocusIdx

    • summary
  • dojox.grid._FocusManager._contextMenuBindNode

    • summary
  • dojox.grid._FocusManager.tabbingOut

    • summary
  • dojox.grid._FocusManager.focusClass

    • summary
  • dojox.grid._FocusManager.focusView

    • summary
  • dojox.grid._FocusManager.initFocusView

    • type
      Function
    • source: [view]
        this.focusView = this.grid.views.getFirstScrollingView() || this.focusView || this.grid.views.views[0];
        this._initColumnHeaders();
    • summary
  • dojox.grid._FocusManager.isFocusCell

    • type
      Function
    • parameters:
      • inCell: (typeof object)
        grid cell object
      • inRowIndex: (typeof int)
        grid row index
    • source: [view]
        return (this.cell == inCell) && (this.rowIndex == inRowIndex);
    • summary
      states if the given cell is focused
    • return_summary
      true of the given grid cell is focused
  • dojox.grid._FocusManager.isLastFocusCell

    • type
      Function
    • source: [view]
        if(this.cell){
         return (this.rowIndex == this.grid.rowCount-1) && (this.cell.index == this.grid.layout.cellCount-1);
        }
        return false;
    • summary
  • dojox.grid._FocusManager.isFirstFocusCell

    • type
      Function
    • source: [view]
        if(this.cell){
         return (this.rowIndex === 0) && (this.cell.index === 0);
        }
        return false;
    • summary
  • dojox.grid._FocusManager.isNoFocusCell

    • type
      Function
    • source: [view]
        return (this.rowIndex < 0) || !this.cell;
    • summary
  • dojox.grid._FocusManager.isNavHeader

    • type
      Function
    • source: [view]
        return (!!this._colHeadNode);
    • summary
      states whether currently navigating among column headers.
    • return_summary
      true if focus is on a column header; false otherwise.
  • dojox.grid._FocusManager.getHeaderIndex

    • type
      Function
    • source: [view]
        if(this._colHeadNode){
         return dojo.indexOf(this._findHeaderCells(), this._colHeadNode);
        }else{
         return -1;
        }
    • summary
      if one of the column headers currently has focus, return its index.
    • return_summary
      index of the focused column header, or -1 if none have focus.
  • dojox.grid._FocusManager._focusifyCellNode

    • type
      Function
    • parameters:
      • inBork: (typeof )
    • source: [view]
        var n = this.cell && this.cell.getNode(this.rowIndex);
        if(n){
         dojo.toggleClass(n, this.focusClass, inBork);
         if(inBork){
          var sl = this.scrollIntoView();
          try{
           if(!this.grid.edit.isEditing()){
            dojox.grid.util.fire(n, "focus");
            if(sl){ this.cell.view.scrollboxNode.scrollLeft = sl; }
           }
          }catch(e){}
         }
        }
    • summary
  • dojox.grid._FocusManager._delayedCellFocus

    • type
      Function
    • source: [view]
        if(this.isNavHeader()||!this.grid._focused){
          return;
        }
        var n = this.cell && this.cell.getNode(this.rowIndex);
        if(n){
         try{
          if(!this.grid.edit.isEditing()){
           dojo.toggleClass(n, this.focusClass, true);
           this.blurHeader();
           dojox.grid.util.fire(n, "focus");
          }
         }
         catch(e){}
        }
    • summary
  • dojox.grid._FocusManager._delayedHeaderFocus

    • type
      Function
    • source: [view]
        if(this.isNavHeader()){
         this.focusHeader();
         this.grid.domNode.focus();
        }
    • summary
  • dojox.grid._FocusManager._initColumnHeaders

    • type
      Function
    • source: [view]
        dojo.forEach(this._headerConnects, dojo.disconnect);
        this._headerConnects = [];
        var headers = this._findHeaderCells();
        for(var i = 0; i < headers.length; i++){
         this._headerConnects.push(dojo.connect(headers[i], "onfocus", this, "doColHeaderFocus"));
         this._headerConnects.push(dojo.connect(headers[i], "onblur", this, "doColHeaderBlur"));
        }
    • summary
  • dojox.grid._FocusManager._findHeaderCells

    • type
      Function
    • source: [view]
      dojo.provide("dojox.grid._FocusManager");


      dojo.require("dojox.grid.util");


      // focus management
      dojo.declare("dojox.grid._FocusManager", null, {
       // summary:
       // Controls grid cell focus. Owned by grid and used internally for focusing.
       // Note: grid cell actually receives keyboard input only when cell is being edited.
       constructor: function(inGrid){
        this.grid = inGrid;
        this.cell = null;
        this.rowIndex = -1;
        this._connects = [];
        this._headerConnects = [];
        this.headerMenu = this.grid.headerMenu;
        this._connects.push(dojo.connect(this.grid.domNode, "onfocus", this, "doFocus"));
        this._connects.push(dojo.connect(this.grid.domNode, "onblur", this, "doBlur"));
        this._connects.push(dojo.connect(this.grid.domNode, "oncontextmenu", this, "doContextMenu"));
        this._connects.push(dojo.connect(this.grid.lastFocusNode, "onfocus", this, "doLastNodeFocus"));
        this._connects.push(dojo.connect(this.grid.lastFocusNode, "onblur", this, "doLastNodeBlur"));
        this._connects.push(dojo.connect(this.grid,"_onFetchComplete", this, "_delayedCellFocus"));
        this._connects.push(dojo.connect(this.grid,"postrender", this, "_delayedHeaderFocus"));
       },
       destroy: function(){
        dojo.forEach(this._connects, dojo.disconnect);
        dojo.forEach(this._headerConnects, dojo.disconnect);
        delete this.grid;
        delete this.cell;
       },
       _colHeadNode: null,
       _colHeadFocusIdx: null,
       _contextMenuBindNode: null,
       tabbingOut: false,
       focusClass: "dojoxGridCellFocus",
       focusView: null,
       initFocusView: function(){
        this.focusView = this.grid.views.getFirstScrollingView() || this.focusView || this.grid.views.views[0];
        this._initColumnHeaders();
       },
       isFocusCell: function(inCell, inRowIndex){
        // summary:
        // states if the given cell is focused
        // inCell: object
        // grid cell object
        // inRowIndex: int
        // grid row index
        // returns:
        // true of the given grid cell is focused
        return (this.cell == inCell) && (this.rowIndex == inRowIndex);
       },
       isLastFocusCell: function(){
        if(this.cell){
         return (this.rowIndex == this.grid.rowCount-1) && (this.cell.index == this.grid.layout.cellCount-1);
        }
        return false;
       },
       isFirstFocusCell: function(){
        if(this.cell){
         return (this.rowIndex === 0) && (this.cell.index === 0);
        }
        return false;
       },
       isNoFocusCell: function(){
        return (this.rowIndex < 0) || !this.cell;
       },
       isNavHeader: function(){
        // summary:
        // states whether currently navigating among column headers.
        // returns:
        // true if focus is on a column header; false otherwise.
        return (!!this._colHeadNode);
       },
       getHeaderIndex: function(){
        // summary:
        // if one of the column headers currently has focus, return its index.
        // returns:
        // index of the focused column header, or -1 if none have focus.
        if(this._colHeadNode){
         return dojo.indexOf(this._findHeaderCells(), this._colHeadNode);
        }else{
         return -1;
        }
       },
       _focusifyCellNode: function(inBork){
        var n = this.cell && this.cell.getNode(this.rowIndex);
        if(n){
         dojo.toggleClass(n, this.focusClass, inBork);
         if(inBork){
          var sl = this.scrollIntoView();
          try{
           if(!this.grid.edit.isEditing()){
            dojox.grid.util.fire(n, "focus");
            if(sl){ this.cell.view.scrollboxNode.scrollLeft = sl; }
           }
          }catch(e){}
         }
        }
       },
       _delayedCellFocus: function(){
        if(this.isNavHeader()||!this.grid._focused){
          return;
        }
        var n = this.cell && this.cell.getNode(this.rowIndex);
        if(n){
         try{
          if(!this.grid.edit.isEditing()){
           dojo.toggleClass(n, this.focusClass, true);
           this.blurHeader();
           dojox.grid.util.fire(n, "focus");
          }
         }
         catch(e){}
        }
       },
       _delayedHeaderFocus: function(){
        if(this.isNavHeader()){
         this.focusHeader();
         this.grid.domNode.focus();
        }
       },
       _initColumnHeaders: function(){
        dojo.forEach(this._headerConnects, dojo.disconnect);
        this._headerConnects = [];
        var headers = this._findHeaderCells();
        for(var i = 0; i < headers.length; i++){
         this._headerConnects.push(dojo.connect(headers[i], "onfocus", this, "doColHeaderFocus"));
         this._headerConnects.push(dojo.connect(headers[i], "onblur", this, "doColHeaderBlur"));
        }
       },
       _findHeaderCells: function(){
        // This should be a one liner:
        // dojo.query("th[tabindex=-1]", this.grid.viewsHeaderNode);
        // But there is a bug in dojo.query() for IE -- see trac #7037.
        var allHeads = dojo.query("th", this.grid.viewsHeaderNode);
        var headers = [];
        for (var i = 0; i < allHeads.length; i++){
         var aHead = allHeads[i];
         var hasTabIdx = dojo.hasAttr(aHead, "tabIndex");
         var tabindex = dojo.attr(aHead, "tabIndex");
         if (hasTabIdx && tabindex < 0) {
          headers.push(aHead);
         }
        }
        return headers;
    • summary
  • dojox.grid._FocusManager._setActiveColHeader

    • type
      Function
    • parameters:
      • colHeaderNode: (typeof Node)
      • colFocusIdx: (typeof Integer)
      • prevColFocusIdx: (typeof Integer)
    • source: [view]
      dojo.provide("dojox.grid._FocusManager");


      dojo.require("dojox.grid.util");


      // focus management
      dojo.declare("dojox.grid._FocusManager", null, {
       // summary:
       // Controls grid cell focus. Owned by grid and used internally for focusing.
       // Note: grid cell actually receives keyboard input only when cell is being edited.
       constructor: function(inGrid){
        this.grid = inGrid;
        this.cell = null;
        this.rowIndex = -1;
        this._connects = [];
        this._headerConnects = [];
        this.headerMenu = this.grid.headerMenu;
        this._connects.push(dojo.connect(this.grid.domNode, "onfocus", this, "doFocus"));
        this._connects.push(dojo.connect(this.grid.domNode, "onblur", this, "doBlur"));
        this._connects.push(dojo.connect(this.grid.domNode, "oncontextmenu", this, "doContextMenu"));
        this._connects.push(dojo.connect(this.grid.lastFocusNode, "onfocus", this, "doLastNodeFocus"));
        this._connects.push(dojo.connect(this.grid.lastFocusNode, "onblur", this, "doLastNodeBlur"));
        this._connects.push(dojo.connect(this.grid,"_onFetchComplete", this, "_delayedCellFocus"));
        this._connects.push(dojo.connect(this.grid,"postrender", this, "_delayedHeaderFocus"));
       },
       destroy: function(){
        dojo.forEach(this._connects, dojo.disconnect);
        dojo.forEach(this._headerConnects, dojo.disconnect);
        delete this.grid;
        delete this.cell;
       },
       _colHeadNode: null,
       _colHeadFocusIdx: null,
       _contextMenuBindNode: null,
       tabbingOut: false,
       focusClass: "dojoxGridCellFocus",
       focusView: null,
       initFocusView: function(){
        this.focusView = this.grid.views.getFirstScrollingView() || this.focusView || this.grid.views.views[0];
        this._initColumnHeaders();
       },
       isFocusCell: function(inCell, inRowIndex){
        // summary:
        // states if the given cell is focused
        // inCell: object
        // grid cell object
        // inRowIndex: int
        // grid row index
        // returns:
        // true of the given grid cell is focused
        return (this.cell == inCell) && (this.rowIndex == inRowIndex);
       },
       isLastFocusCell: function(){
        if(this.cell){
         return (this.rowIndex == this.grid.rowCount-1) && (this.cell.index == this.grid.layout.cellCount-1);
        }
        return false;
       },
       isFirstFocusCell: function(){
        if(this.cell){
         return (this.rowIndex === 0) && (this.cell.index === 0);
        }
        return false;
       },
       isNoFocusCell: function(){
        return (this.rowIndex < 0) || !this.cell;
       },
       isNavHeader: function(){
        // summary:
        // states whether currently navigating among column headers.
        // returns:
        // true if focus is on a column header; false otherwise.
        return (!!this._colHeadNode);
       },
       getHeaderIndex: function(){
        // summary:
        // if one of the column headers currently has focus, return its index.
        // returns:
        // index of the focused column header, or -1 if none have focus.
        if(this._colHeadNode){
         return dojo.indexOf(this._findHeaderCells(), this._colHeadNode);
        }else{
         return -1;
        }
       },
       _focusifyCellNode: function(inBork){
        var n = this.cell && this.cell.getNode(this.rowIndex);
        if(n){
         dojo.toggleClass(n, this.focusClass, inBork);
         if(inBork){
          var sl = this.scrollIntoView();
          try{
           if(!this.grid.edit.isEditing()){
            dojox.grid.util.fire(n, "focus");
            if(sl){ this.cell.view.scrollboxNode.scrollLeft = sl; }
           }
          }catch(e){}
         }
        }
       },
       _delayedCellFocus: function(){
        if(this.isNavHeader()||!this.grid._focused){
          return;
        }
        var n = this.cell && this.cell.getNode(this.rowIndex);
        if(n){
         try{
          if(!this.grid.edit.isEditing()){
           dojo.toggleClass(n, this.focusClass, true);
           this.blurHeader();
           dojox.grid.util.fire(n, "focus");
          }
         }
         catch(e){}
        }
       },
       _delayedHeaderFocus: function(){
        if(this.isNavHeader()){
         this.focusHeader();
         this.grid.domNode.focus();
        }
       },
       _initColumnHeaders: function(){
        dojo.forEach(this._headerConnects, dojo.disconnect);
        this._headerConnects = [];
        var headers = this._findHeaderCells();
        for(var i = 0; i < headers.length; i++){
         this._headerConnects.push(dojo.connect(headers[i], "onfocus", this, "doColHeaderFocus"));
         this._headerConnects.push(dojo.connect(headers[i], "onblur", this, "doColHeaderBlur"));
        }
       },
       _findHeaderCells: function(){
        // This should be a one liner:
        // dojo.query("th[tabindex=-1]", this.grid.viewsHeaderNode);
        // But there is a bug in dojo.query() for IE -- see trac #7037.
        var allHeads = dojo.query("th", this.grid.viewsHeaderNode);
        var headers = [];
        for (var i = 0; i < allHeads.length; i++){
         var aHead = allHeads[i];
         var hasTabIdx = dojo.hasAttr(aHead, "tabIndex");
         var tabindex = dojo.attr(aHead, "tabIndex");
         if (hasTabIdx && tabindex < 0) {
          headers.push(aHead);
         }
        }
        return headers;
       },
       _setActiveColHeader: function(/*Node*/colHeaderNode, /*Integer*/colFocusIdx, /*Integer*/ prevColFocusIdx){
        //console.log("setActiveColHeader() - colHeaderNode:colFocusIdx:prevColFocusIdx = " + colHeaderNode + ":" + colFocusIdx + ":" + prevColFocusIdx);
        dojo.attr(this.grid.domNode, "aria-activedescendant",colHeaderNode.id);
        if (prevColFocusIdx != null && prevColFocusIdx >= 0 && prevColFocusIdx != colFocusIdx){
         dojo.toggleClass(this._findHeaderCells()[prevColFocusIdx],this.focusClass,false);
        }
        dojo.toggleClass(colHeaderNode,this.focusClass, true);
        this._colHeadNode = colHeaderNode;
        this._colHeadFocusIdx = colFocusIdx;
        this._scrollHeader(this._colHeadFocusIdx);
    • summary
  • dojox.grid._FocusManager.scrollIntoView

    • type
      Function
    • source: [view]
        var info = (this.cell ? this._scrollInfo(this.cell) : null);
        if(!info || !info.s){
         return null;
        }
        var rt = this.grid.scroller.findScrollTop(this.rowIndex);
        // place cell within horizontal view
        if(info.n && info.sr){
         if(info.n.offsetLeft + info.n.offsetWidth > info.sr.l + info.sr.w){
          info.s.scrollLeft = info.n.offsetLeft + info.n.offsetWidth - info.sr.w;
         }else if(info.n.offsetLeft < info.sr.l){
          info.s.scrollLeft = info.n.offsetLeft;
         }
        }
        // place cell within vertical view
        if(info.r && info.sr){
         if(rt + info.r.offsetHeight > info.sr.t + info.sr.h){
          this.grid.setScrollTop(rt + info.r.offsetHeight - info.sr.h);
         }else if(rt < info.sr.t){
          this.grid.setScrollTop(rt);
         }
        }


        return info.s.scrollLeft;
    • summary
  • dojox.grid._FocusManager._scrollInfo

    • type
      Function
    • parameters:
      • cell: (typeof )
      • domNode: (typeof )
    • source: [view]
        if(cell){
         var cl = cell,
          sbn = cl.view.scrollboxNode,
          sbnr = {
           w: sbn.clientWidth,
           l: sbn.scrollLeft,
           t: sbn.scrollTop,
           h: sbn.clientHeight
          },
          rn = cl.view.getRowNode(this.rowIndex);
         return {
          c: cl,
          s: sbn,
          sr: sbnr,
          n: (domNode ? domNode : cell.getNode(this.rowIndex)),
          r: rn
         };
        }
        return null;
    • summary
  • dojox.grid._FocusManager._scrollHeader

    • type
      Function
    • parameters:
      • currentIdx: (typeof )
    • source: [view]
        var info = null;
        if(this._colHeadNode){
         var cell = this.grid.getCell(currentIdx);
         info = this._scrollInfo(cell, cell.getNode(0));
        }
        if(info && info.s && info.sr && info.n){
         // scroll horizontally as needed.
         var scroll = info.sr.l + info.sr.w;
         if(info.n.offsetLeft + info.n.offsetWidth > scroll){
          info.s.scrollLeft = info.n.offsetLeft + info.n.offsetWidth - info.sr.w;
         }else if(info.n.offsetLeft < info.sr.l){
          info.s.scrollLeft = info.n.offsetLeft;
         }else if(dojo.isIE <= 7 && cell && cell.view.headerNode){
          // Trac 7158: scroll dojoxGridHeader for IE7 and lower
          cell.view.headerNode.scrollLeft = info.s.scrollLeft;
         }
        }
    • summary
  • dojox.grid._FocusManager._isHeaderHidden

    • type
      Function
    • source: [view]
        var curView = this.focusView;
        if (!curView){
         // find one so we can determine if headers are hidden
         // there is no focusView after adding items to empty grid (test_data_grid_empty.html)
         for (var i = 0, cView; (cView = this.grid.views.views[i]); i++) {
          if(cView.headerNode ){
           curView=cView;
           break;
          }
         }
        }
        return (curView && dojo.getComputedStyle(curView.headerNode).display == "none");
    • summary
      determine if the grid headers are hidden
      relies on documented technique of setting .dojoxGridHeader { display:none; }
    • return_summary
      Boolean
      true if headers are hidden
      false if headers are not hidden
  • dojox.grid._FocusManager.colSizeAdjust

    • type
      Function
    • parameters:
      • e: (typeof )
      • colIdx: (typeof )
      • delta: (typeof )
    • source: [view]
      dojo.provide("dojox.grid._FocusManager");


      dojo.require("dojox.grid.util");


      // focus management
      dojo.declare("dojox.grid._FocusManager", null, {
       // summary:
       // Controls grid cell focus. Owned by grid and used internally for focusing.
       // Note: grid cell actually receives keyboard input only when cell is being edited.
       constructor: function(inGrid){
        this.grid = inGrid;
        this.cell = null;
        this.rowIndex = -1;
        this._connects = [];
        this._headerConnects = [];
        this.headerMenu = this.grid.headerMenu;
        this._connects.push(dojo.connect(this.grid.domNode, "onfocus", this, "doFocus"));
        this._connects.push(dojo.connect(this.grid.domNode, "onblur", this, "doBlur"));
        this._connects.push(dojo.connect(this.grid.domNode, "oncontextmenu", this, "doContextMenu"));
        this._connects.push(dojo.connect(this.grid.lastFocusNode, "onfocus", this, "doLastNodeFocus"));
        this._connects.push(dojo.connect(this.grid.lastFocusNode, "onblur", this, "doLastNodeBlur"));
        this._connects.push(dojo.connect(this.grid,"_onFetchComplete", this, "_delayedCellFocus"));
        this._connects.push(dojo.connect(this.grid,"postrender", this, "_delayedHeaderFocus"));
       },
       destroy: function(){
        dojo.forEach(this._connects, dojo.disconnect);
        dojo.forEach(this._headerConnects, dojo.disconnect);
        delete this.grid;
        delete this.cell;
       },
       _colHeadNode: null,
       _colHeadFocusIdx: null,
       _contextMenuBindNode: null,
       tabbingOut: false,
       focusClass: "dojoxGridCellFocus",
       focusView: null,
       initFocusView: function(){
        this.focusView = this.grid.views.getFirstScrollingView() || this.focusView || this.grid.views.views[0];
        this._initColumnHeaders();
       },
       isFocusCell: function(inCell, inRowIndex){
        // summary:
        // states if the given cell is focused
        // inCell: object
        // grid cell object
        // inRowIndex: int
        // grid row index
        // returns:
        // true of the given grid cell is focused
        return (this.cell == inCell) && (this.rowIndex == inRowIndex);
       },
       isLastFocusCell: function(){
        if(this.cell){
         return (this.rowIndex == this.grid.rowCount-1) && (this.cell.index == this.grid.layout.cellCount-1);
        }
        return false;
       },
       isFirstFocusCell: function(){
        if(this.cell){
         return (this.rowIndex === 0) && (this.cell.index === 0);
        }
        return false;
       },
       isNoFocusCell: function(){
        return (this.rowIndex < 0) || !this.cell;
       },
       isNavHeader: function(){
        // summary:
        // states whether currently navigating among column headers.
        // returns:
        // true if focus is on a column header; false otherwise.
        return (!!this._colHeadNode);
       },
       getHeaderIndex: function(){
        // summary:
        // if one of the column headers currently has focus, return its index.
        // returns:
        // index of the focused column header, or -1 if none have focus.
        if(this._colHeadNode){
         return dojo.indexOf(this._findHeaderCells(), this._colHeadNode);
        }else{
         return -1;
        }
       },
       _focusifyCellNode: function(inBork){
        var n = this.cell && this.cell.getNode(this.rowIndex);
        if(n){
         dojo.toggleClass(n, this.focusClass, inBork);
         if(inBork){
          var sl = this.scrollIntoView();
          try{
           if(!this.grid.edit.isEditing()){
            dojox.grid.util.fire(n, "focus");
            if(sl){ this.cell.view.scrollboxNode.scrollLeft = sl; }
           }
          }catch(e){}
         }
        }
       },
       _delayedCellFocus: function(){
        if(this.isNavHeader()||!this.grid._focused){
          return;
        }
        var n = this.cell && this.cell.getNode(this.rowIndex);
        if(n){
         try{
          if(!this.grid.edit.isEditing()){
           dojo.toggleClass(n, this.focusClass, true);
           this.blurHeader();
           dojox.grid.util.fire(n, "focus");
          }
         }
         catch(e){}
        }
       },
       _delayedHeaderFocus: function(){
        if(this.isNavHeader()){
         this.focusHeader();
         this.grid.domNode.focus();
        }
       },
       _initColumnHeaders: function(){
        dojo.forEach(this._headerConnects, dojo.disconnect);
        this._headerConnects = [];
        var headers = this._findHeaderCells();
        for(var i = 0; i < headers.length; i++){
         this._headerConnects.push(dojo.connect(headers[i], "onfocus", this, "doColHeaderFocus"));
         this._headerConnects.push(dojo.connect(headers[i], "onblur", this, "doColHeaderBlur"));
        }
       },
       _findHeaderCells: function(){
        // This should be a one liner:
        // dojo.query("th[tabindex=-1]", this.grid.viewsHeaderNode);
        // But there is a bug in dojo.query() for IE -- see trac #7037.
        var allHeads = dojo.query("th", this.grid.viewsHeaderNode);
        var headers = [];
        for (var i = 0; i < allHeads.length; i++){
         var aHead = allHeads[i];
         var hasTabIdx = dojo.hasAttr(aHead, "tabIndex");
         var tabindex = dojo.attr(aHead, "tabIndex");
         if (hasTabIdx && tabindex < 0) {
          headers.push(aHead);
         }
        }
        return headers;
       },
       _setActiveColHeader: function(/*Node*/colHeaderNode, /*Integer*/colFocusIdx, /*Integer*/ prevColFocusIdx){
        //console.log("setActiveColHeader() - colHeaderNode:colFocusIdx:prevColFocusIdx = " + colHeaderNode + ":" + colFocusIdx + ":" + prevColFocusIdx);
        dojo.attr(this.grid.domNode, "aria-activedescendant",colHeaderNode.id);
        if (prevColFocusIdx != null && prevColFocusIdx >= 0 && prevColFocusIdx != colFocusIdx){
         dojo.toggleClass(this._findHeaderCells()[prevColFocusIdx],this.focusClass,false);
        }
        dojo.toggleClass(colHeaderNode,this.focusClass, true);
        this._colHeadNode = colHeaderNode;
        this._colHeadFocusIdx = colFocusIdx;
        this._scrollHeader(this._colHeadFocusIdx);
       },
       scrollIntoView: function(){
        var info = (this.cell ? this._scrollInfo(this.cell) : null);
        if(!info || !info.s){
         return null;
        }
        var rt = this.grid.scroller.findScrollTop(this.rowIndex);
        // place cell within horizontal view
        if(info.n && info.sr){
         if(info.n.offsetLeft + info.n.offsetWidth > info.sr.l + info.sr.w){
          info.s.scrollLeft = info.n.offsetLeft + info.n.offsetWidth - info.sr.w;
         }else if(info.n.offsetLeft < info.sr.l){
          info.s.scrollLeft = info.n.offsetLeft;
         }
        }
        // place cell within vertical view
        if(info.r && info.sr){
         if(rt + info.r.offsetHeight > info.sr.t + info.sr.h){
          this.grid.setScrollTop(rt + info.r.offsetHeight - info.sr.h);
         }else if(rt < info.sr.t){
          this.grid.setScrollTop(rt);
         }
        }


        return info.s.scrollLeft;
       },
       _scrollInfo: function(cell, domNode){
        if(cell){
         var cl = cell,
          sbn = cl.view.scrollboxNode,
          sbnr = {
           w: sbn.clientWidth,
           l: sbn.scrollLeft,
           t: sbn.scrollTop,
           h: sbn.clientHeight
          },
          rn = cl.view.getRowNode(this.rowIndex);
         return {
          c: cl,
          s: sbn,
          sr: sbnr,
          n: (domNode ? domNode : cell.getNode(this.rowIndex)),
          r: rn
         };
        }
        return null;
       },
       _scrollHeader: function(currentIdx){
        var info = null;
        if(this._colHeadNode){
         var cell = this.grid.getCell(currentIdx);
         info = this._scrollInfo(cell, cell.getNode(0));
        }
        if(info && info.s && info.sr && info.n){
         // scroll horizontally as needed.
         var scroll = info.sr.l + info.sr.w;
         if(info.n.offsetLeft + info.n.offsetWidth > scroll){
          info.s.scrollLeft = info.n.offsetLeft + info.n.offsetWidth - info.sr.w;
         }else if(info.n.offsetLeft < info.sr.l){
          info.s.scrollLeft = info.n.offsetLeft;
         }else if(dojo.isIE <= 7 && cell && cell.view.headerNode){
          // Trac 7158: scroll dojoxGridHeader for IE7 and lower
          cell.view.headerNode.scrollLeft = info.s.scrollLeft;
         }
        }
       },
       _isHeaderHidden: function(){
        // summary:
        //  determine if the grid headers are hidden
        //  relies on documented technique of setting .dojoxGridHeader { display:none; }
        // returns: Boolean
        //  true if headers are hidden
        //  false if headers are not hidden

        
        var curView = this.focusView;
        if (!curView){
         // find one so we can determine if headers are hidden
         // there is no focusView after adding items to empty grid (test_data_grid_empty.html)
         for (var i = 0, cView; (cView = this.grid.views.views[i]); i++) {
          if(cView.headerNode ){
           curView=cView;
           break;
          }
         }
        }
        return (curView && dojo.getComputedStyle(curView.headerNode).display == "none");
       },
       colSizeAdjust: function (e, colIdx, delta){ // adjust the column specified by colIdx by the specified delta px
        var headers = this._findHeaderCells();
        var view = this.focusView;
        if (!view) {
         for (var i = 0, cView; (cView = this.grid.views.views[i]); i++) {
          // find first view with a tableMap in order to work with empty grid
          if(cView.header.tableMap.map ){
           view=cView;
           break;
          }
         }
        }
        var curHeader = headers[colIdx];
        if (!view || (colIdx == headers.length-1 && colIdx === 0)){
         return; // can't adjust single col. grid
        }
        view.content.baseDecorateEvent(e);
        // need to adjust event with header cell info since focus is no longer on header cell
        e.cellNode = curHeader; //this.findCellTarget(e.target, e.rowNode);
        e.cellIndex = view.content.getCellNodeIndex(e.cellNode);
        e.cell = (e.cellIndex >= 0 ? this.grid.getCell(e.cellIndex) : null);
        if (view.header.canResize(e)){
         var deltaObj = {
          l: delta
         };
         var drag = view.header.colResizeSetup(e,false);
         view.header.doResizeColumn(drag, null, deltaObj);
         view.update();
        }
    • returns
      can't adjust single col. grid
    • summary
  • dojox.grid._FocusManager.styleRow

    • type
      Function
    • parameters:
      • inRow: (typeof )
    • source: [view]
        return;
    • summary
  • dojox.grid._FocusManager.setFocusIndex

    • type
      Function
    • parameters:
      • inRowIndex: (typeof int)
        grid row index
      • inCellIndex: (typeof int)
        grid cell index
    • source: [view]
        this.setFocusCell(this.grid.getCell(inCellIndex), inRowIndex);
    • summary
      focuses the given grid cell
  • dojox.grid._FocusManager.setFocusCell

    • type
      Function
    • parameters:
      • inCell: (typeof object)
        grid cell object
      • inRowIndex: (typeof int)
        grid row index
    • source: [view]
        if(inCell && !this.isFocusCell(inCell, inRowIndex)){
         this.tabbingOut = false;
         if (this._colHeadNode){
          this.blurHeader();
         }
         this._colHeadNode = this._colHeadFocusIdx = null;
         this.focusGridView();
         this._focusifyCellNode(false);
         this.cell = inCell;
         this.rowIndex = inRowIndex;
         this._focusifyCellNode(true);
        }
        // even if this cell isFocusCell, the document focus may need to be rejiggered
        // call opera on delay to prevent keypress from altering focus
        if(dojo.isOpera){
         setTimeout(dojo.hitch(this.grid, 'onCellFocus', this.cell, this.rowIndex), 1);
        }else{
         this.grid.onCellFocus(this.cell, this.rowIndex);
        }
    • summary
      focuses the given grid cell
  • dojox.grid._FocusManager.next

    • type
      Function
    • source: [view]
        if(this.cell){
         var row=this.rowIndex, col=this.cell.index+1, cc=this.grid.layout.cellCount-1, rc=this.grid.rowCount-1;
         if(col > cc){
          col = 0;
          row++;
         }
         if(row > rc){
          col = cc;
          row = rc;
         }
         if(this.grid.edit.isEditing()){ //when editing, only navigate to editable cells
          var nextCell = this.grid.getCell(col);
          if (!this.isLastFocusCell() && (!nextCell.editable ||
           this.grid.canEdit && !this.grid.canEdit(nextCell, row))){
           this.cell=nextCell;
           this.rowIndex=row;
           this.next();
           return;
          }
         }
         this.setFocusIndex(row, col);
        }
    • summary
      focus next grid cell
  • dojox.grid._FocusManager.previous

    • type
      Function
    • source: [view]
        if(this.cell){
         var row=(this.rowIndex || 0), col=(this.cell.index || 0) - 1;
         if(col < 0){
          col = this.grid.layout.cellCount-1;
          row--;
         }
         if(row < 0){
          row = 0;
          col = 0;
         }
         if(this.grid.edit.isEditing()){ //when editing, only navigate to editable cells
          var prevCell = this.grid.getCell(col);
          if (!this.isFirstFocusCell() && !prevCell.editable){
           this.cell=prevCell;
           this.rowIndex=row;
           this.previous();
           return;
          }
         }
         this.setFocusIndex(row, col);
        }
    • summary
      focus previous grid cell
  • dojox.grid._FocusManager.move

    • type
      Function
    • parameters:
      • inRowDelta: (typeof int)
        vertical distance from current focus
      • inColDelta: (typeof int)
        horizontal distance from current focus
    • source: [view]
        var colDir = inColDelta < 0 ? -1 : 1;
        // Handle column headers.
        if(this.isNavHeader()){
         var headers = this._findHeaderCells();
         var savedIdx = currentIdx = dojo.indexOf(headers, this._colHeadNode);
         currentIdx += inColDelta;
         while(currentIdx >=0 && currentIdx < headers.length && headers[currentIdx].style.display == "none"){
          // skip over hidden column headers
          currentIdx += colDir;
         }
         if((currentIdx >= 0) && (currentIdx < headers.length)){
          this._setActiveColHeader(headers[currentIdx],currentIdx, savedIdx);
         }
        }else{
         if(this.cell){
          // Handle grid proper.
          var sc = this.grid.scroller,
           r = this.rowIndex,
           rc = this.grid.rowCount-1,
           row = Math.min(rc, Math.max(0, r+inRowDelta));
          if(inRowDelta){
           if(inRowDelta>0){
            if(row > sc.getLastPageRow(sc.page)){
             //need to load additional data, let scroller do that
             this.grid.setScrollTop(this.grid.scrollTop+sc.findScrollTop(row)-sc.findScrollTop(r));
            }
           }else if(inRowDelta<0){
            if(row <= sc.getPageRow(sc.page)){
             //need to load additional data, let scroller do that
             this.grid.setScrollTop(this.grid.scrollTop-sc.findScrollTop(r)-sc.findScrollTop(row));
            }
           }
          }
          var cc = this.grid.layout.cellCount-1,
          i = this.cell.index,
          col = Math.min(cc, Math.max(0, i+inColDelta));
          var cell = this.grid.getCell(col);
          while(col>=0 && col < cc && cell && cell.hidden === true){
           // skip hidden cells
           col += colDir;
           cell = this.grid.getCell(col);
          }
          if (!cell || cell.hidden === true){
           // don't change col if would move to hidden
           col = i;
          }
          //skip hidden row|cell
          var n = cell.getNode(row);
          if(!n && inRowDelta){
           if((row + inRowDelta) >= 0 && (row + inRowDelta) <= rc){
            this.move(inRowDelta > 0 ? ++inRowDelta : --inRowDelta, inColDelta);
           }
           return;
          }else if((!n || dojo.style(n, "display") === "none") && inColDelta){
           if((col + inRowDelta) >= 0 && (col + inRowDelta) <= cc){
            this.move(inRowDelta, inColDelta > 0 ? ++inColDelta : --inColDelta);
           }
           return;
          }
          this.setFocusIndex(row, col);
          if(inRowDelta){
           this.grid.updateRow(r);
          }
         }
        }
    • summary
      focus grid cell or  simulate focus to column header based on position relative to current focus
  • dojox.grid._FocusManager.previousKey

    • type
      Function
    • parameters:
      • e: (typeof )
    • source: [view]
        if(this.grid.edit.isEditing()){
         dojo.stopEvent(e);
         this.previous();
        }else if(!this.isNavHeader() && !this._isHeaderHidden()) {
         this.grid.domNode.focus(); // will call doFocus and set focus into header.
         dojo.stopEvent(e);
        }else{
         this.tabOut(this.grid.domNode);
         if (this._colHeadFocusIdx != null) { // clear grid header focus
          dojo.toggleClass(this._findHeaderCells()[this._colHeadFocusIdx], this.focusClass, false);
          this._colHeadFocusIdx = null;
         }
         this._focusifyCellNode(false);
        }
    • summary
  • dojox.grid._FocusManager.nextKey

    • type
      Function
    • parameters:
      • e: (typeof )
    • source: [view]
        var isEmpty = (this.grid.rowCount === 0);
        if(e.target === this.grid.domNode && this._colHeadFocusIdx == null){
         this.focusHeader();
         dojo.stopEvent(e);
        }else if(this.isNavHeader()){
         // if tabbing from col header, then go to grid proper.
         this.blurHeader();
         if(!this.findAndFocusGridCell()){
          this.tabOut(this.grid.lastFocusNode);
         }
         this._colHeadNode = this._colHeadFocusIdx= null;
        }else if(this.grid.edit.isEditing()){
         dojo.stopEvent(e);
         this.next();
        }else{
         this.tabOut(this.grid.lastFocusNode);
        }
    • summary
  • dojox.grid._FocusManager.tabOut

    • type
      Function
    • parameters:
      • inFocusNode: (typeof )
    • source: [view]
        this.tabbingOut = true;
        inFocusNode.focus();
    • summary
  • dojox.grid._FocusManager.focusGridView

    • type
      Function
    • source: [view]
        dojox.grid.util.fire(this.focusView, "focus");
    • summary
  • dojox.grid._FocusManager.focusGrid

    • type
      Function
    • parameters:
      • inSkipFocusCell: (typeof )
    • source: [view]
        this.focusGridView();
        this._focusifyCellNode(true);
    • summary
  • dojox.grid._FocusManager.findAndFocusGridCell

    • type
      Function
    • source: [view]
        var didFocus = true;
        var isEmpty = (this.grid.rowCount === 0); // If grid is empty this.grid.rowCount == 0
        if (this.isNoFocusCell() && !isEmpty){
         var cellIdx = 0;
         var cell = this.grid.getCell(cellIdx);
         if (cell.hidden) {
          // if first cell isn't visible, use _colHeadFocusIdx
          // could also use a while loop to find first visible cell - not sure that is worth it
          cellIdx = this.isNavHeader() ? this._colHeadFocusIdx : 0;
         }
         this.setFocusIndex(0, cellIdx);
        }
        else if (this.cell && !isEmpty){
         if (this.focusView && !this.focusView.rowNodes[this.rowIndex]){
          // if rowNode for current index is undefined (likely as a result of a sort and because of #7304)
          // scroll to that row
          this.grid.scrollToRow(this.rowIndex);
         }
         this.focusGrid();
        }else {
         didFocus = false;
        }
        this._colHeadNode = this._colHeadFocusIdx= null;
        return didFocus;
    • summary
      find the first focusable grid cell
    • return_summary
      Boolean
      true if focus was set to a cell
      false if no cell found to set focus onto
  • dojox.grid._FocusManager.focusHeader

    • type
      Function
    • source: [view]
        var headerNodes = this._findHeaderCells();
        var saveColHeadFocusIdx = this._colHeadFocusIdx;
        if (this._isHeaderHidden()){
         // grid header is hidden, focus a cell
         this.findAndFocusGridCell();
        }
        else if (!this._colHeadFocusIdx) {
         if (this.isNoFocusCell()) {
          this._colHeadFocusIdx = 0;
         }
         else {
          this._colHeadFocusIdx = this.cell.index;
         }
        }
        this._colHeadNode = headerNodes[this._colHeadFocusIdx];
        while(this._colHeadNode && this._colHeadFocusIdx >=0 && this._colHeadFocusIdx < headerNodes.length &&
          this._colHeadNode.style.display == "none"){
         // skip over hidden column headers
         this._colHeadFocusIdx++;
         this._colHeadNode = headerNodes[this._colHeadFocusIdx];
        }
        if(this._colHeadNode && this._colHeadNode.style.display != "none"){
         // Column header cells know longer receive actual focus. So, for keyboard invocation of
         // contextMenu to work, the contextMenu must be bound to the grid.domNode rather than the viewsHeaderNode.
         // unbind the contextmenu from the viewsHeaderNode and to the grid when header cells are active. Reset
         // the binding back to the viewsHeaderNode when header cells are no longer acive (in blurHeader) #10483
         if (this.headerMenu && this._contextMenuBindNode != this.grid.domNode){
          this.headerMenu.unBindDomNode(this.grid.viewsHeaderNode);
          this.headerMenu.bindDomNode(this.grid.domNode);
          this._contextMenuBindNode = this.grid.domNode;
         }
         this._setActiveColHeader(this._colHeadNode, this._colHeadFocusIdx, saveColHeadFocusIdx);
         this._scrollHeader(this._colHeadFocusIdx);
         this._focusifyCellNode(false);
        }else {
         // all col head nodes are hidden - focus the grid
         this.findAndFocusGridCell();
        }
    • summary
  • dojox.grid._FocusManager.blurHeader

    • type
      Function
    • source: [view]
        dojo.removeClass(this._colHeadNode, this.focusClass);
        dojo.removeAttr(this.grid.domNode,"aria-activedescendant");
        // reset contextMenu onto viewsHeaderNode so right mouse on header will invoke (see focusHeader)
        if (this.headerMenu && this._contextMenuBindNode == this.grid.domNode) {
         var viewsHeader = this.grid.viewsHeaderNode;
         this.headerMenu.unBindDomNode(this.grid.domNode);
         this.headerMenu.bindDomNode(viewsHeader);
         this._contextMenuBindNode = viewsHeader;
        }
    • summary
  • dojox.grid._FocusManager.doFocus

    • type
      Function
    • parameters:
      • e: (typeof )
    • source: [view]
      dojo.provide("dojox.grid._FocusManager");


      dojo.require("dojox.grid.util");


      // focus management
      dojo.declare("dojox.grid._FocusManager", null, {
       // summary:
       // Controls grid cell focus. Owned by grid and used internally for focusing.
       // Note: grid cell actually receives keyboard input only when cell is being edited.
       constructor: function(inGrid){
        this.grid = inGrid;
        this.cell = null;
        this.rowIndex = -1;
        this._connects = [];
        this._headerConnects = [];
        this.headerMenu = this.grid.headerMenu;
        this._connects.push(dojo.connect(this.grid.domNode, "onfocus", this, "doFocus"));
        this._connects.push(dojo.connect(this.grid.domNode, "onblur", this, "doBlur"));
        this._connects.push(dojo.connect(this.grid.domNode, "oncontextmenu", this, "doContextMenu"));
        this._connects.push(dojo.connect(this.grid.lastFocusNode, "onfocus", this, "doLastNodeFocus"));
        this._connects.push(dojo.connect(this.grid.lastFocusNode, "onblur", this, "doLastNodeBlur"));
        this._connects.push(dojo.connect(this.grid,"_onFetchComplete", this, "_delayedCellFocus"));
        this._connects.push(dojo.connect(this.grid,"postrender", this, "_delayedHeaderFocus"));
       },
       destroy: function(){
        dojo.forEach(this._connects, dojo.disconnect);
        dojo.forEach(this._headerConnects, dojo.disconnect);
        delete this.grid;
        delete this.cell;
       },
       _colHeadNode: null,
       _colHeadFocusIdx: null,
       _contextMenuBindNode: null,
       tabbingOut: false,
       focusClass: "dojoxGridCellFocus",
       focusView: null,
       initFocusView: function(){
        this.focusView = this.grid.views.getFirstScrollingView() || this.focusView || this.grid.views.views[0];
        this._initColumnHeaders();
       },
       isFocusCell: function(inCell, inRowIndex){
        // summary:
        // states if the given cell is focused
        // inCell: object
        // grid cell object
        // inRowIndex: int
        // grid row index
        // returns:
        // true of the given grid cell is focused
        return (this.cell == inCell) && (this.rowIndex == inRowIndex);
       },
       isLastFocusCell: function(){
        if(this.cell){
         return (this.rowIndex == this.grid.rowCount-1) && (this.cell.index == this.grid.layout.cellCount-1);
        }
        return false;
       },
       isFirstFocusCell: function(){
        if(this.cell){
         return (this.rowIndex === 0) && (this.cell.index === 0);
        }
        return false;
       },
       isNoFocusCell: function(){
        return (this.rowIndex < 0) || !this.cell;
       },
       isNavHeader: function(){
        // summary:
        // states whether currently navigating among column headers.
        // returns:
        // true if focus is on a column header; false otherwise.
        return (!!this._colHeadNode);
       },
       getHeaderIndex: function(){
        // summary:
        // if one of the column headers currently has focus, return its index.
        // returns:
        // index of the focused column header, or -1 if none have focus.
        if(this._colHeadNode){
         return dojo.indexOf(this._findHeaderCells(), this._colHeadNode);
        }else{
         return -1;
        }
       },
       _focusifyCellNode: function(inBork){
        var n = this.cell && this.cell.getNode(this.rowIndex);
        if(n){
         dojo.toggleClass(n, this.focusClass, inBork);
         if(inBork){
          var sl = this.scrollIntoView();
          try{
           if(!this.grid.edit.isEditing()){
            dojox.grid.util.fire(n, "focus");
            if(sl){ this.cell.view.scrollboxNode.scrollLeft = sl; }
           }
          }catch(e){}
         }
        }
       },
       _delayedCellFocus: function(){
        if(this.isNavHeader()||!this.grid._focused){
          return;
        }
        var n = this.cell && this.cell.getNode(this.rowIndex);
        if(n){
         try{
          if(!this.grid.edit.isEditing()){
           dojo.toggleClass(n, this.focusClass, true);
           this.blurHeader();
           dojox.grid.util.fire(n, "focus");
          }
         }
         catch(e){}
        }
       },
       _delayedHeaderFocus: function(){
        if(this.isNavHeader()){
         this.focusHeader();
         this.grid.domNode.focus();
        }
       },
       _initColumnHeaders: function(){
        dojo.forEach(this._headerConnects, dojo.disconnect);
        this._headerConnects = [];
        var headers = this._findHeaderCells();
        for(var i = 0; i < headers.length; i++){
         this._headerConnects.push(dojo.connect(headers[i], "onfocus", this, "doColHeaderFocus"));
         this._headerConnects.push(dojo.connect(headers[i], "onblur", this, "doColHeaderBlur"));
        }
       },
       _findHeaderCells: function(){
        // This should be a one liner:
        // dojo.query("th[tabindex=-1]", this.grid.viewsHeaderNode);
        // But there is a bug in dojo.query() for IE -- see trac #7037.
        var allHeads = dojo.query("th", this.grid.viewsHeaderNode);
        var headers = [];
        for (var i = 0; i < allHeads.length; i++){
         var aHead = allHeads[i];
         var hasTabIdx = dojo.hasAttr(aHead, "tabIndex");
         var tabindex = dojo.attr(aHead, "tabIndex");
         if (hasTabIdx && tabindex < 0) {
          headers.push(aHead);
         }
        }
        return headers;
       },
       _setActiveColHeader: function(/*Node*/colHeaderNode, /*Integer*/colFocusIdx, /*Integer*/ prevColFocusIdx){
        //console.log("setActiveColHeader() - colHeaderNode:colFocusIdx:prevColFocusIdx = " + colHeaderNode + ":" + colFocusIdx + ":" + prevColFocusIdx);
        dojo.attr(this.grid.domNode, "aria-activedescendant",colHeaderNode.id);
        if (prevColFocusIdx != null && prevColFocusIdx >= 0 && prevColFocusIdx != colFocusIdx){
         dojo.toggleClass(this._findHeaderCells()[prevColFocusIdx],this.focusClass,false);
        }
        dojo.toggleClass(colHeaderNode,this.focusClass, true);
        this._colHeadNode = colHeaderNode;
        this._colHeadFocusIdx = colFocusIdx;
        this._scrollHeader(this._colHeadFocusIdx);
       },
       scrollIntoView: function(){
        var info = (this.cell ? this._scrollInfo(this.cell) : null);
        if(!info || !info.s){
         return null;
        }
        var rt = this.grid.scroller.findScrollTop(this.rowIndex);
        // place cell within horizontal view
        if(info.n && info.sr){
         if(info.n.offsetLeft + info.n.offsetWidth > info.sr.l + info.sr.w){
          info.s.scrollLeft = info.n.offsetLeft + info.n.offsetWidth - info.sr.w;
         }else if(info.n.offsetLeft < info.sr.l){
          info.s.scrollLeft = info.n.offsetLeft;
         }
        }
        // place cell within vertical view
        if(info.r && info.sr){
         if(rt + info.r.offsetHeight > info.sr.t + info.sr.h){
          this.grid.setScrollTop(rt + info.r.offsetHeight - info.sr.h);
         }else if(rt < info.sr.t){
          this.grid.setScrollTop(rt);
         }
        }


        return info.s.scrollLeft;
       },
       _scrollInfo: function(cell, domNode){
        if(cell){
         var cl = cell,
          sbn = cl.view.scrollboxNode,
          sbnr = {
           w: sbn.clientWidth,
           l: sbn.scrollLeft,
           t: sbn.scrollTop,
           h: sbn.clientHeight
          },
          rn = cl.view.getRowNode(this.rowIndex);
         return {
          c: cl,
          s: sbn,
          sr: sbnr,
          n: (domNode ? domNode : cell.getNode(this.rowIndex)),
          r: rn
         };
        }
        return null;
       },
       _scrollHeader: function(currentIdx){
        var info = null;
        if(this._colHeadNode){
         var cell = this.grid.getCell(currentIdx);
         info = this._scrollInfo(cell, cell.getNode(0));
        }
        if(info && info.s && info.sr && info.n){
         // scroll horizontally as needed.
         var scroll = info.sr.l + info.sr.w;
         if(info.n.offsetLeft + info.n.offsetWidth > scroll){
          info.s.scrollLeft = info.n.offsetLeft + info.n.offsetWidth - info.sr.w;
         }else if(info.n.offsetLeft < info.sr.l){
          info.s.scrollLeft = info.n.offsetLeft;
         }else if(dojo.isIE <= 7 && cell && cell.view.headerNode){
          // Trac 7158: scroll dojoxGridHeader for IE7 and lower
          cell.view.headerNode.scrollLeft = info.s.scrollLeft;
         }
        }
       },
       _isHeaderHidden: function(){
        // summary:
        //  determine if the grid headers are hidden
        //  relies on documented technique of setting .dojoxGridHeader { display:none; }
        // returns: Boolean
        //  true if headers are hidden
        //  false if headers are not hidden

        
        var curView = this.focusView;
        if (!curView){
         // find one so we can determine if headers are hidden
         // there is no focusView after adding items to empty grid (test_data_grid_empty.html)
         for (var i = 0, cView; (cView = this.grid.views.views[i]); i++) {
          if(cView.headerNode ){
           curView=cView;
           break;
          }
         }
        }
        return (curView && dojo.getComputedStyle(curView.headerNode).display == "none");
       },
       colSizeAdjust: function (e, colIdx, delta){ // adjust the column specified by colIdx by the specified delta px
        var headers = this._findHeaderCells();
        var view = this.focusView;
        if (!view) {
         for (var i = 0, cView; (cView = this.grid.views.views[i]); i++) {
          // find first view with a tableMap in order to work with empty grid
          if(cView.header.tableMap.map ){
           view=cView;
           break;
          }
         }
        }
        var curHeader = headers[colIdx];
        if (!view || (colIdx == headers.length-1 && colIdx === 0)){
         return; // can't adjust single col. grid
        }
        view.content.baseDecorateEvent(e);
        // need to adjust event with header cell info since focus is no longer on header cell
        e.cellNode = curHeader; //this.findCellTarget(e.target, e.rowNode);
        e.cellIndex = view.content.getCellNodeIndex(e.cellNode);
        e.cell = (e.cellIndex >= 0 ? this.grid.getCell(e.cellIndex) : null);
        if (view.header.canResize(e)){
         var deltaObj = {
          l: delta
         };
         var drag = view.header.colResizeSetup(e,false);
         view.header.doResizeColumn(drag, null, deltaObj);
         view.update();
        }
       },
       styleRow: function(inRow){
        return;
       },
       setFocusIndex: function(inRowIndex, inCellIndex){
        // summary:
        // focuses the given grid cell
        // inRowIndex: int
        // grid row index
        // inCellIndex: int
        // grid cell index
        this.setFocusCell(this.grid.getCell(inCellIndex), inRowIndex);
       },
       setFocusCell: function(inCell, inRowIndex){
        // summary:
        // focuses the given grid cell
        // inCell: object
        // grid cell object
        // inRowIndex: int
        // grid row index
        if(inCell && !this.isFocusCell(inCell, inRowIndex)){
         this.tabbingOut = false;
         if (this._colHeadNode){
          this.blurHeader();
         }
         this._colHeadNode = this._colHeadFocusIdx = null;
         this.focusGridView();
         this._focusifyCellNode(false);
         this.cell = inCell;
         this.rowIndex = inRowIndex;
         this._focusifyCellNode(true);
        }
        // even if this cell isFocusCell, the document focus may need to be rejiggered
        // call opera on delay to prevent keypress from altering focus
        if(dojo.isOpera){
         setTimeout(dojo.hitch(this.grid, 'onCellFocus', this.cell, this.rowIndex), 1);
        }else{
         this.grid.onCellFocus(this.cell, this.rowIndex);
        }
       },
       next: function(){
        // summary:
        // focus next grid cell
        if(this.cell){
         var row=this.rowIndex, col=this.cell.index+1, cc=this.grid.layout.cellCount-1, rc=this.grid.rowCount-1;
         if(col > cc){
          col = 0;
          row++;
         }
         if(row > rc){
          col = cc;
          row = rc;
         }
         if(this.grid.edit.isEditing()){ //when editing, only navigate to editable cells
          var nextCell = this.grid.getCell(col);
          if (!this.isLastFocusCell() && (!nextCell.editable ||
           this.grid.canEdit && !this.grid.canEdit(nextCell, row))){
           this.cell=nextCell;
           this.rowIndex=row;
           this.next();
           return;
          }
         }
         this.setFocusIndex(row, col);
        }
       },
       previous: function(){
        // summary:
        // focus previous grid cell
        if(this.cell){
         var row=(this.rowIndex || 0), col=(this.cell.index || 0) - 1;
         if(col < 0){
          col = this.grid.layout.cellCount-1;
          row--;
         }
         if(row < 0){
          row = 0;
          col = 0;
         }
         if(this.grid.edit.isEditing()){ //when editing, only navigate to editable cells
          var prevCell = this.grid.getCell(col);
          if (!this.isFirstFocusCell() && !prevCell.editable){
           this.cell=prevCell;
           this.rowIndex=row;
           this.previous();
           return;
          }
         }
         this.setFocusIndex(row, col);
        }
       },
       move: function(inRowDelta, inColDelta) {
        // summary:
        // focus grid cell or simulate focus to column header based on position relative to current focus
        // inRowDelta: int
        // vertical distance from current focus
        // inColDelta: int
        // horizontal distance from current focus


        var colDir = inColDelta < 0 ? -1 : 1;
        // Handle column headers.
        if(this.isNavHeader()){
         var headers = this._findHeaderCells();
         var savedIdx = currentIdx = dojo.indexOf(headers, this._colHeadNode);
         currentIdx += inColDelta;
         while(currentIdx >=0 && currentIdx < headers.length && headers[currentIdx].style.display == "none"){
          // skip over hidden column headers
          currentIdx += colDir;
         }
         if((currentIdx >= 0) && (currentIdx < headers.length)){
          this._setActiveColHeader(headers[currentIdx],currentIdx, savedIdx);
         }
        }else{
         if(this.cell){
          // Handle grid proper.
          var sc = this.grid.scroller,
           r = this.rowIndex,
           rc = this.grid.rowCount-1,
           row = Math.min(rc, Math.max(0, r+inRowDelta));
          if(inRowDelta){
           if(inRowDelta>0){
            if(row > sc.getLastPageRow(sc.page)){
             //need to load additional data, let scroller do that
             this.grid.setScrollTop(this.grid.scrollTop+sc.findScrollTop(row)-sc.findScrollTop(r));
            }
           }else if(inRowDelta<0){
            if(row <= sc.getPageRow(sc.page)){
             //need to load additional data, let scroller do that
             this.grid.setScrollTop(this.grid.scrollTop-sc.findScrollTop(r)-sc.findScrollTop(row));
            }
           }
          }
          var cc = this.grid.layout.cellCount-1,
          i = this.cell.index,
          col = Math.min(cc, Math.max(0, i+inColDelta));
          var cell = this.grid.getCell(col);
          while(col>=0 && col < cc && cell && cell.hidden === true){
           // skip hidden cells
           col += colDir;
           cell = this.grid.getCell(col);
          }
          if (!cell || cell.hidden === true){
           // don't change col if would move to hidden
           col = i;
          }
          //skip hidden row|cell
          var n = cell.getNode(row);
          if(!n && inRowDelta){
           if((row + inRowDelta) >= 0 && (row + inRowDelta) <= rc){
            this.move(inRowDelta > 0 ? ++inRowDelta : --inRowDelta, inColDelta);
           }
           return;
          }else if((!n || dojo.style(n, "display") === "none") && inColDelta){
           if((col + inRowDelta) >= 0 && (col + inRowDelta) <= cc){
            this.move(inRowDelta, inColDelta > 0 ? ++inColDelta : --inColDelta);
           }
           return;
          }
          this.setFocusIndex(row, col);
          if(inRowDelta){
           this.grid.updateRow(r);
          }
         }
        }
       },
       previousKey: function(e){
        if(this.grid.edit.isEditing()){
         dojo.stopEvent(e);
         this.previous();
        }else if(!this.isNavHeader() && !this._isHeaderHidden()) {
         this.grid.domNode.focus(); // will call doFocus and set focus into header.
         dojo.stopEvent(e);
        }else{
         this.tabOut(this.grid.domNode);
         if (this._colHeadFocusIdx != null) { // clear grid header focus
          dojo.toggleClass(this._findHeaderCells()[this._colHeadFocusIdx], this.focusClass, false);
          this._colHeadFocusIdx = null;
         }
         this._focusifyCellNode(false);
        }
       },
       nextKey: function(e) {
        var isEmpty = (this.grid.rowCount === 0);
        if(e.target === this.grid.domNode && this._colHeadFocusIdx == null){
         this.focusHeader();
         dojo.stopEvent(e);
        }else if(this.isNavHeader()){
         // if tabbing from col header, then go to grid proper.
         this.blurHeader();
         if(!this.findAndFocusGridCell()){
          this.tabOut(this.grid.lastFocusNode);
         }
         this._colHeadNode = this._colHeadFocusIdx= null;
        }else if(this.grid.edit.isEditing()){
         dojo.stopEvent(e);
         this.next();
        }else{
         this.tabOut(this.grid.lastFocusNode);
        }
       },
       tabOut: function(inFocusNode){
        this.tabbingOut = true;
        inFocusNode.focus();
       },
       focusGridView: function(){
        dojox.grid.util.fire(this.focusView, "focus");
       },
       focusGrid: function(inSkipFocusCell){
        this.focusGridView();
        this._focusifyCellNode(true);
       },
       findAndFocusGridCell: function(){
        // summary:
        //  find the first focusable grid cell
        // returns: Boolean
        //  true if focus was set to a cell
        //  false if no cell found to set focus onto

        
        var didFocus = true;
        var isEmpty = (this.grid.rowCount === 0); // If grid is empty this.grid.rowCount == 0
        if (this.isNoFocusCell() && !isEmpty){
         var cellIdx = 0;
         var cell = this.grid.getCell(cellIdx);
         if (cell.hidden) {
          // if first cell isn't visible, use _colHeadFocusIdx
          // could also use a while loop to find first visible cell - not sure that is worth it
          cellIdx = this.isNavHeader() ? this._colHeadFocusIdx : 0;
         }
         this.setFocusIndex(0, cellIdx);
        }
        else if (this.cell && !isEmpty){
         if (this.focusView && !this.focusView.rowNodes[this.rowIndex]){
          // if rowNode for current index is undefined (likely as a result of a sort and because of #7304)
          // scroll to that row
          this.grid.scrollToRow(this.rowIndex);
         }
         this.focusGrid();
        }else {
         didFocus = false;
        }
        this._colHeadNode = this._colHeadFocusIdx= null;
        return didFocus;
       },
       focusHeader: function(){
        var headerNodes = this._findHeaderCells();
        var saveColHeadFocusIdx = this._colHeadFocusIdx;
        if (this._isHeaderHidden()){
         // grid header is hidden, focus a cell
         this.findAndFocusGridCell();
        }
        else if (!this._colHeadFocusIdx) {
         if (this.isNoFocusCell()) {
          this._colHeadFocusIdx = 0;
         }
         else {
          this._colHeadFocusIdx = this.cell.index;
         }
        }
        this._colHeadNode = headerNodes[this._colHeadFocusIdx];
        while(this._colHeadNode && this._colHeadFocusIdx >=0 && this._colHeadFocusIdx < headerNodes.length &&
          this._colHeadNode.style.display == "none"){
         // skip over hidden column headers
         this._colHeadFocusIdx++;
         this._colHeadNode = headerNodes[this._colHeadFocusIdx];
        }
        if(this._colHeadNode && this._colHeadNode.style.display != "none"){
         // Column header cells know longer receive actual focus. So, for keyboard invocation of
         // contextMenu to work, the contextMenu must be bound to the grid.domNode rather than the viewsHeaderNode.
         // unbind the contextmenu from the viewsHeaderNode and to the grid when header cells are active. Reset
         // the binding back to the viewsHeaderNode when header cells are no longer acive (in blurHeader) #10483
         if (this.headerMenu && this._contextMenuBindNode != this.grid.domNode){
          this.headerMenu.unBindDomNode(this.grid.viewsHeaderNode);
          this.headerMenu.bindDomNode(this.grid.domNode);
          this._contextMenuBindNode = this.grid.domNode;
         }
         this._setActiveColHeader(this._colHeadNode, this._colHeadFocusIdx, saveColHeadFocusIdx);
         this._scrollHeader(this._colHeadFocusIdx);
         this._focusifyCellNode(false);
        }else {
         // all col head nodes are hidden - focus the grid
         this.findAndFocusGridCell();
        }
       },
       blurHeader: function(){
        dojo.removeClass(this._colHeadNode, this.focusClass);
        dojo.removeAttr(this.grid.domNode,"aria-activedescendant");
        // reset contextMenu onto viewsHeaderNode so right mouse on header will invoke (see focusHeader)
        if (this.headerMenu && this._contextMenuBindNode == this.grid.domNode) {
         var viewsHeader = this.grid.viewsHeaderNode;
         this.headerMenu.unBindDomNode(this.grid.domNode);
         this.headerMenu.bindDomNode(viewsHeader);
         this._contextMenuBindNode = viewsHeader;
        }
       },
       doFocus: function(e){
        // trap focus only for grid dom node
        if(e && e.target != e.currentTarget){
         dojo.stopEvent(e);
         return;
        }
        // do not focus for scrolling if grid is about to blur
        if(!this.tabbingOut){
         this.focusHeader();
        }
        this.tabbingOut = false;
        dojo.stopEvent(e);
    • returns
      can't adjust single col. grid
    • summary
  • dojox.grid._FocusManager.doBlur

    • type
      Function
    • parameters:
      • e: (typeof )
    • source: [view]
        dojo.stopEvent(e); // FF2
    • summary
  • dojox.grid._FocusManager.doContextMenu

    • type
      Function
    • parameters:
      • e: (typeof )
    • source: [view]
      dojo.provide("dojox.grid._FocusManager");


      dojo.require("dojox.grid.util");


      // focus management
      dojo.declare("dojox.grid._FocusManager", null, {
       // summary:
       // Controls grid cell focus. Owned by grid and used internally for focusing.
       // Note: grid cell actually receives keyboard input only when cell is being edited.
       constructor: function(inGrid){
        this.grid = inGrid;
        this.cell = null;
        this.rowIndex = -1;
        this._connects = [];
        this._headerConnects = [];
        this.headerMenu = this.grid.headerMenu;
        this._connects.push(dojo.connect(this.grid.domNode, "onfocus", this, "doFocus"));
        this._connects.push(dojo.connect(this.grid.domNode, "onblur", this, "doBlur"));
        this._connects.push(dojo.connect(this.grid.domNode, "oncontextmenu", this, "doContextMenu"));
        this._connects.push(dojo.connect(this.grid.lastFocusNode, "onfocus", this, "doLastNodeFocus"));
        this._connects.push(dojo.connect(this.grid.lastFocusNode, "onblur", this, "doLastNodeBlur"));
        this._connects.push(dojo.connect(this.grid,"_onFetchComplete", this, "_delayedCellFocus"));
        this._connects.push(dojo.connect(this.grid,"postrender", this, "_delayedHeaderFocus"));
       },
       destroy: function(){
        dojo.forEach(this._connects, dojo.disconnect);
        dojo.forEach(this._headerConnects, dojo.disconnect);
        delete this.grid;
        delete this.cell;
       },
       _colHeadNode: null,
       _colHeadFocusIdx: null,
       _contextMenuBindNode: null,
       tabbingOut: false,
       focusClass: "dojoxGridCellFocus",
       focusView: null,
       initFocusView: function(){
        this.focusView = this.grid.views.getFirstScrollingView() || this.focusView || this.grid.views.views[0];
        this._initColumnHeaders();
       },
       isFocusCell: function(inCell, inRowIndex){
        // summary:
        // states if the given cell is focused
        // inCell: object
        // grid cell object
        // inRowIndex: int
        // grid row index
        // returns:
        // true of the given grid cell is focused
        return (this.cell == inCell) && (this.rowIndex == inRowIndex);
       },
       isLastFocusCell: function(){
        if(this.cell){
         return (this.rowIndex == this.grid.rowCount-1) && (this.cell.index == this.grid.layout.cellCount-1);
        }
        return false;
       },
       isFirstFocusCell: function(){
        if(this.cell){
         return (this.rowIndex === 0) && (this.cell.index === 0);
        }
        return false;
       },
       isNoFocusCell: function(){
        return (this.rowIndex < 0) || !this.cell;
       },
       isNavHeader: function(){
        // summary:
        // states whether currently navigating among column headers.
        // returns:
        // true if focus is on a column header; false otherwise.
        return (!!this._colHeadNode);
       },
       getHeaderIndex: function(){
        // summary:
        // if one of the column headers currently has focus, return its index.
        // returns:
        // index of the focused column header, or -1 if none have focus.
        if(this._colHeadNode){
         return dojo.indexOf(this._findHeaderCells(), this._colHeadNode);
        }else{
         return -1;
        }
       },
       _focusifyCellNode: function(inBork){
        var n = this.cell && this.cell.getNode(this.rowIndex);
        if(n){
         dojo.toggleClass(n, this.focusClass, inBork);
         if(inBork){
          var sl = this.scrollIntoView();
          try{
           if(!this.grid.edit.isEditing()){
            dojox.grid.util.fire(n, "focus");
            if(sl){ this.cell.view.scrollboxNode.scrollLeft = sl; }
           }
          }catch(e){}
         }
        }
       },
       _delayedCellFocus: function(){
        if(this.isNavHeader()||!this.grid._focused){
          return;
        }
        var n = this.cell && this.cell.getNode(this.rowIndex);
        if(n){
         try{
          if(!this.grid.edit.isEditing()){
           dojo.toggleClass(n, this.focusClass, true);
           this.blurHeader();
           dojox.grid.util.fire(n, "focus");
          }
         }
         catch(e){}
        }
       },
       _delayedHeaderFocus: function(){
        if(this.isNavHeader()){
         this.focusHeader();
         this.grid.domNode.focus();
        }
       },
       _initColumnHeaders: function(){
        dojo.forEach(this._headerConnects, dojo.disconnect);
        this._headerConnects = [];
        var headers = this._findHeaderCells();
        for(var i = 0; i < headers.length; i++){
         this._headerConnects.push(dojo.connect(headers[i], "onfocus", this, "doColHeaderFocus"));
         this._headerConnects.push(dojo.connect(headers[i], "onblur", this, "doColHeaderBlur"));
        }
       },
       _findHeaderCells: function(){
        // This should be a one liner:
        // dojo.query("th[tabindex=-1]", this.grid.viewsHeaderNode);
        // But there is a bug in dojo.query() for IE -- see trac #7037.
        var allHeads = dojo.query("th", this.grid.viewsHeaderNode);
        var headers = [];
        for (var i = 0; i < allHeads.length; i++){
         var aHead = allHeads[i];
         var hasTabIdx = dojo.hasAttr(aHead, "tabIndex");
         var tabindex = dojo.attr(aHead, "tabIndex");
         if (hasTabIdx && tabindex < 0) {
          headers.push(aHead);
         }
        }
        return headers;
       },
       _setActiveColHeader: function(/*Node*/colHeaderNode, /*Integer*/colFocusIdx, /*Integer*/ prevColFocusIdx){
        //console.log("setActiveColHeader() - colHeaderNode:colFocusIdx:prevColFocusIdx = " + colHeaderNode + ":" + colFocusIdx + ":" + prevColFocusIdx);
        dojo.attr(this.grid.domNode, "aria-activedescendant",colHeaderNode.id);
        if (prevColFocusIdx != null && prevColFocusIdx >= 0 && prevColFocusIdx != colFocusIdx){
         dojo.toggleClass(this._findHeaderCells()[prevColFocusIdx],this.focusClass,false);
        }
        dojo.toggleClass(colHeaderNode,this.focusClass, true);
        this._colHeadNode = colHeaderNode;
        this._colHeadFocusIdx = colFocusIdx;
        this._scrollHeader(this._colHeadFocusIdx);
       },
       scrollIntoView: function(){
        var info = (this.cell ? this._scrollInfo(this.cell) : null);
        if(!info || !info.s){
         return null;
        }
        var rt = this.grid.scroller.findScrollTop(this.rowIndex);
        // place cell within horizontal view
        if(info.n && info.sr){
         if(info.n.offsetLeft + info.n.offsetWidth > info.sr.l + info.sr.w){
          info.s.scrollLeft = info.n.offsetLeft + info.n.offsetWidth - info.sr.w;
         }else if(info.n.offsetLeft < info.sr.l){
          info.s.scrollLeft = info.n.offsetLeft;
         }
        }
        // place cell within vertical view
        if(info.r && info.sr){
         if(rt + info.r.offsetHeight > info.sr.t + info.sr.h){
          this.grid.setScrollTop(rt + info.r.offsetHeight - info.sr.h);
         }else if(rt < info.sr.t){
          this.grid.setScrollTop(rt);
         }
        }


        return info.s.scrollLeft;
       },
       _scrollInfo: function(cell, domNode){
        if(cell){
         var cl = cell,
          sbn = cl.view.scrollboxNode,
          sbnr = {
           w: sbn.clientWidth,
           l: sbn.scrollLeft,
           t: sbn.scrollTop,
           h: sbn.clientHeight
          },
          rn = cl.view.getRowNode(this.rowIndex);
         return {
          c: cl,
          s: sbn,
          sr: sbnr,
          n: (domNode ? domNode : cell.getNode(this.rowIndex)),
          r: rn
         };
        }
        return null;
       },
       _scrollHeader: function(currentIdx){
        var info = null;
        if(this._colHeadNode){
         var cell = this.grid.getCell(currentIdx);
         info = this._scrollInfo(cell, cell.getNode(0));
        }
        if(info && info.s && info.sr && info.n){
         // scroll horizontally as needed.
         var scroll = info.sr.l + info.sr.w;
         if(info.n.offsetLeft + info.n.offsetWidth > scroll){
          info.s.scrollLeft = info.n.offsetLeft + info.n.offsetWidth - info.sr.w;
         }else if(info.n.offsetLeft < info.sr.l){
          info.s.scrollLeft = info.n.offsetLeft;
         }else if(dojo.isIE <= 7 && cell && cell.view.headerNode){
          // Trac 7158: scroll dojoxGridHeader for IE7 and lower
          cell.view.headerNode.scrollLeft = info.s.scrollLeft;
         }
        }
       },
       _isHeaderHidden: function(){
        // summary:
        //  determine if the grid headers are hidden
        //  relies on documented technique of setting .dojoxGridHeader { display:none; }
        // returns: Boolean
        //  true if headers are hidden
        //  false if headers are not hidden

        
        var curView = this.focusView;
        if (!curView){
         // find one so we can determine if headers are hidden
         // there is no focusView after adding items to empty grid (test_data_grid_empty.html)
         for (var i = 0, cView; (cView = this.grid.views.views[i]); i++) {
          if(cView.headerNode ){
           curView=cView;
           break;
          }
         }
        }
        return (curView && dojo.getComputedStyle(curView.headerNode).display == "none");
       },
       colSizeAdjust: function (e, colIdx, delta){ // adjust the column specified by colIdx by the specified delta px
        var headers = this._findHeaderCells();
        var view = this.focusView;
        if (!view) {
         for (var i = 0, cView; (cView = this.grid.views.views[i]); i++) {
          // find first view with a tableMap in order to work with empty grid
          if(cView.header.tableMap.map ){
           view=cView;
           break;
          }
         }
        }
        var curHeader = headers[colIdx];
        if (!view || (colIdx == headers.length-1 && colIdx === 0)){
         return; // can't adjust single col. grid
        }
        view.content.baseDecorateEvent(e);
        // need to adjust event with header cell info since focus is no longer on header cell
        e.cellNode = curHeader; //this.findCellTarget(e.target, e.rowNode);
        e.cellIndex = view.content.getCellNodeIndex(e.cellNode);
        e.cell = (e.cellIndex >= 0 ? this.grid.getCell(e.cellIndex) : null);
        if (view.header.canResize(e)){
         var deltaObj = {
          l: delta
         };
         var drag = view.header.colResizeSetup(e,false);
         view.header.doResizeColumn(drag, null, deltaObj);
         view.update();
        }
       },
       styleRow: function(inRow){
        return;
       },
       setFocusIndex: function(inRowIndex, inCellIndex){
        // summary:
        // focuses the given grid cell
        // inRowIndex: int
        // grid row index
        // inCellIndex: int
        // grid cell index
        this.setFocusCell(this.grid.getCell(inCellIndex), inRowIndex);
       },
       setFocusCell: function(inCell, inRowIndex){
        // summary:
        // focuses the given grid cell
        // inCell: object
        // grid cell object
        // inRowIndex: int
        // grid row index
        if(inCell && !this.isFocusCell(inCell, inRowIndex)){
         this.tabbingOut = false;
         if (this._colHeadNode){
          this.blurHeader();
         }
         this._colHeadNode = this._colHeadFocusIdx = null;
         this.focusGridView();
         this._focusifyCellNode(false);
         this.cell = inCell;
         this.rowIndex = inRowIndex;
         this._focusifyCellNode(true);
        }
        // even if this cell isFocusCell, the document focus may need to be rejiggered
        // call opera on delay to prevent keypress from altering focus
        if(dojo.isOpera){
         setTimeout(dojo.hitch(this.grid, 'onCellFocus', this.cell, this.rowIndex), 1);
        }else{
         this.grid.onCellFocus(this.cell, this.rowIndex);
        }
       },
       next: function(){
        // summary:
        // focus next grid cell
        if(this.cell){
         var row=this.rowIndex, col=this.cell.index+1, cc=this.grid.layout.cellCount-1, rc=this.grid.rowCount-1;
         if(col > cc){
          col = 0;
          row++;
         }
         if(row > rc){
          col = cc;
          row = rc;
         }
         if(this.grid.edit.isEditing()){ //when editing, only navigate to editable cells
          var nextCell = this.grid.getCell(col);
          if (!this.isLastFocusCell() && (!nextCell.editable ||
           this.grid.canEdit && !this.grid.canEdit(nextCell, row))){
           this.cell=nextCell;
           this.rowIndex=row;
           this.next();
           return;
          }
         }
         this.setFocusIndex(row, col);
        }
       },
       previous: function(){
        // summary:
        // focus previous grid cell
        if(this.cell){
         var row=(this.rowIndex || 0), col=(this.cell.index || 0) - 1;
         if(col < 0){
          col = this.grid.layout.cellCount-1;
          row--;
         }
         if(row < 0){
          row = 0;
          col = 0;
         }
         if(this.grid.edit.isEditing()){ //when editing, only navigate to editable cells
          var prevCell = this.grid.getCell(col);
          if (!this.isFirstFocusCell() && !prevCell.editable){
           this.cell=prevCell;
           this.rowIndex=row;
           this.previous();
           return;
          }
         }
         this.setFocusIndex(row, col);
        }
       },
       move: function(inRowDelta, inColDelta) {
        // summary:
        // focus grid cell or simulate focus to column header based on position relative to current focus
        // inRowDelta: int
        // vertical distance from current focus
        // inColDelta: int
        // horizontal distance from current focus


        var colDir = inColDelta < 0 ? -1 : 1;
        // Handle column headers.
        if(this.isNavHeader()){
         var headers = this._findHeaderCells();
         var savedIdx = currentIdx = dojo.indexOf(headers, this._colHeadNode);
         currentIdx += inColDelta;
         while(currentIdx >=0 && currentIdx < headers.length && headers[currentIdx].style.display == "none"){
          // skip over hidden column headers
          currentIdx += colDir;
         }
         if((currentIdx >= 0) && (currentIdx < headers.length)){
          this._setActiveColHeader(headers[currentIdx],currentIdx, savedIdx);
         }
        }else{
         if(this.cell){
          // Handle grid proper.
          var sc = this.grid.scroller,
           r = this.rowIndex,
           rc = this.grid.rowCount-1,
           row = Math.min(rc, Math.max(0, r+inRowDelta));
          if(inRowDelta){
           if(inRowDelta>0){
            if(row > sc.getLastPageRow(sc.page)){
             //need to load additional data, let scroller do that
             this.grid.setScrollTop(this.grid.scrollTop+sc.findScrollTop(row)-sc.findScrollTop(r));
            }
           }else if(inRowDelta<0){
            if(row <= sc.getPageRow(sc.page)){
             //need to load additional data, let scroller do that
             this.grid.setScrollTop(this.grid.scrollTop-sc.findScrollTop(r)-sc.findScrollTop(row));
            }
           }
          }
          var cc = this.grid.layout.cellCount-1,
          i = this.cell.index,
          col = Math.min(cc, Math.max(0, i+inColDelta));
          var cell = this.grid.getCell(col);
          while(col>=0 && col < cc && cell && cell.hidden === true){
           // skip hidden cells
           col += colDir;
           cell = this.grid.getCell(col);
          }
          if (!cell || cell.hidden === true){
           // don't change col if would move to hidden
           col = i;
          }
          //skip hidden row|cell
          var n = cell.getNode(row);
          if(!n && inRowDelta){
           if((row + inRowDelta) >= 0 && (row + inRowDelta) <= rc){
            this.move(inRowDelta > 0 ? ++inRowDelta : --inRowDelta, inColDelta);
           }
           return;
          }else if((!n || dojo.style(n, "display") === "none") && inColDelta){
           if((col + inRowDelta) >= 0 && (col + inRowDelta) <= cc){
            this.move(inRowDelta, inColDelta > 0 ? ++inColDelta : --inColDelta);
           }
           return;
          }
          this.setFocusIndex(row, col);
          if(inRowDelta){
           this.grid.updateRow(r);
          }
         }
        }
       },
       previousKey: function(e){
        if(this.grid.edit.isEditing()){
         dojo.stopEvent(e);
         this.previous();
        }else if(!this.isNavHeader() && !this._isHeaderHidden()) {
         this.grid.domNode.focus(); // will call doFocus and set focus into header.
         dojo.stopEvent(e);
        }else{
         this.tabOut(this.grid.domNode);
         if (this._colHeadFocusIdx != null) { // clear grid header focus
          dojo.toggleClass(this._findHeaderCells()[this._colHeadFocusIdx], this.focusClass, false);
          this._colHeadFocusIdx = null;
         }
         this._focusifyCellNode(false);
        }
       },
       nextKey: function(e) {
        var isEmpty = (this.grid.rowCount === 0);
        if(e.target === this.grid.domNode && this._colHeadFocusIdx == null){
         this.focusHeader();
         dojo.stopEvent(e);
        }else if(this.isNavHeader()){
         // if tabbing from col header, then go to grid proper.
         this.blurHeader();
         if(!this.findAndFocusGridCell()){
          this.tabOut(this.grid.lastFocusNode);
         }
         this._colHeadNode = this._colHeadFocusIdx= null;
        }else if(this.grid.edit.isEditing()){
         dojo.stopEvent(e);
         this.next();
        }else{
         this.tabOut(this.grid.lastFocusNode);
        }
       },
       tabOut: function(inFocusNode){
        this.tabbingOut = true;
        inFocusNode.focus();
       },
       focusGridView: function(){
        dojox.grid.util.fire(this.focusView, "focus");
       },
       focusGrid: function(inSkipFocusCell){
        this.focusGridView();
        this._focusifyCellNode(true);
       },
       findAndFocusGridCell: function(){
        // summary:
        //  find the first focusable grid cell
        // returns: Boolean
        //  true if focus was set to a cell
        //  false if no cell found to set focus onto

        
        var didFocus = true;
        var isEmpty = (this.grid.rowCount === 0); // If grid is empty this.grid.rowCount == 0
        if (this.isNoFocusCell() && !isEmpty){
         var cellIdx = 0;
         var cell = this.grid.getCell(cellIdx);
         if (cell.hidden) {
          // if first cell isn't visible, use _colHeadFocusIdx
          // could also use a while loop to find first visible cell - not sure that is worth it
          cellIdx = this.isNavHeader() ? this._colHeadFocusIdx : 0;
         }
         this.setFocusIndex(0, cellIdx);
        }
        else if (this.cell && !isEmpty){
         if (this.focusView && !this.focusView.rowNodes[this.rowIndex]){
          // if rowNode for current index is undefined (likely as a result of a sort and because of #7304)
          // scroll to that row
          this.grid.scrollToRow(this.rowIndex);
         }
         this.focusGrid();
        }else {
         didFocus = false;
        }
        this._colHeadNode = this._colHeadFocusIdx= null;
        return didFocus;
       },
       focusHeader: function(){
        var headerNodes = this._findHeaderCells();
        var saveColHeadFocusIdx = this._colHeadFocusIdx;
        if (this._isHeaderHidden()){
         // grid header is hidden, focus a cell
         this.findAndFocusGridCell();
        }
        else if (!this._colHeadFocusIdx) {
         if (this.isNoFocusCell()) {
          this._colHeadFocusIdx = 0;
         }
         else {
          this._colHeadFocusIdx = this.cell.index;
         }
        }
        this._colHeadNode = headerNodes[this._colHeadFocusIdx];
        while(this._colHeadNode && this._colHeadFocusIdx >=0 && this._colHeadFocusIdx < headerNodes.length &&
          this._colHeadNode.style.display == "none"){
         // skip over hidden column headers
         this._colHeadFocusIdx++;
         this._colHeadNode = headerNodes[this._colHeadFocusIdx];
        }
        if(this._colHeadNode && this._colHeadNode.style.display != "none"){
         // Column header cells know longer receive actual focus. So, for keyboard invocation of
         // contextMenu to work, the contextMenu must be bound to the grid.domNode rather than the viewsHeaderNode.
         // unbind the contextmenu from the viewsHeaderNode and to the grid when header cells are active. Reset
         // the binding back to the viewsHeaderNode when header cells are no longer acive (in blurHeader) #10483
         if (this.headerMenu && this._contextMenuBindNode != this.grid.domNode){
          this.headerMenu.unBindDomNode(this.grid.viewsHeaderNode);
          this.headerMenu.bindDomNode(this.grid.domNode);
          this._contextMenuBindNode = this.grid.domNode;
         }
         this._setActiveColHeader(this._colHeadNode, this._colHeadFocusIdx, saveColHeadFocusIdx);
         this._scrollHeader(this._colHeadFocusIdx);
         this._focusifyCellNode(false);
        }else {
         // all col head nodes are hidden - focus the grid
         this.findAndFocusGridCell();
        }
       },
       blurHeader: function(){
        dojo.removeClass(this._colHeadNode, this.focusClass);
        dojo.removeAttr(this.grid.domNode,"aria-activedescendant");
        // reset contextMenu onto viewsHeaderNode so right mouse on header will invoke (see focusHeader)
        if (this.headerMenu && this._contextMenuBindNode == this.grid.domNode) {
         var viewsHeader = this.grid.viewsHeaderNode;
         this.headerMenu.unBindDomNode(this.grid.domNode);
         this.headerMenu.bindDomNode(viewsHeader);
         this._contextMenuBindNode = viewsHeader;
        }
       },
       doFocus: function(e){
        // trap focus only for grid dom node
        if(e && e.target != e.currentTarget){
         dojo.stopEvent(e);
         return;
        }
        // do not focus for scrolling if grid is about to blur
        if(!this.tabbingOut){
         this.focusHeader();
        }
        this.tabbingOut = false;
        dojo.stopEvent(e);
       },
       doBlur: function(e){
        dojo.stopEvent(e); // FF2
       },
       doContextMenu: function(e){
       //stop contextMenu event if no header Menu to prevent default/browser contextMenu
        if (!this.headerMenu){
         dojo.stopEvent(e);
        }
    • returns
      can't adjust single col. grid
    • summary
  • dojox.grid._FocusManager.doLastNodeFocus

    • type
      Function
    • parameters:
      • e: (typeof )
    • source: [view]
        if (this.tabbingOut){
         this._focusifyCellNode(false);
        }else if(this.grid.rowCount >0){
         if (this.isNoFocusCell()){
          this.setFocusIndex(0,0);
         }
         this._focusifyCellNode(true);
        }else {
         this.focusHeader();
        }
        this.tabbingOut = false;
        dojo.stopEvent(e);  // FF2
    • summary
  • dojox.grid._FocusManager.doLastNodeBlur

    • type
      Function
    • parameters:
      • e: (typeof )
    • source: [view]
        dojo.stopEvent(e);  // FF2
    • summary
  • dojox.grid._FocusManager.doColHeaderFocus

    • type
      Function
    • parameters:
      • e: (typeof )
    • source: [view]
        this._setActiveColHeader(e.target,dojo.attr(e.target, "idx"),this._colHeadFocusIdx);
        this._scrollHeader(this.getHeaderIndex());
        dojo.stopEvent(e);
    • summary
  • dojox.grid._FocusManager.doColHeaderBlur

    • type
      Function
    • parameters:
      • e: (typeof )
    • source: [view]
        dojo.toggleClass(e.target, this.focusClass, false);
    • summary
  • dojox.grid._FocusManager.cell

    • summary
  • dojox.grid._FocusManager.rowIndex

    • summary
  • dojox.grid._FocusManager.cell.view.scrollboxNode.scrollLeft

    • summary
  • dojox.grid._FocusManager._headerConnects

    • summary
  • dojox.grid._FocusManager.grid.rowCount

    • summary
  • dojox.grid._FocusManager._colHeadNode.style.display

    • summary
  • dojox.grid._FocusManager.grid

    • summary
  • dojox.grid._FocusManager._connects

    • summary
  • dojox.grid._FocusManager.headerMenu

    • summary
  • dojox.grid

    • type
      Object
    • summary
  • dojox

    • type
      Object
    • summary