source: Dev/branches/rest-dojo-ui/client/dojox/grid/_ViewManager.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: 7.3 KB
Line 
1define([
2        "dojo/_base/declare",
3        "dojo/_base/sniff",
4        "dojo/dom-class"
5], function(declare, has, domClass){
6
7return declare('dojox.grid._ViewManager', null, {
8        // summary:
9        //              A collection of grid views. Owned by grid and used internally for managing grid views.
10        // description:
11        //              Grid creates views automatically based on grid's layout structure.
12        //              Users should typically not need to access individual views or the views collection directly.
13        constructor: function(inGrid){
14                this.grid = inGrid;
15        },
16
17        defaultWidth: 200,
18
19        views: [],
20
21        // operations
22        resize: function(){
23                this.onEach("resize");
24        },
25
26        render: function(){
27                this.onEach("render");
28        },
29
30        // views
31        addView: function(inView){
32                inView.idx = this.views.length;
33                this.views.push(inView);
34        },
35
36        destroyViews: function(){
37                for(var i=0, v; v=this.views[i]; i++){
38                        v.destroy();
39                }
40                this.views = [];
41        },
42
43        getContentNodes: function(){
44                var nodes = [];
45                for(var i=0, v; v=this.views[i]; i++){
46                        nodes.push(v.contentNode);
47                }
48                return nodes;
49        },
50
51        forEach: function(inCallback){
52                for(var i=0, v; v=this.views[i]; i++){
53                        inCallback(v, i);
54                }
55        },
56
57        onEach: function(inMethod, inArgs){
58                inArgs = inArgs || [];
59                for(var i=0, v; v=this.views[i]; i++){
60                        if(inMethod in v){
61                                v[inMethod].apply(v, inArgs);
62                        }
63                }
64        },
65
66        // layout
67        normalizeHeaderNodeHeight: function(){
68                var rowNodes = [];
69                for(var i=0, v; (v=this.views[i]); i++){
70                        if(v.headerContentNode.firstChild){
71                                rowNodes.push(v.headerContentNode);
72                        }
73                }
74                this.normalizeRowNodeHeights(rowNodes);
75        },
76
77        normalizeRowNodeHeights: function(inRowNodes){
78                var h = 0;
79                var currHeights = [];
80                if(this.grid.rowHeight){
81                        h = this.grid.rowHeight;
82                }else{
83                        if(inRowNodes.length <= 1){
84                                // no need to normalize if we are the only one...
85                                return;
86                        }
87                        for(var i=0, n; (n=inRowNodes[i]); i++){
88                                // We only care about the height - so don't use marginBox.  This
89                                // depends on the container not having any margin (which it shouldn't)
90                                // Also - we only look up the height if the cell doesn't have the
91                                // dojoxGridNonNormalizedCell class (like for row selectors)
92                                if(!domClass.contains(n, "dojoxGridNonNormalizedCell")){
93                                        currHeights[i] = n.firstChild.offsetHeight;
94                                        h =  Math.max(h, currHeights[i]);
95                                }
96                        }
97                        h = (h >= 0 ? h : 0);
98       
99                        //Work around odd FF3 rendering bug: #8864.
100                        //A one px increase fixes FireFox 3's rounding bug for fractional font sizes.
101                        if((has('mozilla') || has('ie') > 8 ) && h){h++;}
102                }
103                for(i=0; (n=inRowNodes[i]); i++){
104                        if(currHeights[i] != h){
105                                n.firstChild.style.height = h + "px";
106                        }
107                }
108        },
109       
110        resetHeaderNodeHeight: function(){
111                for(var i=0, v, n; (v=this.views[i]); i++){
112                        n = v.headerContentNode.firstChild;
113                        if(n){
114                                n.style.height = "";
115                        }
116                }
117        },
118
119        renormalizeRow: function(inRowIndex){
120                var rowNodes = [];
121                for(var i=0, v, n; (v=this.views[i])&&(n=v.getRowNode(inRowIndex)); i++){
122                        n.firstChild.style.height = '';
123                        rowNodes.push(n);
124                }
125                this.normalizeRowNodeHeights(rowNodes);
126        },
127
128        getViewWidth: function(inIndex){
129                return this.views[inIndex].getWidth() || this.defaultWidth;
130        },
131
132        // must be called after view widths are properly set or height can be miscalculated
133        // if there are flex columns
134        measureHeader: function(){
135                // need to reset view header heights so they are properly measured.
136                this.resetHeaderNodeHeight();
137                this.forEach(function(inView){
138                        inView.headerContentNode.style.height = '';
139                });
140                var h = 0;
141                // calculate maximum view header height
142                this.forEach(function(inView){
143                        h = Math.max(inView.headerNode.offsetHeight, h);
144                });
145                return h;
146        },
147
148        measureContent: function(){
149                var h = 0;
150                this.forEach(function(inView){
151                        h = Math.max(inView.domNode.offsetHeight, h);
152                });
153                return h;
154        },
155
156        findClient: function(inAutoWidth){
157                // try to use user defined client
158                var c = this.grid.elasticView || -1;
159                // attempt to find implicit client
160                if(c < 0){
161                        for(var i=1, v; (v=this.views[i]); i++){
162                                if(v.viewWidth){
163                                        for(i=1; (v=this.views[i]); i++){
164                                                if(!v.viewWidth){
165                                                        c = i;
166                                                        break;
167                                                }
168                                        }
169                                        break;
170                                }
171                        }
172                }
173                // client is in the middle by default
174                if(c < 0){
175                        c = Math.floor(this.views.length / 2);
176                }
177                return c;
178        },
179
180        arrange: function(l, w){
181                var i, v, vw, len = this.views.length, self = this;
182                // find the client
183                var c = (w <= 0 ? len : this.findClient());
184                // layout views
185                var setPosition = function(v, l){
186                        var ds = v.domNode.style;
187                        var hs = v.headerNode.style;
188
189                        if(!self.grid.isLeftToRight()){
190                                ds.right = l + 'px';
191                                // fixed rtl, the scrollbar is on the right side in FF or WebKit
192                                if (has('ff') < 4 || has('webkit')){
193                                        hs.right = l + v.getScrollbarWidth() + 'px';
194                                        hs.width = parseInt(hs.width, 10) - v.getScrollbarWidth() + 'px';
195                                }else{
196                                        hs.right = l + 'px';
197                                }
198                        }else{
199                                ds.left = l + 'px';
200                                hs.left = l + 'px';
201                        }
202                        ds.top = 0 + 'px';
203                        hs.top = 0;
204                };
205                // for views left of the client
206                //BiDi TODO: The left and right should not appear in BIDI environment. Should be replaced with
207                //leading and tailing concept.
208                for(i=0; (v=this.views[i])&&(i<c); i++){
209                        // get width
210                        vw = this.getViewWidth(i);
211                        // process boxes
212                        v.setSize(vw, 0);
213                        setPosition(v, l);
214                        if(v.headerContentNode && v.headerContentNode.firstChild){
215                                vw = v.getColumnsWidth()+v.getScrollbarWidth();
216                        }else{
217                                vw = v.domNode.offsetWidth;
218                        }
219                        // update position
220                        l += vw;
221                }
222                // next view (is the client, i++ == c)
223                i++;
224                // start from the right edge
225                var r = w;
226                // for views right of the client (iterated from the right)
227                for(var j=len-1; (v=this.views[j])&&(i<=j); j--){
228                        // get width
229                        vw = this.getViewWidth(j);
230                        // set size
231                        v.setSize(vw, 0);
232                        // measure in pixels
233                        vw = v.domNode.offsetWidth;
234                        // update position
235                        r -= vw;
236                        // set position
237                        setPosition(v, r);
238                }
239                if(c<len){
240                        v = this.views[c];
241                        // position the client box between left and right boxes
242                        vw = Math.max(1, r-l);
243                        // set size
244                        v.setSize(vw + 'px', 0);
245                        setPosition(v, l);
246                }
247                return l;
248        },
249
250        // rendering
251        renderRow: function(inRowIndex, inNodes, skipRenorm){
252                var rowNodes = [];
253                for(var i=0, v, n, rowNode; (v=this.views[i])&&(n=inNodes[i]); i++){
254                        rowNode = v.renderRow(inRowIndex);
255                        n.appendChild(rowNode);
256                        rowNodes.push(rowNode);
257                }
258                if(!skipRenorm){
259                        this.normalizeRowNodeHeights(rowNodes);
260                }
261        },
262       
263        rowRemoved: function(inRowIndex){
264                this.onEach("rowRemoved", [ inRowIndex ]);
265        },
266       
267        // updating
268        updateRow: function(inRowIndex, skipRenorm){
269                for(var i=0, v; v=this.views[i]; i++){
270                        v.updateRow(inRowIndex);
271                }
272                if(!skipRenorm){
273                        this.renormalizeRow(inRowIndex);
274                }
275        },
276       
277        updateRowStyles: function(inRowIndex){
278                this.onEach("updateRowStyles", [ inRowIndex ]);
279        },
280       
281        // scrolling
282        setScrollTop: function(inTop){
283                var top = inTop;
284                for(var i=0, v; v=this.views[i]; i++){
285                        top = v.setScrollTop(inTop);
286                        // Work around IE not firing scroll events that cause header offset
287                        // issues to occur.
288                        if(has('ie') && v.headerNode && v.scrollboxNode){
289                                v.headerNode.scrollLeft = v.scrollboxNode.scrollLeft;
290                        }
291                }
292                return top;
293                //this.onEach("setScrollTop", [ inTop ]);
294        },
295       
296        getFirstScrollingView: function(){
297                // summary: Returns the first grid view with a scroll bar
298                for(var i=0, v; (v=this.views[i]); i++){
299                        if(v.hasHScrollbar() || v.hasVScrollbar()){
300                                return v;
301                        }
302                }
303                return null;
304        }
305});
306});
Note: See TracBrowser for help on using the repository browser.