Right Panel
From WikiSky
Description
Data panel with dynamic foldable items. The class rightPanel creates instance of panel container in the parent html element provided in parameter ("parent") all elements have ability to collapse/expand. Collapsed elements on top followed by expanded elements. If element doesn't fit into the panel scrollbar appears. Multiple expanded elements share the panel space equally.
Examples
Source code
/***********************************************
* Data panel with dynamic foldable items (www.wikisky.org)
* The class rightPanel creates instance of panel container
* in the parent html element provided in parameter ("parent")
* all elements have ability to collapse/expand. Collapsed elements on top
* followed by expanded elements. If element doesn't
* fit into the panel scrollbar appears. Multiple expanded elements share
* the panel space equally.
* Visit WIKISKY.ORG at http://www.wikisky.org/wiki/ for full source code
***********************************************/
// manage right panel operations
function rightPanel(parent) {
this.parent=parent;
this.toShow = false;
this.d_main=document.createElement("DIV");
this.style = this.d_main.style;
this.d_main.style.visibility='hidden';
this.d_main.style.border="0px";
this.d_main.style.margin="0px";
this.d_main.style.padding="0px";
this.d_main.style.position="absolute";
this.d_main.style.left="0px";
this.d_main.style.top="0px";
this.d_main.style.width="250px";
this.d_main.style.height="20px";
this.d_main.style.overflow="hidden";
this.parent.appendChild(this.d_main);
//this.left=this.d_main.offsetLeft;
this.top=this.d_main.offsetTop;
this.right=this.d_main.offsetLeft+this.d_main.offsetWidth;
this.bottom=this.d_main.offsetTop+this.d_main.offsetHeight;
this.width = this.d_main.offsetWidth;
this.height = this.d_main.offsetHeight;
this.minWidth = this.width;
this.items = new Array();
this.spaceBetweenItems = 5;
this.onresize = rightPanel_onresize;
this.updateWidth = rightPanel_updateWidth;
this.getMinTitleWidth = rightPanel_getMinTitleWidth;
this.addItem = rightPanel_addItem;
this.show = function(b) { this.toShow=b; this.onresize(); }
}
function rightPanel_onresize() {
if (!this.toShow) {
this.d_main.style.visibility='hidden';
return;
}
this.d_main.style.top = this.top+'px';
var h=this.bottom-this.top;
this.d_main.style.left = (this.right-this.d_main.offsetWidth)+'px';
var exp=new Array();
//show collapsed items first
var pos_y=0;
for(var i in this.items) {
var item=this.items[i];
if (item.visible()) {
item.onresize();
//alert('item='+item+', isExpanded='+item.isExpanded+', setY='+item.setY);
if (item.isExpanded) {
exp.push(item);
} else {
item.setY(pos_y);
item.resetHeight();
pos_y += item.getHeight()+this.spaceBetweenItems;
}
}
}
//show expanded items dividing remaining space equailly
if (exp.length>0) {
this.updateWidth(this.width);
var rm = h-pos_y-2;
var hItem = Math.round((rm - this.spaceBetweenItems*(exp.length-1))/exp.length);
var rm2=rm,n2=0;
for(var i=0; i<exp.length; i++) {
var item=exp[i];
item.setY(pos_y);
item.resetHeight();
if (item.getHeight()>hItem) n2++; else rm2-=item.getHeight()+this.spaceBetweenItems;
}
if (n2<=1) hItem=rm2; else hItem=Math.round((rm2 - this.spaceBetweenItems*(n2-1))/n2);
//find item to apply reminder caused by rounding
var itemToApplyRem=-1;
var t_rm=rm;
for(var i=0; i<exp.length; i++) {
var item=exp[i];
var a=item.getHeight();
if (a>hItem) {itemToApplyRem=i; a=hItem; }
t_rm -= a + (i+1<exp.length ? this.spaceBetweenItems : 0);
}
//show expanded items
for(var i=0; i<exp.length; i++) {
var item=exp[i];
item.setY(pos_y);
item.resetHeight();
var a=item.getHeight();
if (a>hItem) a=hItem+(i==itemToApplyRem?t_rm:0);
pos_y += a;
rm -= a;
item.setHeight(a);
if (i+1<exp.length) {
pos_y+=this.spaceBetweenItems;
rm-=this.spaceBetweenItems;
}
}
} else { //if all items are collapsed
this.updateWidth(Math.min(this.width, Math.max(this.minWidth,this.getMinTitleWidth())));
}
if (pos_y==0) {
this.d_main.style.visibility='hidden';
} else {
this.d_main.style.visibility='visible';
this.d_main.style.height = Math.min(h,pos_y+2)+'px';
}
//alert('this.height='+this.height+', h='+h);
if (h>=0) this.d_main.style.height = (h+(document.all?2:0))+'px';
}
function rightPanel_updateWidth(w) {
this.d_main.style.width=(w-(document.all?0:2))+'px';
this.d_main.style.left = (this.right-this.d_main.offsetWidth)+'px';
for(var i in this.items) {
this.items[i].updateWidth(w);
}
}
function rightPanel_getMinTitleWidth() {
var minWidth=this.width;
for(var i in this.items) {
var item=this.items[i];
if (item.visible()) {
var t=item.getMinTitleWidth();
if (minWidth>t) minWidth=t;
}
}
//alert('rightPanel.getMinTitleWidth(): minWidth='+minWidth);
return minWidth;
}
function rightPanel_addItem(title) {
var t=new rightPanelItem(this, title);
this.items.push(t);
return t;
}
function rightPanelItem(parentObj, title) {
this.parentObj = parentObj;
this.title = title;
this.isExpanded = false; //do not change the value from outside, use expand() and collapse() methods instead
this.d_main=document.createElement("SPAN");
this.d_main.style.visibility='hidden';
this.d_main.style.border="1px solid gray";
this.d_main.style.position="absolute";
this.d_main.style.left="0px";
//this.d_main.style.display="inline";
this.parentObj.d_main.appendChild(this.d_main);
this.d_bg=document.createElement("DIV");
this.d_bg.style.position="absolute";
this.d_bg.style.left="0px";
this.d_bg.style.top="0px";
this.d_bg.style.width="100%";
this.d_bg.style.height="100%";
this.d_bg.style.margin="0px";
this.d_bg.style.backgroundColor='black';
this.d_bg.style.opacity=0.5;
this.d_bg.style.filter='alpha (opacity=50)';
this.d_main.appendChild(this.d_bg);
this.d_title=document.createElement("SPAN");
this.d_title.parentItem=this;
//this.d_title.style.border="1px solid green";
this.d_title.style.position="absolute";
this.d_title.style.left="0px";
this.d_title.style.top="0px";
this.d_title.style.width="100%";
this.d_title.style.height="16px";
this.d_title.style.overflow="hidden";
this.d_title.style.backgroundColor="#404040";
this.d_title.style.color="white";
this.d_title.style.fontSize="8pt";
this.d_title.innerHTML=' '+this.title;
this.d_title.style.cursor='pointer';
this.d_title.onclick=function() { this.title=='Collapse'?this.parentItem.collapse():this.parentItem.expand(); }
this.d_main.appendChild(this.d_title);
this.btn_close = new Image;
this.btn_close.parentItem = this;
this.btn_close.border=0;
this.btn_close.style.position='absolute';
this.btn_close.style.left = (this.parentObj.d_main.offsetWidth-19)+'px';
this.btn_close.style.top = '0px';
this.btn_close.style.width = '15px';
this.btn_close.style.height = '15px';
this.btn_close.style.visibility=;
this.btn_close.srcCollapse = 'img/collapse.gif';
this.btn_close.srcExpand = 'img/expand.gif';
this.btn_close.GALLERYIMG='no';
this.btn_close.title = 'Collapse';
this.btn_close.style.cursor='pointer';
this.btn_close.onclick=function() { this.title=='Collapse'?this.parentItem.collapse():this.parentItem.expand(); }
this.d_main.appendChild(this.btn_close);
this.d_body=document.createElement("SPAN");
this.d_body.parentItem=this;
//this.d_body.style.borderBottom="1px solid red";
this.d_body.style.position="absolute";
this.d_body.style.left="0px";
this.d_body.style.top=(this.d_title.offsetTop+this.d_title.offsetHeight)+"px";
this.d_body.style.width="100%";
this.d_body.style.overflowX="hidden";
this.d_body.style.overflowY="auto";
//this.d_body.style.backgroundColor="green";
this.d_body.style.color="white";
this.d_body.style.fontSize="8pt";
//this.d_body.style.visibility='hidden';
//this.d_body.innerHTML='test';
this.d_main.appendChild(this.d_body);
this.show = function(b) { this.d_main.style.visibility=b?:'hidden'; }
this.visible = function(b) { return this.d_main.style.visibility!='hidden'; }
this.setY = function(y) { this.d_main.style.top = y+'px'; }
this.setHeight = function(h) { this.d_body.style.height = (h-this.d_body.offsetTop)+'px'; this.onresize(); }
this.getHeight = function(h) { return this.d_title.offsetHeight+(this.isExpanded?this.d_body.offsetHeight:0); }
this.resetHeight = function(h) { this.d_body.style.height = null; }
this.onresize = function() {
this.d_main.style.width=(this.parentObj.d_main.offsetWidth-(document.all?0:2))+"px";
this.d_main.style.height=(this.getHeight()+(document.all?2:0))+"px";
this.btn_close.src=this.isExpanded?this.btn_close.srcCollapse:this.btn_close.srcExpand;
this.btn_close.title = this.isExpanded?'Collapse':'Expand';
this.d_title.title = this.isExpanded?'Collapse':'Expand';
this.d_body.style.visibility=this.isExpanded ? : 'hidden';
}
this.updateWidth = function(w) {
this.d_main.style.width=(w-(document.all?0:2))+"px";
this.btn_close.style.left = (w-17)+"px";
}
this.getMinTitleWidth = function() {
var t=this.d_title.style.width;
this.d_title.style.width=;
this.d_title.innerHTML=this.d_title.innerHTML;
var r=this.d_title.offsetWidth+this.btn_close.offsetWidth+2;
this.d_title.style.width=t;
//alert('getMinTitleWidth(): '+r);
return r;
}
this.collapse = function() { this.isExpanded=false; if (this.onCollapse) this.onCollapse(); this.parentObj.onresize(); }
this.expand = function() { this.isExpanded=true; if (this.onExpand) this.onExpand(); this.parentObj.onresize(); }
this.setTitle = function(t) {
this.d_title.innerHTML=this.title=t;
this.parentObj.onresize();
}
this.setBody = function(t) {
var scrollTop = this.d_body.scrollTop;
this.d_body.innerHTML=t;
if (scrollTop>0) this.d_body.scrollTop=scrollTop;
this.parentObj.onresize();
}
this.onresize();
}

