(function($){

	$.fn.accordion = function(options) {

		var defaults = {
			node: 		'div.node',
			heading:	'h2',
			content:	'div.content',
			open:		'open',
			speed:		'normal',
			update:		[],
			forceClose:	true,
			blockLinks:	true
		};
		
		var opts = $.extend(defaults, options);
		
		return $(this).each(function(){
			var nodes = $(opts.node,this);
			var openElm = null;
			var $this = $(this);
			
			nodes.each(function(){

				var obj = this;
				
				setDims(this);
				
				if($(this).hasClass(opts.open) && !openElm) {
					openElm = obj;
					update(obj,true);
					$this.trigger('accordion.open',obj);
				}
				else {
					$(this).removeClass(opts.open);
					$(opts.content,this).hide();
					update(obj,false);
				}
				
				$(this).find(opts.heading)
					.css({cursor:'pointer'})
					.click(function(e){
						if(openElm && openElm != obj && opts.forceClose) {
							closeElem(openElm,function(){
								if(toggleElem(obj)) {
									openElm = obj;
									$this.trigger('accordion.open',obj);
								}
							});
						}
						else {
							if(toggleElem(obj)) {
								openElm = obj;
								update(obj,true);
								$this.trigger('accordion.open',obj);
							}
						}
						e.preventDefault();
					})
					.find('a').each(function(){
						if(opts.blockLinks) {
							$(this).click(function(e){e.preventDefault();});	
						}
					});
					
			});
		});
		
		function setDims(node) {
			$(opts.content,node).show().each(function(){
				var w = this.offsetWidth,
					h = this.offsetHeight;
				$(this).css({width:w+'px',height:h+'px'});
			}).hide();
		}
		
		function closeElem(node,callback) {
			$(node).removeClass(opts.open);
			$('*',node).css({position:'static'});
			$(opts.content,node).slideUp(opts.speed,callback);
			update(node,false);
		}
		
		function update(node,isopen) {
			for(var i=0;i<opts.update.length;i++) {
				$(opts.update[i].selector,node).html(opts.update[i].text[isopen?0:1]).click(function(e){e.preventDefault()});
			}
			if(isopen) setDims(node);
		}
		
		function toggleElem(node) {
			$(node).toggleClass(opts.open);
			$('*',node).css({position:'static'});
			$(opts.content,node).slideToggle(opts.speed,function(){$('*',node).css({position:''});});
			var open = $(node).hasClass(opts.open);
			update(node,open);
			return open;
		}
		
	}

})(jQuery)