123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- /*
- Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
- Available via Academic Free License >= 2.1 OR the modified BSD license.
- see: http://dojotoolkit.org/license for details
- */
- if(!dojo._hasResource["dojox.grid._ViewManager"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
- dojo._hasResource["dojox.grid._ViewManager"] = true;
- dojo.provide("dojox.grid._ViewManager");
- dojo.declare('dojox.grid._ViewManager', null, {
- // summary:
- // A collection of grid views. Owned by grid and used internally for managing grid views.
- // description:
- // Grid creates views automatically based on grid's layout structure.
- // Users should typically not need to access individual views or the views collection directly.
- constructor: function(inGrid){
- this.grid = inGrid;
- },
- defaultWidth: 200,
- views: [],
- // operations
- resize: function(){
- this.onEach("resize");
- },
- render: function(){
- this.onEach("render");
- },
- // views
- addView: function(inView){
- inView.idx = this.views.length;
- this.views.push(inView);
- },
- destroyViews: function(){
- for(var i=0, v; v=this.views[i]; i++){
- v.destroy();
- }
- this.views = [];
- },
- getContentNodes: function(){
- var nodes = [];
- for(var i=0, v; v=this.views[i]; i++){
- nodes.push(v.contentNode);
- }
- return nodes;
- },
- forEach: function(inCallback){
- for(var i=0, v; v=this.views[i]; i++){
- inCallback(v, i);
- }
- },
- onEach: function(inMethod, inArgs){
- inArgs = inArgs || [];
- for(var i=0, v; v=this.views[i]; i++){
- if(inMethod in v){
- v[inMethod].apply(v, inArgs);
- }
- }
- },
- // layout
- normalizeHeaderNodeHeight: function(){
- var rowNodes = [];
- for(var i=0, v; (v=this.views[i]); i++){
- if(v.headerContentNode.firstChild){
- rowNodes.push(v.headerContentNode);
- }
- }
- this.normalizeRowNodeHeights(rowNodes);
- },
- normalizeRowNodeHeights: function(inRowNodes){
- var h = 0;
- var currHeights = [];
- if(this.grid.rowHeight){
- h = this.grid.rowHeight;
- }else{
- if(inRowNodes.length <= 1){
- // no need to normalize if we are the only one...
- return;
- }
- for(var i=0, n; (n=inRowNodes[i]); i++){
- // We only care about the height - so don't use marginBox. This
- // depends on the container not having any margin (which it shouldn't)
- // Also - we only look up the height if the cell doesn't have the
- // dojoxGridNonNormalizedCell class (like for row selectors)
- if(!dojo.hasClass(n, "dojoxGridNonNormalizedCell")){
- currHeights[i] = n.firstChild.offsetHeight;
- h = Math.max(h, currHeights[i]);
- }
- }
- h = (h >= 0 ? h : 0);
-
- //Work around odd FF3 rendering bug: #8864.
- //A one px increase fixes FireFox 3's rounding bug for fractional font sizes.
- if((dojo.isMoz || dojo.isIE > 8) && h){h++;}
- }
- for(i=0; (n=inRowNodes[i]); i++){
- if(currHeights[i] != h){
- n.firstChild.style.height = h + "px";
- }
- }
- },
-
- resetHeaderNodeHeight: function(){
- for(var i=0, v, n; (v=this.views[i]); i++){
- n = v.headerContentNode.firstChild;
- if(n){
- n.style.height = "";
- }
- }
- },
- renormalizeRow: function(inRowIndex){
- var rowNodes = [];
- for(var i=0, v, n; (v=this.views[i])&&(n=v.getRowNode(inRowIndex)); i++){
- n.firstChild.style.height = '';
- rowNodes.push(n);
- }
- this.normalizeRowNodeHeights(rowNodes);
- },
- getViewWidth: function(inIndex){
- return this.views[inIndex].getWidth() || this.defaultWidth;
- },
- // must be called after view widths are properly set or height can be miscalculated
- // if there are flex columns
- measureHeader: function(){
- // need to reset view header heights so they are properly measured.
- this.resetHeaderNodeHeight();
- this.forEach(function(inView){
- inView.headerContentNode.style.height = '';
- });
- var h = 0;
- // calculate maximum view header height
- this.forEach(function(inView){
- h = Math.max(inView.headerNode.offsetHeight, h);
- });
- return h;
- },
- measureContent: function(){
- var h = 0;
- this.forEach(function(inView){
- h = Math.max(inView.domNode.offsetHeight, h);
- });
- return h;
- },
- findClient: function(inAutoWidth){
- // try to use user defined client
- var c = this.grid.elasticView || -1;
- // attempt to find implicit client
- if(c < 0){
- for(var i=1, v; (v=this.views[i]); i++){
- if(v.viewWidth){
- for(i=1; (v=this.views[i]); i++){
- if(!v.viewWidth){
- c = i;
- break;
- }
- }
- break;
- }
- }
- }
- // client is in the middle by default
- if(c < 0){
- c = Math.floor(this.views.length / 2);
- }
- return c;
- },
- arrange: function(l, w){
- var i, v, vw, len = this.views.length;
- // find the client
- var c = (w <= 0 ? len : this.findClient());
- // layout views
- var setPosition = function(v, l){
- var ds = v.domNode.style;
- var hs = v.headerNode.style;
- if(!dojo._isBodyLtr()){
- ds.right = l + 'px';
- // fixed rtl, the scrollbar is on the right side in FF < 4
- if (dojo.isFF < 4) {
- hs.right = l + v.getScrollbarWidth() + 'px';
- }else{
- hs.right = l + 'px';
- }
- if(!dojo.isWebKit){
- hs.width = parseInt(hs.width, 10) - v.getScrollbarWidth() + 'px';
- }
- }else{
- ds.left = l + 'px';
- hs.left = l + 'px';
- }
- ds.top = 0 + 'px';
- hs.top = 0;
- };
- // for views left of the client
- //BiDi TODO: The left and right should not appear in BIDI environment. Should be replaced with
- //leading and tailing concept.
- for(i=0; (v=this.views[i])&&(i<c); i++){
- // get width
- vw = this.getViewWidth(i);
- // process boxes
- v.setSize(vw, 0);
- setPosition(v, l);
- if(v.headerContentNode && v.headerContentNode.firstChild){
- vw = v.getColumnsWidth()+v.getScrollbarWidth();
- }else{
- vw = v.domNode.offsetWidth;
- }
- // update position
- l += vw;
- }
- // next view (is the client, i++ == c)
- i++;
- // start from the right edge
- var r = w;
- // for views right of the client (iterated from the right)
- for(var j=len-1; (v=this.views[j])&&(i<=j); j--){
- // get width
- vw = this.getViewWidth(j);
- // set size
- v.setSize(vw, 0);
- // measure in pixels
- vw = v.domNode.offsetWidth;
- // update position
- r -= vw;
- // set position
- setPosition(v, r);
- }
- if(c<len){
- v = this.views[c];
- // position the client box between left and right boxes
- vw = Math.max(1, r-l);
- // set size
- v.setSize(vw + 'px', 0);
- setPosition(v, l);
- }
- return l;
- },
- // rendering
- renderRow: function(inRowIndex, inNodes, skipRenorm){
- var rowNodes = [];
- for(var i=0, v, n, rowNode; (v=this.views[i])&&(n=inNodes[i]); i++){
- rowNode = v.renderRow(inRowIndex);
- n.appendChild(rowNode);
- rowNodes.push(rowNode);
- }
- if(!skipRenorm){
- this.normalizeRowNodeHeights(rowNodes);
- }
- },
-
- rowRemoved: function(inRowIndex){
- this.onEach("rowRemoved", [ inRowIndex ]);
- },
-
- // updating
- updateRow: function(inRowIndex, skipRenorm){
- for(var i=0, v; v=this.views[i]; i++){
- v.updateRow(inRowIndex);
- }
- if(!skipRenorm){
- this.renormalizeRow(inRowIndex);
- }
- },
-
- updateRowStyles: function(inRowIndex){
- this.onEach("updateRowStyles", [ inRowIndex ]);
- },
-
- // scrolling
- setScrollTop: function(inTop){
- var top = inTop;
- for(var i=0, v; v=this.views[i]; i++){
- top = v.setScrollTop(inTop);
- // Work around IE not firing scroll events that cause header offset
- // issues to occur.
- if(dojo.isIE && v.headerNode && v.scrollboxNode){
- v.headerNode.scrollLeft = v.scrollboxNode.scrollLeft;
- }
- }
- return top;
- //this.onEach("setScrollTop", [ inTop ]);
- },
-
- getFirstScrollingView: function(){
- // summary: Returns the first grid view with a scroll bar
- for(var i=0, v; (v=this.views[i]); i++){
- if(v.hasHScrollbar() || v.hasVScrollbar()){
- return v;
- }
- }
- return null;
- }
-
- });
- }
|