~clinton-collins/familyproject/trunk

« back to all changes in this revision

Viewing changes to ZendFramework/externals/dojo/dojox/grid/_Builder.js

  • Committer: Clinton Collins
  • Date: 2009-06-26 19:54:58 UTC
  • Revision ID: clinton.collins@gmail.com-20090626195458-5ebba0qcvo15xlpy
Initial Import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
dojo.provide("dojox.grid._Builder");
 
2
 
 
3
dojo.require("dojox.grid.util");
 
4
dojo.require("dojo.dnd.Moveable");
 
5
 
 
6
(function(){
 
7
        var dg = dojox.grid;
 
8
 
 
9
        var getTdIndex = function(td){
 
10
                return td.cellIndex >=0 ? td.cellIndex : dojo.indexOf(td.parentNode.cells, td);
 
11
        };
 
12
        
 
13
        var getTrIndex = function(tr){
 
14
                return tr.rowIndex >=0 ? tr.rowIndex : dojo.indexOf(tr.parentNode.childNodes, tr);
 
15
        };
 
16
        
 
17
        var getTr = function(rowOwner, index){
 
18
                return rowOwner && ((rowOwner.rows||0)[index] || rowOwner.childNodes[index]);
 
19
        };
 
20
 
 
21
        var findTable = function(node){
 
22
                for(var n=node; n && n.tagName!='TABLE'; n=n.parentNode);
 
23
                return n;
 
24
        };
 
25
        
 
26
        var ascendDom = function(inNode, inWhile){
 
27
                for(var n=inNode; n && inWhile(n); n=n.parentNode);
 
28
                return n;
 
29
        };
 
30
        
 
31
        var makeNotTagName = function(inTagName){
 
32
                var name = inTagName.toUpperCase();
 
33
                return function(node){ return node.tagName != name; };
 
34
        };
 
35
 
 
36
        var rowIndexTag = dojox.grid.util.rowIndexTag;
 
37
        var gridViewTag = dojox.grid.util.gridViewTag;
 
38
 
 
39
        // base class for generating markup for the views
 
40
        dg._Builder = dojo.extend(function(view){
 
41
                if(view){
 
42
                        this.view = view;
 
43
                        this.grid = view.grid;
 
44
                }
 
45
        },{
 
46
                view: null,
 
47
                // boilerplate HTML
 
48
                _table: '<table class="dojoxGridRowTable" border="0" cellspacing="0" cellpadding="0" role="'+(dojo.isFF<3 ? "wairole:" : "")+'presentation"',
 
49
 
 
50
                // Returns the table variable as an array - and with the view width, if specified
 
51
                getTableArray: function(){
 
52
                        var html = [this._table];
 
53
                        if(this.view.viewWidth){
 
54
                                html.push([' style="width:', this.view.viewWidth, ';"'].join(''));
 
55
                        }
 
56
                        html.push('>');
 
57
                        return html;
 
58
                },
 
59
                
 
60
                // generate starting tags for a cell
 
61
                generateCellMarkup: function(inCell, inMoreStyles, inMoreClasses, isHeader){
 
62
                        var result = [], html;
 
63
                        var waiPrefix = dojo.isFF<3 ? "wairole:" : "";
 
64
                        if(isHeader){
 
65
                                var sortInfo = inCell.index != inCell.grid.getSortIndex() ? "" : inCell.grid.sortInfo > 0 ? 'aria-sort="ascending"' : 'aria-sort="descending"';
 
66
                                html = ['<th tabIndex="-1" role="', waiPrefix, 'columnheader"', sortInfo];
 
67
                        }else{
 
68
                                html = ['<td tabIndex="-1" role="', waiPrefix, 'gridcell"'];
 
69
                        }
 
70
                        inCell.colSpan && html.push(' colspan="', inCell.colSpan, '"');
 
71
                        inCell.rowSpan && html.push(' rowspan="', inCell.rowSpan, '"');
 
72
                        html.push(' class="dojoxGridCell ');
 
73
                        inCell.classes && html.push(inCell.classes, ' ');
 
74
                        inMoreClasses && html.push(inMoreClasses, ' ');
 
75
                        // result[0] => td opener, style
 
76
                        result.push(html.join(''));
 
77
                        // SLOT: result[1] => td classes 
 
78
                        result.push('');
 
79
                        html = ['" idx="', inCell.index, '" style="'];
 
80
                        if(inMoreStyles && inMoreStyles[inMoreStyles.length-1] != ';'){
 
81
                                inMoreStyles += ';';
 
82
                        }
 
83
                        html.push(inCell.styles, inMoreStyles||'', inCell.hidden?'display:none;':'');
 
84
                        inCell.unitWidth && html.push('width:', inCell.unitWidth, ';');
 
85
                        // result[2] => markup
 
86
                        result.push(html.join(''));
 
87
                        // SLOT: result[3] => td style 
 
88
                        result.push('');
 
89
                        html = [ '"' ];
 
90
                        inCell.attrs && html.push(" ", inCell.attrs);
 
91
                        html.push('>');
 
92
                        // result[4] => td postfix
 
93
                        result.push(html.join(''));
 
94
                        // SLOT: result[5] => content
 
95
                        result.push('');
 
96
                        // result[6] => td closes
 
97
                        result.push(isHeader?'</th>':'</td>');
 
98
                        return result; // Array
 
99
                },
 
100
 
 
101
                // cell finding
 
102
                isCellNode: function(inNode){
 
103
                        return Boolean(inNode && inNode!=dojo.doc && dojo.attr(inNode, "idx"));
 
104
                },
 
105
                
 
106
                getCellNodeIndex: function(inCellNode){
 
107
                        return inCellNode ? Number(dojo.attr(inCellNode, "idx")) : -1;
 
108
                },
 
109
                
 
110
                getCellNode: function(inRowNode, inCellIndex){
 
111
                        for(var i=0, row; row=getTr(inRowNode.firstChild, i); i++){
 
112
                                for(var j=0, cell; cell=row.cells[j]; j++){
 
113
                                        if(this.getCellNodeIndex(cell) == inCellIndex){
 
114
                                                return cell;
 
115
                                        }
 
116
                                }
 
117
                        }
 
118
                },
 
119
                
 
120
                findCellTarget: function(inSourceNode, inTopNode){
 
121
                        var n = inSourceNode;
 
122
                        while(n && (!this.isCellNode(n) || (n.offsetParent && gridViewTag in n.offsetParent.parentNode && n.offsetParent.parentNode[gridViewTag] != this.view.id)) && (n!=inTopNode)){
 
123
                                n = n.parentNode;
 
124
                        }
 
125
                        return n!=inTopNode ? n : null 
 
126
                },
 
127
                
 
128
                // event decoration
 
129
                baseDecorateEvent: function(e){
 
130
                        e.dispatch = 'do' + e.type;
 
131
                        e.grid = this.grid;
 
132
                        e.sourceView = this.view;
 
133
                        e.cellNode = this.findCellTarget(e.target, e.rowNode);
 
134
                        e.cellIndex = this.getCellNodeIndex(e.cellNode);
 
135
                        e.cell = (e.cellIndex >= 0 ? this.grid.getCell(e.cellIndex) : null);
 
136
                },
 
137
                
 
138
                // event dispatch
 
139
                findTarget: function(inSource, inTag){
 
140
                        var n = inSource;
 
141
                        while(n && (n!=this.domNode) && (!(inTag in n) || (gridViewTag in n && n[gridViewTag] != this.view.id))){
 
142
                                n = n.parentNode;
 
143
                        }
 
144
                        return (n != this.domNode) ? n : null; 
 
145
                },
 
146
 
 
147
                findRowTarget: function(inSource){
 
148
                        return this.findTarget(inSource, rowIndexTag);
 
149
                },
 
150
 
 
151
                isIntraNodeEvent: function(e){
 
152
                        try{
 
153
                                return (e.cellNode && e.relatedTarget && dojo.isDescendant(e.relatedTarget, e.cellNode));
 
154
                        }catch(x){
 
155
                                // e.relatedTarget has permission problem in FF if it's an input: https://bugzilla.mozilla.org/show_bug.cgi?id=208427
 
156
                                return false;
 
157
                        }
 
158
                },
 
159
 
 
160
                isIntraRowEvent: function(e){
 
161
                        try{
 
162
                                var row = e.relatedTarget && this.findRowTarget(e.relatedTarget);
 
163
                                return !row && (e.rowIndex==-1) || row && (e.rowIndex==row.gridRowIndex);                       
 
164
                        }catch(x){
 
165
                                // e.relatedTarget on INPUT has permission problem in FF: https://bugzilla.mozilla.org/show_bug.cgi?id=208427
 
166
                                return false;
 
167
                        }
 
168
                },
 
169
 
 
170
                dispatchEvent: function(e){
 
171
                        if(e.dispatch in this){
 
172
                                return this[e.dispatch](e);
 
173
                        }
 
174
                },
 
175
 
 
176
                // dispatched event handlers
 
177
                domouseover: function(e){
 
178
                        if(e.cellNode && (e.cellNode!=this.lastOverCellNode)){
 
179
                                this.lastOverCellNode = e.cellNode;
 
180
                                this.grid.onMouseOver(e);
 
181
                        }
 
182
                        this.grid.onMouseOverRow(e);
 
183
                },
 
184
 
 
185
                domouseout: function(e){
 
186
                        if(e.cellNode && (e.cellNode==this.lastOverCellNode) && !this.isIntraNodeEvent(e, this.lastOverCellNode)){
 
187
                                this.lastOverCellNode = null;
 
188
                                this.grid.onMouseOut(e);
 
189
                                if(!this.isIntraRowEvent(e)){
 
190
                                        this.grid.onMouseOutRow(e);
 
191
                                }
 
192
                        }
 
193
                },
 
194
                
 
195
                domousedown: function(e){
 
196
                        if (e.cellNode)
 
197
                                this.grid.onMouseDown(e);
 
198
                        this.grid.onMouseDownRow(e)
 
199
                }
 
200
        });
 
201
 
 
202
        // Produces html for grid data content. Owned by grid and used internally 
 
203
        // for rendering data. Override to implement custom rendering.
 
204
        dg._ContentBuilder = dojo.extend(function(view){
 
205
                dg._Builder.call(this, view);
 
206
        },dg._Builder.prototype,{
 
207
                update: function(){
 
208
                        this.prepareHtml();
 
209
                },
 
210
 
 
211
                // cache html for rendering data rows
 
212
                prepareHtml: function(){
 
213
                        var defaultGet=this.grid.get, cells=this.view.structure.cells;
 
214
                        for(var j=0, row; (row=cells[j]); j++){
 
215
                                for(var i=0, cell; (cell=row[i]); i++){
 
216
                                        cell.get = cell.get || (cell.value == undefined) && defaultGet;
 
217
                                        cell.markup = this.generateCellMarkup(cell, cell.cellStyles, cell.cellClasses, false);
 
218
                                }
 
219
                        }
 
220
                },
 
221
 
 
222
                // time critical: generate html using cache and data source
 
223
                generateHtml: function(inDataIndex, inRowIndex){
 
224
                        var
 
225
                                html = this.getTableArray(),
 
226
                                v = this.view,
 
227
                                cells = v.structure.cells,
 
228
                                item = this.grid.getItem(inRowIndex);
 
229
 
 
230
                        dojox.grid.util.fire(this.view, "onBeforeRow", [inRowIndex, cells]);
 
231
                        for(var j=0, row; (row=cells[j]); j++){
 
232
                                if(row.hidden || row.header){
 
233
                                        continue;
 
234
                                }
 
235
                                html.push(!row.invisible ? '<tr>' : '<tr class="dojoxGridInvisible">');
 
236
                                for(var i=0, cell, m, cc, cs; (cell=row[i]); i++){
 
237
                                        m = cell.markup, cc = cell.customClasses = [], cs = cell.customStyles = [];
 
238
                                        // content (format can fill in cc and cs as side-effects)
 
239
                                        m[5] = cell.format(inRowIndex, item);
 
240
                                        // classes
 
241
                                        m[1] = cc.join(' ');
 
242
                                        // styles
 
243
                                        m[3] = cs.join(';');
 
244
                                        // in-place concat
 
245
                                        html.push.apply(html, m);
 
246
                                }
 
247
                                html.push('</tr>');
 
248
                        }
 
249
                        html.push('</table>');
 
250
                        return html.join(''); // String
 
251
                },
 
252
 
 
253
                decorateEvent: function(e){
 
254
                        e.rowNode = this.findRowTarget(e.target);
 
255
                        if(!e.rowNode){return false};
 
256
                        e.rowIndex = e.rowNode[rowIndexTag];
 
257
                        this.baseDecorateEvent(e);
 
258
                        e.cell = this.grid.getCell(e.cellIndex);
 
259
                        return true; // Boolean
 
260
                }
 
261
        });
 
262
 
 
263
        // Produces html for grid header content. Owned by grid and used internally 
 
264
        // for rendering data. Override to implement custom rendering.
 
265
        dg._HeaderBuilder = dojo.extend(function(view){
 
266
                this.moveable = null;
 
267
                dg._Builder.call(this, view);
 
268
        },dg._Builder.prototype,{
 
269
                _skipBogusClicks: false,
 
270
                overResizeWidth: 4,
 
271
                minColWidth: 1,
 
272
                
 
273
                update: function(){
 
274
                        if(this.tableMap){
 
275
                                this.tableMap.mapRows(this.view.structure.cells);
 
276
                        }else{
 
277
                                this.tableMap = new dg._TableMap(this.view.structure.cells);
 
278
                        }
 
279
                },
 
280
 
 
281
                generateHtml: function(inGetValue, inValue){
 
282
                        var html = this.getTableArray(), cells = this.view.structure.cells;
 
283
                        
 
284
                        dojox.grid.util.fire(this.view, "onBeforeRow", [-1, cells]);
 
285
                        for(var j=0, row; (row=cells[j]); j++){
 
286
                                if(row.hidden){
 
287
                                        continue;
 
288
                                }
 
289
                                html.push(!row.invisible ? '<tr>' : '<tr class="dojoxGridInvisible">');
 
290
                                for(var i=0, cell, markup; (cell=row[i]); i++){
 
291
                                        cell.customClasses = [];
 
292
                                        cell.customStyles = [];
 
293
                                        if(this.view.simpleStructure){
 
294
                                                if(cell.headerClasses){
 
295
                                                        if(cell.headerClasses.indexOf('dojoDndItem') == -1){
 
296
                                                                cell.headerClasses += ' dojoDndItem';
 
297
                                                        }
 
298
                                                }else{
 
299
                                                        cell.headerClasses = 'dojoDndItem';
 
300
                                                }
 
301
                                                if(cell.attrs){
 
302
                                                        if(cell.attrs.indexOf("dndType='gridColumn_") == -1){
 
303
                                                                cell.attrs += " dndType='gridColumn_" + this.grid.id + "'";
 
304
                                                        }
 
305
                                                }else{
 
306
                                                        cell.attrs = "dndType='gridColumn_" + this.grid.id + "'";
 
307
                                                }
 
308
                                        }
 
309
                                        markup = this.generateCellMarkup(cell, cell.headerStyles, cell.headerClasses, true);
 
310
                                        // content
 
311
                                        markup[5] = (inValue != undefined ? inValue : inGetValue(cell));
 
312
                                        // styles
 
313
                                        markup[3] = cell.customStyles.join(';');
 
314
                                        // classes
 
315
                                        markup[1] = cell.customClasses.join(' '); //(cell.customClasses ? ' ' + cell.customClasses : '');
 
316
                                        html.push(markup.join(''));
 
317
                                }
 
318
                                html.push('</tr>');
 
319
                        }
 
320
                        html.push('</table>');
 
321
                        return html.join('');
 
322
                },
 
323
 
 
324
                // event helpers
 
325
                getCellX: function(e){
 
326
                        var x = e.layerX;
 
327
                        if(dojo.isMoz){
 
328
                                var n = ascendDom(e.target, makeNotTagName("th"));
 
329
                                x -= (n && n.offsetLeft) || 0;
 
330
                                var t = e.sourceView.getScrollbarWidth();
 
331
                                if(!dojo._isBodyLtr() && e.sourceView.headerNode.scrollLeft < t)
 
332
                                        x -= t;
 
333
                                //x -= getProp(ascendDom(e.target, mkNotTagName("td")), "offsetLeft") || 0;
 
334
                        }
 
335
                        var n = ascendDom(e.target, function(){
 
336
                                if(!n || n == e.cellNode){
 
337
                                        return false;
 
338
                                }
 
339
                                // Mozilla 1.8 (FF 1.5) has a bug that makes offsetLeft = -parent border width
 
340
                                // when parent has border, overflow: hidden, and is positioned
 
341
                                // handle this problem here ... not a general solution!
 
342
                                x += (n.offsetLeft < 0 ? 0 : n.offsetLeft);
 
343
                                return true;
 
344
                        });
 
345
                        return x;
 
346
                },
 
347
 
 
348
                // event decoration
 
349
                decorateEvent: function(e){
 
350
                        this.baseDecorateEvent(e);
 
351
                        e.rowIndex = -1;
 
352
                        e.cellX = this.getCellX(e);
 
353
                        return true;
 
354
                },
 
355
 
 
356
                // event handlers
 
357
                // resizing
 
358
                prepareResize: function(e, mod){
 
359
                        do{
 
360
                                var i = getTdIndex(e.cellNode);
 
361
                                e.cellNode = (i ? e.cellNode.parentNode.cells[i+mod] : null);
 
362
                                e.cellIndex = (e.cellNode ? this.getCellNodeIndex(e.cellNode) : -1);
 
363
                        }while(e.cellNode && e.cellNode.style.display == "none");
 
364
                        return Boolean(e.cellNode);
 
365
                },
 
366
 
 
367
                canResize: function(e){
 
368
                        if(!e.cellNode || e.cellNode.colSpan > 1){
 
369
                                return false;
 
370
                        }
 
371
                        var cell = this.grid.getCell(e.cellIndex); 
 
372
                        return !cell.noresize && cell.canResize();
 
373
                },
 
374
 
 
375
                overLeftResizeArea: function(e){
 
376
                        //Bugfix for crazy IE problem (#8807).  IE returns position information for the icon and text arrow divs
 
377
                        //as if they were still on the left instead of returning the position they were 'float: right' to.
 
378
                        //So, the resize check ends up checking the wrong adjacent cell.  This checks to see if the hover was over 
 
379
                        //the image or text nodes, then just ignored them/treat them not in scale range.
 
380
                        if(dojo.isIE){
 
381
                                var tN = e.target;
 
382
                                if(dojo.hasClass(tN, "dojoxGridArrowButtonNode") || 
 
383
                                        dojo.hasClass(tN, "dojoxGridArrowButtonChar")){
 
384
                                        return false;
 
385
                                }
 
386
                        }
 
387
 
 
388
                        if(dojo._isBodyLtr()){
 
389
                                return (e.cellIndex>0) && (e.cellX < this.overResizeWidth) && this.prepareResize(e, -1);
 
390
                        }
 
391
                        var t = e.cellNode && (e.cellX < this.overResizeWidth);
 
392
                        return t;
 
393
                },
 
394
 
 
395
                overRightResizeArea: function(e){
 
396
                        //Bugfix for crazy IE problem (#8807).  IE returns position information for the icon and text arrow divs
 
397
                        //as if they were still on the left instead of returning the position they were 'float: right' to.
 
398
                        //So, the resize check ends up checking the wrong adjacent cell.  This checks to see if the hover was over 
 
399
                        //the image or text nodes, then just ignored them/treat them not in scale range.
 
400
                        if(dojo.isIE){
 
401
                                var tN = e.target;
 
402
                                if(dojo.hasClass(tN, "dojoxGridArrowButtonNode") || 
 
403
                                        dojo.hasClass(tN, "dojoxGridArrowButtonChar")){
 
404
                                        return false;
 
405
                                }
 
406
                        }
 
407
 
 
408
                        if(dojo._isBodyLtr()){
 
409
                                return e.cellNode && (e.cellX >= e.cellNode.offsetWidth - this.overResizeWidth);
 
410
                        }
 
411
                        return (e.cellIndex>0) && (e.cellX >= e.cellNode.offsetWidth - this.overResizeWidth) && this.prepareResize(e, -1);
 
412
                },
 
413
 
 
414
                domousemove: function(e){
 
415
                        //console.log(e.cellIndex, e.cellX, e.cellNode.offsetWidth);
 
416
                        if(!this.moveable){
 
417
                                var c = (this.overRightResizeArea(e) ? 'e-resize' : (this.overLeftResizeArea(e) ? 'w-resize' : ''));
 
418
                                if(c && !this.canResize(e)){
 
419
                                        c = 'not-allowed';
 
420
                                }
 
421
                                if(dojo.isIE){
 
422
                                        var t = e.sourceView.headerNode.scrollLeft;
 
423
                                        e.sourceView.headerNode.style.cursor = c || ''; //'default';
 
424
                                        e.sourceView.headerNode.scrollLeft = t;
 
425
                                }else{
 
426
                                        e.sourceView.headerNode.style.cursor = c || ''; //'default';
 
427
                                }
 
428
                                if(c){
 
429
                                        dojo.stopEvent(e);
 
430
                                }
 
431
                        }
 
432
                },
 
433
 
 
434
                domousedown: function(e){
 
435
                        if(!this.moveable){
 
436
                                if((this.overRightResizeArea(e) || this.overLeftResizeArea(e)) && this.canResize(e)){
 
437
                                        this.beginColumnResize(e);
 
438
                                }else{
 
439
                                        this.grid.onMouseDown(e);
 
440
                                        this.grid.onMouseOverRow(e);
 
441
                                }
 
442
                                //else{
 
443
                                //      this.beginMoveColumn(e);
 
444
                                //}
 
445
                        }
 
446
                },
 
447
 
 
448
                doclick: function(e) {
 
449
                        if(this._skipBogusClicks){
 
450
                                dojo.stopEvent(e);
 
451
                                return true;
 
452
                        }
 
453
                },
 
454
 
 
455
                // column resizing
 
456
                beginColumnResize: function(e){
 
457
                        this.moverDiv = document.createElement("div");
 
458
                        dojo.style(this.moverDiv,{position: "absolute", left:0}); // to make DnD work with dir=rtl
 
459
                        dojo.body().appendChild(this.moverDiv);
 
460
                        var m = this.moveable = new dojo.dnd.Moveable(this.moverDiv);
 
461
 
 
462
                        var spanners = [], nodes = this.tableMap.findOverlappingNodes(e.cellNode);
 
463
                        for(var i=0, cell; (cell=nodes[i]); i++){
 
464
                                spanners.push({ node: cell, index: this.getCellNodeIndex(cell), width: cell.offsetWidth });
 
465
                                //console.log("spanner: " + this.getCellNodeIndex(cell));
 
466
                        }
 
467
 
 
468
                        var view = e.sourceView;
 
469
                        var adj = dojo._isBodyLtr() ? 1 : -1;
 
470
                        var views = e.grid.views.views;
 
471
                        var followers = [];
 
472
                        for(var i=view.idx+adj, cView; (cView=views[i]); i=i+adj){
 
473
                                followers.push({ node: cView.headerNode, left: window.parseInt(cView.headerNode.style.left) });
 
474
                        }
 
475
                        var table = view.headerContentNode.firstChild;
 
476
                        var drag = {
 
477
                                scrollLeft: e.sourceView.headerNode.scrollLeft,
 
478
                                view: view,
 
479
                                node: e.cellNode,
 
480
                                index: e.cellIndex,
 
481
                                w: dojo.contentBox(e.cellNode).w,
 
482
                                vw: dojo.contentBox(view.headerNode).w,
 
483
                                table: table,
 
484
                                tw: dojo.contentBox(table).w,
 
485
                                spanners: spanners,
 
486
                                followers: followers
 
487
                        };
 
488
 
 
489
                        m.onMove = dojo.hitch(this, "doResizeColumn", drag);
 
490
 
 
491
                        dojo.connect(m, "onMoveStop", dojo.hitch(this, function(){
 
492
                                this.endResizeColumn(drag);
 
493
                                if(drag.node.releaseCapture){
 
494
                                        drag.node.releaseCapture();
 
495
                                }
 
496
                                this.moveable.destroy();
 
497
                                delete this.moveable;
 
498
                                this.moveable = null;
 
499
                        }));
 
500
 
 
501
                        view.convertColPctToFixed();
 
502
 
 
503
                        if(e.cellNode.setCapture){
 
504
                                e.cellNode.setCapture();
 
505
                        }
 
506
                        m.onMouseDown(e);
 
507
                },
 
508
 
 
509
                doResizeColumn: function(inDrag, mover, leftTop){
 
510
                        var isLtr = dojo._isBodyLtr();
 
511
                        var deltaX = isLtr ? leftTop.l : -leftTop.l;
 
512
                        var w = inDrag.w + deltaX;
 
513
                        var vw = inDrag.vw + deltaX;
 
514
                        var tw = inDrag.tw + deltaX;
 
515
                        if(w >= this.minColWidth){
 
516
                                for(var i=0, s, sw; (s=inDrag.spanners[i]); i++){
 
517
                                        sw = s.width + deltaX;
 
518
                                        s.node.style.width = sw + 'px';
 
519
                                        inDrag.view.setColWidth(s.index, sw);
 
520
                                        //console.log('setColWidth', '#' + s.index, sw + 'px');
 
521
                                }
 
522
                                for(var i=0, f, fl; (f=inDrag.followers[i]); i++){
 
523
                                        fl = f.left + deltaX;
 
524
                                        f.node.style.left = fl + 'px';
 
525
                                }
 
526
                                inDrag.node.style.width = w + 'px';
 
527
                                inDrag.view.setColWidth(inDrag.index, w);
 
528
                                inDrag.view.headerNode.style.width = vw + 'px';
 
529
                                inDrag.view.setColumnsWidth(tw);
 
530
                                if(!isLtr){
 
531
                                        inDrag.view.headerNode.scrollLeft = inDrag.scrollLeft + deltaX;
 
532
                                }
 
533
                        }
 
534
                        if(inDrag.view.flexCells && !inDrag.view.testFlexCells()){
 
535
                                var t = findTable(inDrag.node);
 
536
                                t && (t.style.width = '');
 
537
                        }
 
538
                },
 
539
 
 
540
                endResizeColumn: function(inDrag){
 
541
                        dojo.destroy(this.moverDiv);
 
542
                        delete this.moverDiv;
 
543
                        this._skipBogusClicks = true;
 
544
                        var conn = dojo.connect(inDrag.view, "update", this, function(){
 
545
                                dojo.disconnect(conn);
 
546
                                this._skipBogusClicks = false;
 
547
                        });
 
548
                        setTimeout(dojo.hitch(inDrag.view, "update"), 50);
 
549
                }
 
550
        });
 
551
 
 
552
        // Maps an html table into a structure parsable for information about cell row and col spanning.
 
553
        // Used by HeaderBuilder.
 
554
        dg._TableMap = dojo.extend(function(rows){
 
555
                this.mapRows(rows);
 
556
        },{
 
557
                map: null,
 
558
 
 
559
                mapRows: function(inRows){
 
560
                        // summary: Map table topography
 
561
 
 
562
                        //console.log('mapRows');
 
563
                        // # of rows
 
564
                        var rowCount = inRows.length;
 
565
                        if(!rowCount){
 
566
                                return;
 
567
                        }
 
568
                        // map which columns and rows fill which cells
 
569
                        this.map = [];
 
570
                        for(var j=0, row; (row=inRows[j]); j++){
 
571
                                this.map[j] = [];
 
572
                        }
 
573
                        for(var j=0, row; (row=inRows[j]); j++){
 
574
                                for(var i=0, x=0, cell, colSpan, rowSpan; (cell=row[i]); i++){
 
575
                                        while (this.map[j][x]){x++};
 
576
                                        this.map[j][x] = { c: i, r: j };
 
577
                                        rowSpan = cell.rowSpan || 1;
 
578
                                        colSpan = cell.colSpan || 1;
 
579
                                        for(var y=0; y<rowSpan; y++){
 
580
                                                for(var s=0; s<colSpan; s++){
 
581
                                                        this.map[j+y][x+s] = this.map[j][x];
 
582
                                                }
 
583
                                        }
 
584
                                        x += colSpan;
 
585
                                }
 
586
                        }
 
587
                        //this.dumMap();
 
588
                },
 
589
 
 
590
                dumpMap: function(){
 
591
                        for(var j=0, row, h=''; (row=this.map[j]); j++,h=''){
 
592
                                for(var i=0, cell; (cell=row[i]); i++){
 
593
                                        h += cell.r + ',' + cell.c + '   ';
 
594
                                }
 
595
                                //console.log(h);
 
596
                        }
 
597
                },
 
598
 
 
599
                getMapCoords: function(inRow, inCol){
 
600
                        // summary: Find node's map coords by it's structure coords
 
601
                        for(var j=0, row; (row=this.map[j]); j++){
 
602
                                for(var i=0, cell; (cell=row[i]); i++){
 
603
                                        if(cell.c==inCol && cell.r == inRow){
 
604
                                                return { j: j, i: i };
 
605
                                        }
 
606
                                        //else{console.log(inRow, inCol, ' : ', i, j, " : ", cell.r, cell.c); };
 
607
                                }
 
608
                        }
 
609
                        return { j: -1, i: -1 };
 
610
                },
 
611
                
 
612
                getNode: function(inTable, inRow, inCol){
 
613
                        // summary: Find a node in inNode's table with the given structure coords
 
614
                        var row = inTable && inTable.rows[inRow];
 
615
                        return row && row.cells[inCol];
 
616
                },
 
617
                
 
618
                _findOverlappingNodes: function(inTable, inRow, inCol){
 
619
                        var nodes = [];
 
620
                        var m = this.getMapCoords(inRow, inCol);
 
621
                        //console.log("node j: %d, i: %d", m.j, m.i);
 
622
                        var row = this.map[m.j];
 
623
                        for(var j=0, row; (row=this.map[j]); j++){
 
624
                                if(j == m.j){ continue; }
 
625
                                var rw = row[m.i];
 
626
                                //console.log("overlaps: r: %d, c: %d", rw.r, rw.c);
 
627
                                var n = (rw?this.getNode(inTable, rw.r, rw.c):null);
 
628
                                if(n){ nodes.push(n); }
 
629
                        }
 
630
                        //console.log(nodes);
 
631
                        return nodes;
 
632
                },
 
633
                
 
634
                findOverlappingNodes: function(inNode){
 
635
                        return this._findOverlappingNodes(findTable(inNode), getTrIndex(inNode.parentNode), getTdIndex(inNode));
 
636
                }
 
637
        });
 
638
})();