  /**
   * shows an image in the center of the page
   */
  function ShowImage() {
    this.divImage = null;
    this.iTime = YSDateTime.getCurTime();
    this.oOldSize = new Size(75,75);
    this.oNewSize = new Size(5,5);
    this.bCloseAfterAnimation = false;
    this.lAnimationStart = 0;
    this.img = null;
    
    this.oAnimation = null;
  }
  
  ShowImage.Me = null;
  ShowImage.ANIMATION_DURATION = 400;
  
  ShowImage.Instance = function() {
    if ( ShowImage.Me == null ) ShowImage.Me = new ShowImage();
    return ShowImage.Me;
  };
  
  
  ShowImage.prototype.init = function() {
    if ( this.divImage == null ) {
      this.divImage = document.createElement("div");
      YSCSS.setMultiStyle(this.divImage, ['cursor', 'display', 'position', 'border', 'backgroundColor', 'overflow'], 
        ['pointer', 'none', 'absolute', 'solid 2px #8CA2BD', 'white', 'hidden']);
      this.divImage.onclick = function(e) { ShowImage.Instance().close(e); };
      document.body.appendChild(this.divImage);
    }
    
    if ( this.divImage != null ) {
      YSDOM.removeElementChilds(this.divImage);
      // add loading icon
      var imgLoading = document.createElement('img');
      imgLoading.src = BASE_PATH+'images/loading.gif';
      this.divImage.appendChild(imgLoading);
      
      if ( !this.isShown() )
        this.setSize(new Size(75,75));
      else this.centerImage();
    }
  };
  
  
  ShowImage.prototype.show = function(sSrc) {
    this.init();
    YSCSS.setStyle(this.divImage, 'display', 'block');
    this.loadImage(sSrc);
  };
  
  
  ShowImage.prototype.loadImage = function(sSrc) { 
    this.img = document.createElement('img');
    YSCSS.setStyle(this.img, 'display', 'none');
    YSXML.setAttribute(this.img, 'imgLoaded', 'false');
    this.img.onload = ShowImage.prototype.imageLoaded;
    this.img.src = sSrc+'?time='+this.iTime;
    setTimeout("ShowImage.Instance().img.onload();", 1000);
    
    if ( !this.img.parentNode )
      document.body.appendChild(this.img);
  };
  
  
  ShowImage.prototype.imageLoaded = function() {
    if ( YSXML.getAttribute(this, 'imgLoaded') == 'false' ) {
      YSXML.setAttribute(this, 'imgLoaded', 'true');
      var siThis = ShowImage.Instance();
      if ( siThis.isShown() ) {
        YSCSS.setStyle(this, 'display', 'block');
        YSDOM.removeElementChilds(siThis.divImage);      
        siThis.divImage.appendChild(this);
        
        var oSize = YSDOM.getElementSize(this);
        var oCurSize = YSDOM.getElementSize(siThis.divImage);
        if ( siThis.isClosing() || oSize.width != oCurSize.width || 
             oSize.height != oCurSize.height )
          siThis.animateTo(oSize, false);
      }
    }
  };
  
  
  ShowImage.prototype.isClosing = function() {
    return this.oAnimation != null && this.bCloseAfterAnimation;
  };
  
  
  ShowImage.prototype.animateTo = function(oSize, bClose) {
    if ( this.oAnimation != null && this.bCloseAfterAnimation == bClose ) return;
  
    var imgInner = this.getInnerImage();
    if ( bClose && imgInner != null )
      this.oOldSize = YSDOM.getElementSize(imgInner);
    else if ( !bClose ) this.oOldSize = new Size(75,75);
    else this.oOldSize = YSDOM.getElementSize(this.divImage);
    
    this.centerImage(); // center the inner image
    this.oNewSize = oSize;
    this.bCloseAfterAnimation = bClose;
    var lCurTime = YSDateTime.getCurTime();
    var lDuration = lCurTime - this.lAnimationStart;
    if ( lDuration < ShowImage.ANIMATION_DURATION )
      this.lAnimationStart = lCurTime - (ShowImage.ANIMATION_DURATION - lDuration);
    else this.lAnimationStart = YSDateTime.getCurTime();
    if ( this.oAnimation == null )
      this.oAnimation = setInterval("ShowImage.Instance().run();", 30);
  };
  
  
  ShowImage.prototype.run = function() {
    var oPreviousPosition = YSDOM.getElementPosition(this.divImage);  
    
    var fPercent = Math.min(1, (YSDateTime.getCurTime() - this.lAnimationStart) / ShowImage.ANIMATION_DURATION);
    var iNewWidth  = Math.floor(this.oOldSize.width  + (this.oNewSize.width  - this.oOldSize.width)  * fPercent);
    var iNewHeight = Math.floor(this.oOldSize.height + (this.oNewSize.height - this.oOldSize.height) * fPercent);
    
    this.setSize(new Size(iNewWidth, iNewHeight), false);
    
    var oNewPosition = YSDOM.getElementPosition(this.divImage);
    
    var imgInner = this.getInnerImage();
    if ( imgInner != null ) {
      var oPos = new Pixel(YSCSS.getStyle(imgInner, 'left', true), YSCSS.getStyle(imgInner, 'top', true));
      oPos.top  += oPreviousPosition.top  - oNewPosition.top;
      oPos.left += oPreviousPosition.left - oNewPosition.left;
      YSDOM.setPosition(imgInner, oPos);
    }
    
    if ( fPercent >= 1 ) {
      clearInterval(this.oAnimation);
      this.oAnimation = null;
      if ( this.bCloseAfterAnimation )
        YSCSS.setStyle(this.divImage, 'display', 'none');
      else YSCSS.setMultiStyle(imgInner, ['left', 'top'], ['0px', '0px']);
    }
    
  };
  
  
  ShowImage.prototype.setSize = function (oSize, bPositionImage) {
    if ( !isDefined(bPositionImage) ) bPositionImage = true;
    if ( this.divImage == null ) return;
    var oWindowSize = YSDOM.getWindowSize();
    var oScroll = YSDOM.getDocumentScroll();
    YSCSS.setMultiStyle(this.divImage, ['top', 'left', 'width', 'height'],
      [(oScroll.y+0.5*oWindowSize.height-0.5*oSize.height)+'px',
       (0.5*oWindowSize.width-0.5*oSize.width)+'px',
       oSize.width+'px', oSize.height+'px']);
    if ( bPositionImage ) {
      this.centerImage(oSize);
    }
  };
  
  
  ShowImage.prototype.centerImage = function(oHolderSize) {
    if ( !isDefined(oHolderSize) ) 
      oHolderSize = YSDOM.getElementSize(this.divImage);
    var imgInner = this.getInnerImage();
    if ( imgInner != null ) {
      var oImgSize = YSDOM.getElementSize(imgInner);
      YSCSS.setMultiStyle(imgInner, ['position', 'left', 'top'], 
        ['absolute', Math.floor((oHolderSize.width - oImgSize.width) * 0.5)-1 + 'px',
        Math.floor((oHolderSize.height - oImgSize.height) * 0.5)-1 + 'px']);
    }
  };
  
  ShowImage.prototype.getInnerImage = function () {
    return this.divImage != null && this.divImage.childNodes.length > 0 ? 
        this.divImage.childNodes.item(0) : 
        null;
  }
  
  ShowImage.prototype.isShown = function() {
    return this.divImage != null && 
            YSCSS.getStyle(this.divImage, 'display') == 'block';
  }
  
  ShowImage.prototype.close = function(e) {
    if ( this.divImage != null ) { 
      this.animateTo(new Size(5,5), true);
      this.objShowCaller = null;
    }
  };
