// lupe.js, (C) Walter Bislin, walter.bislins.ch, Dezember 2004
// include: <script src="x.js" type="text/javascript"></script>
// include: <script src="ic.js" type="text/javascript"></script>

var CLupeObj = null;

// CLupeObj.State's
var CLHidden = 0;
var CLLoading = 1;
var CLZoomIn = 2;
var CLZoomed = 3;
var CLZoomOut = 4;

function CLupe()
{
  if (CLupeObj) return; // only one instance allowed!
  // public properties
  this.BorderColor = 'black';
  this.BorderWidth = 1;
  this.TimeSpan = 500;
  this.TimerInterval = 40; // 25 fps
  this.HideSmall = false; // to hide small image during zoom
  this.TimeModifyFunc = null;
  // private properties
  this.SmallPosX = 0;
  this.SmallPosY = 0;
  this.SmallWidth = 0;
  this.SmallHeight = 0;
  this.BigPosX = 0;
  this.BigPosY = 0;
  this.BigWidth = 0;
  this.BigHeight = 0;
  this.StartTime = 0;
  this.Timer = null;
  this.BigImgID = -1;
  this.SmallImg = null;
  this.WaitObj = null;
  this.ZoomImg = null;
  this.State = CLHidden;
  CLupeObj = this;
}

function CLupePreload() { CLupeObj.Preload(CLupePreload.arguments); }
function CLupeHTML() { CLupeObj.HTML(); }
function CLupeZoom(aImgName,aBigImgUrl) { CLupeObj.Zoom(aImgName,aBigImgUrl); }

CLupe.prototype.Preload = function(aImgUrlList) {
  IC.PreloadImages( aImgUrlList );
}

CLupe.prototype.HTML = function()
{
  var s = '<img id="ZoomPic" src="" style="position:absolute;visibility:hidden;z-index:5;';
  if (this.BorderWidth > 0) s += 'border:'+this.BorderWidth+'px solid '+this.BorderColor+';';
  s += '" onclick="CLupeObj.UnZoom()" ondblclick="CLupeObj.NewWindow()">'
  document.writeln( s );
  document.writeln( '<div id="ZoomPicWait" '+
    'style="position:absolute;visibility:hidden;z-index:5;background-color:white;color:blank;width:125px;heigth:20px;text-align:center;font-size:10pt;border:1px solid black;">'+
    'Lade Vergrösserung</div>' );
}

CLupe.prototype.Zoom = function(aImgName, aBigImgUrl)
{
  this.WaitObj = xGetElementById("ZoomPicWait");
  this.ZoomImg = xGetElementById("ZoomPic");
  var bigImgID = IC.FindImageUrl(aBigImgUrl);

  if ((this.State != CLHidden) && (bigImgID != -1) && (bigImgID == this.BigImgID)) {
    if (this.State == CLLoading) {
      xHide( this.WaitObj );
      this.State = CLHidden;
      return;
    }
    if (this.State == CLZoomIn || this.State == CLZoomed) {
      this.UnZoom();
      return;
    }
    // this.State == CLZoomOut
    if (this.Timer) {
      clearTimeout( this.Timer );
      this.Timer = null;
    }
    this.StartTime = xTimeMS() - this.TimeSpan + (xTimeMS() - this.StartTime);
    this.State = CLZoomIn;
    var me = this; // closure -> http://walter.bislins.ch/lexi/closure.html
    this.Timer = setTimeout(function(){me.Enlarge();}, this.TimerInterval);
    return;
  }

  if (this.State == CLLoading) {
    xHide( this.WaitObj );
    this.State = CLHidden;
  }
  else if (this.State != CLHidden) {
    if (this.Timer) {
      clearTimeout( this.Timer );
      this.Timer = null;
    }
    this.HideZoomImg();
  }
  this.SmallImg = xGetElementById(aImgName);
  if ((bigImgID != -1) && IC.IsLoaded(bigImgID)) {
    this.BigImgID = bigImgID;
    this.StartZoom();
  }
  else {
    this.GetSmallImgData();
    var x = (this.SmallWidth - 125) / 2;
    var y = (this.SmallHeight - 20) / 2;
    xMoveTo( this.WaitObj, this.SmallPosX+x, this.SmallPosY+y );
    xShow( this.WaitObj );
    this.State = CLLoading;
    var me = this;
    this.BigImgID = IC.LoadImage( aBigImgUrl, function(aImgID){me.OnLoad(aImgID);} );
  }
}

CLupe.prototype.GetSmallImgData = function()
{
  this.SmallWidth = this.SmallImg.width + 2*this.BorderWidth;
  this.SmallHeight = this.SmallImg.height + 2*this.BorderWidth;
  this.SmallPosX = xPageX(this.SmallImg) + (xWidth(this.SmallImg)-this.SmallWidth)/2; // Ränder berücksichtigen
  this.SmallPosY = xPageY(this.SmallImg) + (xHeight(this.SmallImg)-this.SmallHeight)/2;
}

CLupe.prototype.OnLoad = function( aImgID )
{
  if ((this.State == CLLoading) && (this.BigImgID == aImgID)) {
    this.StartZoom();
  }
}

CLupe.prototype.Range = function( aValue, aMin, aMax ) {
  return aMin + (aMax-aMin)*aValue;
}

CLupe.prototype.StartZoom = function()
{
  this.BigImg = IC.Image(this.BigImgID);
  this.ZoomImg.src = this.BigImg.src;
  this.GetSmallImgData();
  this.BigWidth = this.BigImg.width + 2*this.BorderWidth;
  this.BigHeight = this.BigImg.height + 2*this.BorderWidth;
  this.BigPosX = xScrollLeft() + ((xClientWidth()-this.BigWidth) / 2);
  if (this.BigPosX < 0) this.BigPosX = 0;
  this.BigPosY = xScrollTop() + ((xClientHeight()-this.BigHeight) / 2);
  if (this.BigPosY < 0) this.BigPosY = 0;
  this.StartTime = xTimeMS();
  var me = this; // closure -> http://walter.bislins.ch/lexi/closure.html
  this.Timer = setTimeout(function(){me.Enlarge();}, this.TimerInterval);
}

CLupe.prototype.Enlarge = function()
{
  if (this.Timer) {
    clearTimeout(this.Timer);
    this.Timer = null;
  }
  var param = (xTimeMS() - this.StartTime) / this.TimeSpan;
  var eom = param >= 1;
  if (param > 1) param = 1;
  if (this.TimeModifyFunc) param = this.TimeModifyFunc(param);
  if (param < 0) param = 0;
  if (param > 1) param = 1;
  var x = this.Range( param, this.SmallPosX, this.BigPosX );
  var y = this.Range( param, this.SmallPosY, this.BigPosY );
  var w = this.Range( param, this.SmallWidth, this.BigWidth );
  var h = this.Range( param, this.SmallHeight, this.BigHeight );
  xMoveTo( this.ZoomImg, x, y );
  xResizeTo( this.ZoomImg, w, h );
  if (this.State != CLZoomIn) {
    xHide( this.WaitObj );
    xShow( this.ZoomImg );
    if (this.HideSmall) xHide( this.SmallImg );
    this.State = CLZoomIn;
  }
  var me = this;
  if (eom)
  {
    this.State = CLZoomed;
    this.Timer = setTimeout(function(){me.CheckOutOfWindow();}, 200);
  }
  else
  {
    this.Timer = setTimeout(function(){me.Enlarge();}, this.TimerInterval);
  }
}

CLupe.prototype.CheckOutOfWindow = function()
{
  var space = (xClientHeight()-this.BigHeight) / 2;
  var newY = xScrollTop() + space;
  var toleranz;
  if (space > 0) {
    toleranz = space + (this.BigHeight * 2 / 3);
  } else {
    toleranz = -space + (xClientHeight() * 2 / 3);
  }
  if (Math.abs(newY-this.BigPosY) > toleranz) {
    this.UnZoom();
    return;
  }
  var me = this;
  this.Timer = setTimeout(function(){me.CheckOutOfWindow();}, 200);
}

CLupe.prototype.NewWindow = function()
{
  if (this.HideSmall) xShow( this.SmallImg );
  xHide( this.ZoomImg );
  xMoveTo( this.ZoomImg, 0, 0 );
  xResizeTo( this.ZoomImg, 0, 0 );
  this.State = CLHidden;
  location.href = IC.ImageUrl(this.BigImgID);
}

CLupe.prototype.UnZoom = function()
{
  if (this.State == CLHidden || this.State == CLZoomOut) return;
  if (this.State == CLLoading) {
    xHide( this.WaitObj );
    this.State = CLHidden;
    return;
  }
  if (this.Timer) {
    clearTimeout(this.Timer);
    this.Timer = null;
  }
  this.SmallPosX = xPageX(this.SmallImg) + (xWidth(this.SmallImg)-this.SmallWidth)/2; // Ränder berücksichtigen
  this.SmallPosY = xPageY(this.SmallImg) + (xHeight(this.SmallImg)-this.SmallHeight)/2;
  if (this.State == CLZoomIn) {
    this.StartTime = xTimeMS() - this.TimeSpan + (xTimeMS() - this.StartTime);
  } else {
    this.StartTime = xTimeMS();
  }
  this.State = CLZoomOut;
  var me = this; // closure -> http://walter.bislins.ch/lexi/closure.html
  this.Timer = setTimeout(function(){me.Shrink();}, this.TimerInterval);
}

CLupe.prototype.HideZoomImg = function()
{
  if (this.HideSmall) xShow( this.SmallImg );
  xHide( this.ZoomImg );
  xMoveTo( this.ZoomImg, 0, 0 );
  xResizeTo( this.ZoomImg, 0, 0 );
  this.State = CLHidden;
}

CLupe.prototype.Shrink = function()
{
  if (this.Timer) {
    clearTimeout(this.Timer);
    this.Timer = null;
  }
  var param = (xTimeMS() - this.StartTime) / this.TimeSpan;
  var eom = param >= 1;
  if (param > 1) param = 1;
  if (this.TimeModifyFunc) param = this.TimeModifyFunc(param);
  if (param < 0) param = 0;
  if (param > 1) param = 1;
  var x = this.Range( param, this.BigPosX, this.SmallPosX );
  var y = this.Range( param, this.BigPosY, this.SmallPosY );
  var w = this.Range( param, this.BigWidth, this.SmallWidth );
  var h = this.Range( param, this.BigHeight, this.SmallHeight );
  xMoveTo( this.ZoomImg, x, y );
  xResizeTo( this.ZoomImg, w, h );
  if (eom)
  {
    this.HideZoomImg();
  }
  else
  {
    xMoveTo( this.ZoomImg, x, y );
    xResizeTo( this.ZoomImg, w, h );
    var me = this; // closure -> http://walter.bislins.ch/lexi/closure.html
    this.Timer = setTimeout(function(){me.Shrink();}, this.TimerInterval);
  }
}

CLupeObj = new CLupe();

CLupeObj.TimeModifyFunc = function( aValue ) { return (0.5 - 0.5 * Math.cos(Math.PI*aValue)); }

