// Nicepopups version 1.0
// author: Piotr Jakimów yoyo@akurat.pl

function nicePopups( icoLinkClass, galleryId, popShadow )
{
  /// zmienne
  
  this.galleryId      = galleryId!=null ? galleryId : 'galleryContainer';
  this.icoLinkClass   = icoLinkClass!=null ? icoLinkClass : 'thumb';
  this.popInLayerId   = 'popInDivLayer'; // to musi wylecieć aby było w pełni obiektowe
  this.popImgId       = 'popDivImg'; // to musi wylecieć aby było w pełni obiektowe
  this.popXcloseId    = 'popDivX'; // to musi wylecieć aby było w pełni obiektowe
  this.popAutoClose   = true; /** zamyka automatycznie popup po kliknięciu w inny **/
  this.popCenter      = true;
  this.popMargin      = 3; //default 10
  this.popShadow      = popShadow!=null ? popShadow : true;
  this.popPrevNext    = false; // TODO
  this.totalRefreshes = 0; // licznik settimeout'ów
  
  // definiowanie user agent'a
  
  this.broOP  = window.opera ? true : false;
  this.broIE  = document.getElementById && (navigator.userAgent.indexOf("MSIE") !=-1 && !this.broOP );
  this.broMZ  = document.getElementById && !this.broOP && !this.broIE;

  // deklaracje
  
  this.popup      = null;

  ////// metody
  
  //////////////////// funkcja inicjonująca
  
  this.init = function()
  {
    var thisObj = this;
    document.onclick = function(e)
    {
      if (!e) var e = window.event;
      var clickedObj = e.target ? e.target : e.srcElement;
      return thisObj.clicked( clickedObj );
    }
  }
  
  //////////////////// przechwytuje kliknięcia (w miniaturki)
  //////////////////// i tworzy nowy obiekt popup'u
  
  this.clicked = function( clickedObj )
  {    
    var imgLinkObj = this.isIco( clickedObj );
    
    /// jeśli nie kliknięto miniaturki z linkiem do obrazka - to kończymy
    if( imgLinkObj == false ){ return true; }
    
    if( this.broOP )
    {
      window.open( imgLinkObj.href );
    }
    else
    {
      if( this.popAutoClose )
      {
        /// jeśli już jest jakiś popup to go usuwamy
        if( this.popup ){ this.popupRemove(); }
      }
      
      /// tworzymy nowy popup    
      this.popup = new this.popupObj( this, imgLinkObj.href, imgLinkObj.title );
      this.popup.create();
      this.popup.keepRefreshing();
    }
    
    return false;
  }
  
  /////////////// sprawdza czy kliknięto link do obrazka lub obiekt który
  /////////////// jest jego potomkiem. Zwraca objekt linku do obrazka "<A />"
  
  this.isIco = function( obj )
  {
    if( this.isIcoLink( obj ) )
    {
      return obj;
    }
    else
    {
      var parent = obj.parentNode;
      while( this.isIcoLink( parent ) == false )
      {
        parent = parent.parentNode;
        if( !parent ) return false;
      }
      return parent;
    }
  }
  
  /////////////// sprawdza czy kliknięto link do obrazka
  
  this.isIcoLink = function( obj )
  {
    if( obj.nodeName == 'A' )
    {
      if( this.icoLinkClass != '' && !haveClass( obj, this.icoLinkClass ) )
        return false;
      else
        return true;
    }
    return false;
  }
  
  /////////////// odrębny obiekt jednego popupu
  
  this.popupObj = function( parentObj, imgLinkUri, imgLinkTitle )
  {
    this.parent           = parentObj;
      
    this.imgUri           = imgLinkUri;
    this.imgTitle         = imgLinkTitle;
    this.node             = false;
    this.innerNode        = false;
    this.imgNode          = false;
    this.imgXcloseNode    = false;
    
    this.stopRefreshing   = false;
    this.imgLoaded        = false;
    this.doOnresize       = false;
    this.lastClick        = 0;
    this.stopRefreshingAfter = null;
    this.allowDblClick    = true;
    
    ///// tworzy popup
    
    this.create = function()
    {      
      var prevNextHTML = '';
      
      if( this.parent.popPrevNext )
      {
        // TODO
        prevNextHTML = '<div class="prevNextBar"><strong>&laquo;</strong> Prev | Next <strong>&raquo;</strong></div>';
      }
      
      var inLayerHTML = 
        '<table id="'+this.parent.popInLayerId+'" cellspacing="0" cellpadding="0"'+
        ' style="width:1px;height:1px;">'+
        '<tr>';
      
      if( this.parent.popShadow )
      {
        inLayerHTML +=
          '<td class="SdwTL"></td>'+
          '<td class="SdwT"></td>'+
          '<td class="SdwTR"></td>'+
        '</tr>'+
        '<tr>'+
          '<td class="SdwL"></td>';
      }
      
      inLayerHTML +=
        '<td>'+
         '<div class="outline"><div class="outerImage"><img src="'+this.imgUri+'"'+( this.imgTitle ? ' alt="'+this.imgTitle+'"' : '' )+
         ( this.imgTitle ? ' title="'+this.imgTitle+'"' : '' )+
         ' style="vertical-align:bottom" id="'+this.parent.popImgId+'" /></div>'+
          prevNextHTML+
          '<a href="http://www.google.pl/" title="Zamknij okno (ESC)" id="'+this.parent.popXcloseId+'" class="close">X</a>'+
        '</div></td>';
        
      if( this.parent.popShadow )
      {
        inLayerHTML +=
          '<td class="SdwR"></td>'+
        '</tr>'+
        '<tr>'+
          '<td class="SdwBL"></td>'+
          '<td class="SdwB"></td>'+
          '<td class="SdwBR"></td>';
      }
      
      inLayerHTML +=
        '</tr>'+
        '</table>';
  
      this.node = document.createElement( 'DIV' );
      this.node.className = 'nicepopup nicepopupLoading';
      this.node.innerHTML = inLayerHTML;
      
      // wyśrodkowanie popupu
      if( this.parent.popCenter )
      {
        this.node.style.left     = '50%';
        this.node.style.top      = '50%';
        this.node.style.position = this.parent.broIE ? 'absolute' : 'fixed';
      }
      
      document.body.appendChild( this.node ); // od teraz staje się widoczny
      
      this.innerNode      = byId( this.parent.popInLayerId );
      this.imgNode        = byId( this.parent.popImgId );
      this.imgXcloseNode  = byId( this.parent.popXcloseId );
      
      var thisObj = this;
      
      // nasłuchiwanie najechania na popup
      this.node.onmouseover = function(e){ return thisObj.overed( eTrg(e) ); }
      // nasłuchiwanie zjechania z popupu
      this.node.onmouseout = function(e){ return thisObj.outed( eTrg(e) ); }
      // nasłuchiwanie kliknięć w popup
      this.node.onclick = function(e){ return thisObj.clicked( eTrg(e) ) }
      // nasłuchwanie dwukliknięć w popup
      this.node.ondblclick = function(e){ return thisObj.dblclicked( eTrg(e) ) }
      // nasłuchiwanie kliknięć w close
      this.imgXcloseNode.onclick = function(e){ return thisObj.closeClicked( eTrg(e) ) }
      // nasłuchiwanie klawiszy (close)
      document.onkeydown = function(e){ return thisObj.closeKeypress( evt(e) ) }
      
    }
    
    //// odświerza i kontroluje rozmiar razem z rozmieszczeniem popupa
    
    this.refresh = function()
    {
      if( !this.parent.popup ){ return false; }
      
      // usuwanie "loaded" jeśli obrazek ma już wielkość
      if( !this.imgLoaded && this.imgNode.width > 48 && this.imgNode.height > 48 )
      {
        removeClass( this.node, 'nicepopupLoading' );
        this.imgLoaded = true;
        this.stopRefreshingAfter = 5;
      }    
    
      this.screenHeight     = window.innerHeight ? window.innerHeight : document.body.clientHeight;
      this.screenWidth      = window.innerWidth ? window.innerWidth-16 : document.body.clientWidth;
      this.maxAllowedWidth  = this.screenWidth - ( 2*this.parent.popMargin );
      this.maxAllowedHeight = this.screenHeight - ( 2*this.parent.popMargin );
      this.maxWidth         = this.innerNode.scrollWidth;
      this.maxHeight        = this.innerNode.scrollHeight;
      var scrolTop          = this.parent.broIE ? document.body.scrollTop+this.parent.popMargin : 0;
      var newTopMargin      = 0;
      var thisObj           = this;
      
      if( this.maxWidth > this.maxAllowedWidth )
      {
        var newWidth = this.maxAllowedWidth>0 ? this.maxAllowedWidth+'px' : '0';
        if( newWidth != this.node.style.width ){
          this.node.style.width = newWidth;
        }
        
        if( this.parent.popCenter ){
          var newLeftMargin = this.maxAllowedWidth>0 ? '-'+this.maxAllowedWidth/2+'px' : '0';
          if( newLeftMargin != this.node.style.marginLeft ){
            this.node.style.marginLeft = newLeftMargin;
          }
        }
        
        if( this.parent.broIE ){ this.node.style.overflowX='scroll'; }
        else{
          this.node.style.overflow='scroll';
        }
        
      }
      else
      {
        if( this.node.style.width != this.maxWidth+'px' )
        {
          this.node.style.width = this.maxWidth+'px';
          if( this.parent.popCenter ){
            this.node.style.marginLeft = '-'+(this.maxWidth/2)+'px';
          }
        }
        
        if( this.maxHeight <= this.maxAllowedHeight ){
          this.node.style.overflow='hidden';
          this.node.style.overflowX='hidden';
          this.node.style.overflowY='hidden';
        }
      }
      
      if( this.maxHeight > this.maxAllowedHeight )
      {
        var newHeight = this.maxAllowedHeight>0 ? this.maxAllowedHeight+'px' : '0';
        if( newHeight != this.node.style.height ){
          this.node.style.height = newHeight;
        }
        
        if( this.parent.popCenter ){
          newTopMargin = (-(this.maxAllowedHeight/2)+scrolTop)+'px';
          if( newTopMargin != this.node.style.marginTop ){
            this.node.style.marginTop = newTopMargin;
          }
        }
        
        if( this.parent.broIE ){ this.node.style.overflowY='scroll'; }
        else{ this.node.style.overflow='scroll'; }
        
      }
      else if( this.node.style.height != this.maxHeight+'px' || this.parent.broIE )
      {
        this.node.style.height = this.maxHeight+'px';
        if( this.parent.popCenter ){        
          newTopMargin = (-(this.maxHeight/2)+scrolTop)+'px';
          this.node.style.marginTop = newTopMargin;
        }
        
        if( this.maxWidth > this.maxAllowedWidth ){
          this.node.style.overflow='hidden';
          this.node.style.overflowX='hidden';
          this.node.style.overflowY='hidden'; 
        }
      }
      
      if( !this.doOnresize )
      {
        window.onresize = function (){ thisObj.refresh(); };
        this.doOnresize = true;
      }
      
      if( this.parent.broIE && !this.doScroll )
      {
        window.onscroll = function (){ thisObj.refresh(); };
        this.doScroll = true;
      }
      
    }
    
    //// odświerza co określony odstęp czasu
    
    this.keepRefreshing = function()
    {      
      if( !this.stopRefreshing && ( this.stopRefreshingAfter==null || this.stopRefreshingAfter-- > 0 ) )
      {
        this.refresh();
        this.parent.totalRefreshes++;
        //window.status = 'automaticly refreshed: ' + this.parent.totalRefreshes;
        var thisObj = this;
        setTimeout( function(){ thisObj.keepRefreshing() }, 100 );
      }
    }


    //// obsługuje najechanie na popup
    this.overed = function( overedObj )
    {
      addClass( this.node, 'nicepopupHover' );
      //window.status = 'najechałe¶ na popup, a konkretnie w znacznik: ' + overedObj.nodeName;
      return false;
    }
    
    //// obsługuje zjechanie z popupu
    this.outed = function( outedObj )
    {
      removeClass( this.node, 'nicepopupHover' );
      //window.status = '';
      return false;
    }

    //// obsługuje kliknięcia w popup
    this.clicked = function( clickedObj )
    {
      this.allowDblClick = true;
      
      var now = new Date().getTime();
      if( now-this.lastClick <= 250 ){ return dblclicked( clickedObj ); }
      else{ this.lastClick = now; }
      
      //alert( 'click' );
      //window.status = 'klikn±łe¶ w popup, a konkretnie w znacznik: ' + clickedObj.nodeName;
      return false;
    }
    
    //// obsługuje dwukliknięcia w popup
    this.dblclicked = function( clickedObj )
    {
      if( this.allowDblClick )
      {
        this.parent.popupRemove();
        return false;
      }
    }
    
    //// obsługuje kliknięcia w close
    this.closeClicked = function( clickedObj )
    {
      this.parent.popupRemove();
      return false;
    }
    
    this.closeKeypress = function( ev )
    {
      // ESC
      if( ev.keyCode==27 ){ this.parent.popupRemove(); }
      else{ return true; }
      return false;
    }
    
  }
  
  /////////////// niszczy obiekt popupu
  
  this.popupRemove = function()
  {    
    document.body.removeChild( this.popup.node );
    document.onkeydown = null;
    
    this.node           = null;
    this.popup          = null;
    // <- tu chciałem usuwać event handler z onresize, ale chyba nie ma potrzeby
  }
  
} // popDiv


//////////////////// funkcje pomocnicze (do manipulacji class'ami)

function byId(id)
{
  return document.getElementById(id);
}

function haveClass(obj,cls)
{
  r=new RegExp("(^| )"+cls+"($| )");
  return r.test(obj.className);
}

function removeClass(obj,cls)
{
  r=new RegExp("(^| )("+cls+")($| )");
  obj.className = obj.className.replace(r,"$1$3");
}

function addClass(obj,cls)
{
  if( !cls )
    return false;
  
  if( !haveClass(obj,cls) )
    obj.className += obj.className.length ? " "+cls : cls;
}

// pobiera obiekt z eventu, którego on dotyczy
function eTrg(e)
{
  if (!e) var e = window.event;
  return e.target ? e.target : e.srcElement;
}

function evt(e)
{
  if (!e) return window.event;
  else return e
}

function destroyObj( obj )
{
  obj = null;
}