/* -*- C++ -*- */

/* --------------------------------------------------------------------
 * Sparkle (Motion): The Become Interactive visual effects framework
 * @(#) $Id$
 * --------------------------------------------------------------------
 * Copyright (c) 2006, 2007 Become Interactive
 * http://www.becomeinteractive.co.uk
 * All rights reserved.
 * --------------------------------------------------------------------
 * This software is the confidential and proprietary information of
 * Become Interactive ("Confidential Information").
 *
 * You shall not disclose such Confidential Information and shall use
 * it only in accordance with the terms of the license agreement you
 * with the terms of the license agreement you entered into with
 * Become Interactive.
 * --------------------------------------------------------------------
 */

if(typeof BECOME == 'undefined') BECOME = {};
if(typeof BECOME.classes == 'undefined') BECOME.classes = {};

var Sparkle;

BECOME.classes.Sparkle = function()
{
	this._overlayObj = false;
	this._overlayObj = Shine.createHTMLElement('div');
	Shine.setAttribute(this._overlayObj, 'id', 'sparkle-overlay');
	this._overlayObj.style.display = 'none';
	Shine.body.insertBefore(this._overlayObj, Shine.body.firstChild);
}
/* Code borrowed from Lightbox. 
 * Core code from - quirksmode.org. Edit for Firefox by pHaez.
 */
BECOME.classes.Sparkle.prototype.getPageSize = function()
{	
	var xScroll, yScroll;
	
	if (window.innerHeight && window.scrollMaxY) {	
		xScroll = document.body.scrollWidth;
		yScroll = window.innerHeight + window.scrollMaxY;
	} else if (document.body.scrollHeight && document.body.offsetHeight && document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
		xScroll = document.body.scrollWidth;
		yScroll = document.body.scrollHeight;
	} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
		xScroll = document.body.offsetWidth;
		yScroll = document.body.offsetHeight;
	}
	
	var windowWidth, windowHeight;
	if (self.innerHeight) {	// all except Explorer
		windowWidth = self.innerWidth;
		windowHeight = self.innerHeight;
	} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
		windowWidth = document.documentElement.clientWidth;
		windowHeight = document.documentElement.clientHeight;
	} else if (document.body) { // other Explorers
		windowWidth = document.body.clientWidth;
		windowHeight = document.body.clientHeight;
	}	
	
	// for small pages with total height less then height of the viewport
	if(yScroll < windowHeight){
		pageHeight = windowHeight;
	} else { 
		pageHeight = yScroll;
	}

	// for small pages with total width less then width of the viewport
	if(xScroll < windowWidth){	
		pageWidth = windowWidth;
	} else {
		pageWidth = xScroll;
	}
	arrayPageSize = new Array(pageWidth,pageHeight,windowWidth,windowHeight) 
	return arrayPageSize;
}


BECOME.classes.Sparkle.prototype.showOverlay = function()
{
	var dims;
	
	if(this._overlayObj == false)
	{
		return false;
	}
	Shine.addElementClass(Shine.body, 'sparkle-overlaid');
	this._overlayObj.style.display = 'block';
	dims = this.getPageSize();
	this._overlayObj.style.height = dims[1] + 'px';
	return this._overlayObj;
}
BECOME.classes.Sparkle.prototype.hideOverlay = function()
{
	if(this._overlayObj == false)
	{
		return false;
	}
	Shine.removeElementClass(Shine.body, 'sparkle-overlaid');
	this._overlayObj.style.display = 'none';
	/* XXX: Remove event handlers! */
}
/* Deprecated Sparkle::Core::createPrimaryWindow */
BECOME.classes.Sparkle.prototype.createPrimaryWindow = function(caption, action)
{
	var win, t, p;
	
	win = new BECOME.classes.Window();
	if(typeof action != 'undefined')
	{
		win._outer = Shine.createHTMLElement('form');
		Shine.setAttribute(win._outer, 'action', action);
		Shine.setAttribute(win._outer, 'method', 'POST');
		win.form = win._outer;
	}
	else
	{
		win._outer = Shine.createHTMLElement('div');
		win.form = false;
	}
	win._outer.sparkleWindow = win;
	Shine.setAttribute(win._outer, 'class', 'sparkle-win-primary');
	win._caption = Shine.createHTMLElement('span');
	Shine.setAttribute(win._caption, 'class', 'sparkle-win-caption');
	t = document.createTextNode(caption);
	win._caption.appendChild(t);
	t = Shine.createHTMLElement('div');
	Shine.setAttribute(t, 'class', 'sparkle-win-top');
	p = Shine.createHTMLElement('span');
	Shine.setAttribute(p, 'class', 'sparkle-win-topleft');
	t.appendChild(p);
	t.appendChild(win._caption);
	win._outer.appendChild(t);
	t = Shine.createHTMLElement('div');
	Shine.setAttribute(t, 'class', 'sparkle-win-client');
	win.clientArea = Shine.createHTMLElement('div');
	Shine.setAttribute(win.clientArea, 'class', 'sparkle-win-clientarea');
	t.appendChild(win.clientArea);
	win._outer.appendChild(t);
	t = Shine.createHTMLElement('div');
	Shine.setAttribute(t, 'class', 'sparkle-win-actions');
	win.actionArea = Shine.createHTMLElement('div');
	Shine.setAttribute(win.actionArea, 'class', 'sparkle-win-actarea');
	t.appendChild(win.actionArea);
	win._outer.appendChild(t);
	t = Shine.createHTMLElement('div');
	Shine.setAttribute(t, 'class', 'sparkle-win-bottom');
	p = Shine.createHTMLElement('span');
	Shine.setAttribute(p, 'class', 'sparkle-win-botleft');
	t.appendChild(p);
	p = Shine.createHTMLElement('span');
	Shine.setAttribute(p, 'class', 'sparkle-win-botinner');
	t.appendChild(p);
	win._outer.appendChild(t);
	this._overlayObj.appendChild(win._outer)
	return win;
}
/* Deprecated Sparkle::Window class */
BECOME.classes.Window = function()
{
	this._outer = false;
	this._caption = false;
	this.clientArea = false;
	this.actionArea = false;
	this.form = false;
}

/* Sparkle::Core::createToggle: create a toggleable element that expands and shrinks vertically
 * borrowed from moo.fx by Valerio Proietti (http://mad4milk.net)
 */
BECOME.classes.Sparkle.prototype.createToggleVert = function(element, length)
{
	var s;
	
	if(element.toggle) return;
	if(typeof length == 'undefined' || !length) length = 400;
	element.style.display = 'block';
	element.style.overflow = 'hidden';
	element._sparkleInitialHeight = element.offsetHeight;
	element._sparkleLength = length;
	element._sparkleTo = 0;
	element._sparkleFrom = 0;
	element._sparkleTimer = null;
	element.style.height = '0';
	element.style.display = 'none';
	s = this;
	element.toggle = function()
	{
		if(element._sparkleTo == 0)
		{
			s._expandElementVert(element);
		}
		else
		{
			s._contractElementVert(element);
		}
	};
	element.show = function()
	{
		s._expandElementVert(element);
	};
	element.hide = function()
	{
		s._contractElementVert(element);
	};
}
BECOME.classes.Sparkle.prototype._expandElementVert = function(element)
{
	element.style.display = 'block';
	this._vertExpandGo(element, element.offsetHeight, element._sparkleInitialHeight);
}
BECOME.classes.Sparkle.prototype._contractElementVert = function(element)
{
	this._vertExpandGo(element, element.offsetHeight, 0);
}

BECOME.classes.Sparkle.prototype._vertExpandGo = function(element, from, to)
{
	var start, ev;
	
	start = (new Date).getTime();
	element._sparkleTo = to;
	if(element._sparkleTimer)
	{
		clearInterval(element._sparkleTimer);
	}
	element._sparkleTimer = setInterval(function()
		{
			var time = (new Date).getTime();
			var Tpos = (time - start) / element._sparkleLength;
			var pos;
			if (time >= element._sparkleLength + start)
			{
				pos = to;
				clearInterval (element._sparkleTimer);
				element._sparkleTimer = null;
				if(pos > 0)
				{
					element.style.height = 'auto';
					element._sparkleInitialHeight = element.offsetHeight;
					ev = new Object();
					ev.expanded = true;
					Shine.dispatchEvent(element, 'toggle', ev);
					
				}
				else
				{
					element.style.display = 'none';
					ev = new Object();
					ev.expanded = false;
					Shine.dispatchEvent(element, 'toggle', ev);
				}
			}
			else
			{
				//this time-position, sinoidal transition thing is from script.aculo.us
				pos = ((-Math.cos(Tpos*Math.PI)/2) + 0.5) * (to - from) + from;
				element.style.height = pos + 'px';
			}
		}, 13);
}
if(typeof document.loadHooks=='undefined') document.loadHooks=[];
document.loadHooks.push(function(){Sparkle=new BECOME.classes.Sparkle();});

BECOME.pulldownState = { activeNav: null, activeTrigger: null, target: null, visible: null, inProgress: false };

BECOME.classes.Pulldown = function(block, trigger, name)
{
	if(typeof name == 'undefined') name = block;
	this.name = name;
	this.outer = document.getElementById('container');
	if(!this.outer) return;
	this.block = document.getElementById(block);
	this.trigger = document.getElementById(trigger);
	if(!this.block || !this.trigger) return;
	if(!BECOME.pulldownState.activeNav)
	{
		for(var n = this.trigger.parentNode.firstChild; n; n = n.nextSibling)
		{
			if(Shine.hasElementClass(n, 'active'))
			{
				n.shineOriginalClass = '';
				BECOME.pulldownState.activeNav = n;
				break;
			}
		}
	}
	this.container = Shine.createHTMLElement('div');
	Shine.setAttribute(this.container, 'id', 'pulldown-container-' + name);
	this.inner = Shine.createHTMLElement('div');
	Shine.setAttribute(this.inner, 'class', 'pulldown-inner');
	this.container.appendChild(this.inner);
	this.container.style.visibility = 'hidden';
	Shine.appendFirst(this.outer, this.container);
	Shine.addElementClass(this.outer, 'with-pulldown');
	this.block.parentNode.removeChild(this.block);
	this.inner.appendChild(this.block);
	Sparkle.createToggleVert(this.container);
	this.container.style.visibility = 'visible';
	Shine.addEventHandler(this.trigger, 'click', { host: this, handler: this.onToggle });
	Shine.addEventHandler(this.container, 'toggle', { host: this, handler: this.onToggleComplete });
}
BECOME.classes.Pulldown.prototype.onToggle = function(Shine, sender, ev, data)
{
	if(BECOME.pulldownState.target == this.container)
	{
		if(BECOME.pulldownState.visible == this.container)
		{
			/* Just close this one */
			BECOME.pulldownState.inProgress = true;
			BECOME.pulldownState.target = null;
			if(BECOME.pulldownState.activeTrigger) Shine.setAttribute(BECOME.pulldownState.activeTrigger, 'class', '');
			if(BECOME.pulldownState.activeNav) Shine.setAttribute(BECOME.pulldownState.activeNav, 'class', 'active');
			this.container.toggle();
		}
		else if(BECOME.pulldownState.visible)
		{
			/* A different one is current closing; just reset the fact that
			 * we want to open this one.
			 */
			BECOME.pulldownState.target = null;
		}
	}
	else
	{
		if(BECOME.pulldownState.visible == this.container)
		{
			/* We are currently visible, but about to show something else */
			BECOME.pulldownState.target = this.container;
			BECOME.pulldownState.inProgress = true;
			if(BECOME.pulldownState.activeTrigger) Shine.setAttribute(BECOME.pulldownState.activeTrigger, 'class', '');
			if(BECOME.pulldownState.activeNav) Shine.setAttribute(BECOME.pulldownState.activeNav, 'class', 'active');
			this.container.toggle();
		}
		else if(BECOME.pulldownState.visible != BECOME.pulldownState.target)
		{
			/* Something else is visible, and something else is the target */
			BECOME.pulldownState.target = this.container;
		}
		else if(BECOME.pulldownState.inProgress)
		{
			BECOME.pulldownState.target = this.container;
		}
		else if(BECOME.pulldownState.visible)
		{
			/* Something else is visible */
			BECOME.pulldownState.target = this.container;
			BECOME.pulldownState.inProgress = true;
			if(BECOME.pulldownState.activeTrigger) Shine.setAttribute(BECOME.pulldownState.activeTrigger, 'class', '');
			if(BECOME.pulldownState.activeNav) Shine.setAttribute(BECOME.pulldownState.activeNav, 'class', 'active');
			BECOME.pulldownState.visible.toggle();
		}
		else
		{
			BECOME.pulldownState.target = this.container;
			BECOME.pulldownState.visible = this.container;
			BECOME.pulldownState.inProgress = true;
			if(BECOME.pulldownState.activeTrigger) Shine.setAttribute(BECOME.pulldownState.activeTrigger, 'class', '');
			if(BECOME.pulldownState.activeNav) Shine.setAttribute(BECOME.pulldownState.activeNav, 'class', 'active');
			this.container.toggle();
		}
	}
}
BECOME.classes.Pulldown.prototype.onToggleComplete = function(Shine, sender, ev, data)
{
	if(sender.style.display == 'none')
	{
		BECOME.pulldownState.visible = null;
		if(BECOME.pulldownState.target && BECOME.pulldownState.target != this.container)
		{
			BECOME.pulldownState.visible = BECOME.pulldownState.target;
			BECOME.pulldownState.inProgress = true;
			BECOME.pulldownState.target.toggle();
		}
		else
		{
			BECOME.pulldownState.target = null;
			BECOME.pulldownState.inProgress = false;
			if(BECOME.pulldownState.activeNav)
			{
				Shine.setAttribute(BECOME.pulldownState.activeNav, 'class', 'active');
			}
		}
	}
	else
	{
		BECOME.pulldownState.visible = this.container;
		if(BECOME.pulldownState.target && BECOME.pulldownState.target != this.container)
		{
			BECOME.pulldownState.inProgress = true;
			this.container.toggle();
		}
		else
		{
			BECOME.pulldownState.target = this.container;
			BECOME.pulldownState.inProgress = false;
			BECOME.pulldownState.activeTrigger = this.trigger;
			if(BECOME.pulldownState.activeNav)
			{
				Shine.setAttribute(BECOME.pulldownState.activeNav, 'class', '');
			}
			Shine.setAttribute(this.trigger, 'class', 'active pulled');
		}
	}
}
