/* * Copyright (c) 2007 Tom Coote (http://www.tomcoote.co.uk) * This is licensed under GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program.  If not, see <http://www.gnu.org/licenses/>. * */ /******************************************	Corner Dock Navigation	Author: Tom Coote	Date: 24/06/2007	Web Site: tomcoote.co.uk********************************************//* CornerDock* The main power constructor which creates and returns a new JavaScript object.*/function JSCornerDock(sID, iAreaHeight, iAreaWidth) {	var that = {}; // Must use 'that' so not to confuse with 'this' which is the global object.	/* Private Variables 	*	* These variables can only be accessed by functions inside the scope of	* any instantiation of this constructor.	*/	var iDimensionsBig = 150,		iDimensionsMedium = 100,		iDimensionsSmall = 50;	var eDockArea,		Animations = {}, // Object to store animation info for each dock pic.		speed = 1;    /* Private Functions 	*	* These functions can only be accessed by functions inside the scope of	* any instantiation of this constructor.	*/	function InitiateDock() {		eDockArea = document.getElementById(sID);		var eDockLinks = eDockArea.getElementsByTagName('a'),			i, eImg,			iMiddle = Math.round(eDockLinks.length/2);		eDockArea.style.height = iAreaHeight+'px';		eDockArea.style.width = iAreaWidth+'px';		for(i=0; i < eDockLinks.length; i++) {			eImg = eDockLinks[i].getElementsByTagName('img');			if (eImg.length < 1) {				alert('Image missing from Corner Dock, each link must contain an img tag.');				return;			}			if (eImg.length > 1) {				alert('To many images in Corner Dock link, each link must contain only one img tag.');				return;			}			eImg[0].style.border = 'none';			eImg[0].style.position = 'absolute';			switch (i) {				case (iMiddle) :					eImg[0].style.height = iDimensionsBig+'px';					eImg[0].style.width = iDimensionsBig+'px';					eImg[0].style.top = PositionMiddleTop()+'px';					eImg[0].style.left = PositionMiddleLeft()+'px';					break;				case (iMiddle-1) :					eImg[0].style.height = iDimensionsMedium+'px';					eImg[0].style.width = iDimensionsMedium+'px';					eImg[0].style.top = PositionMiddleUpperTop()+'px';					eImg[0].style.left = PositionMiddleUpperLeft()+'px';					eImg[0].onmouseover = MoveClockWise;					break;				case (iMiddle-2) :					eImg[0].style.height = iDimensionsSmall+'px';					eImg[0].style.width = iDimensionsSmall+'px';					eImg[0].style.top = PositionMiddleUpperMostTop()+'px';					eImg[0].style.left = PositionMiddleUpperMostLeft()+'px';					eImg[0].onmouseover = MoveClockWise;					break;				case (iMiddle+1) :					eImg[0].style.height = iDimensionsMedium+'px';					eImg[0].style.width = iDimensionsMedium+'px';					eImg[0].style.top = PositionMiddleLowerTop()+'px';					eImg[0].style.left = PositionMiddleLowerLeft()+'px';					eImg[0].onmouseover = MoveAntiClockWise;					break;				case (iMiddle+2) :					eImg[0].style.height = iDimensionsSmall+'px';					eImg[0].style.width = iDimensionsSmall+'px';					eImg[0].style.top = PositionMiddleLowerMostTop()+'px';					eImg[0].style.left = PositionMiddleLowerMostLeft()+'px';					eImg[0].onmouseover = MoveAntiClockWise;					break;				default :					eImg[0].style.height = (iDimensionsSmall-10)+'px';					eImg[0].style.width = (iDimensionsSmall-10)+'px';					eImg[0].style.visibility = 'hidden';					if (i < iMiddle) {						eImg[0].style.top = PositionHiddenUpperTop()+'px';						eImg[0].style.left = PositionHiddenUpperLeft()+'px';					}					else {						eImg[0].style.top = PositionHiddenLowerTop()+'px';						eImg[0].style.left = PositionHiddenLowerLeft()+'px';					}			}		}	}	// Positions for all the different states	PositionMiddleTop = function() {		return findPosX(eDockArea) - (iDimensionsBig/2);	};	PositionMiddleLeft = function() {		return findPosY(eDockArea) + iAreaWidth - (iDimensionsBig/2);	};	PositionMiddleUpperTop = function() {		return findPosX(eDockArea) - (iDimensionsMedium) + 30;	};	PositionMiddleUpperLeft = function() {		return findPosY(eDockArea) + iAreaWidth - iDimensionsBig + 20 - (iDimensionsMedium/2);	};	PositionMiddleUpperMostTop = function() {		return findPosX(eDockArea) - (iDimensionsSmall) + 25;	};	PositionMiddleUpperMostLeft = function() {		return findPosY(eDockArea) + iAreaWidth - iDimensionsBig - iDimensionsMedium - 15 + (iDimensionsSmall/2);	};	PositionMiddleLowerTop = function() {		return findPosX(eDockArea) + (iDimensionsBig/2) + 5;	};	PositionMiddleLowerLeft = function() {		return findPosY(eDockArea) + iAreaWidth - (iDimensionsSmall/2);	};	PositionMiddleLowerMostTop = function() {		return findPosX(eDockArea) + (iDimensionsBig/2) + (iDimensionsMedium/2) + iDimensionsSmall + 10;	};	PositionMiddleLowerMostLeft = function() {		return findPosY(eDockArea) + iAreaWidth + 25 - (iDimensionsMedium/2);	};	PositionHiddenUpperTop = function() {		return findPosX(eDockArea);	};	PositionHiddenUpperLeft = function() {		return findPosY(eDockArea) + iAreaWidth - (iDimensionsBig)-(iDimensionsMedium)-(iDimensionsSmall/2);	};	PositionHiddenLowerTop = function() {		return findPosX(eDockArea) + (iDimensionsBig)+(iDimensionsMedium)+(iDimensionsSmall/2) - 30;	};	PositionHiddenLowerLeft = function() {		return findPosY(eDockArea) + iAreaWidth - iDimensionsSmall + 10;	};	function findPosY(obj) {		var curleft = 0;		if(obj.offsetParent)			while(1) 			{			curleft += obj.offsetLeft;			if(!obj.offsetParent)				break;			obj = obj.offsetParent;			}		else if(obj.x)			curleft += obj.x;		return curleft;	}	function findPosX(obj) {		var curtop = 0;		if(obj.offsetParent)			while(1)			{			curtop += obj.offsetTop;			if(!obj.offsetParent)				break;			obj = obj.offsetParent;			}		else if(obj.y)			curtop += obj.y;		return curtop;	}	function GetPosition(eImg) {		if (parseInt(eImg.style.width,10) === (iDimensionsSmall-10)) {			if ((findPosX(eDockArea)+iDimensionsSmall) > parseInt(eImg.style.top,10)) {				return "UpperHidden";			}			else {				return "LowerHidden";			}		}		if (parseInt(eImg.style.width,10) === iDimensionsSmall) {			if (findPosX(eDockArea) > parseInt(eImg.style.top,10)) {				return "UpperSmall";			}			else {				return "LowerSmall";			}		}		if (parseInt(eImg.style.width,10) === iDimensionsMedium) {			if (findPosX(eDockArea) > parseInt(eImg.style.top,10)) {				return "UpperMedium";			}			else {				return "LowerMedium";			}		}		if (parseInt(eImg.style.width,10) === iDimensionsBig) {			return "Big";		}	}	function SetUpEvents() {		var eDockLinks = eDockArea.getElementsByTagName('a'),			i, eImg;		for (i=0; i < eDockLinks.length; i++) {			eImg = eDockLinks[i].getElementsByTagName('img');			eImg[0].onmouseover = null;					switch (GetPosition(eImg[0])) {				case "LowerMedium" :					eImg[0].onmouseover = MoveAntiClockWise;					break;				case "UpperMedium" :					eImg[0].onmouseover = MoveClockWise;					break;				case "LowerSmall" :					eImg[0].onmouseover = MoveAntiClockWise;					break;				case "UpperSmall" :					eImg[0].onmouseover = MoveClockWise;					break;			}		}	}	// Move all images around the dock in a clock wise direction	function MoveClockWise() {		var eDockLinks = eDockArea.getElementsByTagName('a'),			i, eImg, eImgNested;		// Check that we have enough icons to animate		var bCanAnimate = false;		for (i=0; i < eDockLinks.length; i++) {			eImg = eDockLinks[i].getElementsByTagName('img');			if (GetPosition(eImg[0]) === "UpperMedium") {				bCanAnimate = true;				break;			}		}		if (!bCanAnimate) {			return;		}				for (i=0; i < eDockLinks.length; i++) {			eImg = eDockLinks[i].getElementsByTagName('img');			eImg[0].onmouseover = null;					switch (GetPosition(eImg[0])) {				case "Big" :					Animations[eDockLinks[i].id+'width'] = iDimensionsMedium;					Animations[eDockLinks[i].id+'height'] = iDimensionsMedium;					Animations[eDockLinks[i].id+'sizeChange'] = 2;					Animations[eDockLinks[i].id+'pixelsX'] = 7;					Animations[eDockLinks[i].id+'pixelsY'] = 4;					Animations[eDockLinks[i].id+'obj'] = eImg[0];					if (Animations[eDockLinks[i].id+'Interval'] === undefined) {						Animations[eDockLinks[i].id+'Interval'] = setInterval("CornerDock.MoveToPosition('" + eDockLinks[i].id + "')",speed);					}					Animations[eDockLinks[i].id+'posX'] = PositionMiddleLowerTop();					Animations[eDockLinks[i].id+'posY'] = PositionMiddleLowerLeft();					break;				case "LowerMedium" :					Animations[eDockLinks[i].id+'width'] = iDimensionsSmall;					Animations[eDockLinks[i].id+'height'] = iDimensionsSmall;					Animations[eDockLinks[i].id+'sizeChange'] = 3;					Animations[eDockLinks[i].id+'pixelsX'] = 5;					Animations[eDockLinks[i].id+'pixelsY'] = 4;					Animations[eDockLinks[i].id+'obj'] = eImg[0];					if (Animations[eDockLinks[i].id+'Interval'] === undefined) {						Animations[eDockLinks[i].id+'Interval'] = setInterval("CornerDock.MoveToPosition('" + eDockLinks[i].id + "')",speed);					}					Animations[eDockLinks[i].id+'posX'] = PositionMiddleLowerMostTop();					Animations[eDockLinks[i].id+'posY'] = PositionMiddleLowerMostLeft();					break;				case "UpperMedium" :					Animations[eDockLinks[i].id+'width'] = iDimensionsBig;					Animations[eDockLinks[i].id+'height'] = iDimensionsBig;					Animations[eDockLinks[i].id+'sizeChange'] = 2;					Animations[eDockLinks[i].id+'pixelsX'] = 4;					Animations[eDockLinks[i].id+'pixelsY'] = 4;					Animations[eDockLinks[i].id+'obj'] = eImg[0];					if (Animations[eDockLinks[i].id+'Interval'] === undefined) {						Animations[eDockLinks[i].id+'Interval'] = setInterval("CornerDock.MoveToPosition('" + eDockLinks[i].id + "')",speed);					}					Animations[eDockLinks[i].id+'posX'] = PositionMiddleTop();					Animations[eDockLinks[i].id+'posY'] = PositionMiddleLeft();					break;				case "LowerSmall" :					Animations[eDockLinks[i].id+'width'] = iDimensionsSmall-10;					Animations[eDockLinks[i].id+'height'] = iDimensionsSmall-10;					Animations[eDockLinks[i].id+'sizeChange'] = 2;					Animations[eDockLinks[i].id+'pixelsX'] = 4;					Animations[eDockLinks[i].id+'pixelsY'] = 4;					eImg[0].style.visibility = 'hidden';					Animations[eDockLinks[i].id+'obj'] = eImg[0];					if (Animations[eDockLinks[i].id+'Interval'] === undefined) {						Animations[eDockLinks[i].id+'Interval'] = setInterval("CornerDock.MoveToPosition('" + eDockLinks[i].id + "')",speed);					}					Animations[eDockLinks[i].id+'posX'] = PositionHiddenLowerTop();					Animations[eDockLinks[i].id+'posY'] = PositionHiddenLowerLeft();					break;				case "UpperSmall" :					Animations[eDockLinks[i].id+'width'] = iDimensionsMedium;					Animations[eDockLinks[i].id+'height'] = iDimensionsMedium;					Animations[eDockLinks[i].id+'sizeChange'] = 2;					Animations[eDockLinks[i].id+'pixelsX'] = 2;					Animations[eDockLinks[i].id+'pixelsY'] = 2;					Animations[eDockLinks[i].id+'obj'] = eImg[0];					if (Animations[eDockLinks[i].id+'Interval'] === undefined) {						Animations[eDockLinks[i].id+'Interval'] = setInterval("CornerDock.MoveToPosition('" + eDockLinks[i].id + "')",speed);					}					Animations[eDockLinks[i].id+'posX'] = PositionMiddleUpperTop();					Animations[eDockLinks[i].id+'posY'] = PositionMiddleUpperLeft();					break;				case "LowerHidden" :					// Stays there on clock wise.					break;				case "UpperHidden" :					// Not all of them, just the next one in line					eImgNested = eDockLinks[i+1].getElementsByTagName('img');					if (GetPosition(eImgNested[0]) !== "UpperHidden") {						Animations[eDockLinks[i].id+'width'] = iDimensionsSmall;						Animations[eDockLinks[i].id+'height']  = iDimensionsSmall;						Animations[eDockLinks[i].id+'sizeChange'] = 2;						Animations[eDockLinks[i].id+'pixelsX'] = 1;						Animations[eDockLinks[i].id+'pixelsY'] = 1;						eImg[0].style.visibility = 'visible';						Animations[eDockLinks[i].id+'obj'] = eImg[0];						if (Animations[eDockLinks[i].id+'Interval'] === undefined) {							Animations[eDockLinks[i].id+'Interval'] = setInterval("CornerDock.MoveToPosition('" + eDockLinks[i].id + "')",speed);						}						Animations[eDockLinks[i].id+'posX'] = PositionMiddleUpperMostTop();						Animations[eDockLinks[i].id+'posY'] = PositionMiddleUpperMostLeft();					}					break;			}		}	}	// Move all images around the dock in an anti clock wise direction	function MoveAntiClockWise() {		var eDockLinks = eDockArea.getElementsByTagName('a'),			i, eImg, eImgNested;		// Check that we have enough icons to animate		var bCanAnimate = false;		for (i=0; i < eDockLinks.length; i++) {			eImg = eDockLinks[i].getElementsByTagName('img');			if (GetPosition(eImg[0]) === "LowerMedium") {				bCanAnimate = true;				break;			}		}		if (!bCanAnimate) {			return;		}		for (i=0; i < eDockLinks.length; i++) {			eImg = eDockLinks[i].getElementsByTagName('img');			eImg[0].onmouseover = null;					switch (GetPosition(eImg[0])) {				case "Big" :					Animations[eDockLinks[i].id+'width'] = iDimensionsMedium;					Animations[eDockLinks[i].id+'height'] = iDimensionsMedium;					Animations[eDockLinks[i].id+'sizeChange'] = 2;					Animations[eDockLinks[i].id+'pixelsX'] = 4;					Animations[eDockLinks[i].id+'pixelsY'] = 7;					Animations[eDockLinks[i].id+'obj'] = eImg[0];					if (Animations[eDockLinks[i].id+'Interval'] === undefined) {						Animations[eDockLinks[i].id+'Interval'] = setInterval("CornerDock.MoveToPosition('" + eDockLinks[i].id + "')",speed);					}					Animations[eDockLinks[i].id+'posX'] = PositionMiddleUpperTop();					Animations[eDockLinks[i].id+'posY'] = PositionMiddleUpperLeft();					break;				case "LowerMedium" :					Animations[eDockLinks[i].id+'width'] = iDimensionsBig;					Animations[eDockLinks[i].id+'height'] = iDimensionsBig;					Animations[eDockLinks[i].id+'sizeChange'] = 2;					Animations[eDockLinks[i].id+'pixelsX'] = 6;					Animations[eDockLinks[i].id+'pixelsY'] = 2;					Animations[eDockLinks[i].id+'obj'] = eImg[0];					if (Animations[eDockLinks[i].id+'Interval'] === undefined) {						Animations[eDockLinks[i].id+'Interval'] = setInterval("CornerDock.MoveToPosition('" + eDockLinks[i].id + "')",speed);					}					Animations[eDockLinks[i].id+'posX'] = PositionMiddleTop(); 					Animations[eDockLinks[i].id+'posY'] = PositionMiddleLeft();					break;				case "UpperMedium" :					Animations[eDockLinks[i].id+'width'] = iDimensionsSmall;					Animations[eDockLinks[i].id+'height'] = iDimensionsSmall;					Animations[eDockLinks[i].id+'sizeChange'] = 3;					Animations[eDockLinks[i].id+'pixelsX'] = 4;					Animations[eDockLinks[i].id+'pixelsY'] = 6;					Animations[eDockLinks[i].id+'obj'] = eImg[0];					if (Animations[eDockLinks[i].id+'Interval'] === undefined) {						Animations[eDockLinks[i].id+'Interval'] = setInterval("CornerDock.MoveToPosition('" + eDockLinks[i].id + "')",speed);					}					Animations[eDockLinks[i].id+'posX'] = PositionMiddleUpperMostTop();					Animations[eDockLinks[i].id+'posY'] = PositionMiddleUpperMostLeft();					break;				case "LowerSmall" :					Animations[eDockLinks[i].id+'width'] = iDimensionsMedium;					Animations[eDockLinks[i].id+'height'] = iDimensionsMedium;					Animations[eDockLinks[i].id+'sizeChange'] = 2;					Animations[eDockLinks[i].id+'pixelsX'] = 4;					Animations[eDockLinks[i].id+'pixelsY'] = 2;					Animations[eDockLinks[i].id+'obj'] = eImg[0];					if (Animations[eDockLinks[i].id+'Interval'] === undefined) {						Animations[eDockLinks[i].id+'Interval'] = setInterval("CornerDock.MoveToPosition('" + eDockLinks[i].id + "')",speed);					}					Animations[eDockLinks[i].id+'posX'] = PositionMiddleLowerTop(); 					Animations[eDockLinks[i].id+'posY'] = PositionMiddleLowerLeft();					break;				case "UpperSmall" :					Animations[eDockLinks[i].id+'width'] = iDimensionsSmall-10;					Animations[eDockLinks[i].id+'height'] = iDimensionsSmall-10;					Animations[eDockLinks[i].id+'sizeChange'] = 2;					Animations[eDockLinks[i].id+'pixelsX'] = 4;					Animations[eDockLinks[i].id+'pixelsY'] = 4;					eImg[0].style.visibility = 'hidden';					Animations[eDockLinks[i].id+'obj'] = eImg[0];					if (Animations[eDockLinks[i].id+'Interval'] === undefined) {						Animations[eDockLinks[i].id+'Interval'] = setInterval("CornerDock.MoveToPosition('" + eDockLinks[i].id + "')",speed);					}					Animations[eDockLinks[i].id+'posX'] = PositionHiddenUpperTop();					Animations[eDockLinks[i].id+'posY'] = PositionHiddenUpperLeft();					break;				case "LowerHidden" :					// Not all of them, just the next one in line					eImgNested = eDockLinks[i-1].getElementsByTagName('img');					if (GetPosition(eImgNested[0]) !== "LowerHidden") {						Animations[eDockLinks[i].id+'width'] = iDimensionsSmall;						Animations[eDockLinks[i].id+'height']  = iDimensionsSmall;						Animations[eDockLinks[i].id+'sizeChange'] = 2;						Animations[eDockLinks[i].id+'pixelsX'] = 2;						Animations[eDockLinks[i].id+'pixelsY'] = 1;						eImg[0].style.visibility = 'visible';						Animations[eDockLinks[i].id+'obj'] = eImg[0];						if (Animations[eDockLinks[i].id+'Interval'] === undefined) {							Animations[eDockLinks[i].id+'Interval'] = setInterval("CornerDock.MoveToPosition('" + eDockLinks[i].id + "')",speed);						}						Animations[eDockLinks[i].id+'posX'] = PositionMiddleLowerMostTop();						Animations[eDockLinks[i].id+'posY'] = PositionMiddleLowerMostLeft();					}					break;				case "UpperHidden" :					// Stays there on clock wise.					break;			}		}	}	function StopAnimation(sID)	{		var eDockLinks = eDockArea.getElementsByTagName('a'),			i, bFinishedAll = true;		// Clear up the sizes, they could be a few pixels out		if (Animations[sID+'obj']) {			Animations[sID+'obj'].style.width = Animations[sID+'width'] + 'px';			Animations[sID+'obj'].style.height = Animations[sID+'height'] + 'px';		}		Animations[sID+'Interval'] = clearInterval(Animations[sID+'Interval']);		Animations[sID+'posX'] = undefined;		Animations[sID+'posY'] = undefined;		Animations[sID+'obj'] = undefined;		Animations[sID+'width'] = undefined;		Animations[sID+'height'] = undefined;		Animations[sID+'sizeChange'] = undefined;		Animations[sID+'pixelsX'] = undefined;		Animations[sID+'pixelsY'] = undefined;		// Add events back in only when all animation have finished.		for (i=0; i < eDockLinks.length; i++) {			if (Animations[sID+'Interval'] !== undefined) {				bFinishedAll = false;				break;			}		}		if (bFinishedAll) {			// Add events back in.			animating = false;			SetUpEvents();		}	}	/* Public Variables 	*	* These variables are available from the returning object that this constructor creates,	* new public variables can be added to the returning object at any time.	*/	/* Public Functions 	*	* These functions are available from the returning object that this constructor creates,	* new public functions can be added to the returning object at any time.	*/	that.RotateClockWise = function() {		MoveClockWise();	};	that.RotateAntiClockWise = function() {		MoveAntiClockWise();	};	that.MoveToPosition = function(sID) {				var obj = Animations[sID+'obj'];		if (!obj) {			StopAnimation(sID);			return;		}				var currentY = findPosY(obj),		    currentX = findPosX(obj);		var x = Animations[sID+'posX'], y = Animations[sID+'posY'];		var currentWidth = parseInt(obj.style.width,10),			currentHeight = parseInt(obj.style.height,10);		var width = Animations[sID+'width'], height = Animations[sID+'height'],			sizeChange = Animations[sID+'sizeChange'],			pixelsX = Animations[sID+'pixelsX'], 			pixelsY = Animations[sID+'pixelsY'];				// If we have reached the position for this animation stop here.		if (currentX == x && currentY == y) {			StopAnimation(sID);			return;		}		// Change the size of the object		if (currentWidth != width) {			obj.style.width = (width < currentWidth) ? currentWidth - sizeChange +'px' : currentWidth + sizeChange +'px';		}		if (currentHeight != height) {			obj.style.height = (height < currentHeight) ? currentHeight - sizeChange +'px' : currentHeight + sizeChange +'px';		}		// Change the position of the object if it needs changing.		if (currentY != y) {			obj.style.left = (y < currentY) ? currentY - pixelsY +'px' : currentY + pixelsY +'px';		}		if (currentX != x) {			obj.style.top = (x < currentX) ? currentX - pixelsX +'px' : currentX + pixelsX +'px';		}		// Make sure that the current position isn't so close to the required positions		// that it will over shoot it next time around!		if (Math.abs(y - parseInt(obj.style.left,10)) < pixelsY) {			obj.style.left = y +'px';		}		if (Math.abs(x - parseInt(obj.style.top,10)) < pixelsX) {			obj.style.top = x +'px';		}		// Do the same for dimensions		if (Math.abs(width - parseInt(obj.style.width,10)) < sizeChange) {			obj.style.width = width +'px';		}		if (Math.abs(height - parseInt(obj.style.height,10)) < sizeChange) {			obj.style.height = height+'px';		}	};	// Call this to set up the corner dock before returning.	//	InitiateDock();	/* 	* This (or that) is the object returned with all public members and	* functions included above when the contructor is instantiated.	*/    return that;}