642 lines
20 KiB
JavaScript
642 lines
20 KiB
JavaScript
//>>built
|
|
define("dojox/grid/_FocusManager", [
|
|
"dojo/_base/array",
|
|
"dojo/_base/lang",
|
|
"dojo/_base/declare",
|
|
"dojo/_base/connect",
|
|
"dojo/_base/event",
|
|
"dojo/_base/sniff",
|
|
"dojo/query",
|
|
"./util",
|
|
"dojo/_base/html"
|
|
], function(array, lang, declare, connect, event, has, query, util, html){
|
|
|
|
// focus management
|
|
return 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(connect.connect(this.grid.domNode, "onfocus", this, "doFocus"));
|
|
this._connects.push(connect.connect(this.grid.domNode, "onblur", this, "doBlur"));
|
|
this._connects.push(connect.connect(this.grid.domNode, "mousedown", this, "_mouseDown"));
|
|
this._connects.push(connect.connect(this.grid.domNode, "mouseup", this, "_mouseUp"));
|
|
this._connects.push(connect.connect(this.grid.domNode, "oncontextmenu", this, "doContextMenu"));
|
|
this._connects.push(connect.connect(this.grid.lastFocusNode, "onfocus", this, "doLastNodeFocus"));
|
|
this._connects.push(connect.connect(this.grid.lastFocusNode, "onblur", this, "doLastNodeBlur"));
|
|
this._connects.push(connect.connect(this.grid,"_onFetchComplete", this, "_delayedCellFocus"));
|
|
this._connects.push(connect.connect(this.grid,"postrender", this, "_delayedHeaderFocus"));
|
|
},
|
|
destroy: function(){
|
|
array.forEach(this._connects, connect.disconnect);
|
|
array.forEach(this._headerConnects, connect.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 array.indexOf(this._findHeaderCells(), this._colHeadNode);
|
|
}else{
|
|
return -1;
|
|
}
|
|
},
|
|
_focusifyCellNode: function(inBork){
|
|
var n = this.cell && this.cell.getNode(this.rowIndex);
|
|
if(n){
|
|
html.toggleClass(n, this.focusClass, inBork);
|
|
if(inBork){
|
|
var sl = this.scrollIntoView();
|
|
try{
|
|
if(!this.grid.edit.isEditing()){
|
|
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()){
|
|
html.toggleClass(n, this.focusClass, true);
|
|
if(this._colHeadNode){
|
|
this.blurHeader();
|
|
}
|
|
util.fire(n, "focus");
|
|
}
|
|
}
|
|
catch(e){}
|
|
}
|
|
},
|
|
_delayedHeaderFocus: function(){
|
|
if(this.isNavHeader()){
|
|
this.focusHeader();
|
|
this.grid.domNode.focus();
|
|
}
|
|
},
|
|
_initColumnHeaders: function(){
|
|
array.forEach(this._headerConnects, connect.disconnect);
|
|
this._headerConnects = [];
|
|
var headers = this._findHeaderCells();
|
|
for(var i = 0; i < headers.length; i++){
|
|
this._headerConnects.push(connect.connect(headers[i], "onfocus", this, "doColHeaderFocus"));
|
|
this._headerConnects.push(connect.connect(headers[i], "onblur", this, "doColHeaderBlur"));
|
|
}
|
|
},
|
|
_findHeaderCells: function(){
|
|
// This should be a one liner:
|
|
// query("th[tabindex=-1]", this.grid.viewsHeaderNode);
|
|
// But there is a bug in query() for IE -- see trac #7037.
|
|
var allHeads = query("th", this.grid.viewsHeaderNode);
|
|
var headers = [];
|
|
for (var i = 0; i < allHeads.length; i++){
|
|
var aHead = allHeads[i];
|
|
var hasTabIdx = html.hasAttr(aHead, "tabIndex");
|
|
var tabindex = html.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);
|
|
this.grid.domNode.setAttribute("aria-activedescendant",colHeaderNode.id);
|
|
if (prevColFocusIdx != null && prevColFocusIdx >= 0 && prevColFocusIdx != colFocusIdx){
|
|
html.toggleClass(this._findHeaderCells()[prevColFocusIdx],this.focusClass,false);
|
|
}
|
|
html.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);
|
|
if(!cell){ return; }
|
|
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(has("ie") <= 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 && html.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(has("opera")){
|
|
setTimeout(lang.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 = array.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 || html.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()){
|
|
event.stop(e);
|
|
this.previous();
|
|
}else if(!this.isNavHeader() && !this._isHeaderHidden()) {
|
|
this.grid.domNode.focus(); // will call doFocus and set focus into header.
|
|
event.stop(e);
|
|
}else{
|
|
this.tabOut(this.grid.domNode);
|
|
if (this._colHeadFocusIdx != null) { // clear grid header focus
|
|
html.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();
|
|
event.stop(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()){
|
|
event.stop(e);
|
|
this.next();
|
|
}else{
|
|
this.tabOut(this.grid.lastFocusNode);
|
|
}
|
|
},
|
|
tabOut: function(inFocusNode){
|
|
this.tabbingOut = true;
|
|
inFocusNode.focus();
|
|
},
|
|
focusGridView: function(){
|
|
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(){
|
|
html.removeClass(this._colHeadNode, this.focusClass);
|
|
html.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){
|
|
event.stop(e);
|
|
return;
|
|
}
|
|
// don't change focus if clicking on scroller bar
|
|
if(this._clickFocus){
|
|
return;
|
|
}
|
|
// do not focus for scrolling if grid is about to blur
|
|
if(!this.tabbingOut){
|
|
this.focusHeader();
|
|
}
|
|
this.tabbingOut = false;
|
|
event.stop(e);
|
|
},
|
|
doBlur: function(e){
|
|
event.stop(e); // FF2
|
|
},
|
|
doContextMenu: function(e){
|
|
//stop contextMenu event if no header Menu to prevent default/browser contextMenu
|
|
if (!this.headerMenu){
|
|
event.stop(e);
|
|
}
|
|
},
|
|
doLastNodeFocus: function(e){
|
|
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;
|
|
event.stop(e); // FF2
|
|
},
|
|
doLastNodeBlur: function(e){
|
|
event.stop(e); // FF2
|
|
},
|
|
doColHeaderFocus: function(e){
|
|
this._setActiveColHeader(e.target,html.attr(e.target, "idx"),this._colHeadFocusIdx);
|
|
this._scrollHeader(this.getHeaderIndex());
|
|
event.stop(e);
|
|
},
|
|
doColHeaderBlur: function(e){
|
|
html.toggleClass(e.target, this.focusClass, false);
|
|
},
|
|
_mouseDown: function(e){
|
|
// a flag indicating grid is being focused by clicking
|
|
this._clickFocus = dojo.some(this.grid.views.views, function(v){
|
|
return v.scrollboxNode === e.target;
|
|
});
|
|
},
|
|
_mouseUp: function(e){
|
|
this._clickFocus = false;
|
|
}
|
|
});
|
|
}); |