/* LANGUAGE PROTOTYPES  */

// http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:forEach
if (!Array.prototype.forEach)
{
	Array.prototype.forEach = function(fun /*, thisp*/)
	{
		var len = this.length;
		if (typeof fun != "function")
			throw new TypeError();

		var thisp = arguments[1];
		for (var i = 0; i < len; i++)
		{
			if (i in this)
				fun.call(thisp, this[i], i, this);
		}
	};
}

// http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf
if (!Array.prototype.indexOf)
{
//alert('indexOf support missing!');
	Array.prototype.indexOf = function(elt /*, from*/)
	{
		var len = this.length;

		var from = Number(arguments[1]) || 0;
		from = (from < 0)
				? Math.ceil(from)
				: Math.floor(from);
		if (from < 0)
			from += len;

		for (; from < len; from++)
		{
			if (from in this &&
					this[from] === elt)
				return from;
		}
		return -1;
	};
}

// http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:lastIndexOf
if (!Array.prototype.lastIndexOf)
{
//alert('lastIndexOf support missing!');
	Array.prototype.lastIndexOf = function(elt /*, from*/)
	{
		var len = this.length;

		var from = Number(arguments[1]);
		if (isNaN(from))
		{
			from = len - 1;
		}
		else
		{
			from = (from < 0)
					? Math.ceil(from)
					: Math.floor(from);
			if (from < 0)
				from += len;
			else if (from >= len)
				from = len - 1;
		}

		for (; from > -1; from--)
		{
			if (from in this &&
					this[from] === elt)
				return from;
		}
		return -1;
	};
}

/* GENERIC FUNCTIONS */

var implode = function (glue, arr)
{
	var result = '';
	var i = 0;
	arr.forEach(function(id){
		if(i)
			result += glue;
		else
			i = 1;
		
		result += id;
	});
	return result;
}

var in_array = function (needle, haystack, strict)
{
	strict = strict == undefined ? false : strict;
	var result = false;
	
	if(strict)
	{
		haystack.forEach(function(value){
			if(value === needle)
				result = true;
		});
	}
	else
	{
		haystack.forEach(function(value){
			if(value == needle)
				result = true;
		});
	}
	
	return result;
}

var str_repeat = function (str, repeat)
{
	var output = '';
	for(var i = 0; i < repeat; i++)
		output += str;
	return output;
}

/* CUSTOM FUNCTIONS */

/**
* based on: http://techpatterns.com/downloads/javascript_cookies.php
*/
var cookieSet = function(name, value, expires, path, domain, secure) 
{
	// set time, it's in milliseconds
	var today = new Date();
	today.setTime(today.getTime());
	
	var expiresDate = null;
	if(expires)
		expiresDate = new Date(today.getTime() + (expires * 1000));
	
	document.cookie = name +'='+ escape(value) +
		((expires) ? ';expires='+ expiresDate.toGMTString() : '') +
		((path) ? ';path='+ path : '') +
		((domain) ? ';domain='+ domain : '') +
		((secure) ? ';secure' : '');
}
var cookieGet = function (name)
{
	// split cookies up into name/value pairs
	var cookieList = document.cookie.split(';'); // document.cookie only returns name=value
	
	var cookie = '';
	var cookieName = '';
	var cookieValue = '';
	for(i = 0; i < cookieList.length; i++)
	{
		// split apart each name=value pair
		cookie = cookieList[i].split('=');
		
		// check cookie name
		cookieName = cookie[0].replace(/^\s+|\s+$/g, ''); // trim left/right whitespaces
		if(cookieName == name)
		{
			// check if cookie has no value
			if(cookie.length > 1)
			{
				cookieValue = unescape(cookie[1].replace(/^\s+|\s+$/g, '')); // trim left/right whitespaces
				if(cookieValue.length > 1)
					return cookieValue;
			}
			return null;
		}
	}
	return false;
}
var cookieDelete = function (name, path, domain)
{
	if(cookieGet(name) !== false)
	{
		document.cookie = name +'='+
			((path) ? ";path=" + path : '') +
			((domain) ? ";domain=" + domain : '') +
			';expires=Thu, 01-Jan-1970 00:00:01 GMT';
	}
}
var cookieTest = function()
{
	var i = cookieGet('cookie');
	if(i === false)
	{
		cookieSet('cookie', '1');
		i = cookieGet('cookie');
	}
	if(i === false)
		return false;
	else
		return true;
}
/*
Toni Rantanen
http://www.kotimaa.fi/verkkopalvelut
*/


/* LIBRARY EXTENSIONS */

function arrayAssocToUrlVars(values)
{
	if(!values.length())
		return false;
	
	var result = '';
	values.reset();
	var i = 0;
	while(key = values.next())
	{
		if(i)
			result += '&';
		else
			i = 1;
		result += key +'='+ values.get(key);
	}
	return result;
}



/* GENERAL  */

function getUrl(p)
{
	if(p == 'path')
	{
		return location.protocol +'//'+ location.host + location.pathname;
	}
	else if(p == 'vars')
		return location.search.substring(1);
	else
		return location.href;
}

function getUrlPath(url)
{
	if(url == undefined)
		return getUrl('path');
	
	var vars = url.split('?', 2);
	return vars[0];
}

function getUrlVars(url)
{
	if(url == undefined)
		url = getUrl('vars');
	else
	{
		var search = url.split('?', 2);
		if(search.length == 2)
			url = search[1];
	}
	
	var vars = url.split('&');
	var result = new ArrayAssoc();
	vars.forEach(function(rawvar){
		var pos = rawvar.indexOf('=');
		var key = rawvar.substring(0, pos);
		var val = unescape(rawvar.substring(pos + 1));
		//result.push(v);
		//alert("key: "+ k);
		//alert("val: "+ v);
		//result[k] = v;
		result.add(key, val);
	});
	/*
	for(i = 0; i < vars.length; i++)
	{
		eq = vars[i].indexOf('=');
		key = vars[i].substring(0, eq);
		val = unescape(vars[i].substring(eq + 1));
		result[key] = val;
	}
	*/
	//alert("result_length: "+ result.current());
	return result;
}

function openPage(url, name, scrollbar, width, height)
{
	var left = (screen.width) ? (screen.width - width) / 2 : 100;
	var top = (screen.height) ? (screen.height - height) / 2 : 100;
	var scrollbar = (scrollbar) ? 'yes' : 'no';
	
	if(name == undefined)
	{
		var date = new Date();
		name = date.getTime();
	}
	properties = "width="+ width +",height="+ height +",scrollbars="+ scrollbar +",top="+ top +",left="+ left;
	window.open(url, name, properties);
}

// arguments[n] mukainen laajennus argumenttien käsittelyyn
// path pitäisi ottaa viimeisestä mahdollisesta urlista
function combineUrls(url, vars)
{
	var path = getUrlPath(url);
	var urlvars = getUrlVars(url);
	var newvars = getUrlVars(vars);
	urlvars.merge(newvars, true);
	return path +'?'+ arrayAssocToUrlVars(urlvars);
}

/**
* Function : dump()
* Arguments: The data - array,hash(associative array),object
*    The level - OPTIONAL
* Returns  : The textual representation of the array.
* This function was inspired by the print_r function of PHP.
* This will accept some data as the argument and return a
* text that will be a more readable version of the
* array/hash/object that is given.
*/
/*
function alertdump(val,level)
{
	if(!level) level = 0;
	alert(dump(val));
}
function docdump(val,level)
{
	if(!level) level = 0;
	document.write("<pre>"+ dump(val) +"</pre>");
}
function dump(arr,level) {
	var dumped_text = "";
	if(!level) level = 0;
	
	//The padding given at the beginning of the line.
	var level_padding = "";
	for(var j=0;j<level+1;j++) level_padding += "    ";
	
	if(typeof(arr) == 'object') { //Array/Hashes/Objects 
		for(var item in arr) {
			var value = arr[item];
			
			if(typeof(value) == 'object') { //If it is an array,
				dumped_text += level_padding + "'" + item + "' ...\n";
				dumped_text += dump(value,level+1);
			} else {
				dumped_text += level_padding + "'" + item + "' => \"" + value + "\"\n";
			}
		}
	} else { //Stings/Chars/Numbers etc.
		dumped_text = "===>"+arr+"<===("+typeof(arr)+")";
	}
	return dumped_text;
}
*/

/**
* variable/object dumper for debuging v1.0 2008.07.29
* Toni Rantanen
* http://www.kotimaa.fi/verkkopalvelut
* based on: http://www.brandnewbox.co.uk/articles/details/a_print_r_equivalent_for_javascript/ - by: A Sohn (asohn@aircanopy.net)
*/
function alertdump(obj, maxDepth, skipKeys)
{
	alert(dump(obj, maxDepth, skipKeys));
}
function docdump(obj, maxDepth, skipKeys)
{
	var result = dump(obj, maxDepth, skipKeys);
	result = result.replace(/\n/g, "<br />\n");
	result = result.replace(/    /g, "&nbsp;&nbsp;&nbsp;&nbsp;");
	//document.write("<pre>"+ result +"</pre>");
	document.write(result);
	document.close();
	return true;
}
function dumpHtml(obj, doc, maxDepth)
{
	doc = doc == undefined ? false : doc;
	/* type filtering for the future ?
	var types = new Array(
		'HTMLBodyElement',
		'HTMLDocument',
		'NamedNodeMap',
		'NodeList',
		'CSSStyleDeclaration',
		'XULControllers' // mozilla
	);*/
	var keys = new Array(
		'controllers', // mozilla xul controllers
		'parentNode',
		//'childNodes',
		'offsetParent',
		//'innerHTML',
		'firstChild',
		'lastChild',
		'previousSibling',
		'nextSibling',
		'ownerElement',
		'ownerDocument',
		'attributes',
		'style'
	);
	if(doc)
		return docdump(obj, maxDepth, keys);
	else
		return dump(obj, maxDepth, keys);
}
function dump(obj, maxDepth, skipKeys)
{
	var tmp = {dump: obj};
	return _dump(tmp, maxDepth, skipKeys);
}
function _dump(obj, maxDepth, skipKeys, indent, depth)
{
	var ws = '    ';
	var result = '';
	
	maxDepth = maxDepth == undefined ? 5 : maxDepth;
	skipKeys = skipKeys == undefined ? new Array() : skipKeys;
	indent = (!indent) ? 0 : indent;
	depth = (!depth) ? 0 : depth;
	
	if(depth > maxDepth)
	{
		result += str_repeat(ws, indent) + '*Maximum Depth Reached*\n';
		return result;
	}
	
	for(var key in obj)
	{
		var keyType = '';
		try { keyType = typeof(obj[key]); }
		catch(e) { keyType = '*Unknown type*'; }
		
		var keyStr = '';
		try { keyStr = obj[key] === null ? 'null' : obj[key].toString(); }
		catch(e) { keyStr = '*Unknown content*'; }
		
		// print type and name
		result += str_repeat(ws, indent);
		if(keyType == 'object' && keyStr.indexOf('object ') == 1)
			result += keyStr;
		else
			result += '['+ keyType +']';
		result += " '"+ key +"' => ";
		
		if(keyType == 'object')// Objects/Arrays/Hashes
		{
			if(keyStr == 'null')
				result += 'null';
			else if(!in_array(key, skipKeys))
			{
				result += '\n'+ str_repeat(ws, indent) +'(\n';
				indent++;
				result += _dump(obj[key], maxDepth, skipKeys, indent, depth + 1);
				indent--;
				result += str_repeat(ws, indent) +')';
			}
			else
			{
				result += '*Filtered object*';
			}
		}
		else // Stings/Chars/Numbers
		{
			if(keyType == 'function' && keyStr.indexOf('[native code]') != -1)
				result += '*Native*';
			else if(keyType == 'string')
				result += '"'+ keyStr +'"';
			else
				result += keyStr;
		}
		result += '\n';
	}
	
	return result;
}

/**
addLoadEvent by Simon Willison - http://simon.incutio.com/
Usage example:
addLoadEvent(nameOfSomeFunctionToRunOnPageLoad);
addLoadEvent(function() {
	// more code to run on page load
});
*/
function addLoadEvent(func)
{
	var oldonload = window.onload;
	
	// check if function has been set to the onload event
	if(typeof window.onload != 'function')
	{
		// set func as the onload event function
		window.onload = func;
	}
	else
	{
		// set container function to call old & new function
		window.onload = function()
		{
			oldonload();
			func();
		}
	}
}