/*
 * @author  : Greg Wilton (Queensland Treasury)
 * @version : 4.0 (2004-02-27)
 */
var Expandable = function (varName, header, content, button) {
	this.varName = varName;
	this.match = new this.Matcher(header, content);
	this.button = button;
};

Expandable.prototype.itemStore = new Array();

Expandable.prototype.isSupported = function () {
	var ua = navigator.userAgent;
	var IE_OSX = ua.indexOf("MSIE 5.2") != -1 && ua.indexOf("Mac") != -1;
	return (document.getElementById && !IE_OSX) ? true : false;
};

Expandable.prototype.init = function (id, openRows, singeView) {
	if (this.isSupported()) {
		// initialize expandable system
		var section = document.getElementById(id);
		if (section != null) {
			var row = 0;
			var obj = section.firstChild;
			while (obj != null) {
				// find the header row
				if (this.match.isHeader(obj)) {
					var header = obj;
					var content = null;
					
					// find the content linked with the header row
					obj = obj.nextSibling;
					while (obj != null && !this.match.isHeader(obj)) {
						if (content == null && this.match.isContent(obj)) {
							content = obj;
						}
						obj = obj.nextSibling;
					}
					
					var button = this.formatItem(header, content, row);
					this.itemStore[row++] = new this.Item(
							header, button, content);
				
				} else {
					obj = obj.nextSibling;
				}
			}
		}
		
		// force only on item to be open at a time
		if (singeView) {
			if (openRows) {
				openRows = (openRows.length > 0) ? [openRows[0]] : [];
			}
			this.toggle = this.toggleAll;
		} 
		
		// open specified elements - if requested
		if (openRows) {
			for (var i = openRows.length - 1; i >= 0; i--) {
				if (this.isExpandable(openRows[i])) {
					var obj = this.itemStore[openRows[i]];
					this.open(obj.content, obj.button, row);
				}
			}
		}
	}
};

// extension point - overwrite if required
Expandable.prototype.formatItem = function (header, content, row) {
	// return button if one was created
	return null;
};

Expandable.prototype.toggle = function (row) {
	var items = this.itemStore;
	
	// If required objects are not present cancel the action
	if (!this.isExpandable(row)) { return; }
	
	// Process action
	var opening = items[row].content.style.display == "none";
	if (opening) {
		this.open(items[row].content, items[row].button, row);
	} else {
		this.closeAndScroll(row);
	}
};

Expandable.prototype.toggleAll = function (row) {
	var items = this.itemStore;
	
	// If required objects are not present close all open items
	if (!this.isExpandable(row)) {
		for (var i = items.length - 1; i >= 0; i--) {
			var button = items[i].button;
			var content = items[i].content;
			if (button && content) {
				var isOpen = content.style.display == "block";
				if (isOpen) {
					this.close(content, button, row);
				}
			}
		}
		return;
	}
	
	// Process action
	var opening = items[row].content.style.display == "none";
	if (opening) {
		var pos = this.getOffsetTop(items[row].header) - this.getScrollTop();
		var doScroll = false;
		for (var i = 0; i < items.length; i++) {
			var button = items[i].button;
			var content = items[i].content;
			if (content && button) {
				var isOpen = content.style.display == "block";
				if (isOpen && i < row) {
					var header = items[i].header;
					if (!doScroll && this.isAboveVisibleArea(header)) {
						doScroll = true;
					}
					this.close(content, button, row);
				} else if (i == row) {
					this.open(content, button, row);
					if (doScroll) {
						scrollTo(0, this.getOffsetTop(items[i].header) - pos);
					}
				} else if (isOpen) {
					this.close(content, button, row);
				}
			}
		}
	} else {
		this.closeAndScroll(row);
	}
};

Expandable.prototype.closeAndScroll = function (row) {
	var items = this.itemStore;
	var notVisible = this.isAboveVisibleArea(items[row].header);
	var header, pos;
	if (notVisible) {
		header = items[row + 1].header;
		pos = this.getOffsetTop(header) - this.getScrollTop();
	}
	this.close(items[row].content, items[row].button, row);
	if (notVisible) {
		scrollTo(0, this.getOffsetTop(header) - pos);
	}
}

Expandable.prototype.open = function (content, button, row) {
	content.style.display = "block";
	this.button.open(button, row);
}

Expandable.prototype.close = function (content, button, row) {
	content.style.display = "none";
	this.button.close(button, row);
};

Expandable.prototype.getOffsetTop = function (node) {
	var y = 0;
	while (node && node.tagName != "BODY") {
		y += node.offsetTop;
		node = node.offsetParent;
	}
	return y;
};

Expandable.prototype.getScrollTop = function () {
	if (window.pageYOffset) {
		return window.pageYOffset;
	} else if (document.documentElement && document.documentElement.scrollTop) {
		return document.documentElement.scrollTop;
	} else {
		return document.body.scrollTop;
	}
};

Expandable.prototype.isAboveVisibleArea = function (header) {
	return this.getOffsetTop(header) < this.getScrollTop();
};

Expandable.prototype.isExpandable = function (row) {
	var items = this.itemStore;
	return items[row] && items[row].content && items[row].button;
}


Expandable.prototype.Matcher = function (header, content) {
	this.header = header.toUpperCase();
	this.content = content.toUpperCase();
};
Expandable.prototype.Matcher.prototype.isHeader = function (obj) {
	return obj.tagName == this.header;
};
Expandable.prototype.Matcher.prototype.isContent = function (obj) {
	return obj.tagName == this.content;
};


Expandable.prototype.Item = function (header, button, content) {
	this.header = header;
	this.button = button;
	this.content = content;
};