/////////////////////////////////////////////////////////////////////
// Основных проблем с этим кодом две.
// 1. Он слегка глючит, в разных браузерах - по-разному. Есть проблемы с border'ами элементов, ошибки при прокрутке внутри элементов и некоторые другие.
// 2. Он медленный. Каждый раз приходится пройти всю цепочку offsetParent'ов.
function getOffsetSum(elem) {
    var top=0, left=0
    while(elem) {
        top = top + parseInt(elem.offsetTop)
        left = left + parseInt(elem.offsetLeft)
        elem = elem.offsetParent        
    }
 
    return left, top
}

/////////////////////////////////////////////////////////////////////
// 1. Получить ограничивающий прямоугольник для элемента.
// 2. Задать две переменных для удобства
// 3. Вычислить прокрутку документа. Все браузеры, кроме IE, поддерживают pageXOffset/pageYOffset, а в IE, при наличии DOCTYPE прокрутка вычисляется либо на documentElement(<html>), иначе на body - что есть то и берем
// 4. Документ(html или body) бывает сдвинут относительно окна (IE). Получаем этот сдвиг.
// 5. Прибавляем к координатам относительно окна прокрутку и вычитаем сдвиг html/body, чтобы получить координаты относительно документа
// Для Firefox дополнительно мы округляем координаты вызовом Math.round().
function getOffsetRect(elem) {
    // (1)
    var box = elem.getBoundingClientRect()
 
    // (2)
    var body = document.body
    var docElem = document.documentElement
 
    // (3)
    var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop
    var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft
 
    // (4)
    var clientTop = docElem.clientTop || body.clientTop || 0
    var clientLeft = docElem.clientLeft || body.clientLeft || 0
 
    // (5)
    var top  = box.top +  scrollTop - clientTop
    var left = box.left + scrollLeft - clientLeft
 
    return Math.round(left), Math.round(top)
}

function getOffset(elem) {
//    if (elem.getBoundingClientRect) {
        // "правильный" вариант
//        return getOffsetRect(elem)
//    } else {
        // пусть работает хоть как-то
        return getOffsetSum(elem)
//    }
}

function ImageExpander(oThumb, sImgSrc)
{
	// store thumbnail image and overwrite its onclick handler.
	this.oThumb = oThumb;
	this.oThumb.expander = this;
	this.oThumb.onclick = function() { this.expander.expand(); }
	
	// record original size
	this.smallWidth = oThumb.offsetWidth;
	this.smallHeight = oThumb.offsetHeight;	

	this.bExpand = true;
	this.bTicks = false;
	
	// self organized list
	if ( !window.aImageExpanders )
	{
		window.aImageExpanders = new Array();
	}
	window.aImageExpanders.push(this);

	// create the full sized image.
	this.oImg = new Image();
	this.oImg.expander = this;
	this.oImg.onload = function(){this.expander.onload();}
	this.oImg.src = sImgSrc;
}

ImageExpander.prototype.onload = function()
{
	this.oDiv = document.createElement("div");
	document.body.appendChild(this.oDiv);
	this.oDiv.appendChild(this.oImg);
	this.oDiv.style.position = "absolute";
	this.oDiv.expander = this;
	this.oDiv.onclick = function() {this.expander.toggle();};
	this.bigWidth = this.oImg.width;
	this.bigHeight = this.oImg.height;
	
	if ( this.bExpand )
	{
		this.expand();
	}
	else
	{
		this.oDiv.style.visibility = "hidden";
		this.oImg.style.visibility = "hidden";
	}
	this.oImg.title = "Уменьшить.";
}
ImageExpander.prototype.toggle = function()
{
	this.bExpand = !this.bExpand;
	if ( this.bExpand )
	{
		for ( var i in window.aImageExpanders )
			if ( window.aImageExpanders[i] !== this )
				window.aImageExpanders[i].reduce();
	} 
}
ImageExpander.prototype.expand = function()
{
	// set direction of expansion.
	this.bExpand = true;

	// set all other images to reduce
	for ( var i in window.aImageExpanders )
		if ( window.aImageExpanders[i] !== this )
			window.aImageExpanders[i].reduce();

	// if not loaded, don't continue just yet
	if ( !this.oDiv ) return;
	
	// hide the thumbnail
	this.oThumb.style.visibility = "hidden";
	
	// calculate initial dimensions

	this.x = 	this.oThumb.offsetLeft
	oParent = this.oThumb.offsetParent
	
	//for (i=1; i<=9; i=i+1)
	while (oParent)
	{
		this.x = this.x + oParent.offsetLeft
		oParent =  oParent.offsetParent

	}

	this.y = 	this.oThumb.offsetTop
	oParent = this.oThumb.offsetParent
	//for (i=1; i<=9; i=i+1)
	while (oParent)
	{
		this.y = this.y + oParent.offsetTop
		oParent =  oParent.offsetParent

	}


	this.w = this.oThumb.clientWidth;
	this.h = this.oThumb.clientHeight;
	
	var cw = document.body.clientWidth;
	var ch = document.body.clientHeight;
	var cx = document.body.scrollLeft + cw / 2;
	var cy = document.body.scrollTop + ch / 2;

	this.oDiv.style.left = this.x + "px"; 
	this.oDiv.style.top = this.y + "px";
	this.oImg.style.width = this.w + "px";
	this.oImg.style.height = this.h + "px";
	this.oDiv.style.visibility = "visible";
	this.oImg.style.visibility = "visible";
	
	// start the animation engine.
	if ( !this.bTicks )
	{
		this.bTicks = true;
		var pThis = this;
		window.setTimeout(function(){pThis.tick();},25);	
	}
}
ImageExpander.prototype.reduce = function()
{
	// set direction of expansion.
	this.bExpand = false;
}
ImageExpander.prototype.tick = function()
{
	// calculate screen dimensions
	var cw = document.body.clientWidth;
	var ch = document.body.clientHeight;
	var cx = document.body.scrollLeft + cw / 2;
	var cy = document.body.scrollTop + ch / 2;

	// calculate target
	var tw,th,tx,ty;
	if ( this.bExpand )
	{
		tw = this.bigWidth;
		th = this.bigHeight;
		if ( tw > cw )
		{
			th *= cw / tw;
			tw = cw;
		}	
		if ( th > ch )
		{
			tw *= ch / th;
			th = ch;
		}
		tx = cx - tw / 2;
		ty = cy - th / 2; 
	}
	else
	{
		tw = this.smallWidth;
		th = this.smallHeight;
		
	tx = 	this.oThumb.offsetLeft
	oParent = this.oThumb.offsetParent
	
	//for (i=1; i<=9; i=i+1)
	while (oParent)
	{
		tx = tx + oParent.offsetLeft
		oParent =  oParent.offsetParent

	}

	ty = 	this.oThumb.offsetTop
	oParent = this.oThumb.offsetParent
	//for (i=1; i<=9; i=i+1)
	while (oParent)
	{
		ty = ty + oParent.offsetTop
		oParent =  oParent.offsetParent

	}

		
		
		
		
	        //tx =            this.oThumb.offsetLeft+
			//	this.oThumb.offsetParent.offsetLeft+
			//	this.oThumb.offsetParent.offsetParent.offsetLeft+
			//	this.oThumb.offsetParent.offsetParent.offsetParent.offsetLeft+
			//	this.oThumb.offsetParent.offsetParent.offsetParent.offsetParent.offsetLeft +
			//	this.oThumb.offsetParent.offsetParent.offsetParent.offsetParent.offsetParent.offsetLeft +
			//	this.oThumb.offsetParent.offsetParent.offsetParent.offsetParent.offsetParent.offsetParent.offsetLeft +
			//	this.oThumb.offsetParent.offsetParent.offsetParent.offsetParent.offsetParent.offsetParent.offsetParent.offsetLeft +
			//	this.oThumb.offsetParent.offsetParent.offsetParent.offsetParent.offsetParent.offsetParent.offsetParent.offsetParent.offsetLeft ;

		//ty = 	this.oThumb.offsetTop+
		//	this.oThumb.offsetParent.offsetTop+
		//	this.oThumb.offsetParent.offsetParent.offsetTop+
		//	this.oThumb.offsetParent.offsetParent.offsetParent.offsetTop+
		//	this.oThumb.offsetParent.offsetParent.offsetParent.offsetParent.offsetTop+
		//	this.oThumb.offsetParent.offsetParent.offsetParent.offsetParent.offsetParent.offsetTop+
		//	this.oThumb.offsetParent.offsetParent.offsetParent.offsetParent.offsetParent.offsetParent.offsetTop+
		//	this.oThumb.offsetParent.offsetParent.offsetParent.offsetParent.offsetParent.offsetParent.offsetParent.offsetTop+
		//	this.oThumb.offsetParent.offsetParent.offsetParent.offsetParent.offsetParent.offsetParent.offsetParent.offsetParent.offsetTop+
		//	this.oThumb.offsetParent.offsetParent.offsetParent.offsetParent.offsetParent.offsetParent.offsetParent.offsetParent.offsetParent.offsetTop;
	}	
	// move 5% closer to target
	var nHit = 0;
	var fMove = function(n,tn) 
	{
		var dn = tn - n;
		if ( Math.abs(dn) < 3 )
		{
			nHit++;
			return tn;
		}
		else
		{
			return n + dn / 10;
		}
	}
	this.x = fMove(this.x, tx);
	this.y = fMove(this.y, ty);
	this.w = fMove(this.w, tw);
	this.h = fMove(this.h, th);
	
	this.oDiv.style.left = this.x + "px";
	this.oDiv.style.top = this.y + "px";

	this.oImg.style.width = this.w + "px";
	this.oImg.style.height = this.h + "px";

	// if reducing and size/position is a match, stop the tick	
	if ( !this.bExpand && (nHit == 4) )
	{
		this.oImg.style.visibility = "hidden";
		this.oDiv.style.visibility = "hidden";
		this.oThumb.style.visibility = "visible";

		this.bTicks = false;
	}
	
	if ( this.bTicks )
	{
		var pThis = this;
		window.setTimeout(function(){pThis.tick();},25);
	}
}
