(function($) {
	var CLASSES = {
		open: "open",
		closed: "closed",
		expandable: "expandable",
		collapsable: "collapsable",
		lastCollapsable: "lastCollapsable",
		lastExpandable: "lastExpandable",
		last: "last",
		hitarea: "hitarea"
	};
	
	$.extend($.fn, {
		swapClass: function(c1, c2) {
			return this.each(function() {
				var $this = $(this);
				if ( $.className.has(this, c1) )
					$this.removeClass(c1).addClass(c2);
				else if ( $.className.has(this, c2) )
					$this.removeClass(c2).addClass(c1);
			});
		},
		replaceclass: function(c1, c2) {
			return this.each(function() {
				var $this = $(this);
				if ( $.className.has(this, c1) )
					$this.removeClass(c1).addClass(c2);
			});
		},
		Treeview: function(settings) {
			settings = $.extend({}, settings);
			function treeController(tree, control) {
				function handler(filter) {
					return function() {
						toggler.apply( $("." + CLASSES.hitarea, tree).filter(function() {
							return filter ? $(this).parent("." + filter).length : true;
						}) );
						return false;
					}
				}
				$(":eq(0)", control).click( handler(CLASSES.collapsable) );
				$(":eq(1)", control).click( handler(CLASSES.expandable) );
				$(":eq(2)", control).click( handler() ); 
			}
			function toggler() {
				$( this ).parent()
					.swapClass( CLASSES.collapsable, CLASSES.expandable )
					.swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
					.find( ">ul" )
					.toggle( settings.speed, settings.toggle );
				if ( settings.unique ) {
					$( this ).parent()
						.siblings()
						.replaceclass( CLASSES.collapsable, CLASSES.expandable )
						.replaceclass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
						.find( ">ul" )
						.hide( settings.speed, settings.toggle );
				}
			}
			this.addClass("treeview");
			$("li:last-child", this).addClass(CLASSES.last);
			$( (settings.collapsed ? "li" : "li." + CLASSES.closed) + ":not(." + CLASSES.open + ") > ul", this).hide();
			$("li[ul]", this)
				.filter("[>ul:hidden]")
					.addClass(CLASSES.expandable)
					.swapClass(CLASSES.last, CLASSES.lastExpandable)
					.end()
				.not("[>ul:hidden]")
					.addClass(CLASSES.collapsable)
					.swapClass(CLASSES.last, CLASSES.lastCollapsable)
					.end()
				.find("." + CLASSES.hitarea)
				.toggle( toggler, toggler );
			if ( settings.control )
				treeController(this, settings.control);
			return this;
		}
	});
})(jQuery);