source: Dev/branches/rest-dojo-ui/client/dojox/layout/GridContainer.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

File size: 18.0 KB
Line 
1define([
2        "dojo/_base/kernel",
3        "dojo/_base/array",
4        "dojo/_base/connect",
5        "dojo/_base/declare",
6        "dojo/_base/html",
7        "dojo/_base/lang",
8        "dojo/_base/window",
9        "dojo/ready",   // dojo.ready
10        "dojox/layout/GridContainerLite"
11],function(dojo){
12        return dojo.declare(
13                "dojox.layout.GridContainer",
14                dojox.layout.GridContainerLite,
15        {
16                // summary:
17                //              A grid containing any kind of objects and acting like web portals.
18                //
19                // description:
20                //              This component inherits of all features of gridContainerLite plus :
21                //                      - Resize colums
22                //                      - Add / remove columns
23                //                      - Fix columns at left or at right.
24                // example:
25                //      |       <div dojoType="dojox.layout.GridContainer" nbZones="3" isAutoOrganized="true">
26                //      |               <div dojoType="dijit.layout.ContentPane">Content Pane 1 : Drag Me !</div>
27                //      |               <div dojoType="dijit.layout.ContentPane">Content Pane 2 : Drag Me !</div>
28                //      |               <div dojoType="dijit.layout.ContentPane">Content Pane 3 : Drag Me !</div>
29                //      |       </div>
30                //
31                // example:
32                //      |       dojo.ready(function(){
33                //      |               var cpane1 = new dijit.layout.ContentPane({ title:"cpane1", content: "Content Pane 1 : Drag Me !" }),
34                //      |                       cpane2 = new dijit.layout.ContentPane({ title:"cpane2", content: "Content Pane 2 : Drag Me !" }),
35                //      |                       cpane3 = new dijit.layout.ContentPane({ title:"cpane3", content: "Content Pane 3 : Drag Me !" });
36                //      |
37                //      |               var widget = new dojox.layout.GridContainer({
38                //      |                       nbZones: 3,
39                //      |                       isAutoOrganized: true
40                //      |               }, dojo.byId("idNode"));
41                //      |               widget.addChild(cpane1, 0, 0);
42                //      |               widget.addChild(cpane2, 1, 0);
43                //      |               widget.addChild(cpane3, 2, 1);
44                //      |               widget.startup();
45                //      |       });
46
47                // hasResizableColumns: Boolean
48                //              Allow or not resizing of columns by a grip handle.
49                hasResizableColumns: true,
50
51                // liveResizeColumns: Boolean
52                //              Specifies whether columns resize as you drag (true) or only upon mouseup (false)
53                liveResizeColumns : false,
54
55                // minColWidth: Integer
56                //              Minimum column width in percentage.
57                minColWidth: 20,
58
59                // minChildWidth: Integer
60                //              Minimum children width in pixel (only used for IE6 which doesn't handle min-width css property)
61                minChildWidth: 150,
62
63                // mode: String
64                //              Location to add/remove columns, must be set to 'left' or 'right' (default).
65                mode: "right",
66
67                // isRightFixed: Boolean
68                //              Define if the last right column is fixed.
69                //              Used when you add or remove columns by calling setColumns method.
70                isRightFixed: false,
71
72                // isLeftFixed: Boolean
73                //              Define if the last left column is fixed.
74                //              Used when you add or remove columns by calling setColumns method.
75                isLeftFixed: false,
76
77                startup: function(){
78                        // summary:
79                        //              Call the startup of GridContainerLite and place grips
80                        //              if user has chosen the hasResizableColumns attribute to true.
81
82                        //console.log("dojox.layout.GridContainer ::: startup");
83                        this.inherited(arguments);
84                        if(this.hasResizableColumns){
85                                for(var i = 0; i < this._grid.length - 1; i++){
86                                        this._createGrip(i);
87                                }
88                                // If widget has a container parent, grips will be placed
89                                // by method onShow.
90                                if(!this.getParent()){
91                                        // Fix IE7 :
92                                        //              The CSS property height:100% for the grip
93                                        //              doesn't work anytime. It's necessary to wait
94                                        //              the end of loading before to place grips.
95                                        dojo.ready(dojo.hitch(this, "_placeGrips"));
96                                }
97                        }
98                },
99
100                resizeChildAfterDrop : function(/*Node*/node, /*Object*/targetArea, /*Integer*/indexChild){
101                        // summary:
102                        //              Call when a child is dropped.
103                        // description:
104                        //              Allow to resize and put grips
105                        // node:
106                        //              domNode of dropped widget.
107                        // targetArea:
108                        //              AreaManager Object containing information of targetArea
109                        // indexChild:
110                        //              Index where the dropped widget has been placed
111
112                        if(this.inherited(arguments)){
113                                this._placeGrips();
114                        }
115                },
116
117                onShow: function(){
118                        // summary:
119                        //              Place grips in the right place when the GridContainer becomes visible.
120
121                        //console.log("dojox.layout.GridContainer ::: onShow");
122                        this.inherited(arguments);
123                        this._placeGrips();
124                },
125
126                resize: function(){
127                        // summary:
128                        //              Resize the GridContainer widget and columns.
129                        //              Replace grips if it's necessary.
130                        // tags:
131                        //              callback
132
133                        //console.log("dojox.layout.GridContainer ::: resize");
134                        this.inherited(arguments);
135                        // Fix IE6 :
136                        //              IE6 calls method resize itself.
137                        //              If the GridContainer is not visible at this time,
138                        //              the method _placeGrips can return a negative value with
139                        //              contentBox method. (see method _placeGrip() with Fix Ie6 for the height)
140                        if(this._isShown() && this.hasResizableColumns){
141                                this._placeGrips();
142                        }
143                },
144
145                _createGrip: function(/*Integer*/ index){
146                        // summary:
147                        //              Create a grip for a specific zone.
148                        // index:
149                        //              index where the grip has to be created.
150                        // tags:
151                        //              protected
152
153                        //console.log("dojox.layout.GridContainer ::: _createGrip");
154                        var dropZone = this._grid[index],
155                                grip = dojo.create("div", { 'class': "gridContainerGrip" }, this.domNode);
156                        dropZone.grip = grip;
157                        dropZone.gripHandler = [
158                                this.connect(grip, "onmouseover", function(e){
159                                        var gridContainerGripShow = false;
160                                        for(var i = 0; i < this._grid.length - 1; i++){
161                                                if(dojo.hasClass(this._grid[i].grip, "gridContainerGripShow")){
162                                                        gridContainerGripShow = true;
163                                                        break;
164                                                }
165                                        }
166                                        if(!gridContainerGripShow){
167                                                dojo.removeClass(e.target, "gridContainerGrip");
168                                                dojo.addClass(e.target, "gridContainerGripShow");
169                                        }
170                                })[0],
171                                this.connect(grip, "onmouseout", function(e){
172                                        if(!this._isResized){
173                                                dojo.removeClass(e.target, "gridContainerGripShow");
174                                                dojo.addClass(e.target, "gridContainerGrip");
175                                        }
176                                })[0],
177                                this.connect(grip, "onmousedown", "_resizeColumnOn")[0],
178                                this.connect(grip, "ondblclick", "_onGripDbClick")[0]
179                        ];
180                },
181
182                _placeGrips: function(){
183                        // summary:
184                        //              Define the position of a grip and place it on page.
185                        // tags:
186                        //              protected
187
188                        //console.log("dojox.layout.GridContainer ::: _placeGrips");
189                        var gripWidth, height, left = 0, grip;
190                        var scroll = this.domNode.style.overflowY;
191
192                        dojo.forEach(this._grid, function(dropZone){
193                                if(dropZone.grip){
194                                        grip = dropZone.grip;
195                                        if(!gripWidth){
196                                                gripWidth = grip.offsetWidth / 2;
197                                        }
198
199                                        left += dojo.marginBox(dropZone.node).w;
200
201                                        dojo.style(grip, "left", (left - gripWidth) + "px");
202                                        //if(dojo.isIE == 6){ do it fot all navigators
203                                        if(!height){
204                                                height = dojo.contentBox(this.gridNode).h;
205                                        }
206                                        if(height > 0){
207                                                dojo.style(grip, "height", height + "px");
208                                        }
209                                        //}
210                                }
211                        }, this);
212                },
213
214                _onGripDbClick: function(){
215                        // summary:
216                        //              Called when a double click is catch. Resize all columns with the same width.
217                        //              The method resize of children have to be called.
218                        // tags:
219                        //              callback protected
220
221                        //console.log("dojox.layout.GridContainer ::: _onGripDbClick");
222                        this._updateColumnsWidth(this._dragManager);
223                        this.resize();
224                },
225
226                _resizeColumnOn: function(/*Event*/e){
227                        // summary:
228                        //              Connect events to listen the resize action.
229                        //              Change the type of width columns (% to px).
230                        //              Calculate the minwidth according to the children.
231                        // tags:
232                        //              callback
233
234                        //console.log("dojox.layout.GridContainer ::: _resizeColumnOn", e);
235                        this._activeGrip = e.target;
236                        this._initX = e.pageX;
237                        e.preventDefault();
238
239                        dojo.body().style.cursor = "ew-resize";
240
241                        this._isResized = true;
242
243                        var tabSize = [];
244                        var grid;
245                        var i;
246
247                        for(i = 0; i < this._grid.length; i++){
248                                tabSize[i] = dojo.contentBox(this._grid[i].node).w;
249                        }
250
251                        this._oldTabSize = tabSize;
252
253                        for(i = 0; i < this._grid.length; i++){
254                                grid = this._grid[i];
255                                if(this._activeGrip == grid.grip){
256                                        this._currentColumn = grid.node;
257                                        this._currentColumnWidth = tabSize[i];
258                                        this._nextColumn = this._grid[i + 1].node;
259                                        this._nextColumnWidth = tabSize[i + 1];
260                                }
261                                grid.node.style.width = tabSize[i] + "px";
262                        }
263
264                        // calculate the minWidh of all children for current and next column
265                        var calculateChildMinWidth = function(childNodes, minChild){
266                                var width = 0;
267                                var childMinWidth = 0;
268
269                                dojo.forEach(childNodes, function(child){
270                                        if(child.nodeType == 1){
271                                                var objectStyle = dojo.getComputedStyle(child);
272                                                var minWidth = (dojo.isIE) ? minChild : parseInt(objectStyle.minWidth);
273
274                                                childMinWidth = minWidth +
275                                                                        parseInt(objectStyle.marginLeft) +
276                                                                        parseInt(objectStyle.marginRight);
277
278                                                if(width < childMinWidth){
279                                                        width = childMinWidth;
280                                                }
281                                        }
282                                });
283                                return width;
284                        }
285                        var currentColumnMinWidth = calculateChildMinWidth(this._currentColumn.childNodes, this.minChildWidth);
286
287                        var nextColumnMinWidth = calculateChildMinWidth(this._nextColumn.childNodes, this.minChildWidth);
288
289                        var minPix = Math.round((dojo.marginBox(this.gridContainerTable).w * this.minColWidth) / 100);
290
291                        this._currentMinCol = currentColumnMinWidth;
292                        this._nextMinCol = nextColumnMinWidth;
293
294                        if(minPix > this._currentMinCol){
295                                this._currentMinCol = minPix;
296                        }
297                        if(minPix > this._nextMinCol){
298                                this._nextMinCol = minPix;
299                        }
300                        this._connectResizeColumnMove = dojo.connect(dojo.doc, "onmousemove", this, "_resizeColumnMove");
301                        this._connectOnGripMouseUp = dojo.connect(dojo.doc, "onmouseup", this, "_onGripMouseUp");
302                },
303
304                _onGripMouseUp: function(){
305                        // summary:
306                        //              Call on the onMouseUp only if the reiszeColumnMove was not called.
307                        // tags:
308                        //              callback
309
310                        //console.log(dojox.layout.GridContainer ::: _onGripMouseUp");
311                        dojo.body().style.cursor = "default";
312
313                        dojo.disconnect(this._connectResizeColumnMove);
314                        dojo.disconnect(this._connectOnGripMouseUp);
315
316                        this._connectOnGripMouseUp = this._connectResizeColumnMove = null;
317
318                        if(this._activeGrip){
319                                dojo.removeClass(this._activeGrip, "gridContainerGripShow");
320                                dojo.addClass(this._activeGrip, "gridContainerGrip");
321                        }
322
323                        this._isResized = false;
324                },
325
326                _resizeColumnMove: function(/*Event*/e){
327                        // summary:
328                        //              Change columns size.
329                        // tags:
330                        //              callback
331
332                        //console.log("dojox.layout.GridContainer ::: _resizeColumnMove");
333                        e.preventDefault();
334                        if(!this._connectResizeColumnOff){
335                                dojo.disconnect(this._connectOnGripMouseUp);
336                                this._connectOnGripMouseUp = null;
337                                this._connectResizeColumnOff = dojo.connect(dojo.doc, "onmouseup", this, "_resizeColumnOff");
338                        }
339
340                        var d = e.pageX - this._initX;
341                        if(d == 0){ return; }
342
343                        if(!(this._currentColumnWidth + d < this._currentMinCol ||
344                                        this._nextColumnWidth - d < this._nextMinCol)){
345
346                                this._currentColumnWidth += d;
347                                this._nextColumnWidth -= d;
348                                this._initX = e.pageX;
349                                this._activeGrip.style.left = parseInt(this._activeGrip.style.left) + d + "px";
350
351                                if(this.liveResizeColumns){
352                                        this._currentColumn.style["width"] = this._currentColumnWidth + "px";
353                                        this._nextColumn.style["width"] = this._nextColumnWidth + "px";
354                                        this.resize();
355                                }
356                        }
357                },
358
359                _resizeColumnOff: function(/*Event*/e){
360                        // summary:
361                        //              Disconnect resize events.
362                        //              Change the type of width columns (px to %).
363                        // tags:
364                        //              callback
365
366                        //console.log("dojox.layout.GridContainer ::: _resizeColumnOff");
367                        dojo.body().style.cursor = "default";
368
369                        dojo.disconnect(this._connectResizeColumnMove);
370                        dojo.disconnect(this._connectResizeColumnOff);
371
372                        this._connectResizeColumnOff = this._connectResizeColumnMove = null;
373
374                        if(!this.liveResizeColumns){
375                                this._currentColumn.style["width"] = this._currentColumnWidth + "px";
376                                this._nextColumn.style["width"] = this._nextColumnWidth + "px";
377                                //this.resize();
378                        }
379
380                        var tabSize = [],
381                                testSize = [],
382                                tabWidth = this.gridContainerTable.clientWidth,
383                                node,
384                                update = false,
385                                i;
386
387                        for(i = 0; i < this._grid.length; i++){
388                                node = this._grid[i].node;
389                                if(dojo.isIE){
390                                        tabSize[i] = dojo.marginBox(node).w;
391                                        testSize[i] = dojo.contentBox(node).w;
392                                }
393                                else{
394                                        tabSize[i] = dojo.contentBox(node).w;
395                                        testSize = tabSize;
396                                }
397                        }
398
399                        for(i = 0; i < testSize.length; i++){
400                                if(testSize[i] != this._oldTabSize[i]){
401                                        update = true;
402                                        break;
403                                }
404                        }
405
406                        if(update){
407                                var mul = dojo.isIE ? 100 : 10000;
408                                for(i = 0; i < this._grid.length; i++){
409                                        this._grid[i].node.style.width = Math.round((100 * mul * tabSize[i]) / tabWidth) / mul + "%";
410                                }
411                                this.resize();
412                        }
413
414                        if(this._activeGrip){
415                                dojo.removeClass(this._activeGrip, "gridContainerGripShow");
416                                dojo.addClass(this._activeGrip, "gridContainerGrip");
417                        }
418
419                        this._isResized = false;
420                },
421
422                setColumns: function(/*Integer*/nbColumns){
423                        // summary:
424                        //              Set the number of columns.
425                        // nbColumns:
426                        //              Number of columns
427
428                        //console.log("dojox.layout.GridContainer ::: setColumns");
429                        var z, j;
430                        if(nbColumns > 0){
431                                var length = this._grid.length,
432                                        delta = length - nbColumns;
433                                if(delta > 0){
434                                        var count = [], zone, start, end, nbChildren;
435                                        // Check if right or left columns are fixed
436                                        // Columns are not taken in account and can't be deleted
437                                        if(this.mode == "right"){
438                                                end = (this.isLeftFixed && length > 0) ? 1 : 0;
439                                                start = (this.isRightFixed) ? length - 2 : length - 1
440                                                for(z = start; z >= end; z--){
441                                                        nbChildren = 0;
442                                                        zone = this._grid[z].node;
443                                                        for(j = 0; j < zone.childNodes.length; j++){
444                                                                if(zone.childNodes[j].nodeType == 1 && !(zone.childNodes[j].id == "")){
445                                                                        nbChildren++;
446                                                                        break;
447                                                                }
448                                                        }
449                                                        if(nbChildren == 0){ count[count.length] = z; }
450                                                        if(count.length >= delta){
451                                                                this._deleteColumn(count);
452                                                                break;
453                                                        }
454                                                }
455                                                if(count.length < delta){
456                                                        dojo.publish("/dojox/layout/gridContainer/noEmptyColumn", [this]);
457                                                }
458                                        }
459                                        else{ // mode = "left"
460                                                start = (this.isLeftFixed && length > 0) ? 1 : 0;
461                                                end = (this.isRightFixed) ? length - 1 : length;
462                                                for(z = start; z < end; z++){
463                                                        nbChildren = 0;
464                                                        zone = this._grid[z].node;
465                                                        for(j = 0; j < zone.childNodes.length; j++){
466                                                                if(zone.childNodes[j].nodeType == 1 && !(zone.childNodes[j].id == "")){
467                                                                        nbChildren++;
468                                                                        break;
469                                                                }
470                                                        }
471                                                        if(nbChildren == 0){ count[count.length] = z; }
472                                                        if(count.length >= delta){
473                                                                this._deleteColumn(count);
474                                                                break;
475                                                        }
476                                                }
477                                                if(count.length < delta){
478                                                        //Not enough empty columns
479                                                        dojo.publish("/dojox/layout/gridContainer/noEmptyColumn", [this]);
480                                                }
481                                        }
482                                }
483                                else{
484                                        if(delta < 0){ this._addColumn(Math.abs(delta)); }
485                                }
486                                if(this.hasResizableColumns){ this._placeGrips(); }
487                        }
488                },
489
490                _addColumn: function(/*Integer*/nbColumns){
491                        // summary:
492                        //              Add some columns.
493                        // nbColumns:
494                        //              Number of column to added
495                        // tags:
496                        //              private
497
498                        //console.log("dojox.layout.GridContainer ::: _addColumn");
499                        var grid = this._grid,
500                                dropZone,
501                                node,
502                                index,
503                                length,
504                                isRightMode = (this.mode == "right"),
505                                accept = this.acceptTypes.join(","),
506                                m = this._dragManager;
507
508                        //Add a grip to the last column
509                        if(this.hasResizableColumns && ((!this.isRightFixed && isRightMode)
510                                || (this.isLeftFixed && !isRightMode && this.nbZones == 1) )){
511                                this._createGrip(grid.length - 1);
512                        }
513
514                        for(var i = 0; i < nbColumns; i++){
515                                // Fix CODEX defect #53025 :
516                                //              Apply acceptType attribute on each new column.
517                                node = dojo.create("td", {
518                                        'class': "gridContainerZone dojoxDndArea" ,
519                                        'accept': accept,
520                                        'id': this.id + "_dz" + this.nbZones
521                                });
522
523                                length = grid.length;
524
525                                if(isRightMode){
526                                        if(this.isRightFixed){
527                                                index = length - 1;
528                                                grid.splice(index, 0, {
529                                                        'node': grid[index].node.parentNode.insertBefore(node, grid[index].node)
530                                                });
531                                        }
532                                        else{
533                                                index = length;
534                                                grid.push({ 'node': this.gridNode.appendChild(node) });
535                                        }
536                                }
537                                else{
538                                        if(this.isLeftFixed){
539                                                index = (length == 1) ? 0 : 1;
540                                                this._grid.splice(1, 0, {
541                                                        'node': this._grid[index].node.parentNode.appendChild(node, this._grid[index].node)
542                                                });
543                                                index = 1;
544                                        }
545                                        else{
546                                                index = length - this.nbZones;
547                                                this._grid.splice(index, 0, {
548                                                        'node': grid[index].node.parentNode.insertBefore(node, grid[index].node)
549                                                });
550                                        }
551                                }
552                                if(this.hasResizableColumns){
553                                        //Add a grip to resize columns
554                                        if((!isRightMode && this.nbZones != 1) ||
555                                                        (!isRightMode && this.nbZones == 1 && !this.isLeftFixed) ||
556                                                                (isRightMode && i < nbColumns-1) ||
557                                                                        (isRightMode && i == nbColumns-1 && this.isRightFixed)){
558                                                this._createGrip(index);
559                                        }
560                                }
561                                // register tnbZoneshe new area into the areaManager
562                                m.registerByNode(grid[index].node);
563                                this.nbZones++;
564                        }
565                        this._updateColumnsWidth(m);
566                },
567
568                _deleteColumn: function(/*Array*/indices){
569                        // summary:
570                        //              Remove some columns with indices passed as an array.
571                        // indices:
572                        //              Column index array
573                        // tags:
574                        //              private
575
576                        //console.log("dojox.layout.GridContainer ::: _deleteColumn");
577                        var child, grid, index,
578                                nbDelZones = 0,
579                                length = indices.length,
580                                m = this._dragManager;
581                        for(var i = 0; i < length; i++){
582                                index = (this.mode == "right") ? indices[i] : indices[i] - nbDelZones;
583                                grid = this._grid[index];
584
585                                if(this.hasResizableColumns && grid.grip){
586                                        dojo.forEach(grid.gripHandler, function(handler){
587                                                dojo.disconnect(handler);
588                                        });
589                                        dojo.destroy(this.domNode.removeChild(grid.grip));
590                                        grid.grip = null;
591                                }
592
593                                m.unregister(grid.node);
594                                dojo.destroy(this.gridNode.removeChild(grid.node));
595                                this._grid.splice(index, 1);
596                                this.nbZones--;
597                                nbDelZones++;
598                        }
599
600                        // last grip
601                        var lastGrid = this._grid[this.nbZones-1];
602                        if(lastGrid.grip){
603                                dojo.forEach(lastGrid.gripHandler, dojo.disconnect);
604                                dojo.destroy(this.domNode.removeChild(lastGrid.grip));
605                                lastGrid.grip = null;
606                        }
607
608                        this._updateColumnsWidth(m);
609                },
610
611                _updateColumnsWidth: function(/*Object*/ manager){
612                        // summary:
613                        //              Update the columns width.
614                        // manager:
615                        //              dojox.mdnd.AreaManager singleton
616                        // tags:
617                        //              private
618
619                        //console.log("dojox.layout.GridContainer ::: _updateColumnsWidth");
620                        this.inherited(arguments);
621                        manager._dropMode.updateAreas(manager._areaList);
622                },
623
624                destroy: function(){
625                        dojo.unsubscribe(this._dropHandler);
626                        this.inherited(arguments);
627                }
628        });
629});
Note: See TracBrowser for help on using the repository browser.