﻿
// add multiple loadevents: use it AFTER the start of body tag
// to preserve inline functions!
// (source: http://simon.incutio.com/archive/2004/05/26/addLoadEvent)

function addLoadEvent(func) {
	var oldonload = window.onload;
	if (typeof window.onload != 'function') 
	{
		window.onload = func;
	} else {
		window.onload = function() {
			if (oldonload) { oldonload(); }
			func();
		}
	}
}

// = = = = = = = = = = = = = = = = = = = = = = = = = = =
// DOMPARSER FOR IE AND SAFARI
// (source: http://erik.eae.net/archives/2005/07/03/20.19.18/)
// = = = = = = = = = = = = = = = = = = = = = = = = = = =

if (typeof DOMParser == "undefined") {
	DOMParser = function () {}
	
	DOMParser.prototype.parseFromString = function (str, contentType) {
	  if (typeof ActiveXObject != "undefined") {
		 var d = new ActiveXObject("MSXML.DomDocument");
		 d.loadXML(str);
		 return d;
	  } else if (typeof XMLHttpRequest != "undefined") {
		 var req = new XMLHttpRequest;
		 req.open("GET", "data:" + (contentType || "application/xml") +
						 ";charset=utf-8," + encodeURIComponent(str), false);
		 if (req.overrideMimeType) {
			req.overrideMimeType(contentType);
		 }
		 req.send(null);
		 return req.responseXML;
	  }
	}
}

// = = = = = = = = = = = = = = = = = = = = = = = = = = =
// SPECIAL EVENTS
// = = = = = = = = = = = = = = = = = = = = = = = = = = =

//mouseenter/leave emulation based on pattern 
//recognition instead of cancelling the bubble
function onMouseLeave( pTarget, pAction ) {
	pTarget.realLeaveFunction = pAction; //store action
	pTarget.leaveFunction = function() { pTarget.realLeaveFunction(); }

	if (pTarget.onmouseout) pTarget.onmouseoutSave1 = pTarget.onmouseout; //Save1 previous mouseout
	pTarget.onmouseout = function() {
		if (pTarget.onmouseoutSave1) pTarget.onmouseoutSave1();
		this.ltimer = setTimeout(this.leaveFunction.bind(this),100);
	}
	
	if (pTarget.onmouseover) pTarget.onmouseoverSave1 = pTarget.onmouseover; //Save1 previous mouseover
	pTarget.onmouseover = function() {
		if (pTarget.onmouseoverSave1) pTarget.onmouseoverSave1();
		clearTimeout(this.ltimer);
	}

}

function onMouseEnter( pTarget, pAction ) {
	
	pTarget.enterFunction = pAction; //store action
	
	pTarget.stepPattern = function() { this.epattern = -1; } //reset pattern

	if (pTarget.onmouseover) pTarget.onmouseoverSave2 = pTarget.onmouseover; //save previous mouseover
	pTarget.onmouseover = function() {
		if (pTarget.onmouseoverSave2) pTarget.onmouseoverSave2();
		if (this.epattern == 1) { this.epattern = 0; clearTimeout(this.etimer); }
			else { (this.epattern = 0); this.enterFunction(); }
	}
	
	if (pTarget.onmouseout) pTarget.onmouseoutSave2 = pTarget.onmouseout; //save previous mouseout
	pTarget.onmouseout = function() {
		if (pTarget.onmouseoutSave2) pTarget.onmouseoutSave2();
		if (this.epattern == 0) this.epattern = 1;
		this.etimer = setTimeout(this.stepPattern.bind(this),100);
	}
}


// = = = = = = = = = = = = = = = = = = = = = = = = = = =
// PROTOTYPE ENHANCEMENT
// = = = = = = = = = = = = = = = = = = = = = = = = = = =


//shorthand for getElementsByTagName
function $T() {
	var elements = new Array();
	var elStrings = new Array();
	var elObjects = new Array();
	
	for (var i = 0; i < arguments.length; i++) { 
		if (arguments[i] != null)
			if (typeof arguments[i] == 'string') elStrings.push(arguments[i])
				else elObjects.push(arguments[i]); 
	}
	
	elObjects.each( function(eo){ 
		elStrings.each( function(es){ 
			elements = elements.concat($A( eo.getElementsByTagName(es) ));
		});
	});

	return elements;
}

//string.trim -- remove whitespace
String.prototype.ltrim = function () { var re = /\s*((\S+\s*)*)/; return this.replace(re, "$1"); }
String.prototype.rtrim = function () { var re = /((\s*\S+)*)\s*/; return this.replace(re, "$1"); }
String.prototype.trim = function () { return this.rtrim().ltrim(); }

//string.toArray
String.prototype.toArray = function() {
	var pString = this;
	var retArr  = new Array();
	for (var i = 0; i < pString.length; i++) retArr.push(pString.substr(i,1));
	return retArr;
}

//string.toUrlParams
String.prototype.toUrlParams = function( /*pValuePairs*/ ) {
    var pString = this;
    var m = 0;
    for (var i = 0; i < arguments.length; i++) { 
		if (arguments[i] != null)
			if (typeof arguments[i] == 'string')
                if (!arguments[i].has('=null')) //never send nulls!
                {
                    if (m > 0) pString += "&"; 
                    pString += arguments[i];
                    m++;
                }
	}
    if (m > 0) pString = "?" +  pString;
	return pString;
}

//+array.toString -- only for valid indexes
Array.prototype.toString = function() {
	var retString = new String();
	var pArr  = this;
	pArr.each( function(ae) { retString += ae });
	return retString;
}


//array.has (uses proto's indexOf)
Array.prototype.has = function( pItem) {
	if (this.indexOf( pItem ) != -1) return true
		else return false;
}

//array.remove (remove item, NOT the item at index)
Array.prototype.remove = function( pItem ) {
	var pos = this.indexOf( pItem );
	if (pos != -1) this.splice(pos,1);
}

//string.has
String.prototype.has = function ( pSubStr ) { if (this.indexOf(pSubStr)!=-1) { return(true); } else return(false); }

//string.flip -- change first substring to second and vice versa
String.prototype.flip = function( pFrom, pTo ) {
	if (this.has(pFrom)) return(this.replace(pFrom,pTo))
		else return(this.replace(pTo,pFrom));
}

//string.addOrRemove -- removes if exists, add otherwise
String.prototype.addOrRemove = function( pSubString ) {
	if (this.has(pSubString)) return(this.replace(pSubString,''))
		else return(this+pSubString);
}

//string.remove
String.prototype.remove = function( pSubString ) { return(this.replace(pSubString,'')); }

//string.addonce -- add if does not exist
String.prototype.addonce = function( pSubString ) { if (!this.has(pSubString)) return (this+pSubString); else return (this); }

//string.toXML
String.prototype.toXML = function () { return ((new DOMParser()).parseFromString(this, "text/xml")); }

//xmlEntities
String.prototype.xmlEntities = function() {
	var pString = this;
	pString = pString.replace(/&nbsp;/gi,'\u00a0'); //nbsp
	pString = pString.replace(/&amp;/gi,'\u0026'); //amp
	return pString;
}

//string.filter -- filter out characters based on regexp
String.prototype.filter = function( pRegexp ) {
	var validChars = pRegexp;
	var stringBuff = this;
	var failed = 0;
	var selChar = new String();
	
	for (var i = 0; i < stringBuff.length; i++)
	{
		var selChar = stringBuff.substr(i,1);
		if (selChar.match(validChars)==null)
		{
			failed = 1;
			stringBuff = stringBuff.replace(selChar,'?');
		}
	}
	if (failed == 1) { stringBuff = stringBuff.replace(/\?/gi,''); }
	return(stringBuff);
}


//window.setHeight without prototyping
window.setHeight = function( pNum ) { window.resizeBy( 0, pNum - document.documentElement.clientHeight ); }

//event.parent wo proto (IE still sucks)
Event = new Object();
Event.parent = function( pEvent ) {
	if (pEvent.srcElement) return pEvent.srcElement
			else if (pEvent.target) return pEvent.target
				else return null;
}

//enhance proto's Element (singletonish)
Object.extend(Element, {

	//Element.append - the cleaner way... proto 1.5 will be better with its Element.Methods
	//can accept text when pChild's first char is "$"
	append: function( pTarget, pChild ) { 
		if (pChild.indexOf('$') == 0) return pTarget.appendChild( document.createTextNode( pChild.substr(1,pChild.length-1).xmlEntities() ) );
			else return pTarget.appendChild( document.createElement( pChild ) ); 
	},
	
	//Element.genocide - kill all children 
	genocide: function( pTarget ){
		if (typeof(pTarget) == "string") pTarget = $(pTarget); //is it okay? other methods are still dumb!!
		if (pTarget == null) return false;
		
		while (pTarget.childNodes[0]) { pTarget.removeChild(pTarget.childNodes[0]); }
		return true;
	},
	
	//Element.suicide - destroy self, the nice way
	suicide: function( pTarget ){ pTarget.parentNode.removeChild(pTarget); },
	
	//Element.alpha (aka setOpacity in Scripta)	
	alpha: function( pTarget, opacity ) {
		opacity = (opacity == 100)?99.999:opacity;
		pTarget.style.filter = "alpha(opacity:"+opacity+")";
		pTarget.style.KHTMLOpacity = opacity/100;
		pTarget.style.MozOpacity = opacity/100;
		pTarget.style.opacity = opacity/100;
	}
	
});

//kill events
function destroyOnClick( pItem ) {
	pItem.onclick = function(){}
}



// = = = = = = = = = = = = = = = = = = = = = = = = = = =
// ADD BROWSER DETECTION ROUTINES HERE
// = = = = = = = = = = = = = = = = = = = = = = = = = = =

var isIE = false; //because ie performance is pure crap
if (navigator.userAgent.has("MSIE")) isIE = true;


// = = = = = = = = = = = = = = = = = = = = = = = = = = =
// WARNING MESSAGE DUMPER
// = = = = = = = = = = = = = = = = = = = = = = = = = = =

var warnBuffer = new String;
var d_debugMode = false;
function sayWarning(pString) {
    if (d_debugMode == true)
    {
        target = $('warningMessages');
        pString = '<p>'+String(pString).escapeHTML()+'</p>';
        if (target == undefined)
        {
            /*addLoadEvent(function(){ //rewritten*/
                var bufftarget = Element.append(document.body,'DIV');
                bufftarget.id='warningMessages';
                bufftarget.style.display = 'block'; //!
                bufftarget.clear = function() { this.innerHTML = ''; }
                bufftarget.hide  = function() { this.style.display = 'none'; }
                bufftarget.innerHTML = pString;
            /*});*/
        } else {
            
            target.style.display = 'block';
            target.innerHTML += pString;
        }
    }
}

// = = = = = = = = = = = = = = = = = = = = = = = = = = =
// PERFORMANCE DEBUG
// = = = = = = = = = = = = = = = = = = = = = = = = = = =

/*usage:
tm = new tTimeMeasurement();
doSomething();
tm.stop();
alert(tm.result);
*/

var tTimeMeasurement = Class.create();
tTimeMeasurement.prototype = {
	
	initialize: function( pTarget, pClass, pTimes ){
		this.catchctime();
		this.oldms = this.catchctime(); 
	},
	
	catchctime: function() {
		this.clientTime = new Date()
		this.h  = this.clientTime.getHours();
		this.m  = this.clientTime.getMinutes();
		this.s  = this.clientTime.getSeconds();
		this.ms = this.clientTime.getMilliseconds();
		return (this.ms + this.s*1000 + this.m*60*1000 + this.h*60*60*1000);
	},
	
	stop: function () {
		this.result = this.catchctime() - this.oldms;
	}
}


// = = = = = = = = = = = = = = = = = = = = = = = = = = =
// SMALL EFFECTS
// = = = = = = = = = = = = = = = = = = = = = = = = = = =


tEffect_ClassVibration = Class.create();
tEffect_ClassVibration.prototype = {
	
	initialize: function( pTarget, pClass, pTimes ){
		this.target = pTarget;
		this.cssClass = pClass;
		this.oldClass = '';
		
		this.times = 0;
		//if (pTimes%2==0) this.times++;
		this.times = pTimes*2;
		this.counter = 0;
		this.odd = false;
		
		if (this.target.className != '') this.oldClass = this.target.className;
		
		//place effect-lock on DOM element, not the object this time;
		//otherwise just initiate timer and call lockdown
		if ((this.target.effectLock == undefined) || (this.target.effectLock == false))
		{
			this.target.effectLock = true;
			this.timer = setInterval(this.onTimer.bind(this),8);
		}
	},
	
	onTimer: function () {
		this.counter++;
		if ((this.counter == 10) && (this.times != 0))
		{ 
			this.odd = !this.odd; 
			this.counter = 0;
			this.times--;
			if (this.odd) { this.target.className = this.cssClass; }
				else this.target.className = this.oldClass;
		}
        
		//clear effect and break lock
		if ( this.times == 0) 
		{
			clearInterval(this.timer);
			this.target.effectLock = false;
		}
	}
}

tEffect_ClassFlipFlop = Class.create();
tEffect_ClassFlipFlop.prototype = {
	
	initialize: function( pTarget, pClass, pInterval ){
		this.target = pTarget;
		this.cssClass = pClass;
		this.oldClass = '';
		this.interval = pInterval;
		this.counter = 0;
		
		if (this.target.className != '') this.oldClass = this.target.className;
		if ((this.target.effectLock == undefined) || (this.target.effectLock == false))
		{
			this.target.effectLock = true;
			this.target.className = this.cssClass;
			this.timer = setTimeout(this.onTimer.bind(this), this.interval );
		}
	},
	
	onTimer: function () {
		this.target.className = this.oldClass;
		this.target.effectLock = false;
	}
}

//collect individual effects into wrapper object
var kEffect = new Object();
kEffect.classVibration = tEffect_ClassVibration;
kEffect.classFlipFlop  = tEffect_ClassFlipFlop;

// = = = = = = = = = = = = = = = = = = = = = = = = = = =
// XMLHELPER OBJECT
// = = = = = = = = = = = = = = = = = = = = = = = = = = =

var tXMLHelper = Class.create(); //IE sucks big time
tXMLHelper.prototype = {
			
	initialize: function( pXMLDocument ){
		this.xmldocument = pXMLDocument;
	},
	
	getFirstValue: function ( pTag ) {
		if (pTag.has('.')) 
		{
			var pTags = pTag.split('.');
			return(this.xmldocument.getElementsByTagName(pTags[0])[0].getAttribute(pTags[1]));
		}
		if ((this.xmldocument.getElementsByTagName(pTag)[0].firstChild) == null) return ''; //tag IS empty!
		return(this.xmldocument.getElementsByTagName(pTag)[0].firstChild.nodeValue);
	},
	
	getAll: function ( pTag ) { 
		//return(this.xmldocument.getElementsByTagName(pTag)[0].getElementsByTagName('*'));
	},
	
	nodeExists: function ( pTag ) {
		if (this.xmldocument.getElementsByTagName(pTag)[0] == undefined) return false
				else return true;
	},
	
	nodeToString: function ( pTag ) {
		var xmlNode = this.xmldocument.getElementsByTagName(pTag)[0];
		var text = '';
		if (xmlNode.text) text = xmlNode.text
				else text = xmlNode.textContent;
		if (text == undefined) text = '';
		return text; //#WARNING: modified after revision #69
	}
}

// = = = = = = = = = = = = = = = = = = = = = = = = = = =
// COOKIE OBJECT
// = = = = = = = = = = = = = = = = = = = = = = = = = = =

var tCookie = Class.create();
Object.extend(tCookie.prototype, {

	initialize: function() {
	},
	

	set: function(name,value,days)
	{
		if (days)
		{
			var date = new Date();
			date.setTime(date.getTime()+(days*24*60*60*1000));
			var expires = "; expires="+date.toGMTString();
		}
		else var expires = "";
		document.cookie = name+"="+value+expires+"; path=/";
	},

	get: function(name)
	{
		var nameEQ = name + "=";
		var retVal = null;
		var cookies = document.cookie.split(';');
		cookies.each(function(cookieItem){
			while (cookieItem.charAt(0)==' ') cookieItem = cookieItem.substring(1,cookieItem.length);
			if (cookieItem.indexOf(nameEQ) == 0) retVal = cookieItem.substring(nameEQ.length,cookieItem.length);
		});
		return retVal;
	},

	erase: function(name)
	{
		this.set(name,"",-1);
	}

});
var simpleCookie = new tCookie();


// = = = = = = = = = = = = = = = = = = = = = = = = = = =
// HEARTBEAT / PULSE
// = = = = = = = = = = = = = = = = = = = = = = = = = = =

// initiates a pulse with a queue;
// all objects attached to the queue should have a tick
// function which will be called upon tick; it is the object, 
// who should take care of suspend/resume self.

function tick( pTarget) {
	//if (g_superLock == false) //#TODO: az ora keseset megoldani?? kell ez egyaltalan??
		executionQueue.each( function(execItem){
			if (execItem.tick()) execItem.tick();
		});
}

var pe = new PeriodicalExecuter(tick, 1); //global speed in secs; DO NOT MODIFY!
var executionQueue = new Array();
var g_superLock = false;

// = = = = = = = = = = = = = = = = = = = = = = = = = = =
// CORE TICKABLE OBJECT
// = = = = = = = = = = = = = = = = = = = = = = = = = = =

var tTickable = Class.create();
tTickable.prototype = {
	
	initialize: function() {

		this.locked = false;
		this.launchAtTick = 1;
		this.tickCounter = 1;
		
		executionQueue.push(this);
		this.postInit();
	},
	
	postInit: function(){
		//extend this
	},
	
	freeze: function() {
		executionQueue.remove(this);
	},
	
	isValidResponse: function( pResponse ) {
		if ((pResponse == undefined) || (pResponse == null) || (pResponse == '')) return false;
			else return true;
	},
	
	unlock: function() { this.locked = false; },
	
	lock: function() { this.locked = true; },
	
	canRun: function() {
		this.tickCounter--;
		if (this.tickCounter == 0) 
		{
			this.tickCounter = this.launchAtTick;
			return true;
		} else {
			return false;
		}
	},
	
	setFrequency: function( pSecs ) {
		this.launchAtTick = pSecs * 1;
	},
	
	forceTick: function( pSecs ) {
		this.tickCounter = 1;
		this.tick();
	},
	
	innerTick: function() {
		//extend this
	},
	
	tick: function() {
		if (this.canRun())
		{
			if (this.locked == false)
			{
				this.lock();
				this.innerTick();				
				this.unlock();
			}
		}
	}
	
}


