source: Dev/trunk/src/client/dojox/grid/_ViewManager.js @ 532

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

Added Dojo 1.9.3 release.

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 < 4
192                                if(has('ff') < 4){
193                                        hs.right = l + v.getScrollbarWidth() + 'px';
194                                }else{
195                                        hs.right = l + 'px';
196                                }
197                                if(!has('webkit') && hs.width != 'auto'){
198                                        hs.width = parseInt(hs.width, 10) - v.getScrollbarWidth() + 'px';                                       
199                                }
200                        }else{
201                                ds.left = l + 'px';
202                                hs.left = l + 'px';
203                        }
204                        ds.top = 0 + 'px';
205                        hs.top = 0;
206                };
207                // for views left of the client
208                //BiDi TODO: The left and right should not appear in BIDI environment. Should be replaced with
209                //leading and tailing concept.
210                for(i=0; (v=this.views[i])&&(i<c); i++){
211                        // get width
212                        vw = this.getViewWidth(i);
213                        // process boxes
214                        v.setSize(vw, 0);
215                        setPosition(v, l);
216                        if(v.headerContentNode && v.headerContentNode.firstChild){
217                                vw = v.getColumnsWidth()+v.getScrollbarWidth();
218                        }else{
219                                vw = v.domNode.offsetWidth;
220                        }
221                        // update position
222                        l += vw;
223                }
224                // next view (is the client, i++ == c)
225                i++;
226                // start from the right edge
227                var r = w;
228                // for views right of the client (iterated from the right)
229                for(var j=len-1; (v=this.views[j])&&(i<=j); j--){
230                        // get width
231                        vw = this.getViewWidth(j);
232                        // set size
233                        v.setSize(vw, 0);
234                        // measure in pixels
235                        vw = v.domNode.offsetWidth;
236                        // update position
237                        r -= vw;
238                        // set position
239                        setPosition(v, r);
240                }
241                if(c<len){
242                        v = this.views[c];
243                        // position the client box between left and right boxes
244                        vw = Math.max(1, r-l);
245                        // set size
246                        v.setSize(vw + 'px', 0);
247                        setPosition(v, l);
248                }
249                return l;
250        },
251
252        // rendering
253        renderRow: function(inRowIndex, inNodes, skipRenorm){
254                var rowNodes = [];
255                for(var i=0, v, n, rowNode; (v=this.views[i])&&(n=inNodes[i]); i++){
256                        rowNode = v.renderRow(inRowIndex);
257                        n.appendChild(rowNode);
258                        rowNodes.push(rowNode);
259                }
260                if(!skipRenorm){
261                        this.normalizeRowNodeHeights(rowNodes);
262                }
263        },
264       
265        rowRemoved: function(inRowIndex){
266                this.onEach("rowRemoved", [ inRowIndex ]);
267        },
268       
269        // updating
270        updateRow: function(inRowIndex, skipRenorm){
271                for(var i=0, v; v=this.views[i]; i++){
272                        v.updateRow(inRowIndex);
273                }
274                if(!skipRenorm){
275                        this.renormalizeRow(inRowIndex);
276                }
277        },
278       
279        updateRowStyles: function(inRowIndex){
280                this.onEach("updateRowStyles", [ inRowIndex ]);
281        },
282       
283        // scrolling
284        setScrollTop: function(inTop){
285                var top = inTop;
286                for(var i=0, v; v=this.views[i]; i++){
287                        top = v.setScrollTop(inTop);
288                        // Work around IE not firing scroll events that cause header offset
289                        // issues to occur.
290                        if(has('ie') && v.headerNode && v.scrollboxNode){
291                                v.headerNode.scrollLeft = v.scrollboxNode.scrollLeft;
292                        }
293                }
294                return top;
295                //this.onEach("setScrollTop", [ inTop ]);
296        },
297       
298        getFirstScrollingView: function(){
299                // summary:
300                //              Returns the first grid view with a scroll bar
301                for(var i=0, v; (v=this.views[i]); i++){
302                        if(v.hasHScrollbar() || v.hasVScrollbar()){
303                                return v;
304                        }
305                }
306                return null;
307        }
308});
309});
Note: See TracBrowser for help on using the repository browser.