278 lines
6.3 KiB
JavaScript
278 lines
6.3 KiB
JavaScript
|
if(!dojo._hasResource["dojox.grid._grid.views"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||
|
dojo._hasResource["dojox.grid._grid.views"] = true;
|
||
|
dojo.provide("dojox.grid._grid.views");
|
||
|
|
||
|
dojo.declare('dojox.grid.views', 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;
|
||
|
for(var i=0, n, o; (n=inRowNodes[i]); i++){
|
||
|
h = Math.max(h, (n.firstChild.clientHeight)||(n.firstChild.offsetHeight));
|
||
|
}
|
||
|
h = (h >= 0 ? h : 0);
|
||
|
//
|
||
|
var hpx = h + 'px';
|
||
|
for(var i=0, n; (n=inRowNodes[i]); i++){
|
||
|
if(n.firstChild.clientHeight!=h){
|
||
|
n.firstChild.style.height = hpx;
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
//console.log('normalizeRowNodeHeights ', h);
|
||
|
//
|
||
|
// querying the height here seems to help scroller measure the page on IE
|
||
|
if(inRowNodes&&inRowNodes[0]){
|
||
|
inRowNodes[0].parentNode.offsetHeight;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
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){
|
||
|
with(v.domNode.style){
|
||
|
if(!dojo._isBodyLtr()){
|
||
|
right = l + 'px';
|
||
|
}else{
|
||
|
left = l + 'px';
|
||
|
}
|
||
|
top = 0 + 'px';
|
||
|
}
|
||
|
with(v.headerNode.style){
|
||
|
if(!dojo._isBodyLtr()){
|
||
|
right = l + 'px';
|
||
|
}else{
|
||
|
left = l + 'px';
|
||
|
}
|
||
|
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);
|
||
|
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){
|
||
|
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);
|
||
|
}
|
||
|
this.normalizeRowNodeHeights(rowNodes);
|
||
|
},
|
||
|
|
||
|
rowRemoved: function(inRowIndex){
|
||
|
this.onEach("rowRemoved", [ inRowIndex ]);
|
||
|
},
|
||
|
|
||
|
// updating
|
||
|
updateRow: function(inRowIndex, inHeight){
|
||
|
for(var i=0, v; v=this.views[i]; i++){
|
||
|
v.updateRow(inRowIndex, inHeight);
|
||
|
}
|
||
|
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);
|
||
|
}
|
||
|
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.hasScrollbar()){
|
||
|
return v;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
});
|
||
|
|
||
|
}
|