
/**
 * Zooming with an array of tiles
 * @ctor
 * @public
 * @tparam object oTileset
 */

function iwZoomObject(oIwTileSet)
{
	// variables
	this.oIwTileSet = oIwTileSet; //object of Tileset
	this.aZoomTileSet = null;
	this.nZoomTilesX = 3;
	this.nZoomTilesY = 3;
	this.nTileSetX = oIwTileSet.nTotalTilesX;
	this.nTileSetY = oIwTileSet.nTotalTilesY;
	this.nLeftTopTileNumX = 0;
	this.nLeftTopTileNumY = 0;
	this.nNumberFirstTile = 0;
	this.aPlaceTileSetDIV = null;
	this.aPlaceTileSetIMG = null;
	this.aTotalTileList = null; 
	this.aVisibleTileList = null; 
	this.aZoomTilesNodes = null;
	this.nZoomTileZIndex = 0;
	this.nZoomTileSetTop = 0; // top
	this.nZoomTileSetLeft = 0; // left
	this.nTileWidth = oIwTileSet.nTilesize;
	this.nTileHeight = oIwTileSet.nTilesize;
	this.nVisibleWidth = oIwTileSet.nVisibleWidth;
	this.nVisibleHeight = oIwTileSet.nVisibleHeight;
	this.nZoomCenterPixelX = 0;
	this.nZoomCenterPixelY = 0;
	this.nPanningWidth = 0;
	this.nPanningHeight = 0;
	this.nLastTilesizeMeter = 0;
	this.nCurrentTilesizeMeter = 0;
	
	this.oDivTileMap = null;
	this.divTileMapZoom = null;
	
	this.nZoomSteps = 4;
	this.nZoomStepNumber = 0;
	
	this.nZoomSingleStepX = 0;
	this.nZoomSingleStepY = 0;
	this.nMoveSingleStepX = 0;
	this.nMoveSingleStepY = 0;
	
	this.nZoomFaktor = 1;
	this.nLimitationOfTileSize = 4200;
	
	this.bCloneTiles = false;
	this.bPrepareZoomOnSlider = false;

	this.oZoomTimeout	= null;
	
	this.fOnZoomEffectEnd = null;
	
	// private methods
	this.CreateZoomTileSet = CreateZoomTileSet;
	this.PlaceZoomTileSet = PlaceZoomTileSet;
	this.isTileInVisibleWindow = isTileInVisibleWindow;
	this.PlaceZoomTileSetByStep = PlaceZoomTileSetByStep;
	this.HorizonZoomTiles = HorizonZoomTiles;
	this.HAVZoomTiles = HAVZoomTiles;
	this.VerticalZoomTiles = VerticalZoomTiles;
	this.ZoomTiles = ZoomTiles;
	this.MoveTiles = MoveTiles;
	this.End_Zoom = End_Zoom;
	this.ZoomTileSet = ZoomTileSet;
	this.InitZoomTileSet = InitZoomTileSet;
	
	this.zoomDivTiles = zoomDivTiles;
	this.zoomDivTilesOnSliderByStep = zoomDivTilesOnSliderByStep;
	this.zoomDivTilesOnSlider = zoomDivTilesOnSlider;
	this.createDivZoomTiles = createDivZoomTiles;
	this.getZoomPosition = getZoomPosition;
	this.setArrayOfWholeTiles = setArrayOfWholeTiles;
	this.setArrayOfVisibleWindow = setArrayOfVisibleWindow;
	this.getLeftTopOfVisibleWindow = getLeftTopOfVisibleWindow;
	this.setArrayForCloneDIV = setArrayForCloneDIV;
	this.getZoomArea = getZoomArea;
	//this.getZoomAreaNoCopy = getZoomAreaNoCopy;
	this.getZoomAreaByStep = getZoomAreaByStep;
	this.appendZoomDIVSet = appendZoomDIVSet;
	this.getZoomLimitation = getZoomLimitation;
	
	//public methods
	this.isExistZoomDIVSet = isExistZoomDIVSet;
	this.removeZoomDIVSet = removeZoomDIVSet;
	this.SetZoomFactor = SetZoomFactor;
	this.GetZoomFactor = GetZoomFactor;
	this.SetDivTileMap = SetDivTileMap;
	this.SetLastTilesizeMeter = SetLastTilesizeMeter;
	this.SetCurrentTilesizeMeter = SetCurrentTilesizeMeter;
	this.GetLastTilesizeMeter = GetLastTilesizeMeter;
	this.GetCurrentTilesizeMeter = GetCurrentTilesizeMeter;
	this.GetZoomCenterPixelX = GetZoomCenterPixelX;
	this.GetZoomCenterPixelY = GetZoomCenterPixelY;
	this.SetZoomCenterPixelX = SetZoomCenterPixelX;
	this.SetZoomCenterPixelY = SetZoomCenterPixelY;
	this.Zoom = Zoom;
	this.ZoomByStep = ZoomByStep;
	this.PrepareZoomOnSlider = PrepareZoomOnSlider;
	this.ZoomOnSlider = ZoomOnSlider;
	this.SetZoomTileZIndex = SetZoomTileZIndex;
	this.GetZoomTileZIndex = GetZoomTileZIndex;
	this.SetOnZoomEffectEnd = SetOnZoomEffectEnd;
	
	// constructor
	this.InitZoomTileSet();
}


/**
 * Init function for zooming
 * @ctor
 * @private
 * @tparam nXKachel, nYKachel, nWKachel, nHKachel, nXPosition, nYPosition, nZIndex
 */
function CreateZoomTileSet(nXKachel, nYKachel, nWKachel, nHKachel, nXPosition, nYPosition, nZIndex)
{
	this.aZoomTileSet = new Array( nXKachel * nYKachel );
	
	for (var y=0; y<nYKachel; y++)
	{	
		for (var x=0; x<nXKachel; x++)
		{
      nPos = y*nXKachel + x;
			this.aZoomTileSet[nPos] = new Object();
			this.aZoomTileSet[nPos].left = nXPosition + nWKachel * x;
			this.aZoomTileSet[nPos].top = nYPosition + nHKachel * y;
			this.aZoomTileSet[nPos].width = nWKachel;
			this.aZoomTileSet[nPos].height = nHKachel;
			this.aZoomTileSet[nPos].zindex = nZIndex;
			this.aZoomTileSet[nPos].zooming = true;
		}
	}
}

/**
 * Draw function for zooming
 * @ctor
 * @private
 * @tparam aKachelList, aImageList, nXKachel, nYKachel
 */
function PlaceZoomTileSet(aKachelList, nXKachel, nYKachel)
{
	var nKachelNum = 0;
	for (var y=0; y<nYKachel; y++)
	{	
		for (var x=0; x<nXKachel; x++)
		{
			if (nKachelNum < this.aPlaceTileSetDIV.length)
			{
        nPos = y*nXKachel + x;
				this.aPlaceTileSetDIV[nKachelNum].top = this.aZoomTileSet[nPos].top;
				this.aPlaceTileSetDIV[nKachelNum].left = this.aZoomTileSet[nPos].left;
				this.aPlaceTileSetDIV[nKachelNum].width = this.aZoomTileSet[nPos].width;
				this.aPlaceTileSetDIV[nKachelNum].height = this.aZoomTileSet[nPos].height;
				this.aPlaceTileSetDIV[nKachelNum].zIndex = this.nZoomTileZIndex;
				
				this.aPlaceTileSetIMG[nKachelNum].width = this.aZoomTileSet[nPos].width;
				this.aPlaceTileSetIMG[nKachelNum].height = this.aZoomTileSet[nPos].height;			
				nKachelNum ++;
			}
		}
	}
}

function isTileInVisibleWindow(DivTop, DivLeft, DivRight, DivBottom, StartX, StartY, EndX, EndY)
{
	//VisibleWindow
	var nStartX = StartX;
	var nStartY = StartY;
	var nEndX = EndX;
	var nEndY = EndY;

	// Div of Tile
	var nDivTop = DivTop;
	var nDivLeft = DivLeft;
	var nDivRight = DivRight;
	var nDivBottom = DivBottom;
	
	if (  
			(	// if a Tile bigger then visibile window
				(nDivLeft <= nStartX) && (nDivRight >= nEndX) 
				&& 
				( (nDivTop >= nStartY && nDivTop <= nEndY)
					||
					(nDivBottom >= nStartY && nDivBottom <= nEndY)
				)
				
				||
				
				(nDivTop <= nStartY) && (nDivBottom >= nEndY) 
				&& 
				( (nDivLeft >= nStartX && nDivLeft <= nEndX)
					||
					(nDivRight >= nStartX && nDivRight <= nEndX)
				)
				
				||
				
				(nDivLeft <= nStartX) && (nDivRight >= nEndX) 
				&&
				(nDivTop <= nStartY) && (nDivBottom >= nEndY) 
			)			
			||
			(
				// if a Tile in a Visible window
				(nDivTop > nStartY && nDivTop < nEndY ) &&						//Top, Left
				(nDivLeft > nStartX && nDivLeft < nEndX ) 
				||
				(nDivTop > nStartY && nDivTop < nEndY ) &&						//Top, Right
				(nDivRight> nStartX && nDivRight < nEndX )
				||
				(nDivBottom > nStartY && nDivBottom < nEndY ) &&			//Bottom, Left
				(nDivLeft > nStartX && nDivLeft < nEndX )
				||
				(nDivBottom > nStartY && nDivBottom < nEndY ) &&			//Bottom, Right
				(nDivRight > nStartX && nDivRight < nEndX ) 
			)
		)
		{			
			return true;	
		}
		else
		{
			return false;
		}
} //end if

/**
 * Draw function for zooming for visible window
 * @ctor
 * @private
 * @tparam aKachelList, aImageList, nXKachel, nYKachel
 */
function PlaceZoomTileSetByStep(aKachelList, nXKachel, nYKachel)
{
	//position of visible window
	var nStartX = 0;
	var nStartY = 0;
	var nEndX = this.nVisibleWidth;
	var nEndY = this.nVisibleHeight;

	var nTileNum = 0;
	for (var y=0; y<nYKachel; y++)
	{	
		for (var x=0; x<nXKachel; x++)
		{
			if (nTileNum < this.aPlaceTileSetDIV.length)
			{
        nPos = y*nXKachel + x;
				var nDivTop = parseInt(this.aZoomTileSet[nPos].top);
				var nDivLeft = parseInt(this.aZoomTileSet[nPos].left);
				var nDivRight = nDivLeft + this.aZoomTileSet[nPos].width;
				var nDivBottom = nDivTop + this.aZoomTileSet[nPos].height;

				this.aPlaceTileSetDIV[nTileNum].top = this.aZoomTileSet[nPos].top;
				this.aPlaceTileSetDIV[nTileNum].left = this.aZoomTileSet[nPos].left;
				this.aPlaceTileSetDIV[nTileNum].width = this.aZoomTileSet[nPos].width;
				this.aPlaceTileSetDIV[nTileNum].height = this.aZoomTileSet[nPos].height;
				this.aPlaceTileSetDIV[nTileNum].zIndex = this.nZoomTileZIndex;
						
				this.aPlaceTileSetIMG[nTileNum].width = this.aZoomTileSet[nPos].width;
				this.aPlaceTileSetIMG[nTileNum].height = this.aZoomTileSet[nPos].height;			
			} //end if
			nTileNum ++;
		} //end for nXKachel
	} // end for nYKachel
}

/**
 * zooming in horrizon direction
 * @ctor
 * @private
 * @tparam length_X, num_X, num_Y
 */
function HorizonZoomTiles(length_X, num_X, num_Y)
{
	num_step_X = Math.floor( Math.abs(length_X) / num_X ) ;
	mod_step_X = Math.abs(length_X) % num_X ;

	if (length_X < 0) 
	{
		pre_step = -1;
	}
	else 
	{
		pre_step = 1;
	}
	
	for (var y=0; y<num_Y; y++)
	{
		//set horizon tiles with step value
		for (var i=0; i<num_X; i++)
		{
      nPos = i +y*num_X;
			this.aZoomTileSet[nPos].left = (this.aZoomTileSet[nPos].left) + pre_step * i * num_step_X;
			this.aZoomTileSet[nPos].width = (this.aZoomTileSet[nPos].width) + pre_step * num_step_X;
		}
	
		for (var j=mod_step_X-1; j>=0; j--)
		{
			if (pre_step < 0)
			{
				max_num = (this.aZoomTileSet[y*num_X].width);
				start_num = 0;
	
				for (var i=0; i<num_X; i++)
				{
          nPos = i + y*num_X;
					if ((this.aZoomTileSet[nPos].width)>=max_num)
					{
						max_num = (this.aZoomTileSet[nPos].width);
						start_num = i;
					}
				}
			}
			else
			{
				min_num = (this.aZoomTileSet[y*num_X].width);
				start_num = 0;
	
				for (var i=0; i<num_X; i++)
				{
          nPos = i + y*num_X;
					if ((this.aZoomTileSet[nPos].width)< min_num)
					{
						min_num = (this.aZoomTileSet[nPos].width);
						start_num = i;
					}
				}
			}
		
			//set horizon tiles with mod value
			ni = start_num + y*num_X;
			this.aZoomTileSet[ni].width = (this.aZoomTileSet[ni].width) +pre_step;			
			for (var k = start_num+1; k<num_X; k++)
			{
				nk = k + y*num_X;
				this.aZoomTileSet[nk].left = (this.aZoomTileSet[nk].left) + pre_step;
			}					
		}	
	}
}

/**
 * zooming in horrizon and vertical directions in same time
 * @ctor
 * @private
 * @tparam length_X, num_X, num_Y
 */
function HAVZoomTiles(length_X, num_X, num_Y)
{
	num_step_X = Math.floor( Math.abs(length_X) / num_X ) ;
	mod_step_X = Math.abs(length_X) % num_X ;

	if (length_X < 0) 
	{
		pre_step = -1;
	}
	else 
	{
		pre_step = 1;
	}
	
	for (var y=0; y<num_Y; y++)
	{
		//set tiles with step value
		for (var i=0; i<num_X; i++)
		{
      nPos = i +y*num_X;
			this.aZoomTileSet[nPos].left = (aZoomTileSet[nPos].left) + pre_step * i * num_step_X;
			this.aZoomTileSet[nPos].width = (aZoomTileSet[nPos].width) + pre_step * num_step_X;
			
			this.aZoomTileSet[nPos].top = (aZoomTileSet[nPos].top) + pre_step * y * num_step_X;
			this.aZoomTileSet[nPos].height = (aZoomTileSet[nPos].height) + pre_step * num_step_X;
		}
		for (var j=mod_step_X-1; j>=0; j--)
		{
			if (pre_step < 0)
			{
				max_num = (this.aZoomTileSet[y*num_X].width);
				start_num = 0;
	
				for (var i=0; i<num_X; i++)
				{
          nPos = i + y*num_X;
					if ((this.aZoomTileSet[nPos].width)>=max_num)
					{
						max_num = (this.aZoomTileSet[nPos].width);
						start_num = i;
					}
				}
			}
			else
			{
				min_num = (this.aZoomTileSet[y*num_X].width);
				start_num = 0;
	
				for (var i=0; i<num_X; i++)
				{
          nPos = i + y*num_X;
					if ((this.aZoomTileSet[nPos].width)< min_num)
					{
						min_num = (this.aZoomTileSet[nPos].width);
						start_num = i;
					}
				}
			}
		
			//set horizon tiles with mod value
			ni = start_num + y*num_X;
			this.aZoomTileSet[ni].width = (this.aZoomTileSet[ni].width) +pre_step;
					
			for (var k = start_num+1; k<num_X; k++)
			{
				nk = k + y*num_X;
				this.aZoomTileSet[nk].left = (this.aZoomTileSet[nk].left) + pre_step;				
			}					
		}	
	}
}


/**
 * zooming in vertical direction
 * @ctor
 * @private
 * @tparam length_X, num_X, num_Y
 */
function VerticalZoomTiles(length_Y, num_X, num_Y)
{
	num_step_Y = Math.floor( Math.abs(length_Y) / num_Y ) ;
	mod_step_Y = Math.abs(length_Y) % num_Y ;

	if (length_Y < 0)  
	{
		pre_step = -1;
	}
	else
	{
		pre_step = 1;
	}
	
	for (var x=0; x<num_X; x++)
	{
		//set vertical tiles with step value
		for (var i=0; i<num_Y; i++)
		{
      nPos = num_X*i + x;
			this.aZoomTileSet[nPos].top = (this.aZoomTileSet[nPos].top) + pre_step *i * num_step_Y;
			this.aZoomTileSet[nPos].height = (this.aZoomTileSet[nPos].height) +pre_step * num_step_Y;
		}
	
		for (var j=mod_step_Y-1; j>=0; j--)
		{
			if (pre_step < 0)
			{
				max_num = (this.aZoomTileSet[x].height);
				start_num = 0;
	
				for (var i=0; i<num_Y; i++)
				{
          nPos = num_X*i + x;
					if ((this.aZoomTileSet[nPos].height)>=max_num)
					{
						max_num = (this.aZoomTileSet[nPos].height);
						start_num = i;
					}
				}
			}
			else
			{
				min_num = (this.aZoomTileSet[x].height);
				start_num = 0;
	
				for (var i=0; i<num_Y; i++)
				{
          nPos = num_X*i + x;
					if ((this.aZoomTileSet[nPos].height)< min_num)
					{
						min_num = (this.aZoomTileSet[nPos].height);
						start_num = i;
					}
				}
			}
			
			//set vertical tiles with mod value
			ni = start_num*num_X + x;
			this.aZoomTileSet[ni].height = (this.aZoomTileSet[ni].height) +pre_step;	
			for (var k = start_num+1; k<num_Y; k++)
			{
				ni = k*num_X + x;
				this.aZoomTileSet[ni].top = (this.aZoomTileSet[ni].top) + pre_step;
			}
		}
	}
}

/**
 * Call for zoom function for zooming
 * @ctor
 * @private
 * @tparam length_X, length_Y, num_X, num_Y
 */
function ZoomTiles(length_X, length_Y, num_X, num_Y)
{
	this.HorizonZoomTiles( length_X, num_X, num_Y);
	this.VerticalZoomTiles( length_Y, num_X, num_Y);
}

/**
 * Move function for zooming
 * @ctor
 * @private
 * @tparam length_X, length_Y, num_X, num_Y
 */
function MoveTiles(length_X, length_Y, num_X, num_Y)
{
	for (var i=0; i<num_X*num_Y; i++)
	{
		this.aZoomTileSet[i].left += length_X;
		this.aZoomTileSet[i].top += length_Y;
	}
}

/**
 * Set zoom status function for zooming
 * @ctor
 * @private
 * @tparam num_X, num_Y
 */
function End_Zoom(num_X, num_Y)
{
	for (var i=0; i<num_X*num_Y; i++)
	{
		this.aZoomTileSet[i].zooming = false;
	}
}

/**
 * recusion call function for zooming
 * @ctor
 * @private
 * @tparam 
 */
function ZoomTileSet()
{
	if (this.nZoomStepNumber>0)
	{
		//only for last step
		if (this.nZoomStepNumber == 1)
		{
			this.zoomDivTilesOnSliderByStep(this.nZoomCenterPixelX, this.nZoomCenterPixelY, this.nZoomFaktor);
		}
		else
		{
			this.ZoomTiles( this.nZoomSingleStepX, this.nZoomSingleStepY, this.nZoomTilesX, this.nZoomTilesY);
			this.MoveTiles( this.nMoveSingleStepX, this.nMoveSingleStepY, this.nZoomTilesX, this.nZoomTilesY);
			this.PlaceZoomTileSet(this.aTotalTileList, this.nZoomTilesX, this.nZoomTilesY);
		}
		this.nZoomStepNumber --;			
		this.oZoomTimeout = window.setTimeout("oTileset.oZoomObject.ZoomTileSet()", 0);	
	}
	else
	{
		// end of zoom
		this.End_Zoom(this.nZoomTilesX, this.nZoomTilesY);
		this.nZoomStepNumber = this.nZoomSteps;
		window.clearTimeout(this.oZoomTimeout);
		this.oZoomTimeout = null;
		if (this.fOnZoomEffectEnd)
		{
			this.fOnZoomEffectEnd();
		}
	}
}

/**
 * constructor function for zoom object
 * @ctor
 * @private
 * @tparam 
 */
function InitZoomTileSet()
{
	this.nTileSetX = this.oIwTileSet.nTotalTilesX;
	this.nTileSetY = this.oIwTileSet.nTotalTilesY;
	this.nTileWidth = this.oIwTileSet.nTilesize;
	this.nTileHeight = this.oIwTileSet.nTilesize;
	this.nVisibleWidth = this.oIwTileSet.nVisibleWidth;
	this.nVisibleHeight = this.oIwTileSet.nVisibleHeight;
	
	//optimation for Microsoft Internet Explorer	
	if (navigator.appName == "Microsoft Internet Explorer")
	{
		this.bCloneTiles = false;
		this.nZoomSteps = 8;
		this.nLimitationOfTileSize = 10000;
	}
	else
	{
		this.bCloneTiles = true;
		this.nZoomSteps = 4;
		this.nLimitationOfTileSize = 4200;	
	}
}

function Zoom(StartX, StartY, EndX, EndY)
{
	this.SetDivTileMap();
	this.createDivZoomTiles(this.oDivTileMap);
	this.getZoomPosition(StartX, StartY, EndX, EndY);
	this.getZoomLimitation();
	this.getZoomArea(this.nZoomCenterPixelX, this.nZoomCenterPixelY);
	this.appendZoomDIVSet();
	this.CreateZoomTileSet(this.nZoomTilesX, this.nZoomTilesY, this.nTileWidth, this.nTileHeight, this.nZoomTileSetLeft, this.nZoomTileSetTop, this.nZoomTileZIndex);	
	this.zoomDivTiles(this.nZoomCenterPixelX, this.nZoomCenterPixelY, this.nZoomFaktor, this.nZoomSteps);
}

function zoomDivTiles(ZoomCenterPixelX, ZoomCenterPixelY, ZoomFaktor, ZoomSteps)
{
	this.nZoomSingleStepX = Math.round( this.nTileWidth * this.nZoomTilesX * (ZoomFaktor - 1) / ZoomSteps );
	this.nZoomSingleStepY = Math.round( this.nTileHeight * this.nZoomTilesY * (ZoomFaktor - 1) / ZoomSteps );
	var nVisibleCenterX =  this.nVisibleWidth / 2 - this.nZoomTileSetLeft;
	var nVisibleCenterY =  this.nVisibleHeight / 2 - this.nZoomTileSetTop;
	var nNewZoomCenterX = (ZoomCenterPixelX - this.nZoomTileSetLeft) * ZoomFaktor;
	var nNewZoomCenterY = (ZoomCenterPixelY - this.nZoomTileSetTop) * ZoomFaktor;

	this.nMoveSingleStepX = Math.round( ( nVisibleCenterX - nNewZoomCenterX ) / ZoomSteps ); 
	this.nMoveSingleStepY = Math.round( ( nVisibleCenterY - nNewZoomCenterY ) / ZoomSteps ); 

	this.nZoomStepNumber = ZoomSteps;
	this.ZoomTileSet();
}

function zoomDivTilesOnSliderByStep(ZoomCenterPixelX, ZoomCenterPixelY, ZoomFaktor)
{
	var nSliderTileLeft = this.nZoomTileSetLeft;
	var nSliderTileTop = this.nZoomTileSetTop;
	var nSliderTileWidth = this.nTileWidth;
	var nSliderTileHeight = this.nTileHeight;

	//create new array for zooming
	this.CreateZoomTileSet(this.nZoomTilesX, this.nZoomTilesY, this.nTileWidth, this.nTileHeight, this.nZoomTileSetLeft, this.nZoomTileSetTop, this.nZoomTileZIndex);
		
	this.nZoomSingleStepX = Math.round( nSliderTileWidth * this.nZoomTilesX * (ZoomFaktor - 1) );
	this.nZoomSingleStepY = Math.round( nSliderTileHeight * this.nZoomTilesY * (ZoomFaktor - 1) );

	this.ZoomTiles(this.nZoomSingleStepX, this.nZoomSingleStepY, this.nZoomTilesX, this.nZoomTilesY);		
	
	var nVisibleCenterX =  this.nVisibleWidth / 2 - nSliderTileLeft;
	var nVisibleCenterY =  this.nVisibleHeight / 2 - nSliderTileTop;
	
	var nNewZoomCenterX = 0;
	var nOriginalX = ZoomCenterPixelX - nSliderTileLeft;
	var nCenterTileNumX = Math.floor(nOriginalX / this.nTileWidth);
	var nXinTile = nOriginalX - this.nTileWidth * nCenterTileNumX;
	nCenterTileNumX = nCenterTileNumX + 1;
	if (nCenterTileNumX < 2)
	{
		nNewZoomCenterX = nXinTile / this.nTileWidth * this.aZoomTileSet[0].width;
	}
	else
	{
		for (var nTileNum = 0; nTileNum <= nCenterTileNumX - 2; nTileNum++)
		{
			nNewZoomCenterX = nNewZoomCenterX + this.aZoomTileSet[nTileNum].width;
		}
		nNewZoomCenterX = nNewZoomCenterX + nXinTile / this.nTileWidth * this.aZoomTileSet[nCenterTileNumX-1].width;
	}

	var nNewZoomCenterY = 0;
	var nOriginalY = ZoomCenterPixelY - nSliderTileTop;
	var nCenterTileNumY = Math.floor(nOriginalY / this.nTileHeight);
	var nYinTile = nOriginalY - this.nTileHeight * nCenterTileNumY;
	nCenterTileNumY = nCenterTileNumY + 1;
	if (nCenterTileNumY < 2)
	{
		nNewZoomCenterY = nYinTile / this.nTileHeight * this.aZoomTileSet[0].height;
	}
	else
	{
		for (var nTileNumY = 0; nTileNumY <= nCenterTileNumY - 2; nTileNumY++)
		{
			nNewZoomCenterY = nNewZoomCenterY + this.aZoomTileSet[nCenterTileNumX + this.nZoomTilesX*nTileNumY].height;
		}
		nNewZoomCenterY = nNewZoomCenterY + nYinTile / this.nTileHeight * this.aZoomTileSet[nCenterTileNumX-1 + this.nZoomTilesX*(nCenterTileNumY-1)].height;
	}
	this.nMoveSingleStepX = Math.round( ( nVisibleCenterX - nNewZoomCenterX ) ); 
	this.nMoveSingleStepY = Math.round( ( nVisibleCenterY - nNewZoomCenterY ) ); 

	this.MoveTiles(this.nMoveSingleStepX, this.nMoveSingleStepY, this.nZoomTilesX, this.nZoomTilesY);
	
	if ( this.aZoomTileSet[0].width < this.nLimitationOfTileSize )
	{
		this.PlaceZoomTileSetByStep(this.aTotalTileList, this.nZoomTilesX, this.nZoomTilesY);
	}
}

function zoomDivTilesOnSlider(ZoomCenterPixelX, ZoomCenterPixelY, ZoomFaktor)
{
	nSliderTileLeft = this.aZoomTileSet[0].left;
	nSliderTileTop = this.aZoomTileSet[0].top;
	nSliderTileWidth = this.aZoomTileSet[0].width;
	nSliderTileHeight = this.aZoomTileSet[0].height;
	
	nZoomSingleStepX = Math.round( nSliderTileWidth * nZoomTilesX * (ZoomFaktor - 1) );
	nZoomSingleStepY = Math.round( nSliderTileHeight * nZoomTilesY * (ZoomFaktor - 1) );	
	nVisibleCenterX =  nVisibleWidth / 2 - nSliderTileLeft;
	nVisibleCenterY =  nVisibleHeight / 2 - nSliderTileTop;
	nNewZoomCenterX = (ZoomCenterPixelX - nSliderTileLeft) * ZoomFaktor;
	nNewZoomCenterY = (ZoomCenterPixelY - nSliderTileTop) * ZoomFaktor;
	nMoveSingleStepX = Math.round( ( nVisibleCenterX - nNewZoomCenterX )); 
	nMoveSingleStepY = Math.round( ( nVisibleCenterY - nNewZoomCenterY )); 
	
	ZoomTiles(nZoomSingleStepX, nZoomSingleStepY, nZoomTilesX, nZoomTilesY);
	MoveTiles(nMoveSingleStepX, nMoveSingleStepY, nZoomTilesX, nZoomTilesY);
	PlaceZoomTileSet(aTotalTileList, nZoomTilesX, nZoomTilesY);
	
	if (aZoomTileSet[0].width <= 15)
	{
		max_slider = mapSlider.getValue();
	}
	if (aZoomTileSet[0].width >= 600)
	{
		min_slider = mapSlider.getValue();
	}	
}

function createDivZoomTiles(oDivTiles)
{
	this.oDivTileMap = oDivTiles;
	this.divTileMapZoom = oDivTiles.cloneNode(false);
	this.divTileMapZoom.id = "divTileMapZoom";

	if (BrowserDetect.browser == "Safari" || BrowserDetect.browser == "Konqueror")
	{
		this.divTileMapZoom.style.visibility = "visible";
		this.divTileMapZoom.style.zIndex = 2; // for besser showlabel(synconisieren)
	}
	else
	{
		this.divTileMapZoom.style.visibility = "hidden";
	}

	oDivTiles.parentNode.appendChild(this.divTileMapZoom);
}

function getZoomPosition(StartX, StartY, EndX, EndY)
{
	if ((StartX == EndX) || (StartY == EndY))
	{
		return;  //no Zooming
	}
	
	var nStartX = StartX;
	var nStartY = StartY;
	var nEndX = EndX;
	var nEndY = EndY;
	
	var nWidthChange = 0;
	var nHeightChange = 0;
	
	this.nZoomCenterPixelX = Math.round( (nStartX + nEndX) / 2 );
	this.nZoomCenterPixelY = Math.round( (nStartY + nEndY) / 2 );
	
	//calculate right panning area with ratio from visiblewindow
	var nVisibleRatio = this.nVisibleWidth / this.nVisibleHeight;
	
	this.nPanningWidth = Math.abs( nStartX - nEndX );
	this.nPanningHeight = Math.abs( nStartY - nEndY );

	var nZoomAreaRatio = this.nPanningWidth / this.nPanningHeight ;
		
	if (nZoomAreaRatio < nVisibleRatio)
	{
		nWidthChange =  ( Math.abs((nEndY - nStartY)) * nVisibleRatio - Math.abs((nEndX - nStartX)) ) /2 ;		
		nStartY = nStartY;
		nEndY = nEndY;		
		if (nStartX < nEndX)
		{
			nStartX = Math.round( nStartX - nWidthChange );
			nEndX = Math.round( nEndX + nWidthChange );
		}
		else
		{
			nStartX = Math.round( nStartX + nWidthChange );
			nEndX = Math.round( nEndX - nWidthChange );
		}
	}
	else  
	{	
		nHeightChange = ( Math.abs((nEndX - nStartX)) / nVisibleRatio - Math.abs((nEndY - nStartY)) )/2 ;		
		nStartX = nStartX;
		nEndX = nEndX;		
		if (nStartY < nEndY)
		{
	  	nStartY = Math.round( nStartY - nHeightChange );
		  nEndY = Math.round( nEndY + nHeightChange );		
		}
		else
		{
	  	nStartY = Math.round( nStartY + nHeightChange );
		  nEndY = Math.round( nEndY - nHeightChange );				
		}
	}
	//new PanningArea
	this.nPanningWidth = Math.abs( nStartX - nEndX );
	this.nPanningHeight = Math.abs( nStartY - nEndY );
	
	//calculate nZoomFaktor
	if (nStartX < nEndX) // zoom in
	{
	  this.nZoomFaktor = this.nVisibleWidth / Math.abs( nStartX - nEndX );
	}
	else // zoom out
	{
		this.nZoomFaktor = Math.abs( nStartX - nEndX ) / this.nVisibleWidth;
	}
}

function setArrayOfWholeTiles(bCopy)
{
	this.aZoomTilesNodes = new Array(0);
	
	for (var nTile = 0; nTile < this.oDivTileMap.childNodes.length; nTile++)
	{
		var oChild = this.oDivTileMap.childNodes[nTile];
		
		//check is DIV node
		if ((oChild.nodeName == "DIV") && oChild.id != "divTileMap")
		{		
				this.aZoomTilesNodes.push(oChild);
		}
	} //end for			
}

function setArrayOfVisibleWindow(ZoomCenterPixelX, ZoomCenterPixelY, bCopy)
{
	this.aZoomTilesNodes = new Array(0);
	
	//get all zoomable tiles in visible window
	var nStartX = ZoomCenterPixelX - this.nPanningWidth/2;
	if (nStartX > 0)
	{
		nStartX = 0;
	}
	var nStartY = ZoomCenterPixelY - this.nPanningHeight/2;
	if (nStartY >0)
	{
		nStartY = 0;
	}
	
	var nEndX = ZoomCenterPixelX + this.nPanningWidth/2;

	if (nEndX < this.nVisibleWidth)
	{
		nEndX = this.nVisibleWidth;
	}	
	var nEndY = ZoomCenterPixelY + this.nPanningHeight/2;
	if (nEndY < this.nVisibleHeight)
	{
		nEndY = this.nVisibleHeight;
	}		

	for (var nTile = 0; nTile < this.oDivTileMap.childNodes.length; nTile++)
	{
		var oChild = this.oDivTileMap.childNodes[nTile];
		
		//check is DIV node
		if ((oChild.nodeName == "DIV") && oChild.id != "divTileMap")
		{
			var nDivTop = parseInt(oChild.style.top);
			var nDivLeft = parseInt(oChild.style.left);
			var nDivRight = nDivLeft + this.nTileWidth;
			var nDivBottom = nDivTop + this.nTileHeight;
			
			//check Tile in visible window	
			if ( this.isTileInVisibleWindow(nDivTop, nDivLeft, nDivRight, nDivBottom, nStartX, nStartY, nEndX, nEndY) )
			{
					this.aZoomTilesNodes.push(oChild);					
			}
		} 
	} //end for		
}

function getLeftTopOfVisibleWindow()
{
	var nStartTilesX = 0;
	var nStartTilesY = 0;
	var nTilesX = 0;
	var nTilesY = 0;

	var nLeftMin = parseInt(this.aZoomTilesNodes[0].style.left);
	nStartTilesX = (parseInt(this.aZoomTilesNodes[0].id.substring(this.aZoomTilesNodes[0].id.indexOf("_",1)+1, this.aZoomTilesNodes[0].id.lastIndexOf("_"))));
	
	var nTopMin = parseInt(this.aZoomTilesNodes[0].style.top);
	nStartTilesY = (parseInt(this.aZoomTilesNodes[0].id.substring(this.aZoomTilesNodes[0].id.lastIndexOf("_")+1)));

	var nRightMax = parseInt(this.aZoomTilesNodes[0].style.left);
	nTilesX = (parseInt(this.aZoomTilesNodes[0].id.substring(this.aZoomTilesNodes[0].id.indexOf("_",1)+1, this.aZoomTilesNodes[0].id.lastIndexOf("_"))));
	
	var nBottomMax = parseInt(this.aZoomTilesNodes[0].style.top);
	nTilesY = (parseInt(this.aZoomTilesNodes[0].id.substring(this.aZoomTilesNodes[0].id.lastIndexOf("_")+1)));		

	for (var nTileNum = 0; nTileNum < this.aZoomTilesNodes.length; nTileNum++)
	{
		if (parseInt(this.aZoomTilesNodes[nTileNum].style.left) < nLeftMin)
		{
			nLeftMin = parseInt(this.aZoomTilesNodes[nTileNum].style.left);
			nStartTilesX = (parseInt(this.aZoomTilesNodes[nTileNum].id.substring(this.aZoomTilesNodes[nTileNum].id.indexOf("_",1)+1, this.aZoomTilesNodes[nTileNum].id.lastIndexOf("_"))));				
		}
		if (parseInt(this.aZoomTilesNodes[nTileNum].style.top) < nTopMin)
		{
			nTopMin = parseInt(this.aZoomTilesNodes[nTileNum].style.top);
			nStartTilesY = (parseInt(this.aZoomTilesNodes[nTileNum].id.substring(this.aZoomTilesNodes[nTileNum].id.lastIndexOf("_")+1)));
		}			

		if (parseInt(this.aZoomTilesNodes[nTileNum].style.left) > nRightMax)
		{
			nRightMax = parseInt(this.aZoomTilesNodes[nTileNum].style.left);
			nTilesX = (parseInt(this.aZoomTilesNodes[nTileNum].id.substring(this.aZoomTilesNodes[nTileNum].id.indexOf("_",1)+1, this.aZoomTilesNodes[nTileNum].id.lastIndexOf("_"))));
		}

		if (parseInt(this.aZoomTilesNodes[nTileNum].style.top) > nBottomMax)
		{
			nBottomMax = parseInt(this.aZoomTilesNodes[nTileNum].style.top);
			nTilesY = (parseInt(this.aZoomTilesNodes[nTileNum].id.substring(this.aZoomTilesNodes[nTileNum].id.lastIndexOf("_")+1)));
		}
	}

	//calculate horizontal and vertical number of tiles	
	this.nZoomTilesX = nTilesX - nStartTilesX + 1;
	this.nZoomTilesY = nTilesY - nStartTilesY + 1;
	if (this.nZoomTilesX <= 0)
	{
		this.nZoomTilesX = this.nZoomTilesX + this.nTileSetX;
	}
	if (this.nZoomTilesY <= 0)
	{
		this.nZoomTilesY = this.nZoomTilesY + this.nTileSetY;
	}
	
	//lefttop position of tile in visible window
	this.nZoomTileSetLeft = nLeftMin;
	this.nZoomTileSetTop = nTopMin;
	
	//lefttop number of tile in visible window
	this.nLeftTopTileNumX = nStartTilesX;
	this.nLeftTopTileNumY = nStartTilesY;
}

function setArrayForCloneDIV(bCopy)
{
	this.aZoomTilesNodes = new Array(0);
	this.aPlaceTileSetIMG = new Array(0);
	this.aPlaceTileSetDIV = new Array(0);	

	var nTileNum = 0;
	for (var nRow=0; nRow<this.nZoomTilesY; nRow++)
	{
		for (var nCol=0; nCol<this.nZoomTilesX; nCol++)
		{
			var divTile = document.getElementById('divTile_'+( (this.nLeftTopTileNumX + nCol) % this.nTileSetX)+'_'+((this.nLeftTopTileNumY + nRow) % this.nTileSetY) );
			if (bCopy)
			{
				var divTileClone = divTile.cloneNode(false);
				divTileClone.id = "C_" + divTile.id;
				for (var nChild = 0; nChild < divTile.childNodes.length; nChild++)
				{
					if (divTile.childNodes[nChild].nodeName == "IMG")
					{
						//var oImage = new Image();
						var oImage 		= document.createElement('img');
						oImage.id = "C_" + divTile.childNodes[nChild].id;
						//oImage.style.visibility = "hidden";
						oImage.src = "img/blank.gif";
						oImage.width = divTile.childNodes[nChild].width;
						oImage.height = divTile.childNodes[nChild].height;
						divTileClone.appendChild(oImage);
					}					
				}
						
				// no copy
				divTile.id = "z"+divTile.id;
				divTile.style.zIndex = 0;
				this.aZoomTilesNodes.push(divTile);				
				this.aPlaceTileSetDIV.push(divTile.style);
				
				for (var nChild = 0; nChild < divTile.childNodes.length; nChild++)
				{
					if (divTile.childNodes[nChild].nodeName == "IMG")
					{
						divTile.childNodes[nChild].id = "z"+ divTile.childNodes[nChild].id;
								
						this.aPlaceTileSetIMG.push(divTile.childNodes[nChild]);
					}
				}
				
				// append new Tiles				
				divTileClone.id = divTileClone.id.substring(2);
				for (var nChild = 0; nChild < divTileClone.childNodes.length; nChild++)
				{
					if (divTileClone.childNodes[nChild].nodeName == "IMG")
					{
						divTileClone.childNodes[nChild].id = divTileClone.childNodes[nChild].id.substring(2);
					}					
				}
				this.oDivTileMap.appendChild(divTileClone);
				
				var nIndex = 0;
				for (var iRow = 0; iRow < oTileset.nTotalTilesY; iRow++)
				{
					for (var iCol = 0; iCol < oTileset.nTotalTilesX; iCol++)
					{
						oTileset.aTiles[nIndex].oDiv = document.getElementById("divTile_" + iCol + "_" + iRow);
						oTileset.aTiles[nIndex].oImg = document.getElementById("imgTile_" + iCol + "_" + iRow);
						nIndex ++;
					}
				}					
			}
			else
			{
				divTile.id = "z"+divTile.id;
				divTile.style.zIndex = 1;
				this.aZoomTilesNodes.push(divTile);				
				this.aPlaceTileSetDIV.push(divTile.style);
				
				for (var nChild = 0; nChild < divTile.childNodes.length; nChild++)
				{
					if (divTile.childNodes[nChild].nodeName == "IMG")
					{
						divTile.childNodes[nChild].id = "z"+ divTile.childNodes[nChild].id;
								
						this.aPlaceTileSetIMG.push(divTile.childNodes[nChild]);
					}
				}							
			}
			nTileNum++;
		}
	}	
}

function getZoomArea(ZoomCenterPixelX, ZoomCenterPixelY)
{
	this.setArrayOfWholeTiles(this.bCloneTiles);
	this.getLeftTopOfVisibleWindow();
	this.setArrayForCloneDIV(this.bCloneTiles);	
}

function getZoomAreaByStep(ZoomCenterPixelX, ZoomCenterPixelY)
{
	//VisibleWindow for start at nStartX = 0 and nStartY = 0
	var nStartX = 0;
	var nStartY = 0;
	var nEndX = this.nVisibleWidth;
	var nEndY = this.nVisibleHeight;
	
	// for zoomin and zoomout 
	this.setArrayOfVisibleWindow(ZoomCenterPixelX, ZoomCenterPixelY, this.bCloneTiles);	
	this.getLeftTopOfVisibleWindow();
	this.setArrayForCloneDIV(this.bCloneTiles);	
}

function appendZoomDIVSet()
{
	if (this.divTileMapZoom != null)
	{
		for (var i=0; i<this.aZoomTilesNodes.length; i++)
		{
			this.divTileMapZoom.appendChild(this.aZoomTilesNodes[i]);			
		}
	}
}

function removeZoomDIVSet()
{
	var divZoom = document.getElementById("divTileMapZoom");
	if (divZoom != null)
	{
		divZoom.parentNode.removeChild(divZoom);
	}
}

function isExistZoomDIVSet()
{
	var divZoom = document.getElementById("divTileMapZoom");
	return divZoom;
}

function getZoomLimitation()
{
	var CurrentTilesizeMeter = this.oIwTileSet.nTilesizeMeter;
	if ( CurrentTilesizeMeter/this.nZoomFaktor < A_TILESIZE_METER[0] ) 
	{
		this.nZoomFaktor = CurrentTilesizeMeter/A_TILESIZE_METER[0];
		return A_TILESIZE_METER[0];
	}

	if ( CurrentTilesizeMeter/this.nZoomFaktor > A_TILESIZE_METER[A_TILESIZE_METER.length-1] ) 
	{
		this.nZoomFaktor = CurrentTilesizeMeter/A_TILESIZE_METER[A_TILESIZE_METER.length-1];
		return A_TILESIZE_METER[A_TILESIZE_METER.length-1];
	}
}

function SetOnZoomEffectEnd(fCallback)
{
	this.fOnZoomEffectEnd = fCallback;
}

	this.nZoomCenterPixelX = 0;
	this.nZoomCenterPixelY = 0;
	
function GetZoomCenterPixelX()
{
	return this.nZoomCenterPixelX;
}	

function GetZoomCenterPixelY()
{
	return this.nZoomCenterPixelY;
}

function SetZoomCenterPixelX(nZoomCenterPixelX)
{
	this.nZoomCenterPixelX = nZoomCenterPixelX;
}	

function SetZoomCenterPixelY(nZoomCenterPixelY)
{
	this.nZoomCenterPixelY = nZoomCenterPixelY;
}

function SetZoomFactor(nFactor)
{
	this.nZoomFaktor = nFactor;
}

function GetZoomFactor()
{
	return this.nZoomFaktor;
}

function SetDivTileMap()
{
	var divTileMapID = "divTileMap";
	var divTileMap = document.getElementById(divTileMapID);
	this.oDivTileMap = divTileMap;
}

function SetLastTilesizeMeter(LastTilesizeMeter)
{
	this.nLastTilesizeMeter = LastTilesizeMeter;
}

function SetCurrentTilesizeMeter(CurrentTilesizeMeter)
{
	this.nCurrentTilesizeMeter = CurrentTilesizeMeter;
}

function GetLastTilesizeMeter()
{
	return this.nLastTilesizeMeter;
}

function GetCurrentTilesizeMeter()
{
	return this.nCurrentTilesizeMeter;
}


function ZoomByStep(nFactor)
{
	this.nZoomCenterPixelX	= Math.round(this.nVisibleWidth		/ 2);
	this.nZoomCenterPixelY	= Math.round(this.nVisibleHeight	/ 2);
	this.nPanningWidth			= this.nVisibleWidth;
	this.nPanningHeight		= this.nVisibleHeight;

	this.SetZoomFactor(nFactor);
	this.SetDivTileMap();
	this.createDivZoomTiles(this.oDivTileMap);
	this.getZoomArea(this.nZoomCenterPixelX, this.nZoomCenterPixelY);
	this.appendZoomDIVSet();
	this.CreateZoomTileSet(this.nZoomTilesX, this.nZoomTilesY, this.nTileWidth, this.nTileHeight, this.nZoomTileSetLeft, this.nZoomTileSetTop, this.nZoomTileZIndex);		
	this.zoomDivTiles(this.nZoomCenterPixelX, this.nZoomCenterPixelY, this.nZoomFaktor, this.nZoomSteps);	
}


function PrepareZoomOnSlider(TilesizeMeter)
{
	this.bPrepareZoomOnSlider = true;
	this.SetLastTilesizeMeter(TilesizeMeter);
	this.SetCurrentTilesizeMeter(TilesizeMeter);
	this.SetDivTileMap();
	this.createDivZoomTiles(this.oDivTileMap);
	this.getZoomPosition(0, 0, this.nVisibleWidth, this.nVisibleHeight);
	this.getZoomAreaByStep(this.nZoomCenterPixelX, this.nZoomCenterPixelY);
	this.appendZoomDIVSet();
	this.CreateZoomTileSet(this.nZoomTilesX, this.nZoomTilesY, this.nTileWidth, this.nTileHeight, this.nZoomTileSetLeft, this.nZoomTileSetTop, this.nZoomTileZIndex);										
}

function ZoomOnSlider(CurrentTilesizeMeter)
{
	this.SetCurrentTilesizeMeter(CurrentTilesizeMeter);
	this.SetZoomFactor( this.nLastTilesizeMeter / this.nCurrentTilesizeMeter );
	this.zoomDivTilesOnSliderByStep(this.nVisibleWidth/2, this.nVisibleHeight/2, this.nZoomFaktor);
}

function SetZoomTileZIndex(nZIndex)
{
	this.nZoomTileZIndex = nZIndex;
}

function GetZoomTileZIndex()
{
	return this.nZoomTileZIndex;
}
