// http://tech.groups.yahoo.com/group/ydn-javascript/messages/25406?threaded=1&m=e&var=1&tidx=1

(function() {

	var Sel = YAHOO.util.Selector,
		Ev = YAHOO.util.Event,
		Dom = YAHOO.util.Dom,
		IDom = IRIS.util.Dom;

	IRIS.widget.Expander = function( container, event ) {
		this.container = container;
		if( event ) {
			this.event = event;
		}
		YAHOO.util.Event.onDOMReady(this.init, this, true);
	}

	IRIS.widget.Expander.prototype = {
		container: null,
		selector: '.handle',
		event: 'click',
		handles: [],
		bodies: {},
		expanded: [],
		expandedClass: 'expanded',
		collapsedClass: 'collapsed',
		unit: 'px',
		animationSpeed: 300, // units per second
		duration: 1,
		init: function() {
			var i;
			if( typeof this.container == 'string' ) {
				this.container = document.getElementById(this.container);
			}
			if( this.container ) {
				IRIS.widget.Expander.instances[this.container.id] = this;
				var handles = this.getHandles(), i;
				for( i = 0; i < handles.length; i++ ) {
					Ev.addListener(handles[i], this.event, this.handleEvent, this, true);
				}
			}
		},
		handleEvent: function( e ) {
			var handle = (e.srcElement ? e.srcElemtn : e.target);
			if( !this.isExpanded(handle) ) {
				this.expand(handle);
			}
			else {
				this.collapse(handle);
			}
		},
		isExpanded: function( handle ) {
			return (this.expanded.indexOf(handle) !== -1);
		},
		expand: function( handle ) {
			var body = this.getBody(handle), anim;
			if( body ) {
				anim = new YAHOO.util.Anim(body, {
						height: {to: body.scrollHeight},
						unit: this.unit
				}, this.getDuration(handle, body));
				Dom.addClass(body, this.expandedClass);
				anim.onComplete.subscribe(function() {
						this.setExpanded(handle, body)
					}, this, true
				);
				anim.animate();
			}
		},
		setExpanded: function( handle, body ) {
			Dom.removeClass(body, this.collapsedClass);
			this.expanded.push(handle);
		},
		collapse: function( handle ) {
			var body = this.getBody(handle), anim;
			if( body ) {
				anim = new YAHOO.util.Anim(body, {
						height: {to: 0},
						unit: this.unit
				}, this.getDuration(handle, body));
				Dom.addClass(body, this.collapsedClass);
				anim.onComplete.subscribe(function() {
						this.setCollapsed(handle, body)
					}, this, true
				);
				anim.animate();
			}
		},
		setCollapsed: function( handle, body ) {
			var i;
			Dom.removeClass(body, this.expandedClass);
			do {
				i = this.expanded.indexOf(handle);
				if( i != -1 ) {
					this.expanded[i] = null;
				}
			}
			while( i != -1 );
		},
		getDuration: function( handle, body ) {
			var duration;
			if( this.animationSpeed ) {
				duration = body.scrollHeight / this.animationSpeed;
			}
			else {
				duration = this.duration;
			}
			return duration;
		},
		getBody: function( handle ) {},
		getHandles: function() {
			if( !this.handles.length ) {
				var i, body, handle;
				this.handles = this.selectHandles();
				for( i = 0; i < this.handles.length; i++ ) {
					handle = this.handles[i];
					if( body = this.getBody(handle) ) {
						if( body.offsetHeight > 0 ) {
							this.setExpanded(handle, body);
						}
					}
				}
			}
			return this.handles;
		},
		selectHandles: function() {
			return Sel.query(this.selector, this.container);
		}
	}

	IRIS.widget.ListExpander = function( container ) {
		IRIS.widget.ListExpander.superclass.constructor.call(this, container);
	};

	YAHOO.extend(IRIS.widget.ListExpander, IRIS.widget.Expander, {
		ignoreEmptyLists: true,
		selectHandles: function() {
			var handles = IDom.getChildrenByTagName(this.container, 'li'), i;
			if( this.event == 'click' ) {
				var links = [], link, handle;
				for( i = 0; i < handles.length; i++ ) {
					handle = handles[i];
					if( this.getBody(handle) 
							&& (link = IDom.getChildrenByTagName(handle, 'a', 1)[0]) ) {
						links[links.length] = link;
						link.href = 'javascript: void(0)';
					}
				}
				handles = links;
			}
			return handles;
		},
		getBody: function( handle ) {
			var parent, body;
			if( handle.tagName.toUpperCase() == 'LI' ) {
				parent = handle;
			}
			else {
				parent = IDom.getParentsByTagName(handle, 'LI', 1)[0];
			}
			if( parent ) {
				body = IDom.getChildrenByTagName(parent, 'UL', 1)[0];
				if( body && this.ignoreEmptyLists
						&& !IDom.getChildrenByTagName(body, 'LI', 1).length ) {
					body = null;
				}
				return body;
			}
		}
	});

	IRIS.widget.Expander.instances = {};
	IRIS.widget.Expander.getInstance = function( el ) {
		if( typeof el == 'object' ) {
			el = el.id;
		}
		return IRIS.widget.Expander.instances[el];
	}

}());
