source: Dev/trunk/src/client/dojox/layout/GridContainer.js @ 536

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

Added Dojo 1.9.3 release.

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