function Fader( parent, loader, options )

{

  var options; 

  

  this.parent           = parent;

  this.loader           = loader;



  options               = options || {};

  this.context          = options.context || document;

  this.timer            = options.timer || new Timer();

  this.width            = options.width || 800;

  this.height           = options.height || 600;

  this.loaderImageUrl   = options.loaderImageUrl || "loader.gif";

  this.duration         = options.duration || 1000;

  this.fadeSpeed        = options.fadeSpeed || 1000;

  this.deferredLoaders  = options.deferredLoaders || [];



  this.pages                  = [];

  this.lastShowTime           = 0;

  this.currentPageIndex       = null;

  

  this.initializeFrame();

  this.initializeLoader();

  this.initializeContent();

  this.startLoader();

  this.startDeferredLoaders();

}



Fader.prototype =

{

  initializeFrame: function()

  {

    this.frameDiv = this.context.createElement( "div" );

    this.frameDiv.className = "fader_frame";

    this.frameDiv.style.width = this.width + "px";

    this.frameDiv.style.height = this.height + "px";

    this.parent.appendChild( this.frameDiv );

  },



  initializeLoader: function()

  {

    var image;



    this.loaderDiv = this.context.createElement( "div" );

    this.loaderDiv.className = "fader_loader";

    this.loaderDiv.style.position = "absolute";



    image = this.context.createElement( "img" );

    image.src = this.loaderImageUrl;



    this.loaderDiv.appendChild( image );

    this.frameDiv.appendChild( this.loaderDiv );

  },

  

  initializeContent: function()

  {

    this.contentDiv = this.context.createElement( "div" );

    this.contentDiv.className = "fader_content";

    this.frameDiv.appendChild( this.contentDiv );

    $( this.contentDiv ).hide();    

  },



  startLoader: function()

  {

    this.loader.loaded.attach( this.loaderLoaded.bind( this ) );

    this.loader.load();

  },

  

  startDeferredLoaders: function()

  {

    var i, loader;

    

    for ( i = 0; i < this.deferredLoaders.length; ++i )

    {

      loader = this.deferredLoaders[ i ];

      loader.loaded.attach( this.deferredLoaderLoaded.bind( this ) );

      loader.load();

    }

  },

  

  loaderLoaded: function()

  {

    this.createPagesFromLoader( loader );

    

    this.showFirstPage();

    this.hideLoader();



    this.timer.tick.attach( this.timerTick.bind( this ) );

    this.timer.start();

  },

  

  deferredLoaderLoaded: function( loader )

  {

    this.createPagesFromLoader( loader );

  },

  

  createPagesFromLoader: function( loader )

  {

    var page;

    var elements = loader.getElements();

    

    for ( i = 0; i < elements.length; ++i )

    {

      page = this.createPage( elements[ i ] );

      this.pages.push( page );

      this.contentDiv.appendChild( page )

      $( page ).hide();

    }

  },

  

  createPage: function( element )

  {

    var pageDiv = this.context.createElement( "div" );

    pageDiv.className = "fader_page";

    pageDiv.style.position = "absolute";

    pageDiv.appendChild( element );

    return pageDiv;

  },

  

  hideLoader: function()

  {

    $( this.loaderDiv ).hide(); 

  },

  

  showFirstPage: function()

  {

    if ( this.pages.length > 0 )

    {

      $( this.contentDiv ).show();

      this.showPage( 0, false );

    }

  },

  

  showNextPage: function()

  {

    if ( this.pages.length > 0 )

    {

      var j = ( this.currentPageIndex + 1 ) % this.pages.length;

      this.showPage( j, true );

    }

  },

  

  showPage: function( pageIndex, fade )

  {

    var currentPage;

    var nextPage;



    this.lastShowTime = new Date().getTime();

    

    if ( this.currentPageIndex !== null )

    {

      currentPage = this.pages[ this.currentPageIndex ];

      

      if ( fade ) $( currentPage ).fadeOut( this.fadeSpeed )

      else $( currentPage ).hide();

    }

    

    nextPage = this.pages[ pageIndex ];

    

    if ( fade ) $( nextPage ).fadeIn( this.fadeSpeed );

    else $( nextPage ).show();

    

    this.currentPageIndex = pageIndex;

  },

  

  timerTick: function()

  {

    this.update();

  },



  update: function()

  {

    if ( new Date().getTime() - this.lastShowTime > this.duration )

    {

      this.showNextPage();  

    }

  }

};

