﻿/**
 * Compact (compact content sections)
 * @version 2.0
 * @since 23/07/2007
 * 
 * Unobtrusive DHTML clickey-hidey content sections (vertical accordian or tabbed display).
 * Changelog: 2.0 has been rewritten using jquery
 * 
 * @author Andrew Ramsden
 * @see http://irama.org/web/dhtml/jquery/plugins/compact/
 * @license Common Public License Version 1.0 <http://www.opensource.org/licenses/cpl1.0.txt>
 * @requires jQuery <http://jquery.com/>
 * @requires jquery.utilities.js <http://irama.org/web/dhtml/jquery/utilities/>
 * @requires jquery.dimensions.js plugin
 *
 *
 * @example Use the following HTML:
	 <div class="compact">
		<div class="section" id="first-section">
			<h2>Section title</h2>
			<p>Some content.</p>
		</div>
		<div class="section" id="another">
			<h2>Another title</h2>
			<p>Some content.</p>
		</div>
	 </div>
 *
 * Then use the following JavaScript on page load:
 * <code>$('.compact').compact();</code>
 *
 * Notes:
 *    * The selector can be changed to target whichever element contains all of the 
 *      collapsable content sections.
 *    * Each section within MUST have a unique id.
 *
 */
/* start config */
var compactConfig = {
	containerClass : 'compact',
	sectionClass   : 'section',
	headingClass   : 'heading',
	activeClass    : 'active',
	expandClass    : 'accordian',
	tabbedClass    : 'tabbed',
	defaultType    : 'accordian',
	contentClass   : 'content',
	toggleClass    : 'toggle',
	closedClass    : 'closed',
	openClass      : 'open',
	currentClass   : 'current'
};
/* end config */


(function($) {// start closure
	
	var currentCompactFrag = '';
	var compactPollId = null;
	
	$(document).ready(function() {
		sections = $('.'+compactConfig.containerClass).not('.'+compactConfig.activeClass);
		if (sections.size()>0) {
			sections.compact();
		}
	});
	
	$.fn.extend({
		compact: function() {
			var sections = $(this).not('.'+compactConfig.activeClass);
			if (sections.size()>0) {
				sections.each(initCompactSections);
				$.compactPollFrag();
				if (compactPollId === null) {
					compactPollId = window.setInterval($.compactPollFrag, 1000);
				}
			}
			return $(this);
		}
	});
	
	var initCompactSections = function () {
		// Which type? expandable or tabbed?
			// if no type specified, set default type
				if (
					!$(this).hasClass(compactConfig.expandClass) &&
					!$(this).hasClass(compactConfig.tabbedClass)
				) {
					$(this).addClass(compactConfig.defaultType);
				}
			// handle setup of types
				if ($(this).hasClass(compactConfig.expandClass)) {
					$(this).find('div.'+compactConfig.sectionClass).each(setupExpandableCompactSection);
					$(this).addClass(compactConfig.activeClass);
				} else { // tabbed
					//$(this).find('div.'+compactConfig.sectionClass).each(setupTabbedCompactSection);
					setupTabs.apply(this);
					$(this).addClass(compactConfig.activeClass);
				}
			return;
	};
	// is applied to each div.compact.expandable/div.section
	function setupExpandableCompactSection() {
		// make sure section has an id
			if(typeof $(this).attr('id') === 'undefined') {
				if (typeof console !== 'undefined') {
					console.error('Each compact section must have an unique id');
				}
				$(this).addClass('error');
				return;
			}
			
		// Get the the first and biggest heading for the link text
			var heading = $(this).firstHeading();
			var tempA = $('<a>'+heading.text()+'</a>');
			tempA.addClass(compactConfig.toggleClass);
			tempA.attr('href','#'+$(this).attr('id'));
			tempA.click(expandableToggleAction);
			heading.empty();
			heading.append(tempA);
			heading.addClass(compactConfig.headingClass);
			
		// wrap content
			var tempContent = $(this).children().not(heading);
			tempContent.remove();
			var tempContainer = $('<div class="'+compactConfig.contentClass+'"></div>');
			tempContainer.append(tempContent);
			$(this).append(tempContainer);
		
			collapseSection.apply(this);
	};
	function setupTabs () {
		
		var tabGroup = this;
		var tabList = $('<ul class="nl tabs"></ul>');
		var firstTab = null;
		
		$(this).find('div.'+compactConfig.sectionClass).each(function () {
			// is applied to each 'div.section' in this 'div.compact.tabbed' group
			
			// make sure section has an id
				if($(this).attr('id') == 'undefined') {
					if (typeof console !== 'undefined') {
						console.error('Each compact section must have an unique id');
					}
					$(this).addClass('error');
					return false;
				}
				var id = $(this).attr('id');
				
			// Get the the first and biggest heading for the link text
				heading = $(this).firstHeading();
				heading.addClass(compactConfig.headingClass);
				hText = heading.text();
			
			// add to tab list
				listItem = $('<li><a href="#'+id+'">'+hText+'</a></li>');
				listItem.find('a').click(activateTab);
				tabList.append(listItem);
			
			// wrap content
				var tempContent = $(this).children().not(heading);
				tempContent.remove();
				var tempContainer = $('<div class="content"></div>');
				tempContainer.append(tempContent);
				$(this).append(tempContainer);
			
			// open or close tab
				if (firstTab == null) {
					firstTab = this;
					expandSection.apply(this);
					listItem.addClass(compactConfig.currentClass);
				} else {
					collapseSection.apply(this);
					listItem.removeClass(compactConfig.currentClass);
				}
		});
		
		$(tabGroup).prepend(tabList);
	};
	/*// is applied to each div.compact.tabbed/div.section
	function setupTabbedCompactSection() {
		// to be implemented
		
		
	}*/
	function expandableToggleAction() {
		if ($(this).parent().siblings('div.'+compactConfig.contentClass).css('display') == 'none') {
			expandAction.apply(this);
			return false;
		} else {
			collapseAction.apply(this);
			return false;
		}
	};
	function expandAction() {
		$(this).parent().parent().siblings('.section.open').each(collapseSection);
		$(this).parent().parent().each(expandSection);
		// update frag id
			currentCompactFrag = $(this).parent().parent().attr('id');
			$.frag(currentCompactFrag,false);
		return false;
	};
	function collapseAction() {
		$(this).parent().parent().each(collapseSection);
		// update frag id
			currentCompactFrag = '';
			$.frag(currentCompactFrag,false);
		return false;
	};
	function expandSection() {
		$(this).removeClass(compactConfig.closedClass);
		$(this).addClass(compactConfig.openClass);
		//$(this).children('.'+compactConfig.contentClass).show(); // show is now handled by CSS
		alink = $(this).find('.'+compactConfig.toggleClass);
		if (typeof alink !== 'undefined') {
			alink.attr('title','Click to collapse the '+alink.text()+' section');
		}
	};
	function collapseSection() {
		$(this).removeClass(compactConfig.openClass);
		$(this).addClass(compactConfig.closedClass);
		//$(this).children('.'+compactConfig.contentClass).hide(); // hide is now handled by CSS
		alink = $(this).find('.'+compactConfig.toggleClass);
		if (typeof alink !== 'undefined') {
			alink.attr('title','Click to expand the '+alink.text()+' section');
		}
	};
	$.compactPollFrag = function () { // called once per second
		var frag = $.frag();
		var resetPos = null;
		if (frag == currentCompactFrag) return;
		
		// if first time polled, will need to reset position after activating tab
			if (currentCompactFrag == '') {
				resetPos = $('#'+frag).position();
			}
			
		activateSectionById(frag);
		
		// reset page position
			if (resetPos !== null) {
				$(window).scrollTop(resetPos.top);
				$(window).scrollLeft(resetPos.left);
			}
		
		
		// if tabbed, scroll to top of tabs (scrolls to content by default)
		if ($('#'+frag).parents('.'+compactConfig.tabbedClass).size() > 0) {
			pos = $('#'+frag).parents('.'+compactConfig.containerClass+':lt(1)').position();
			$(window).scrollTop(pos.top);
			$(window).scrollLeft(pos.left);
		}
	};
	function activateSectionById (sectionId) {
		return $('.'+compactConfig.containerClass+' #'+sectionId).each(activateSection);
	};
	function activateSection () {
			$(this).siblings().each(collapseSection);
			expandSection.apply(this);
			currentCompactFrag = $(this).attr('id');
			$.frag(currentCompactFrag,false);
			// update tab status if tabbed
			if ($(this).parents('.'+compactConfig.containerClass).hasClass(compactConfig.tabbedClass)) {
				// find the anchor with href that ends with the frag
				$('a[href$="#'+$(this).attr('id')+'"]').each(setCurrentTab);
			}
		return;
	};
	function activateTab () {
		// activate matching section, strip hash from href to get correct id
		href = $(this).attr('href');
		activateSectionById(href.substr(href.indexOf('#')+1));
		setCurrentTab.apply(this);
		return false; // so anchor href isn't followed
	};
	function setCurrentTab () {
		$(this).parent().siblings().removeClass(compactConfig.currentClass);
		$(this).parent().addClass(compactConfig.currentClass);
	};
})(jQuery); // end closure

