function DivContainer()
{
	return this;
}

DivContainer.prototype.init = function(container, header, open)
{
	this.container = container;
	this.id = container? container.id : 0;
	this.header = header;
	if(header)
		header.control = this;
	container.control = this;
	this.controls = getElementNodes(header);
	if(this.id){
		if(open){
			this.image = images.arrowDown.cloneNode(false);
			this.container.style.display = "";
		}else{
			this.image = images.arrowRight.cloneNode(false);
			this.container.style.display = "none";
		}
		this._enableControls(this.container.style.display != "none");
	
		if(header){
			if(header.addEventListener){
				header.addEventListener('click', function(eventObj){
						try{
							var target = eventObj.target;
							if(!target.onclick){
								while(target && !target.control && !target.onclick && target.nodeName.toLowerCase() != "a")
									target = target.parentNode;
								if(target && target.control)
									target.control.toggle();
							}
						}catch(e){
							log('*** exception: ' + e);
						}
					}, false);
			}else if(header.attachEvent){
				header.attachEvent('onclick', function(){
						try{
							var target = event.srcElement;
							if(!target.onclick){
								while(target && !target.control && !target.onclick && target.nodeName.toLowerCase() != "a")
									target = target.parentNode;
								if(target && target.control)
									target.control.toggle();
							}
						}catch(e){
							log('*** exception: ' + e);
						}
					});
			}
			if(header.firstChild)
				header.insertBefore(this.image, header.firstChild);
			else
				header.appendChild(this.image);
		}
	}
	return this;
}

DivContainer.prototype.toString = function() { return "DivContainer"; }

DivContainer.prototype._enableControls = function(flag)
{
	if(this.controls)
		for(var n=0;n<this.controls.length;n++)
			this.controls[n].style.display = flag? '' : 'none';
}

DivContainer.prototype.enableControls = function(flag)
{
	if(this.controls){
		for(var n=0;n<this.controls.length;n++)
			this.controls[n].style.display = flag? '' : 'none';
	}
}

DivContainer.prototype.toggle = function()
{
	if(this.container.style.display != "none"){
		this.container.style.display = "none";
		this.image.src = images.arrowRight.src;
		this.image.title = images.arrowRight.title;
		Notification.postNotification("ContainerDidCollapse", this.container);
	}else{
		this.container.style.display = "";
		this.image.src = images.arrowDown.src;
		this.image.title = images.arrowDown.title;
		Notification.postNotification("ContainerDidExpand", this.container);
	}
	this.enableControls(this.container.style.display != "none");
}

DivContainer.prototype.setVisible = function(flag)
{
	if(!flag && this.container.style.display != "none"){
		this.container.style.display = "none";
		this.image.src = images.arrowRight.src;
		this.image.title = images.arrowRight.title;
		Notification.postNotification("ContainerDidCollapse", this.container);
	}else if(flag && this.container.style.display == "none"){
		this.container.style.display = "";
		this.image.src = images.arrowDown.src;
		this.image.title = images.arrowDown.title;
		Notification.postNotification("ContainerDidExpand", this.container);
	}
	this.enableControls(this.container.style.display != "none");
}

DivContainer.prototype.highlightSelector = function(target, flag) { }


function Container()
{
	return this;
}

Container.prototype = new DivContainer();

Container.prototype.toString = function() { return "Container"; }

Container.prototype.init = function(container, header, property, cache, open)
{
	var mode = (open == undefined)? true : (open? true : false);
	this.name = property;
	this.cells = new Array();
	if(container){
		DivContainer.prototype.init.apply(this, [container, header, mode]);
		var statusArray = null;
		if(cache && cache.status)
			statusArray = cache.status.split(',');
		var list = this.container.getElementsByTagName('input');
		// initialize cells; a cell contains a checkbox
		// cell.chbx = <checkbox>
		for(var n=0;n<list.length;n++){
			var box = list[n];
			var cell = box.parentNode;
			var off = cell.getAttribute("off");
			if(box.type == 'checkbox' && !off /*&& !box.disabled*/){ // added check for disabled
				this.cells.push(cell);
				cell.chbx = box;
				this.updateCellStatus(cell, box.checked?1:0);
			}
		}
		this.initEventListeners();
	}
	return this;
}

// returns an array of selected cells' names or 
// null if nothing or everything is selected
Container.prototype._getSearchOptions = function()
{
	var array = new Array();
	for(var n=0;n<this.cells.length;n++)
		if(this.cells[n].chbx.checked)
			array.push(this.cells[n].chbx.value);
	if(array.length == this.cells.length)
		array.status = "all";
	return (array.length > 0 || this.cells.length == 0)? array : null;
}

// adds selected cells' names to options
Container.prototype.getSearchOptions = function(options)
{
	options[this.name] = this._getSearchOptions();
}

// creates event handlers
Container.prototype.initEventListeners = function()
{
	if(this.container.addEventListener){
		this.container.addEventListener('click', function(eventObj){
				var target = eventObj.target;
				var ctrl = eventObj.currentTarget.control;
				ctrl.toggleCellStatus(target);
				eventObj.stopPropagation();
			}, false);
	}else if(this.container.attachEvent){
		this.container.attachEvent('onclick', function(){
				var target = event.srcElement;
				var ctrl = _controlForNode(target);
				ctrl.toggleCellStatus(target);
				event.cancelBubble = true;
			});
	}
}

Container.prototype.toggleCellStatus = function(sender)
{
	var cell = null;
	if(sender.nodeName.toLowerCase() == 'input' && sender.type == 'checkbox'){
		cell = sender.parentNode;
		this.updateCellStatus(cell, sender.checked? 1 : 0);
	}
	// post notification
	this.notifyCell(cell);
}

Container.prototype.updateCellStatus = function(cell, status)
{
	switch(status){
		case 0: cell.style.color = 'rgb(27,75,83)'; break; // 'rgb(63,89,114)'
		case 1: cell.style.color = ''; break;
	}
}

Container.prototype.setCellStatus = function(cell, status)
{
	if(cell.chbx)
		cell.chbx.checked = status != 0;
	this.updateCellStatus(cell, status);
}

Container.prototype.notifyAll = function()
{
	if(this.notificationName)
		Notification.postNotification(this.notificationName, this, this.selectedCellInfo());
}

Container.prototype.notifyCell = function(cell)
{
	if(cell && this.notificationName)
		Notification.postNotification(this.notificationName, this, this.getCellInfo(cell));
}

Container.prototype.enableAll = function(flag)
{
	try{
		for(var n=0;n<this.cells.length;n++){
			var cell = this.cells[n];
			if(cell.chbx && !cell.chbx.disabled){
			//	cell.chbx.checked = flag;
				this.setCellStatus(cell, flag? 1 : 0);
			}
		}
		// post notification
		this.notifyAll();
	}catch(e){
		logError(e);
	}
}

Container.prototype.enableGroup = function(flag, node)
{
	var group = node.getAttribute("group");
	try{
		for(var n=0;n<this.cells.length;n++){
			var cell = this.cells[n];
			if(cell.getAttribute("group") == group){
				if(cell.chbx && !cell.chbx.disabled){
				//	cell.chbx.checked = flag;
					this.setCellStatus(cell, flag? 1 : 0);
				}
			}
		}
		// post notification
		this.notifyAll();
	}catch(e){
		logError(e);
	}

}

Container.prototype.enableGroupTag = function(tag, group, flag)
{
	try{
		for(var n=0;n<this.cells.length;n++){
			var cell = this.cells[n];
			if(cell.getAttribute(tag) == group){
				if(cell.chbx && !cell.chbx.disabled){
				//	cell.chbx.checked = flag;
					this.setCellStatus(cell, flag? 1 : 0);
				}
			}
		}
		// post notification
		this.notifyAll();
	}catch(e){
		logError(e);
	}

}

Container.prototype.selectedCellInfo = function()
{
	// subclass responsibility
	return null;
}

Container.prototype.getCellInfo = function(cell)
{
	// subclass responsibility
	return null;
}

// Multiple div container
function ContainerList()
{
	this.cells = new Array();
	for(var n=0;n<arguments.length;n++)
		this.cells = this.cells.concat(arguments[n].cells);
	this.name = arguments[0].name;
	return this;
}

// returns an array of selected cells' names or 
// null if nothing or everything is selected
ContainerList.prototype._getSearchOptions = function()
{
	var array = new Array();
	var count = 0;
	for(var n=0;n<this.cells.length;n++){
		if(this.cells[n].chbx.checked)
			array.push(this.cells[n].chbx.value);
		if(!this.cells[n].chbx.disabled)
			count += 1;
	}
	if(array.length == this.cells.length)
		array.status = "all"
	else if(array.length == count)
		array.status = "all-enabled";
	return (array.length > 0 || count == 0)? array : null;
}

// adds selected cells' names to options
ContainerList.prototype.getSearchOptions = function(options)
{
	options[this.name] = this._getSearchOptions();
}


function ChrmContainer()
{
	this.chrmImages = new Array();
	return this;
}

ChrmContainer.prototype = new Container();

ChrmContainer.prototype.notificationName = "ChrmStateDidChange";

ChrmContainer.prototype.toString = function() { return "ChrmContainer"; }

ChrmContainer.prototype.initChrmImage = function(image)
{
	var src = image.src;
	var l = src.indexOf('?');
	var paramStr = src.substr(l + 1);
	var param = Utils._parseParams(paramStr);
		
	// create disabled image
	delete param.hue;
	param.enabled='false';
	image.disSrc = src.substr(0, l) + '?' + Utils._encodeParams(param);
	var disImage = $element('img');
	disImage.src = image.disSrc;
	this.chrmImages.push(disImage);
	image._src = src;
}

ChrmContainer.prototype.init = function(container, header, property, open)
{
	var mode = (open == undefined)? true : (open? true : false);
	Container.prototype.init.apply(this, [container, header, property, mode]);
	this.chrmMap = new Object(); // cells by chrm
	if(this.container){
		var cells = this.container.getElementsByTagName('td');
		for(var n=0;n<cells.length;n++){
			var cell = cells[n];
			var off = cell.getAttribute("off");
			if(!off){
				this.cells.push(cell);
				cell.image = cell.getElementsByTagName('img')[0];
				cell.chbx = cell.getElementsByTagName('input')[0];
				cell.span = cell.getElementsByTagName('span')[0];
				var  chrm = cell.getAttribute("uid");
				if(chrm)
					this.chrmMap[chrm] = cell;
				cell.control = this;
				this.initChrmImage(cell.image);
				if(!cell.chbx.checked)
					this.updateCellStatus(cell, 0);
				else
					this.updateCellStatus(cell, 1);
			}
		}
		this.initEventListeners();
		NotificationCenter.addObserver(this, "updateCounts", "PlacementCountDidChange", null);
	}
	return this;
}

ChrmContainer.prototype.updateCounts = function(note)
{
	var ctrl = note.object; // responds to 'placementCountForChromosome'
	for(var n=0;n<this.cells.length;n++){
		var cell = this.cells[n];
		if(cell.span){
			var chr = cell.getAttribute("uid");
			var count = ctrl.placementCountForChromosome(chr);
			if(count > 0)
				cell.span.innerHTML = "(" + count + ")";
			else
				cell.span.innerHTML = "(-)";
		}
	}
}

ChrmContainer.prototype.getSearchOptions = function(options)
{
	var array = new Array();
	for(var n=0;n<this.cells.length;n++){
		if(this.cells[n].chbx.checked)
			array.push(this.cells[n].chbx.value);
	}
	if(array.length == this.cells.length)
		array.status = "all";
	if(array.length > 0 || this.cells.length == 0)
		options.chr = array;
}

ChrmContainer.prototype.updateChrmImage = function(img, status)
{
	if(img) switch(status){
		case 0:
			img.src = img.disSrc; break;
		case 1:
			img.src = img._src; break;
	}
}

ChrmContainer.prototype.updateCellStatus = function(cell, status)
{
	this.updateChrmImage(cell.image, status);
}

ChrmContainer.prototype.selectedCellInfo = function()
{
	var array = new Array();
	for(var n=0;n<this.cells.length;n++){
		var cell = this.cells[n];
		if(!cell.chbx.disabled){
			var info = new Object();
			info.uid = cell.getAttribute("uid");
			info.status = cell.chbx.checked? 1 : 0;
			array.push(info);
		}
	}
	return array;
}

ChrmContainer.prototype.getCellInfo = function(cell)
{
	var array = new Array();
	var info = new Object();
	info.uid = cell.getAttribute("uid");
	info.status = cell.chbx.checked? 1 : 0;
	array.push(info);
	return array;
}


function AsmbContainer()
{
//	Container.apply(this, [container, header]);
	return this;
}


AsmbContainer.prototype = new Container();

AsmbContainer.prototype.notificationName = "AssemblyStateDidChange";

AsmbContainer.prototype.toString = function() { return "AsmbContainer"; }

AsmbContainer.prototype.selectedCellInfo = function()
{
	var array = new Array();
	for(var n=0;n<this.cells.length;n++){
		var cell = this.cells[n];
		if(!cell.chbx.disabled){
			var info = new Object();
			info.asmb = cell.getAttribute("asmb");
			info.status = cell.chbx.checked? 1 : 0;
			array.push(info);
		}
	}
	return array;
}

AsmbContainer.prototype.getCellInfo = function(cell)
{
	var array = new Array();
	var info = new Object();
	info.asmb = cell.getAttribute("asmb");
	info.status = cell.chbx.checked? 1 : 0;
	array.push(info);
	return array;
}
