/*********************************************************************************
  *	This script is property of 
  * G8media Advertising, Hamburg (Germany) 
  * http://www.g8media.de 
  * Author: Sascha "w3ksel" Schulz <s.schulz at g8media dot de>
  * Version: 0.3b
  * 
  * If you want to use this: contact us.
  *
  * [note]
  * to enable this script, change the following configs and run
  * g8kinetic_initiate() when the window is loaded.
  *
  * [example]
  * window.onload = function(){ g8kinetic_initiate(); }
**********************************************************************************/




/*********************************************************************************
	core arrays containing config and runtime data
**********************************************************************************/
var cfg_g8kinetic = new Array();
var run_g8kinetic = new Array();



/*********************************************************************************
	config
**********************************************************************************/


// id of the element wrapping the whole kinetic interface
// used to hide/show the interface
cfg_g8kinetic['id_kinetic_wrap_all'] = "g8kinetic_wrap_all";
// wrap of the kinetic element, the "window"
cfg_g8kinetic['id_kinetic_wrap'] = "kinetic_wrap";
// wrap of the kinetic items, this element will be moved by obj.style.top
cfg_g8kinetic['id_kinetic_content'] = "kinetic_content";
// amount of pixels the kinetic items will be moved vertically
cfg_g8kinetic['px_offset'] = -1;
// amount of intervals
cfg_g8kinetic['num_intervals'] = 35;
// prefix of relation attribute of anchors
cfg_g8kinetic['rel_prefix'] = "g8kinetic";
// resize height of kinetic wrap when active
cfg_g8kinetic['kinetic_wrap_height'] = 300;
// hide box by default
cfg_g8kinetic['autohide'] = true;
// run kinetic by default. this will be overwritten by autohide
cfg_g8kinetic['autorun'] = true;



/*********************************************************************************
	runtime data
**********************************************************************************/

run_g8kinetic['interval'];
run_g8kinetic['status'];
run_g8kinetic['break'];
run_g8kinetic['hidden'];



/*********************************************************************************
	initiates script. outsource and run the initialisation eleswere on demand
**********************************************************************************/

//window.onload = function() {	g8kinetic_initiate(); }





/*********************************************************************************
	core methods
**********************************************************************************/


function g8kinetic_read_cfg(expr){
	var cfg_array = cfg_g8kinetic;
	if(!cfg_array)			alert("g8kinetic: cfg array not found");
	if(null != cfg_array[expr])	return cfg_array[expr];
		else				alert("g8kinetic: cfg expression '"+expr+"' not found");
}


function g8kinetic_initiate(){
	var autohide = g8kinetic_read_cfg('autohide');
	var autorun = g8kinetic_read_cfg('autorun');
	var rels = g8kinetic_getRelAnchors();
	g8kinetic_modifyElements(rels);

	//alert("g8kinetic initialisation: vars, modified");

	// set default runtime values
	run_g8kinetic['status'] = false;
	run_g8kinetic['break'] = false;
	run_g8kinetic['hidden'] = false;
	
	if(true == autohide)
		g8kinetic_toggleVisibility();
	else{
		if(true == autorun)
			g8kinetic_start();
	}
	//alert("g8kinetic: initialisation completed");
}

// returns all anchors having the "rel"-tag with valid pattern
function g8kinetic_getRelAnchors(){
	var rel = g8kinetic_read_cfg("rel_prefix");
	var anchors = document.getElementsByTagName("a");
	var rels = new Array();
	var regex = new RegExp("^"+rel+"(\\[[cmd=[a-zA-Z0-9\\-\\_]+\\])*$");
	// browse anchors
	for(var i=0; i< anchors.length; i++){
		if(anchors[i].rel && regex.test(anchors[i].rel))
			rels.push(anchors[i]);
	}
	// return matches
	return rels;
}


// attaches an "onclick"-handler to given elements
function g8kinetic_modifyElements(stack){
	for(var i=0; i<stack.length; i++){
		if(!stack[i].href)		continue;
		// add handler
		stack[i].onclick = g8kinetic_run;				
	}
	return true;
}

// run kinetic by anchors
function g8kinetic_run(){
//	alert("g8kinetic_run()");
	var cmds = g8kinetic_getCmds(this.rel);
	switch(cmds['cmd']){
		case 'start':
			g8kinetic_start();
		break;
		case 'break':
			g8kinetic_toggleBreak();
		break;
		case 'end':
			g8kinetic_end();
		break;
		case 'toggle-invis':
			g8kinetic_toggleVisibility();
		break;
	}
	return false;
}


// returns array of commands from string. Will be provied with raw String from "rel"-tag
function g8kinetic_getCmds(str){
	var regex = new RegExp("(cmd=[a-zA-Z0-9\\-\\_\\.]+)+","g");
	var cmd = str.match(regex);
	var cmds = new Array();
	
	// prevent js from bombing if regex got no match
	if(!cmd)				return cmds;
	
	// browse matches
	for(var i=0; i<cmd.length; i++){
		var pos = cmd[i].indexOf("=");
		var key = cmd[i].substr(0,pos); 
		var value = cmd[i].substr(pos+1, cmd[i].length)
		cmds[key] = value;				
	}	
	return cmds;
}



function g8kinetic_start(){
	// get configs
	var id_wrap 		= g8kinetic_read_cfg('id_kinetic_wrap');
	var id_content		= g8kinetic_read_cfg('id_kinetic_content');
	var num_intervals 	= g8kinetic_read_cfg('num_intervals');
	var wrap_height 	= g8kinetic_read_cfg('kinetic_wrap_height');
	// get objects
	var wrap 		= document.getElementById(id_wrap);
	var content 	= document.getElementById(id_content);
	// get runtime data
	var hidden	= run_g8kinetic['hidden'];
	var status	= run_g8kinetic['status'];
	
	//alert("g8kinetic start: vars set");
	
	// verify kinetic is not already running or hidden
	if(true == hidden || true == status){
		//alert("g8kinetic start: abort");
		return false;	
	}
	
	if(!wrap || !content){
		alert("g8kinetic_start() err1");
		return false;
	}
	
	// initiate positions
	wrap.style.height = wrap_height+"px";
	content.style.top = wrap_height+"px";
	// initiate interval
	run_g8kinetic['interval'] = window.setInterval(g8kinetic_move, num_intervals);
	run_g8kinetic['status'] = true;
	// overwrite break value to prevent user mistakes
	run_g8kinetic['break'] = false;
	//alert("g8kinetic start: completed");
}


function g8kinetic_toggleBreak(){
	// toggle boolean value
	run_g8kinetic['break'] = !run_g8kinetic['break'];
}


function g8kinetic_end(){
	// get ids
	var id_kinetic_wrap = g8kinetic_read_cfg("id_kinetic_wrap");
	var id_kinetic_content = g8kinetic_read_cfg("id_kinetic_content");
	
	// change runtime data
	window.clearInterval(run_g8kinetic['interval']);
	run_g8kinetic['status'] = false;
	run_g8kinetic['break'] = false;
	
	// unset position and height values of kinetic and wrap object	
	document.getElementById(id_kinetic_wrap).style.height = "auto";
	document.getElementById(id_kinetic_content).style.top = "0px";
}



function g8kinetic_toggleVisibility(){
	// get ids
	var id_wrap_all	= g8kinetic_read_cfg("id_kinetic_wrap_all");
	var id_wrap		= g8kinetic_read_cfg("id_kinetic_wrap");
	// get objects
	var wrap_all	= document.getElementById(id_wrap_all);
	var wrap 		= document.getElementById(id_wrap);
	// get configs and runtime data
	var hidden 		= run_g8kinetic['hidden'];
	var status 		= run_g8kinetic['status'];
	var autorun 	= g8kinetic_read_cfg('autorun');
	
	// verify required objects available
	if(!wrap_all || !wrap){
		alert("g8kinetic: required objects not found");
		return false;
	}
	
	// toggle by value of 'hidden' (runtime data)
	switch(hidden){
		// box is hidden at the moment
		case true:
			// show box
			wrap_all.style.left = "0px";
			// update runtime data
			// runtime value of 'hidden' has to be false to start kinetic
			run_g8kinetic['hidden'] = false;
			// lookup if autorun is enabled
			if(true == autorun)
				g8kinetic_start();
		break;
		// box is visible at the moment
		case false:
			// hide box
			wrap_all.style.left = (-1*wrap.offsetWidth)+"px";
			// stop kinetic if active
			if(true == status)
				g8kinetic_end();
			// update runtime data
			run_g8kinetic['hidden'] = true;
		break;
		// illegal warning
		default:
			// throw error message
			alert("g8kinetic_toggle_visibility() error! illegal value, contact admin");
	}
}


function g8kinetic_move(){
	//alert("g8kinetic move: begin");
	// first of all: check if kinetic is on break, abort method in case
	if(true == run_g8kinetic['break'])	{
		//alert("g8kinetic move: abort due to break");
		return false;
	}
	// as second: check if status is active, abort method if not
	if(false == run_g8kinetic['status']){
		//alert("g8kinetic move: abort due to status");
		return false;
	}
	//alert("g8kinetic move: not aborted");
	
	// get configs
	var id_kinetic_content	= g8kinetic_read_cfg('id_kinetic_content');
	var id_kinetic_wrap		= g8kinetic_read_cfg('id_kinetic_wrap');
	var offset= g8kinetic_read_cfg("px_offset");
	
	// get objects
	var obj		= document.getElementById(id_kinetic_content);
	var wrap 	= document.getElementById(id_kinetic_wrap);

	// verify objects are available
	if(!obj || !wrap){
		alert("g8kinetic_move() required objects not found");
		return false
	}
	// get current offset, cut of unit expression at the end (px/pt)
	var curOffset = obj.style.top;
	var unitPos = curOffset.indexOf("px");
	if(unitPos == -1){
		unitPos = curOffset.indexOf("pt");
		if(unitPos == -1)
			unitPos = 0;
	}	
	
	// define next offset
	var nextOffset = curOffset.substr(0, unitPos) *1 +offset;
	if(nextOffset + obj.offsetHeight < 0)
		nextOffset = wrap.offsetHeight;
	else
		if(nextOffset > wrap.offsetHeight)
			nextOffset = 0 - obj.offsetHeight;
	
	// set new offset
	obj.style.top = nextOffset+"px";
}
