var previewTime     = 2;    // Время в миллисекундах между фреймами анимации масштабирования
var previewSteps    = 15;   // Кол-во фреймов анимации масштабирования
var includeFade     = 0;    // Если 1 то при масштабировании картинки полупрозрачные.
var minBorder       = 90;   // Amount of padding between large, scaled down images, and the window edges

var ImagesURI   = './im/preview/'; // Location of the preview images

// Инициализация
var windowWidth = 0, windowHeight = 0, windowScroll = 0; windowScrollWidth = 0; windowScrollHeight = 0;
var previewOpen = false, preloadFrame = 1, preloadActive = false, preloadTime = 0, imgPreload = new Image();
var preloadAnimTimer = 0;

var previewActive = new Array(); 
var previewTimer  = new Array(); 
var previewOrigW  = new Array(); 
var previewOrigH  = new Array();
var previewOrigX  = new Array(); 
var previewOrigY  = new Array();

var previewID         = "PreviewBox";
var previewImageID    = "PreviewImage";
var waitAnimID        = "WaitAnimBox";
var waitAnimImageID   = "WaitAnimImage";

// Инициализируем масштабирование. Функцию надо прописать, например, в <body onload="initPreview()">
function initPreview() 
{
	updateHrefObjectPreviewEvents();
	insertPreviewHTML();
	previewdiv = document.getElementById(previewID);  
	previewimg = document.getElementById(previewImageID);
}

// Добавляем обработчики сообщений от мыши, для href помеченных для preview
function updateHrefObjectPreviewEvents() 
{
	if (!document.getElementsByTagName)
		return;

	var links = document.getElementsByTagName("a");
	for (i = 0; i < links.length; i++) 
	{
		if ((links[i].getAttribute("href")) && (links[i].getAttribute("rel") == "preview"))
		{
			links[i].onclick = function (event) { return previewClick(this, event); };
			links[i].onmouseover = function () { previewPreload(this); };
		}
	}
}

// Загружаем большую картинку, когда загрузка закончена выставляем preloadActive = false,
function previewPreload(from) 
{
    var theimage = from.getAttribute("href");
    // загружаем, только если это изображение еще не загружено
    if (imgPreload.src.indexOf(from.getAttribute("href").substr(from.getAttribute("href").lastIndexOf("/"))) == -1) 
    {
        preloadActive = true;
        imgPreload = new Image();
        imgPreload.onload = function(){preloadActive = false;}
        imgPreload.src = theimage;
    }
}

// Стартуем загрузку большого изображения, включаем анимацию пока изображение не загрзится
function preloadAnimStart() 
{
	preloadTime = new Date();
	document.getElementById(waitAnimID).style.left = (windowWidth / 2) + 'px';
	document.getElementById(waitAnimID).style.top = ((windowHeight / 2) + windowScroll) + 'px';
	document.getElementById(waitAnimID).style.visibility = "visible";	
	preloadFrame = 1;
	document.getElementById(waitAnimImageID).src = ImagesURI+'wait_anim_'+preloadFrame+'.png';  
	preloadAnimTimer = setInterval("preloadAnim()", 50);
}

// Показываем анимацию пока изображение не загружено
function preloadAnim(from) 
{
	if (preloadActive != false)
	{
		document.getElementById(waitAnimImageID).src = ImagesURI+'wait_anim_'+preloadFrame+'.png';
		preloadFrame++;
		if (preloadFrame > 12) preloadFrame = 1;
	}
	else 
	{
		document.getElementById(waitAnimID).style.visibility = "hidden";    
		clearInterval(preloadAnimTimer);
		preloadAnimTimer = 0;
		previewIn(preloadFrom);
	}
}

//Обрабатываем клик мышью на изображении
function previewClick(from, evt) 
{
	var shift = getShift(evt);

	// если зажата кнопка Alt не запускаем превью
	if (!evt && window.event && (window.event.metaKey || window.event.altKey)) 
		return true;
	else if (evt && (evt.metaKey|| evt.altKey)) 
		return true;

	// Получаем размеры окна и сдвиги скроллеров
	getSize();

	// Ждем пока большое изображение загрузится
	if (preloadActive == true) 
	{
		if (preloadAnimTimer == 0) 
		{
			preloadFrom = from;
			preloadAnimStart();	
		}
	} 
	else 
	{
	    previewPreload(from);//на всякий случай проверим загрузилась ли большая картинка 
		  previewIn(from, shift);
	}
	return false;
}

function previewIn(from, shift) 
{
	previewimg.src = from.getAttribute("href");

	if (from.childNodes[0].width) 
	{
		startW = from.childNodes[0].width;
		startH = from.childNodes[0].height;
		startPos = findElementPos(from.childNodes[0]);
	}
	else 
	{
		startW = 50;
		startH = 12;
		startPos = findElementPos(from);
	}

	hostX = startPos[0];
	hostY = startPos[1];

	if (document.getElementById('scroller')) 
		hostX = hostX - document.getElementById('scroller').scrollLeft;

	endW = imgPreload.width;
	endH = imgPreload.height;

	if (previewActive[previewImageID] != true) 
	{
		previewOrigW[previewImageID] = startW;
		previewOrigH[previewImageID] = startH;
		previewOrigX[previewImageID] = hostX;
		previewOrigY[previewImageID] = hostY;

		previewimg.style.width  = startW + 'px';
		previewimg.style.height = startH + 'px';
		previewdiv.style.left   = hostX + 'px';
		previewdiv.style.top    = hostY + 'px';

		if (includeFade == 1) 
			setOpacity(0, previewID);
		previewdiv.style.visibility = "visible";

		sizeRatio = endW / endH;
		if (endW > windowWidth - minBorder) 
		{
			endW = windowWidth - minBorder;
			endH = endW / sizeRatio;
		}
		if (endH > windowHeight - minBorder) 
		{
			endH = windowHeight - minBorder;
			endW = endH * sizeRatio;
		}

		previewChangeX = ((windowWidth / 2) - (endW / 2) - hostX);
		previewChangeY = (((windowHeight / 2) - (endH / 2) - hostY) + windowScroll);
		previewChangeW = (endW - startW);
		previewChangeH = (endH - startH);
	
		if (shift) 
			tempSteps = previewSteps * 7;
		else 
			tempSteps = previewSteps;

		previewCurrent = 0;

		if (includeFade == 1) 
		{
			fadeCurrent = 0;
			fadeAmount = (0 - 100) / tempSteps;
		}
		else 
		{
			fadeAmount = 0;
		}
		
		previewTimer[previewImageID] = setInterval("previewElement('"+previewID+"', '"+previewImageID+"', "+previewCurrent+", "+startW+", "+previewChangeW+", "+startH+", "+previewChangeH+", "+hostX+", "+previewChangeX+", "+hostY+", "+previewChangeY+", "+tempSteps+", "+includeFade+", "+fadeAmount+", 'previewDoneIn(previewID)')", previewTime);		
		previewActive[previewImageID] = true; 
	}
}

function previewOut(from, evt) 
{
	if (getShift(evt)) 
		tempSteps = previewSteps * 7;
	else 
		tempSteps = previewSteps;

	if (previewActive[previewImageID] != true) 
	{
		startX = parseInt(previewdiv.style.left);
		startY = parseInt(previewdiv.style.top);
		startW = previewimg.width;
		startH = previewimg.height;
		previewChangeX = previewOrigX[previewImageID] - startX;
		previewChangeY = previewOrigY[previewImageID] - startY;
		previewChangeW = previewOrigW[previewImageID] - startW;
		previewChangeH = previewOrigH[previewImageID] - startH;

		previewCurrent = 0;

		if (includeFade == 1) 
		{
			fadeCurrent = 0;
			fadeAmount = (100 - 0) / tempSteps;
		}
		else
		{
			fadeAmount = 0;
		}

		previewTimer[previewImageID] = setInterval("previewElement('"+previewID+"', '"+previewImageID+"', "+previewCurrent+", "+startW+", "+previewChangeW+", "+startH+", "+previewChangeH+", "+startX+", "+previewChangeX+", "+startY+", "+previewChangeY+", "+tempSteps+", "+includeFade+", "+fadeAmount+", 'previewDone(previewID, previewImageID)')", previewTime);	
		previewActive[previewImageID] = true;
	}
}

function previewDoneIn(previewdiv, previewImageID) 
{
	previewOpen = true;
	previewdiv = document.getElementById(previewdiv);
	document.onkeypress = getKey;
}

function previewDone(previewdiv, previewImageID) 
{
	previewOpen = false;

	previewOrigH[previewImageID] = "";
	previewOrigW[previewImageID] = "";
	document.getElementById(previewdiv).style.visibility = "hidden";
	previewActive[previewImageID] == false;

	document.onkeypress = null;
}

function previewElement(previewdiv, previewImageID, previewCurrent, previewStartW, previewChangeW, previewStartH, previewChangeH, previewStartX, previewChangeX, previewStartY, previewChangeY, previewSteps, includeFade, fadeAmount, execWhenDone) 
{
	if (previewCurrent == (previewSteps + 1)) 
	{
		previewActive[previewImageID] = false;
		clearInterval(previewTimer[previewImageID]);

		if (execWhenDone != "") 
			eval(execWhenDone);
	} 
	else 
	{
		if (includeFade == 1) 
		{
			if (fadeAmount < 0) 
				setOpacity(Math.abs(previewCurrent * fadeAmount), previewdiv);
			else 
				setOpacity(100 - (previewCurrent * fadeAmount), previewdiv);
		}
	  
		moveW = cubicInOut(previewCurrent, previewStartW, previewChangeW, previewSteps);
		moveH = cubicInOut(previewCurrent, previewStartH, previewChangeH, previewSteps);
		moveX = cubicInOut(previewCurrent, previewStartX, previewChangeX, previewSteps);
		moveY = cubicInOut(previewCurrent, previewStartY, previewChangeY, previewSteps);
	
		document.getElementById(previewdiv).style.left = moveX + 'px';
		document.getElementById(previewdiv).style.top = moveY + 'px';
		previewimg.style.width = moveW + 'px';
		previewimg.style.height = moveH + 'px';
	
		previewCurrent++;
		
		clearInterval(previewTimer[previewImageID]);
		previewTimer[previewImageID] = setInterval("previewElement('"+previewdiv+"', '"+previewImageID+"', "+previewCurrent+", "+previewStartW+", "+previewChangeW+", "+previewStartH+", "+previewChangeH+", "+previewStartX+", "+previewChangeX+", "+previewStartY+", "+previewChangeY+", "+previewSteps+", "+includeFade+", "+fadeAmount+", '"+execWhenDone+"')", previewTime);
        temp = "previewElement('"+previewdiv+"', '"+previewImageID+"', "+previewCurrent+", "+previewStartW+", "+previewChangeW+", "+previewStartH+", "+previewChangeH+", "+previewStartX+", "+previewChangeX+", "+previewStartY+", "+previewChangeY+", "+previewSteps+", "+includeFade+", "+fadeAmount+", '"+execWhenDone+"')", previewTime		
	}
}

function getKey(evt) 
{
    if (!evt) 
        theKey = event.keyCode;
    else 
        theKey = evt.keyCode;

    if (theKey == 27) // ESC
        previewOut(this, evt);
}

function fadeOut(elem) 
{
	if (elem.id) 
		fadeElementSetup(elem.id, 100, 0, 10);
}

function fadeIn(elem) 
{
	if (elem.id)
		fadeElementSetup(elem.id, 0, 100, 10);	
}

var fadeActive = new Array();
var fadeQueue  = new Array();
var fadeTimer  = new Array();
var fadeClose  = new Array();
var fadeMode   = new Array();
function fadeElementSetup(previewImageID, fdStart, fdEnd, fdSteps, fdClose, fdMode) 
{
	if (fadeActive[previewImageID] == true) 
	{
		fadeQueue[previewImageID] = new Array(previewImageID, fdStart, fdEnd, fdSteps);
	}
	else 
	{
		fadeSteps = fdSteps;
		fadeCurrent = 0;
		fadeAmount = (fdStart - fdEnd) / fadeSteps;
		fadeTimer[previewImageID] = setInterval("fadeElement('"+previewImageID+"', '"+fadeCurrent+"', '"+fadeAmount+"', '"+fadeSteps+"')", 15);
		fadeActive[previewImageID] = true;
		fadeMode[previewImageID] = fdMode;
		
		if (fdClose == 1) 
			fadeClose[previewImageID] = true;
		else 
			fadeClose[previewImageID] = false;
	}
}

function fadeElement(previewImageID, fadeCurrent, fadeAmount, fadeSteps) 
{
    if (fadeCurrent == fadeSteps) 
    {
        clearInterval(fadeTimer[previewImageID]);
        fadeActive[previewImageID] = false;
        fadeTimer[previewImageID] = false;

        if (fadeClose[previewImageID] == true) 
            document.getElementById(previewImageID).style.visibility = "hidden";
    
        if (fadeQueue[previewImageID] && fadeQueue[previewImageID] != false) 
        {
            fadeElementSetup(fadeQueue[previewImageID][0], fadeQueue[previewImageID][1], fadeQueue[previewImageID][2], fadeQueue[previewImageID][3]);
            fadeQueue[previewImageID] = false;
        }
    } 
    else 
    {
        fadeCurrent++;

        if (fadeAmount < 0) 
            setOpacity(Math.abs(fadeCurrent * fadeAmount), previewImageID);
        else 
            setOpacity(100 - (fadeCurrent * fadeAmount), previewImageID);

        clearInterval(fadeTimer[previewImageID]);
        fadeTimer[previewImageID] = setInterval("fadeElement('"+previewImageID+"', '"+fadeCurrent+"', '"+fadeAmount+"', '"+fadeSteps+"')", 15);
    }
}

function setOpacity(opacity, previewImageID) 
{
	var object = document.getElementById(previewImageID).style;

	if ((navigator.userAgent.indexOf("Firefox") != -1) && (opacity == 100))
	    opacity = 99.9999;

	object.filter = "alpha(opacity=" + opacity + ")";
	object.opacity = (opacity / 100);
}

function cubicInOut(t, b, c, d)
{
	if ((t/=d/2) < 1) 
        return c/2*t*t*t + b;
	return c/2*((t-=2)*t*t + 2) + b;
}

function getSize() 
{
	if (self.innerHeight) 
	{
		windowWidth     = window.innerWidth;
		windowHeight    = window.innerHeight;
		windowScroll    = window.pageYOffset;
	}
	else if (document.documentElement && document.documentElement.clientHeight) 
	{
		windowWidth = document.documentElement.clientWidth;
		windowHeight = document.documentElement.clientHeight;
		windowScroll = document.documentElement.scrollTop;
	}
	else if (document.body) 
	{
		windowWidth = document.body.clientWidth;
		windowHeight = document.body.clientHeight;
		windowScroll = document.body.scrollTop;
	}

	if (window.innerHeight && window.scrollMaxY) 
	{
		windowScrollWidth = document.body.scrollWidth;
		windowScrollHeight = window.innerHeight + window.scrollMaxY;
	}
	else if (document.body.scrollHeight > document.body.offsetHeight) 
	{
		windowScrollWidth = document.body.scrollWidth;
		windowScrollHeight = document.body.scrollHeight;
	}
	else 
	{
		windowScrollWidth = document.body.offsetWidth;
		windowScrollHeight = document.body.offsetHeight;
	}
}

function getShift(evt) 
{
	var shift = false;
	if (!evt && window.event) 
		shift = window.event.shiftKey;
	else if (evt) 
	{
		shift = evt.shiftKey;
		if (shift) 
		    evt.stopPropagation();
	}
	return shift;
}

function findElementPos(elemFind)
{
    var elemX = 0;
    var elemY = 0;
    do 
    {
        elemX += elemFind.offsetLeft;
        elemY += elemFind.offsetTop;
    }
    while (elemFind = elemFind.offsetParent)

    return Array(elemX, elemY);
}

function insertPreviewHTML() 
{
	var inBody = document.getElementsByTagName("body").item(0);
	
	var inWaitAnimBox = document.createElement("div");
	inWaitAnimBox.setAttribute('id', waitAnimID);
	inWaitAnimBox.style.position    = 'absolute';
	inWaitAnimBox.style.left        = '10px';
	inWaitAnimBox.style.top         = '10px';
	inWaitAnimBox.style.visibility  = 'hidden';
	inWaitAnimBox.style.zIndex      = '525';
	inBody.insertBefore(inWaitAnimBox, inBody.firstChild);
	
	var inWaitAnimImage = document.createElement("img");
	inWaitAnimImage.setAttribute('id', waitAnimImageID);
	inWaitAnimImage.setAttribute('src', ImagesURI+'wait_anim_1.png');
	inWaitAnimBox.appendChild(inWaitAnimImage);
	
		
	var inPreviewBox = document.createElement("div");
	inPreviewBox.setAttribute('id', previewID);
	
	inPreviewBox.style.position         = 'absolute'; 
	inPreviewBox.style.left             = '10px';
	inPreviewBox.style.top              = '10px';
	inPreviewBox.style.visibility       = 'hidden';
	inPreviewBox.style.zIndex           = '499';	
	inBody.insertBefore(inPreviewBox, inBody.firstChild);
	
	
	var inImage = document.createElement("img");
	inImage.onclick = function (event) { previewOut(this, event); return false; };	
	inImage.setAttribute('src', ImagesURI+'preview_spacer.gif');
	inImage.setAttribute('id', previewImageID);
	inImage.setAttribute('border', '1');
	inImage.style.display   = 'block';
	inImage.style.width     = '10px';
	inImage.style.height    = '10px';
	inImage.style.cursor    = 'pointer';
	inPreviewBox.appendChild(inImage);
}
