/* ProgramMover version 1.1.5 - Fixed bug with loading settings including non danish channels.
 * A change require that the outer div is now absolute insted of relative.
 * The program uses the following objects.
 * ChannelHost - 
 * 		name - The name of this ChannelHost (N/A)
 *    id - The id for this ChannelHost. (N/A)
 * 		channelTargetArray - An array containing all the ChannelTarget objects which belong to this target.
 * ChannelTarget - A ChannelTarget is an dragable object.
 *		channelId - The channel id which identify the channel in the database.
 * 		parentHost - The ChannelHost object where this channelTarget is located now.
 *    orgParentHost - The original ChannelHost.
 *    xPos,yPos - The position in the grid.
 * DropTarget - Represent a position where an image is dropped. It contains the following fields:
 * 		xPos - The x position in the grid. (That is 0 for the left most position, 1 for the next one, and so on).
 *		yPos - The y position in the grid. (That is 0 for the first row, 1 for the next row and so on).
 *    targetDiv - The div that is a target for this drop. (Either myChannelsDiv or chooseChannelsDiv)'
 * myChannelsDiv/chooseProgramsDiv - The 2 divs
 * 		numChannelsInLine - The number of ChannelTarget objects that can be show besides each other  (N/A)
 * 		ImageOffset(X|Y) - The X/Y offset between images. (N/A)
 */

var myChannelsDiv;
var chooseChannelsDiv;
var channelHostArray;
var currentHost; // The ChannelHost object that are the current source channel (Visible in chooseChannels div)
// visibleMyProgramsHeight and currentMyProgramsHeight are ONLY modified by the setImage function.
// var visibleMyProgramsHeight=minMyProgramsHeight; // Height (Number of objects that can be) in the MyPrograms box. This will grow as more objects are added.
var currentMyProgramsHeight=0; // Current height of MyPrograms. (In number of channels).
var channelHostArray;  // Contains the four ChannelHost objects. (dk,uk,se,no)

var myProgramsChannelHost; // The ChannelHost object for myPrograms.
// Contains x,y for where the object that is beeing dragged must be positioned, if it is released now.
// Contains moveDown which is a boolean if the current move have resultet in objects beeing moved down.
var currentDropStatus=new Object();

function myFunc(mouseEvent) {
	if(!mouseEvent) {
		// This is ie6 or other buggy browser.
		mouseEvent=window.event;
		var src=mouseEvent.srcElement;
		while(!src.id)
			src=src.parentNode;
		targetId=src.id;
	}
	else {
		// Nice browser.
		targetId=mouseEvent.currentTarget.id;
	}
	var channel=dd.elements[targetId];

	if(channel.parentHost==myProgramsChannelHost) {
		// A move from myChannels to chooseChannels.
		moveImagesUp(myProgramsChannelHost,channel.xPos,channel.yPos);
		moveToFreeSpot(channel,channel.orgParentHost);
	 	if(channel.orgParentHost!=currentHost)
			channel.hide();
	}
	else {
		// A move from chooseChannels to myChannels
		moveImagesUp(currentHost,channel.xPos,channel.yPos);
		moveToFreeSpot(channel,myProgramsChannelHost);
	}
	dd.elements['dragImage'].hide();
}

/** Take a list of name,imagePath,channelId and create the dynamic drag and drop images, and add
 * them to the given host channel. They will have the id DynGen + channelId */
function initChannelTargetList(list,hostChannel,doMoveToFreeSpot) {
	var dndTarget=document.getElementById('dndTarget');

	for(i=0;i<list.length;i+=6) {
		var channelName=list[i];
		var channelImage=list[i+1];
		var channelId=list[i+2];
		var channelType=list[i+3];
		var imageWidth=list[i+4];
		var imageHeight=list[i+5];

		if(dd.elements['DynGen'+channelId]) {
			// This entry is already allocated, so don't do that again.
			continue;
		}
		
		var div=makeLogoDiv(channelName,channelType,channelImage,imageWidth,imageHeight,dndTarget,'DynGen'+channelId);
		div.ondblclick=myFunc;

		ADD_DHTML(div.id);
		dd.elements[div.id].setDropFunc(dropFunc);
		dd.elements[div.id].setDragFunc(dragFunc);
		dd.elements[div.id].setPickFunc(pickFunc);
		dd.elements[div.id].parentHost=hostChannel;
		dd.elements[div.id].orgParentHost=hostChannel;
		dd.elements[div.id].xPos=0;
		dd.elements[div.id].yPos=0;
		dd.elements[div.id].setCursor('move');

		if(doMoveToFreeSpot) 
			moveToFreeSpot(dd.elements[div.id],hostChannel);
		else {
			moveToFreeSpot(dd.elements[div.id],hostChannel);
			dd.elements[div.id].hide();
		}
	}
}

function saveSettings() {
	var order='';
	var channelId='';
	var counter=0;
	for(var y=0;y!=currentMyProgramsHeight;y++) {
		for(var x=0;x!=myChannelsDiv.numChannelsInLine;x++) {
			var channel=getChannelAt(myProgramsChannelHost,x,y);
			if(channel)
				channelId+="channelId[]=" + channel.id.substr(6) +"&";
			else
				channelId+="channelId[]=0&";
		}
	}
	//encode action
	SelectedSettings = 'action=save';
	//show ads
	SelectedSettings += '&ads='+dgebi('settingsAdsSelector').options[dgebi('settingsAdsSelector').selectedIndex].value;
	//activate pro summary
	SelectedSettings += '&prosummary='+dgebi('settingsProSummary').options[dgebi('settingsProSummary').selectedIndex].value;
	//select frontpage settings
	SelectedSettings += '&frontpage='+dgebi('settingsFrontpage').value;
	SelectedSettings += '&period_start='+dgebi('settingsPeriod_start').value;
	SelectedSettings += '&period_end='+dgebi('settingsPeriod_end').value;
	str='/scripts/profile/favorits.php?' + channelId + SelectedSettings;
	window.location=str;
}

function initChannelHost(languageName) {
	var host=Object();
	host.name=languageName;
	host.channelTargetArray=new Array();
	host.initialized=false;
	return host;
}

function init() {
 	// <script type='text/javascript'>SET_DHTML();</script>
	SET_DHTML();
	currentMyProgramsHeght=0;
	myChannelsDiv=document.getElementById('myChannelsDiv');
	myChannelsDiv.numChannelsInLine=configNumChannelsInMyChanneLine;
	myChannelsDiv.imageOffsetX=configImageOffsetX; // The offset between images on the x axis;
	myChannelsDiv.imageOffsetY=configImageOffsetY;  // The offset between images on the y axis;
	chooseChannelsDiv=document.getElementById('chooseChannelsDiv');
	chooseChannelsDiv.numChannelsInLine=configNumChannelsInChooseChanneLine;
	chooseChannelsDiv.imageOffsetX=configImageOffsetX;
	chooseChannelsDiv.imageOffsetY=configImageOffsetY;
	chooseChannelsDiv.extraYOffset=configExtraYOffset;
	currentDropStatus.moveDown=false;

	channelHostArray=new Array();
	channelHostArray.dk=initChannelHost('dk');
	channelHostArray.uk=initChannelHost('uk');
	channelHostArray.se=initChannelHost('se');
	channelHostArray.no=initChannelHost('no');
	channelHostArray.de=initChannelHost('de');
	channelHostArray.en=initChannelHost('en');
	channelHostArray.na=initChannelHost('na');
	myProgramsChannelHost=initChannelHost('my');
	var size=Math.max(Math.max(Math.max(Math.max(Math.max(channelTargetListdk.length,channelTargetListno.length),channelTargetListse.length),channelTargetListuk.length),channelTargetListna.length),channelTargetListen.length);
	size=Math.round(size/(6*chooseChannelsDiv.numChannelsInLine)+0.5);
	chooseChannelsDiv.style.height=(chooseChannelsDiv.imageOffsetY*size) + 'px';

	initChannelTargetList(channelTargetListdk,channelHostArray.dk,true);
	channelHostArray.dk.initialized=true;

	currentHost=channelHostArray.dk;
	var dragImage=makeDivWithImage('dragImage','/imgs/programmove/dragImage.gif',document.getElementById('dndTarget'));
	ADD_DHTML(dragImage.id);
	dd.elements.dragImage.hide();
}

/* Return the yPos for the lowest free position with the given xPos at the given host */
function getLowestFreePos(host,xPos) {
	for(name in host) {
		for(var y=0;;y++) {
			if(getChannelAt(host,xPos,y)==null)
				return y;
		}
	}
	alert("No free channel found");
}

function pickFunc() {
	var pickObject=dd.obj;
	pickObject.setOpacity(configOpaqueValue);
	if(pickObject.parentHost==myProgramsChannelHost) {
		removeImageFromHostChannel(pickObject);
		currentDropStatus.moveDown=true;
	}
	currentDropStatus.x=dd.obj.xPos;
	currentDropStatus.y=dd.obj.yPos;
}

/** This function removes the image from the host channel. It should be called
 * when an drag is starting.
 */
function removeImageFromHostChannel(channel) {
	channel.parentHost.channelTargetArray[channel.id]=null;
}

var first=true
function dragFunc() {
	var dragObject=dd.obj;
	var dropTarget=getDropTarget(dragObject.x-dragObject.defx,dragObject.y-dragObject.defy,dragObject);
	var host=myProgramsChannelHost;

	window.status= ("dragFunc currentDropStatus.x,y=" + currentDropStatus.x + "," + currentDropStatus.y);
	if(currentDropStatus.moveDown) {
		// Find out if this drag moved the channel in a way that causes other channels to move up.
		if(!dropTarget) {
			moveImagesUp(host,currentDropStatus.x,currentDropStatus.y+1);
			currentDropStatus.moveDown=false;
		}
		else if(dropTarget.xPos!=currentDropStatus.x || dropTarget.yPos!=currentDropStatus.y) {
			moveImagesUp(host,currentDropStatus.x,currentDropStatus.y+1);
			currentDropStatus.moveDown=false;
		}
	}

	if(dropTarget && dropTarget.targetDiv==myChannelsDiv) {
		// First find out if there is an other channel below this.
		var channel;
		if(currentDropStatus.moveDown==false && (channel=getChannelAt(host,dropTarget.xPos,dropTarget.yPos))) {
			currentDropStatus.moveDown=true;
			dd.elements['dragImage'].hide();
			moveImagesDown(host,dropTarget.xPos,dropTarget.yPos);

			currentDropStatus.x=dropTarget.xPos;
			currentDropStatus.y=dropTarget.yPos;
			moveDragSelectionTo(dropTarget.xPos,dropTarget.yPos);
		}
		else {
			var yPos=getLowestFreePos(host,dropTarget.xPos);

			currentDropStatus.x=dropTarget.xPos;
			currentDropStatus.y=yPos;
			moveDragSelectionTo(dropTarget.xPos,yPos);
		}
	}
	else {
		dd.elements['dragImage'].hide(); // moveTo(0,-100);
	}
}

function moveDragSelectionTo(xPos,yPos) {
	var drag=dd.elements['dragImage'];
	var xPixelPos=drag.defx+xPos*myChannelsDiv.imageOffsetX;
	var yPixelPos=yPos*myChannelsDiv.imageOffsetY+drag.defy;
	drag.moveTo(xPixelPos + configMarginLeft,yPixelPos);
	drag.show();
}

/** Move this image to a new position */
function moveTargetChannel(channel,host,xPos,yPos) {
	// Find the first free position.
	var freePos=-1;
//	for(i=yPos;i!=visibleMyProgramsHeight;i++) {
	for(i=yPos;i!=currentMyProgramsHeight+1;i++) {
		if(getChannelAt(host,xPos,i)==null) {
			freePos=i;
			break;
		}
	}
	setImage(channel,host,xPos,yPos);
	if(freePos>yPos) {
		for(i=freePos-1;i!=yPos-1;i--) {
			var channel=getChannelAt(host,xPos,i);
			setImage(channel,host,xPos,i+1);
		}
	}
}

/** Move all images at positon xPos,yPos and below one sted down. */
function moveImagesDown(host,xPos,yPos) {
//	for(var y=visibleMyProgramsHeight;y!=yPos-1;y--) {
	for(var y=currentMyProgramsHeight;y!=yPos-1;y--) {
		var channel=getChannelAt(host,xPos,y);
		if(channel) {
			setImage(channel,host,channel.xPos,channel.yPos+1);
		}
	}
}

/** Move all images at positon xPos,yPos and below one sted up. */
function moveImagesUp(host,xPos,yPos) {
	for(var y=yPos;;y++) {
		var channel=getChannelAt(host,xPos,y);
		if(!channel) {
			break;
		}
		setImage(channel,host,channel.xPos,channel.yPos-1);
	}
}

/** Return the channel at the given position, or null if theres no channel there 
 * (Maa kunne laves smart med en general foreach og en inline funktion).
 */
function getChannelAt(host,xPos,yPos) {
	for(name in host.channelTargetArray) {
		var channel=host.channelTargetArray[name];
  	if(!channel)
  		continue;
		if(channel.xPos==xPos && channel.yPos==yPos) {
			return channel;
		}
	}
	return null;
}

/** Move this channel back to its last known good position. */
function revertMove(channel) {
		if(channel.parentHost==myProgramsChannelHost) {
			moveImagesDown(channel.parentHost,channel.xPos,channel.yPos);
	}
	setImage(channel,channel.parentHost,channel.xPos,channel.yPos);	
}

/** This function is called each time an channel is dropped */
function dropFunc() {
	var channel=dd.obj;
	channel.setOpacity(1.0);

	var dropTarget=getDropTarget(channel.x-channel.defx,channel.y-channel.defy);
	if(dropTarget==null) {
		revertMove(channel);
	}
	else if(dropTarget.targetDiv==myChannelsDiv) {
		if(channel.parentHost==currentHost) {
			moveImagesUp(channel.parentHost,channel.xPos,channel.yPos);
		}
		moveTargetChannel(channel,myProgramsChannelHost,currentDropStatus.x,currentDropStatus.y);
	}
	else if(dropTarget.targetDiv==chooseChannelsDiv) {
		if(channel.parentHost!=myProgramsChannelHost) {
			// An internal move in the chooseChannels box is not posible, so just move it back.
			revertMove(channel);
		}
		else {
			if(channel.orgParentHost!=currentHost)
				channel.hide();
 			moveToFreeSpot(channel,channel.orgParentHost);
		}
	}
	else {
		alert("Error, Unknown drop target");
	}
	currentDropStatus.moveDown=false;
}

/** Return a DropTarget object, for the given position. Or null if it's not a valid drop target. */
function getDropTarget(x,y) {
//	alert("Pixel hit (" + x + "," + y + ")");

	var dropTarget=new Object();
	// Calculate posible hit for myChannelsDiv
	var xPos=Math.round(x/myChannelsDiv.imageOffsetX);
	var yPos=Math.round(y/myChannelsDiv.imageOffsetY);

//	alert("Hit at (" + xPos + "," + yPos + ")");

	channel=dd.obj;
//	if(xPos>=0 && xPos<myChannelsDiv.numChannelsInLine && yPos>=0 && yPos<visibleMyProgramsHeight) {
	if(xPos>=0 && xPos<myChannelsDiv.numChannelsInLine && yPos>=0 && yPos< Math.max(minMyProgramsHeight,currentMyProgramsHeight+1)) {
		// This is a hit in myChannelsDiv.
		dropTarget.xPos=xPos;
		dropTarget.yPos=yPos;
		dropTarget.targetDiv=myChannelsDiv;
	}
	else {
		var yPos=Math.round( (y-chooseChannelsDiv.extraYOffset)/chooseChannelsDiv.imageOffsetY);
//		alert("Second Hit at (" + xPos + "," + yPos + ")");

		if(xPos>=0 && xPos<chooseChannelsDiv.numChannelsInLine && yPos>=0 && yPos<=currentMyProgramsHeight) {
			// This is a hit to chooseChannelsDiv
			dropTarget.xPos=xPos;
			dropTarget.yPos=yPos;
			dropTarget.targetDiv=chooseChannelsDiv;
 		}
		else {
			// No hit.
			dropTarget=null;
		}
	}
	return dropTarget;
}

/*
 * Add the given targetChannel to this targetElement at the first free spot.
*/
function moveToFreeSpot(channel,host) {
	var numChannelsInLine= (host==myProgramsChannelHost ? myChannelsDiv.numChannelsInLine : chooseChannelsDiv.numChannelsInLine);
	for(y=0;;y++) {
		for(x=0;x!=numChannelsInLine;x++) {
			if(getChannelAt(host,x,y)==null) {
				setImage(channel,host,x,y);
				return;
			}
		}
	}
}

/*
 * Add the given targetChannel to this targetElement at the given pos.
 * targetChannel is an Channel object, and targetElement is a div element
 * which contains channel objects.
*/
function setImage(targetChannel,host,xPos,yPos) {
	if(targetChannel.parentHost) {
		targetChannel.parentHost.channelTargetArray[targetChannel.id]=null;
	}
	targetChannel.parentHost=host;
	host.channelTargetArray[targetChannel.id]=targetChannel;
	targetChannel.xPos=xPos;
	targetChannel.yPos=yPos;
	var y=+yPos*myChannelsDiv.imageOffsetY+targetChannel.defy+(host==myProgramsChannelHost ? 0 : chooseChannelsDiv.extraYOffset);

	targetChannel.moveTo(targetChannel.defx+xPos*myChannelsDiv.imageOffsetX+configMarginLeft,y);

	if(host==myProgramsChannelHost) {
		if(currentMyProgramsHeight==yPos) {
			// This move increases the currentMyProgramsHeight.
			currentMyProgramsHeight=yPos+1;

			if(currentMyProgramsHeight >= minMyProgramsHeight) {
				myChannelsDiv.style.height=pixelAdd(myChannelsDiv.style.height,41);
				chooseChannelsDiv.extraYOffset+=41;
				fixChooseChannels(true);
			}
		}
		else if(currentMyProgramsHeight >= minMyProgramsHeight) {
			// Find out if the myChannelsDiv need to shrink
			var shrink=true;
			for(var x=0;x!=myChannelsDiv.numChannelsInLine;x++) {
				if(getChannelAt(host,x,currentMyProgramsHeight-1)) {
					shrink=false;
					break;
				}
			}
			if(shrink) {
				currentMyProgramsHeight--;
				fixChooseChannels(false);
				myChannelsDiv.style.height=pixelAdd(myChannelsDiv.style.height,-41);
				chooseChannelsDiv.extraYOffset-=41;
			}
		}
	}
	else {
		
	}
}

/** Move all images in ChooseChannels 41 pixels up or down. */
function fixChooseChannels(moveUp) {
	for(hostName in channelHostArray) {
		var host=channelHostArray[hostName];
		
		for(name in host.channelTargetArray) {
			var channel=host.channelTargetArray[name];
	  	if(!channel)
	  		continue;
			channel.moveBy(0,41*(moveUp?1:-1));
		}
	}
}

function idToNum(id) { return parseInt(id.substr(0,2)); }
function numToId(num) { return 'id' + num; }

function dkChannels() {
	if(currentHost!=channelHostArray.dk) {
		if(channelHostArray.dk.initialized==false) {
			initChannelTargetList(channelTargetListdk,channelHostArray.dk,true);
			channelHostArray.dk.initialized=true;
		}

		hideAllChannelsForHost(currentHost);
		showAllChannelsForHost(channelHostArray.dk);
		currentHost=channelHostArray.dk;
		changeChannelsSelected('DK');
	}
}
function seChannels() {
	if(currentHost!=channelHostArray.se) {
		if(channelHostArray.se.initialized==false) {
			initChannelTargetList(channelTargetListse,channelHostArray.se,true);
			channelHostArray.se.initialized=true;
		}

		hideAllChannelsForHost(currentHost);
		showAllChannelsForHost(channelHostArray.se);
		currentHost=channelHostArray.se;
		changeChannelsSelected('SE');
	}
}
function deChannels() {
	if(currentHost!=channelHostArray.de) {
		if(channelHostArray.de.initialized==false) {
			initChannelTargetList(channelTargetListde,channelHostArray.de,true);
			channelHostArray.de.initialized=true;
		}

		hideAllChannelsForHost(currentHost);
		showAllChannelsForHost(channelHostArray.de);
		currentHost=channelHostArray.de;
		changeChannelsSelected('DE');
	}
}

function ukChannels() {
	if(currentHost!=channelHostArray.uk) {
		if(channelHostArray.uk.initialized==false) {
			initChannelTargetList(channelTargetListuk,channelHostArray.uk,false);
			channelHostArray.uk.initialized=true;
		}

		hideAllChannelsForHost(currentHost);
		showAllChannelsForHost(channelHostArray.uk);
		currentHost=channelHostArray.uk;
		changeChannelsSelected('UK');
	}
}

function noChannels() {
	if(currentHost!=channelHostArray.no) {
		if(channelHostArray.no.initialized==false) {
			initChannelTargetList(channelTargetListno,channelHostArray.no,false);
			channelHostArray.no.initialized=true;
		}
		hideAllChannelsForHost(currentHost);
		showAllChannelsForHost(channelHostArray.no);
		currentHost=channelHostArray.no;
		changeChannelsSelected('NO');
	}
}

function enChannels() {
	if(currentHost!=channelHostArray.en) {
		if(channelHostArray.en.initialized==false) {
			initChannelTargetList(channelTargetListen,channelHostArray.en,false);
			channelHostArray.en.initialized=true;
		}
		hideAllChannelsForHost(currentHost);
		showAllChannelsForHost(channelHostArray.en);
		currentHost=channelHostArray.en;
		changeChannelsSelected('EN');
	}
}

function naChannels() {
	if(currentHost!=channelHostArray.na) {
		if(channelHostArray.na.initialized==false) {
			initChannelTargetList(channelTargetListna,channelHostArray.na,false);
			channelHostArray.na.initialized=true;
		}
		hideAllChannelsForHost(currentHost);
		showAllChannelsForHost(channelHostArray.na);
		currentHost=channelHostArray.na;
		changeChannelsSelected('NA');
	}
}

function changeChannelsSelected(selectedLang) {
	$('#channelsSelectedDK').removeClass('faneSelected');
	$('#channelsSelectedSE').removeClass('faneSelected');
	$('#channelsSelectedNO').removeClass('faneSelected');
	$('#channelsSelectedUK').removeClass('faneSelected');
	$('#channelsSelectedDE').removeClass('faneSelected');
	$('#channelsSelectedEN').removeClass('faneSelected');
	$('#channelsSelectedNA').removeClass('faneSelected');
	$('#channelsSelected'+selectedLang).addClass('faneSelected');
}

/** Hide all channels that are owned by the given host */
function hideAllChannelsForHost(host) {
	for(name in host.channelTargetArray) {
		var channel=host.channelTargetArray[name];
  	if(!channel)
  		continue;
		channel.hide();
	}
}

function showAllChannelsForHost(host) {
	for(name in host.channelTargetArray) {
		var channel=host.channelTargetArray[name];
  	if(!channel)
  		continue;
		channel.show();
	}
}
/* Create a div tag called divId. append a img as a child to this div,
 * and append the div to the given parent node.
 * result: The newly created div node.
 */
var priv_magicOffset=-38;
var divImageCounter=0;
function makeDivWithImage(divId,imagePath,parentNode) {
	var div=document.createElement('div');
	var img=document.createElement('img');
	img.src=imagePath;
	img.width=234;
	img.height=36;
	div.style.position="absolute";
	div.style.top='0px';
	div.style.left='0px';
	div.style.width='232px';
	div.style.height='34px';
	div.id=divId;
	div.appendChild(img);
	parentNode.appendChild(div);
	return div;
}

function makeLogoDiv(channelName,channelType,imagePath,imageWidth,imageHeight,parentNode,divId) {
// alert(channelName+","+channelType+","+imagePath+","+imageWidth+","+imageHeight+","+parentNode+","+divId);
	var div=document.createElement('div');
	div.className='programMoverDiv';
	div.style.top='0px';
	div.style.left='0px';
	div.style.width='232px';
	div.style.height='34px';

	div.id=divId;

	var span1=document.createElement('div');
	span1.className='programMoverTitle';
	span1.appendChild(document.createTextNode(channelName));

	div.appendChild(span1);
	var span2=document.createElement('div');
	span2.className='programMoverType';
	span2.appendChild(document.createTextNode(channelType));
	div.appendChild(span2);

	var img=document.createElement('img');
	img.src=imagePath;
	img.width=imageWidth;
	img.height=imageHeight;
	img.style.position='absolute';
	img.style.right=0;
	img.style.top=Math.round((36-imageHeight)/2-0.5)+'px';
	img.className='programMoverImage'
	div.appendChild(img);

	parentNode.appendChild(div);
	return div;
}

/** currentHeight is a height in pixels(Such as the string 10px) and the result is a new pixel string where 
 * add have been added to the height.
 */
function pixelAdd(currentHeight,add) {
	return (parseInt(currentHeight.substr(0,currentHeight.length-2))+add) + 'px';
}

/** arrayLookupByKey. I can't belive there is not a function to do this, but I could not find it. 
	Note that this method work on all Object. (Because Object is a hashmap, so it really is a method
	to find if out if the object have a field with the given value.
	Return the name of the field that contanis the key, null if the value is not found.
	The key is only returned if (key%mod)==pos
*/
function hashmapLookupByValue(value,array,pos,mod) {
	var counter=0;
	for(name in array) {
		if(array[name]==value && ((counter%mod)==pos)) {
			return name;
		}
		counter++;
	}
	return null;
}


