source: Dev/trunk/src/client/dojox/grid/_FocusManager.js @ 529

Last change on this file since 529 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 20.2 KB
Line 
1define([
2        "dojo/_base/array",
3        "dojo/_base/lang",
4        "dojo/_base/declare",
5        "dojo/_base/connect",
6        "dojo/_base/event",
7        "dojo/_base/sniff",
8        "dojo/query",
9        "./util",
10        "dojo/_base/html"
11], function(array, lang, declare, connect, event, has, query, util, html){
12
13// focus management
14return declare("dojox.grid._FocusManager", null, {
15        // summary:
16        //              Controls grid cell focus. Owned by grid and used internally for focusing.
17        //              Note: grid cell actually receives keyboard input only when cell is being edited.
18        constructor: function(inGrid){
19                this.grid = inGrid;
20                this.cell = null;
21                this.rowIndex = -1;
22                this._connects = [];
23                this._headerConnects = [];
24                this.headerMenu = this.grid.headerMenu;
25                this._connects.push(connect.connect(this.grid.domNode, "onfocus", this, "doFocus"));
26                this._connects.push(connect.connect(this.grid.domNode, "onblur", this, "doBlur"));
27                this._connects.push(connect.connect(this.grid.domNode, "mousedown", this, "_mouseDown"));
28                this._connects.push(connect.connect(this.grid.domNode, "mouseup", this, "_mouseUp"));
29                this._connects.push(connect.connect(this.grid.domNode, "oncontextmenu", this, "doContextMenu"));
30                this._connects.push(connect.connect(this.grid.lastFocusNode, "onfocus", this, "doLastNodeFocus"));
31                this._connects.push(connect.connect(this.grid.lastFocusNode, "onblur", this, "doLastNodeBlur"));
32                this._connects.push(connect.connect(this.grid,"_onFetchComplete", this, "_delayedCellFocus"));
33                this._connects.push(connect.connect(this.grid,"postrender", this, "_delayedHeaderFocus"));
34        },
35        destroy: function(){
36                array.forEach(this._connects, connect.disconnect);
37                array.forEach(this._headerConnects, connect.disconnect);
38                delete this.grid;
39                delete this.cell;
40        },
41        _colHeadNode: null,
42        _colHeadFocusIdx: null,
43        _contextMenuBindNode: null,
44        tabbingOut: false,
45        focusClass: "dojoxGridCellFocus",
46        focusView: null,
47        initFocusView: function(){
48                this.focusView = this.grid.views.getFirstScrollingView() || this.focusView || this.grid.views.views[0];
49                this._initColumnHeaders();
50        },
51        isFocusCell: function(inCell, inRowIndex){
52                // summary:
53                //              states if the given cell is focused
54                // inCell: object
55                //              grid cell object
56                // inRowIndex: int
57                //              grid row index
58                // returns:
59                //              true of the given grid cell is focused
60                return (this.cell == inCell) && (this.rowIndex == inRowIndex);
61        },
62        isLastFocusCell: function(){
63                if(this.cell){
64                        return (this.rowIndex == this.grid.rowCount-1) && (this.cell.index == this.grid.layout.cellCount-1);
65                }
66                return false;
67        },
68        isFirstFocusCell: function(){
69                if(this.cell){
70                        return (this.rowIndex === 0) && (this.cell.index === 0);
71                }
72                return false;
73        },
74        isNoFocusCell: function(){
75                return (this.rowIndex < 0) || !this.cell;
76        },
77        isNavHeader: function(){
78                // summary:
79                //              states whether currently navigating among column headers.
80                // returns:
81                //              true if focus is on a column header; false otherwise.
82                return (!!this._colHeadNode);
83        },
84        getHeaderIndex: function(){
85                // summary:
86                //              if one of the column headers currently has focus, return its index.
87                // returns:
88                //              index of the focused column header, or -1 if none have focus.
89                if(this._colHeadNode){
90                        return array.indexOf(this._findHeaderCells(), this._colHeadNode);
91                }else{
92                        return -1;
93                }
94        },
95        _focusifyCellNode: function(inBork){
96                var n = this.cell && this.cell.getNode(this.rowIndex);
97                if(n){
98                        html.toggleClass(n, this.focusClass, inBork);
99                        if(inBork){
100                                var sl = this.scrollIntoView();
101                                try{
102                                        if(has("webkit") || !this.grid.edit.isEditing()){
103                                                util.fire(n, "focus");
104                                                if(sl){ this.cell.view.scrollboxNode.scrollLeft = sl; }
105                                        }
106                                }catch(e){}
107                        }
108                }
109        },
110        _delayedCellFocus: function(){
111                if(this.isNavHeader()||!this.grid.focused){
112                                return;
113                }
114                var n = this.cell && this.cell.getNode(this.rowIndex);
115                if(n){
116                        try{
117                                if(!this.grid.edit.isEditing()){
118                                        html.toggleClass(n, this.focusClass, true);
119                                        if(this._colHeadNode){
120                                                this.blurHeader();
121                                        }
122                                        util.fire(n, "focus");
123                                }
124                        }
125                        catch(e){}
126                }
127        },
128        _delayedHeaderFocus: function(){
129                if(this.isNavHeader()){
130                        this.focusHeader();
131                        //this.grid.domNode.focus();
132                }
133        },
134        _initColumnHeaders: function(){
135                array.forEach(this._headerConnects, connect.disconnect);
136                this._headerConnects = [];
137                var headers = this._findHeaderCells();
138                for(var i = 0; i < headers.length; i++){
139                        this._headerConnects.push(connect.connect(headers[i], "onfocus", this, "doColHeaderFocus"));
140                        this._headerConnects.push(connect.connect(headers[i], "onblur", this, "doColHeaderBlur"));
141                }
142        },
143        _findHeaderCells: function(){
144                // This should be a one liner:
145                //      query("th[tabindex=-1]", this.grid.viewsHeaderNode);
146                // But there is a bug in query() for IE -- see trac #7037.
147                var allHeads = query("th", this.grid.viewsHeaderNode);
148                var headers = [];
149                for (var i = 0; i < allHeads.length; i++){
150                        var aHead = allHeads[i];
151                        var hasTabIdx = html.hasAttr(aHead, "tabIndex");
152                        var tabindex = html.attr(aHead, "tabIndex");
153                        if (hasTabIdx && tabindex < 0) {
154                                headers.push(aHead);
155                        }
156                }
157                return headers;
158        },
159        _setActiveColHeader: function(/*Node*/colHeaderNode, /*Integer*/colFocusIdx, /*Integer*/ prevColFocusIdx){
160                //console.log("setActiveColHeader() - colHeaderNode:colFocusIdx:prevColFocusIdx = " + colHeaderNode + ":" + colFocusIdx + ":" + prevColFocusIdx);
161                this.grid.domNode.setAttribute("aria-activedescendant",colHeaderNode.id);
162                if (prevColFocusIdx != null && prevColFocusIdx >= 0 && prevColFocusIdx != colFocusIdx){
163                        html.toggleClass(this._findHeaderCells()[prevColFocusIdx],this.focusClass,false);
164                }
165                html.toggleClass(colHeaderNode,this.focusClass, true);
166                this._colHeadNode = colHeaderNode;
167                this._colHeadFocusIdx = colFocusIdx;
168                this._scrollHeader(this._colHeadFocusIdx);
169        },
170        scrollIntoView: function(){
171                var info = (this.cell ? this._scrollInfo(this.cell) : null);
172                if(!info || !info.s){
173                        return null;
174                }
175                var rt = this.grid.scroller.findScrollTop(this.rowIndex);
176                // place cell within horizontal view
177                if(info.n && info.sr){
178                        if(info.n.offsetLeft + info.n.offsetWidth > info.sr.l + info.sr.w){
179                                info.s.scrollLeft = info.n.offsetLeft + info.n.offsetWidth - info.sr.w;
180                        }else if(info.n.offsetLeft < info.sr.l){
181                                info.s.scrollLeft = info.n.offsetLeft;
182                        }
183                }
184                // place cell within vertical view
185                if(info.r && info.sr){
186                        if(rt + info.r.offsetHeight > info.sr.t + info.sr.h){
187                                this.grid.setScrollTop(rt + info.r.offsetHeight - info.sr.h);
188                        }else if(rt < info.sr.t){
189                                this.grid.setScrollTop(rt);
190                        }
191                }
192
193                return info.s.scrollLeft;
194        },
195        _scrollInfo: function(cell, domNode){
196                if(cell){
197                        var cl = cell,
198                                sbn = cl.view.scrollboxNode,
199                                sbnr = {
200                                        w: sbn.clientWidth,
201                                        l: sbn.scrollLeft,
202                                        t: sbn.scrollTop,
203                                        h: sbn.clientHeight
204                                },
205                                rn = cl.view.getRowNode(this.rowIndex);
206                        return {
207                                c: cl,
208                                s: sbn,
209                                sr: sbnr,
210                                n: (domNode ? domNode : cell.getNode(this.rowIndex)),
211                                r: rn
212                        };
213                }
214                return null;
215        },
216        _scrollHeader: function(currentIdx){
217                var info = null;
218                if(this._colHeadNode){
219                        var cell = this.grid.getCell(currentIdx);
220                        if(!cell){ return; }
221                        info = this._scrollInfo(cell, cell.getNode(0));
222                }
223                if(info && info.s && info.sr && info.n){
224                        // scroll horizontally as needed.
225                        var scroll = info.sr.l + info.sr.w;
226                        if(info.n.offsetLeft + info.n.offsetWidth > scroll){
227                                info.s.scrollLeft = info.n.offsetLeft + info.n.offsetWidth - info.sr.w;
228                        }else if(info.n.offsetLeft < info.sr.l){
229                                info.s.scrollLeft = info.n.offsetLeft;
230                        }else if(has('ie') <= 7 && cell && cell.view.headerNode){
231                                // Trac 7158: scroll dojoxGridHeader for IE7 and lower
232                                cell.view.headerNode.scrollLeft = info.s.scrollLeft;
233                        }
234                }
235        },
236        _isHeaderHidden: function(){
237                // summary:
238                //              determine if the grid headers are hidden
239                //              relies on documented technique of setting .dojoxGridHeader { display:none; }
240                // returns: Boolean
241                //              true if headers are hidden
242                //              false if headers are not hidden
243               
244                var curView = this.focusView;
245                if (!curView){
246                        // find one so we can determine if headers are hidden
247                        // there is no focusView after adding items to empty grid (test_data_grid_empty.html)
248                        for (var i = 0, cView; (cView = this.grid.views.views[i]); i++) {
249                                if(cView.headerNode ){
250                                        curView=cView;
251                                        break;
252                                }
253                        }
254                }
255                return (curView && html.getComputedStyle(curView.headerNode).display == "none");
256        },
257        colSizeAdjust: function (e, colIdx, delta){ // adjust the column specified by colIdx by the specified delta px
258                var headers = this._findHeaderCells();
259                var view = this.focusView;
260                if(!view || !view.header.tableMap.map){
261                        for(var i = 0, cView; (cView = this.grid.views.views[i]); i++){
262                                // find first view with a tableMap in order to work with empty grid
263                                if(cView.header.tableMap.map){
264                                        view=cView;
265                                        break;
266                                }
267                        }
268                }
269                var curHeader = headers[colIdx];
270                if (!view || (colIdx == headers.length-1 && colIdx === 0)){
271                        return; // can't adjust single col. grid
272                }
273                view.content.baseDecorateEvent(e);
274                // need to adjust event with header cell info since focus is no longer on header cell
275                e.cellNode = curHeader; //this.findCellTarget(e.target, e.rowNode);
276                e.cellIndex = view.content.getCellNodeIndex(e.cellNode);
277                e.cell = (e.cellIndex >= 0 ? this.grid.getCell(e.cellIndex) : null);
278                if (view.header.canResize(e)){
279                        var deltaObj = {
280                                l: delta
281                        };
282                        var drag = view.header.colResizeSetup(e,false);
283                        view.header.doResizeColumn(drag, null, deltaObj);
284                        view.update();
285                }
286        },
287        styleRow: function(inRow){
288                return;
289        },
290        setFocusIndex: function(inRowIndex, inCellIndex){
291                // summary:
292                //              focuses the given grid cell
293                // inRowIndex: int
294                //              grid row index
295                // inCellIndex: int
296                //              grid cell index
297                this.setFocusCell(this.grid.getCell(inCellIndex), inRowIndex);
298        },
299        setFocusCell: function(inCell, inRowIndex){
300                // summary:
301                //              focuses the given grid cell
302                // inCell: object
303                //              grid cell object
304                // inRowIndex: int
305                //              grid row index
306                if(inCell && !this.isFocusCell(inCell, inRowIndex)){
307                        this.tabbingOut = false;
308                        if (this._colHeadNode){
309                                this.blurHeader();
310                        }
311                        this._colHeadNode = this._colHeadFocusIdx = null;
312                        this.focusGridView();
313                        this._focusifyCellNode(false);
314                        this.cell = inCell;
315                        this.rowIndex = inRowIndex;
316                        this._focusifyCellNode(true);
317                }
318                // even if this cell isFocusCell, the document focus may need to be rejiggered
319                // call opera on delay to prevent keypress from altering focus
320                if(has('opera')){
321                        setTimeout(lang.hitch(this.grid, 'onCellFocus', this.cell, this.rowIndex), 1);
322                }else{
323                        this.grid.onCellFocus(this.cell, this.rowIndex);
324                }
325        },
326        next: function(){
327                // summary:
328                //      focus next grid cell
329                if(this.cell){
330                        var row=this.rowIndex, col=this.cell.index+1, cc=this.grid.layout.cellCount-1, rc=this.grid.rowCount-1;
331                        if(col > cc){
332                                col = 0;
333                                row++;
334                        }
335                        if(row > rc){
336                                col = cc;
337                                row = rc;
338                        }
339                        if(this.grid.edit.isEditing()){ //when editing, only navigate to editable cells
340                                var nextCell = this.grid.getCell(col);
341                                if (!this.isLastFocusCell() && (!nextCell.editable ||
342                                        this.grid.canEdit && !this.grid.canEdit(nextCell, row))){
343                                        this.cell=nextCell;
344                                        this.rowIndex=row;
345                                        this.next();
346                                        return;
347                                }
348                        }
349                        this.setFocusIndex(row, col);
350                }
351        },
352        previous: function(){
353                // summary:
354                //      focus previous grid cell
355                if(this.cell){
356                        var row=(this.rowIndex || 0), col=(this.cell.index || 0) - 1;
357                        if(col < 0){
358                                col = this.grid.layout.cellCount-1;
359                                row--;
360                        }
361                        if(row < 0){
362                                row = 0;
363                                col = 0;
364                        }
365                        if(this.grid.edit.isEditing()){ //when editing, only navigate to editable cells
366                                var prevCell = this.grid.getCell(col);
367                                if (!this.isFirstFocusCell() && !prevCell.editable){
368                                        this.cell=prevCell;
369                                        this.rowIndex=row;
370                                        this.previous();
371                                        return;
372                                }
373                        }
374                        this.setFocusIndex(row, col);
375                }
376        },
377        move: function(inRowDelta, inColDelta) {
378                // summary:
379                //              focus grid cell or  simulate focus to column header based on position relative to current focus
380                // inRowDelta: int
381                //              vertical distance from current focus
382                // inColDelta: int
383                //              horizontal distance from current focus
384
385                var colDir = inColDelta < 0 ? -1 : 1;
386                // Handle column headers.
387                if(this.isNavHeader()){
388                        var headers = this._findHeaderCells();
389                        var savedIdx = currentIdx = array.indexOf(headers, this._colHeadNode);
390                        currentIdx += inColDelta;
391                        while(currentIdx >=0 && currentIdx < headers.length && headers[currentIdx].style.display == "none"){
392                                // skip over hidden column headers
393                                currentIdx += colDir;
394                        }
395                        if((currentIdx >= 0) && (currentIdx < headers.length)){
396                                this._setActiveColHeader(headers[currentIdx],currentIdx, savedIdx);
397                        }
398                }else{
399                        if(this.cell){
400                                // Handle grid proper.
401                                var sc = this.grid.scroller,
402                                        r = this.rowIndex,
403                                        rc = this.grid.rowCount-1,
404                                        row = Math.min(rc, Math.max(0, r+inRowDelta));
405                                if(inRowDelta){
406                                        if(inRowDelta>0){
407                                                if(row > sc.getLastPageRow(sc.page)){
408                                                        //need to load additional data, let scroller do that
409                                                        this.grid.setScrollTop(this.grid.scrollTop+sc.findScrollTop(row)-sc.findScrollTop(r));
410                                                }
411                                        }else if(inRowDelta<0){
412                                                if(row <= sc.getPageRow(sc.page)){
413                                                        //need to load additional data, let scroller do that
414                                                        this.grid.setScrollTop(this.grid.scrollTop-sc.findScrollTop(r)-sc.findScrollTop(row));
415                                                }
416                                        }
417                                }
418                                var cc = this.grid.layout.cellCount-1,
419                                i = this.cell.index,
420                                col = Math.min(cc, Math.max(0, i+inColDelta));
421                                var cell = this.grid.getCell(col);
422                                while(col>=0 && col < cc && cell && cell.hidden === true){
423                                        // skip hidden cells
424                                        col += colDir;
425                                        cell = this.grid.getCell(col);
426                                }
427                                if (!cell || cell.hidden === true){
428                                        // don't change col if would move to hidden
429                                        col = i;
430                                }
431                                //skip hidden row|cell
432                                var n = cell.getNode(row);
433                                if(!n && inRowDelta){
434                                        if((row + inRowDelta) >= 0 && (row + inRowDelta) <= rc){
435                                                this.move(inRowDelta > 0 ? ++inRowDelta : --inRowDelta, inColDelta);
436                                        }
437                                        return;
438                                }else if((!n || html.style(n, "display") === "none") && inColDelta){
439                                        if((col + inColDelta) >= 0 && (col + inColDelta) <= cc){
440                                                this.move(inRowDelta, inColDelta > 0 ? ++inColDelta : --inColDelta);
441                                        }
442                                        return;
443                                }
444                                this.setFocusIndex(row, col);
445                                if(inRowDelta){
446                                        this.grid.updateRow(r);
447                                }
448                        }
449                }
450        },
451        previousKey: function(e){
452                if(this.grid.edit.isEditing()){
453                        event.stop(e);
454                        this.previous();
455                }else if(!this.isNavHeader() && !this._isHeaderHidden()) {
456                        this.grid.domNode.focus(); // will call doFocus and set focus into header.
457                        event.stop(e);
458                }else{
459                        this.tabOut(this.grid.domNode);
460                        if (this._colHeadFocusIdx != null) { // clear grid header focus
461                                html.toggleClass(this._findHeaderCells()[this._colHeadFocusIdx], this.focusClass, false);
462                                this._colHeadFocusIdx = null;
463                        }
464                        this._focusifyCellNode(false);
465                }
466        },
467        nextKey: function(e) {
468                var isEmpty = (this.grid.rowCount === 0);
469                if(e.target === this.grid.domNode && this._colHeadFocusIdx == null){
470                        this.focusHeader();
471                        event.stop(e);
472                }else if(this.isNavHeader()){
473                        // if tabbing from col header, then go to grid proper.
474                        this.blurHeader();
475                        if(!this.findAndFocusGridCell()){
476                                this.tabOut(this.grid.lastFocusNode);
477                        }
478                        this._colHeadNode = this._colHeadFocusIdx= null;
479                }else if(this.grid.edit.isEditing()){
480                        event.stop(e);
481                        this.next();
482                }else{
483                        this.tabOut(this.grid.lastFocusNode);
484                }
485        },
486        tabOut: function(inFocusNode){
487                this.tabbingOut = true;
488                inFocusNode.focus();
489        },
490        focusGridView: function(){
491                util.fire(this.focusView, "focus");
492        },
493        focusGrid: function(inSkipFocusCell){
494                this.focusGridView();
495                this._focusifyCellNode(true);
496        },
497        findAndFocusGridCell: function(){
498                // summary:
499                //              find the first focusable grid cell
500                // returns: Boolean
501                //              true if focus was set to a cell
502                //              false if no cell found to set focus onto
503               
504                var didFocus = true;
505                var isEmpty = (this.grid.rowCount === 0); // If grid is empty this.grid.rowCount == 0
506                if (this.isNoFocusCell() && !isEmpty){
507                        var cellIdx = 0;
508                        var cell = this.grid.getCell(cellIdx);
509                        if (cell.hidden) {
510                                // if first cell isn't visible, use _colHeadFocusIdx
511                                // could also use a while loop to find first visible cell - not sure that is worth it
512                                cellIdx = this.isNavHeader() ? this._colHeadFocusIdx : 0;
513                        }
514                        this.setFocusIndex(0, cellIdx);
515                }
516                else if (this.cell && !isEmpty){
517                        if (this.focusView && !this.focusView.rowNodes[this.rowIndex]){
518                                // if rowNode for current index is undefined (likely as a result of a sort and because of #7304)
519                                // scroll to that row
520                                this.grid.scrollToRow(this.rowIndex);
521                        }
522                        this.focusGrid();
523                }else {
524                        didFocus = false;
525                }
526                this._colHeadNode = this._colHeadFocusIdx= null;
527                return didFocus;
528        },
529        focusHeader: function(){
530                var headerNodes = this._findHeaderCells();
531                var saveColHeadFocusIdx = this._colHeadFocusIdx;
532                if (this._isHeaderHidden()){
533                        // grid header is hidden, focus a cell
534                        this.findAndFocusGridCell();
535                }
536                else if (!this._colHeadFocusIdx) {
537                        if (this.isNoFocusCell()) {
538                                this._colHeadFocusIdx = 0;
539                        }
540                        else {
541                                this._colHeadFocusIdx = this.cell.index;
542                        }
543                }
544                this._colHeadNode = headerNodes[this._colHeadFocusIdx];
545                while(this._colHeadNode && this._colHeadFocusIdx >=0 && this._colHeadFocusIdx < headerNodes.length &&
546                                this._colHeadNode.style.display == "none"){
547                        // skip over hidden column headers
548                        this._colHeadFocusIdx++;
549                        this._colHeadNode = headerNodes[this._colHeadFocusIdx];
550                }
551                if(this._colHeadNode && this._colHeadNode.style.display != "none"){
552                        // Column header cells know longer receive actual focus.  So, for keyboard invocation of
553                        // contextMenu to work, the contextMenu must be bound to the grid.domNode rather than the viewsHeaderNode.
554                        // unbind the contextmenu from the viewsHeaderNode and to the grid when header cells are active.  Reset
555                        // the binding back to the viewsHeaderNode when header cells are no longer acive (in blurHeader) #10483
556                        if (this.headerMenu && this._contextMenuBindNode != this.grid.domNode){
557                                this.headerMenu.unBindDomNode(this.grid.viewsHeaderNode);
558                                this.headerMenu.bindDomNode(this.grid.domNode);
559                                this._contextMenuBindNode = this.grid.domNode;
560                        }
561                        this._setActiveColHeader(this._colHeadNode, this._colHeadFocusIdx, saveColHeadFocusIdx);
562                        this._scrollHeader(this._colHeadFocusIdx);
563                        this._focusifyCellNode(false);
564                }else {
565                        // all col head nodes are hidden - focus the grid
566                        this.findAndFocusGridCell();
567                }
568        },
569        blurHeader: function(){
570                html.removeClass(this._colHeadNode, this.focusClass);
571                html.removeAttr(this.grid.domNode,"aria-activedescendant");
572                // reset contextMenu onto viewsHeaderNode so right mouse on header will invoke (see focusHeader)
573                if (this.headerMenu && this._contextMenuBindNode == this.grid.domNode) {
574                        var viewsHeader = this.grid.viewsHeaderNode;
575                        this.headerMenu.unBindDomNode(this.grid.domNode);
576                        this.headerMenu.bindDomNode(viewsHeader);
577                        this._contextMenuBindNode = viewsHeader;
578                }
579        },
580        doFocus: function(e){
581                // trap focus only for grid dom node
582                if(e && e.target != e.currentTarget){
583                        event.stop(e);
584                        return;
585                }
586                // don't change focus if clicking on scroller bar
587                if(this._clickFocus){
588                        return;
589                }
590                // do not focus for scrolling if grid is about to blur
591                if(!this.tabbingOut){
592                        this.focusHeader();
593                }
594                this.tabbingOut = false;
595                event.stop(e);
596        },
597        doBlur: function(e){
598                event.stop(e);  // FF2
599        },
600        doContextMenu: function(e){
601        //stop contextMenu event if no header Menu to prevent default/browser contextMenu
602                if (!this.headerMenu){
603                        event.stop(e);
604                }
605        },
606        doLastNodeFocus: function(e){
607                if (this.tabbingOut){
608                        this._focusifyCellNode(false);
609                }else if(this.grid.rowCount >0){
610                        if (this.isNoFocusCell()){
611                                this.setFocusIndex(0,0);
612                        }
613                        this._focusifyCellNode(true);
614                }else {
615                        this.focusHeader();
616                }
617                this.tabbingOut = false;
618                event.stop(e);   // FF2
619        },
620        doLastNodeBlur: function(e){
621                event.stop(e);   // FF2
622        },
623        doColHeaderFocus: function(e){
624                this._setActiveColHeader(e.target,html.attr(e.target, "idx"),this._colHeadFocusIdx);
625                this._scrollHeader(this.getHeaderIndex());
626                event.stop(e);
627        },
628        doColHeaderBlur: function(e){
629                html.toggleClass(e.target, this.focusClass, false);
630        },
631        _mouseDown: function(e){
632                // a flag indicating grid is being focused by clicking
633                this._clickFocus = dojo.some(this.grid.views.views, function(v){
634                        return v.scrollboxNode === e.target;
635                });
636        },
637        _mouseUp: function(e){
638                this._clickFocus = false;
639        }
640});
641});
Note: See TracBrowser for help on using the repository browser.