
//------------------------------------------------------------------------------
// Classes/objects handling all layers/popup in the site :                    //
//------------------------------------------------------------------------------




function PageHolder ( options )
{
    //--------------------------------------------------------------------------
    // Method instanciation :                                                 //
    //--------------------------------------------------------------------------


    // Hide selects under the page content only interesting under IE
    this.HideSelects = function ()
    {
        if ( !Prototype.Browser.IE ) return;

        if (!this._masked) this._masked = new Array();
        
        // Get Rect of the page
        page = $( this._page );
        pagePos = Position.cumulativeOffset( page );

        pageLeft = pagePos[0];
        pageTop = pagePos[1];
        pageRight = pageLeft + page.getWidth();
        pageBottom = pageTop + page.getHeight();

        // Check every selects ...
        selects = document.getElementsByTagName('select'); 

        for (var i = 0; i < selects.length; i++) 
        { 
            select = $( selects[i] ); 
            if ( 'hidden' == select.style.visibility ) continue;

            pos = Position.cumulativeOffset( select );

            if ( pos[0] > pageRight ) continue;
            if ( pos[1] > pageBottom ) continue;
            if ( pos[0] + select.getWidth() < pageLeft ) continue;
            if ( pos[1] + select.getHeight() < pageTop ) continue;

            this._masked.push( select );
            select.style.visibility = 'hidden';
        } 

    }

    // Closes the layer (and the masker if there is one)
    this.Close = function()
    {
        if ( this._dead ) return;
        if ( this._masker )
        {
            this._masker.remove();

        }
        // IE Demasking selects
        if ( this._masked )
        {
            for ( var i = 0; i < this._masked.length ; i ++ )
            {
                this._masked[i].style.visibility = 'visible';
            }
            this._masked = null;
        }
        this._page.remove();
        PageLayers.UnReferenceMe( this._idx );
        $( document.body ).setStyle( { overflow: this._oldBodyScroll } );
        document.body.scroll = this._oldIEScroll;
        this._dead = true;
    }

    // Hides the page (but do not delete it)
    this.Hide = function()
    {
        if ( this._masker ) this._masker.hide();
        this._page.hide();
    }

    // returns true if the given dom element is a member of the page
    this.IsInPage = function ( elt )
    {
        if ( !elt ) return false;
        var elem = $( elt );

        return elem.descendantOf( this._page );
    }
    
    // Create the style attribute based on options and set it
    this._SetStyle = function ()
    {
        var styles = '';
        this._page.style.position = 'absolute';
        this._page.style.left = this.GetX() + 'px'; 
        this._page.style.top  = this.GetY() + 'px'; 
        if ( !this.IsAutoSize() )
        {
            this._page.style.width  = this.GetWidth() + 'px'; 
            this._page.style.height = this.GetHeight() + 'px';
        }
        this._page.style.overflow = this.ScrollType();

        // IE:
        if ( "hidden" == this.ScrollType() )
        {
            document.body.scroll = 'no';
        }
        else
        {
            document.body.scroll = 'auto';
        }
    }

    // Set the content of the page itself:
    this.SetContent = function ( elt )
    {
        this._CreateContent();
        this._content.appendChild( elt );
        if ( !this.IsAutoSize() ) Position.clone( this._page, elt );
        if ( Prototype.Browser.IE ) this._page.innerHTML += '';
    }

    // Load a URL in the page by AJAX
    this.LoadUrl = function( url )
    {
        if (!url) return;
        this._CreateContent();
        
        // Creates a dummy content that will be replaced by Ajax:
        docContent = Element.extend( document.createElement( 'div' ) );
        docContent.style.position = 'absolute';
        docContent.setAttribute( 'id', 'replacableContent' );
        this._content.appendChild( docContent );
        Position.clone( this._page, docContent );

        new Ajax.Request( url
                        , {
                            onFailure: function() { PageLayers.FindPageFor( $('replacableContent') ).Close(); },
                            onSuccess: function( transport ) 
                            {
                                $('replacableContent').replace( transport.responseText ); 
                            }
                          }
                        );
    }

    // Called when the window is resized ... take care of center/modal ...
    this.OnWindowResize = function()
    {
        if ( this.IsModal() ) Position.clone( $( document.documentElement ), this._masker );
        if ( this.IsCentered() )
        {
            this._Center();
            this._SetStyle();
        }
    }

    //--------------------------------------------------------------------------
    // Private part                                                           //
    //--------------------------------------------------------------------------


    // Creates a loading placeholder:
    this._CreateLoading = function ()
    {
        this._CreateContent();
        var div = $( document.createElement( 'div' ) );
        div.addClassName( 'loadingpage' );
        var waitImg = $( document.createElement( 'img' ) );

        waitImg.setAttribute( 'src', PageLayers.loadingImg.src );
        div.appendChild( waitImg );

        div.appendChild( document.createElement( 'br' ) );
        div.appendChild( document.createTextNode( 'Chargement en cours' ) );
        div.appendChild( document.createElement( 'br' ) );
        div.appendChild( document.createTextNode( '... Veuillez patienter ...' ) );

        this._content.appendChild( div );

        // center the loading div:

        var size = div.getDimensions();
        div.setStyle({
                       position: 'relative'
                     , left: ( ( this.GetWidth()  - size.width  ) / 2 ) + 'px'
                     , top:  ( ( this.GetHeight() - size.height ) / 2 ) + 'px'
                     , width: size.width   + 'px'
                     , height: size.height + 'px'
                    });
    }    
    // Create a div to disable the page inputs (and gray it)
    this._MakeMasker = function ()
    {
        // Deactivate scrolling
        if ( this.IsModal() && this.FitsInWindow() )
        {
            document.body.style.overflow = 'hidden';
            document.body.scroll = "no";
            // IE: should use more tricks:
        }
        var rect = PageLayers.GetClientRect();

        // IE sucks, we have to hide all selects prior to show the page

        if ( Prototype.Browser.IE )
        {
            selects = document.getElementsByTagName( 'select' );
            this._masked = new Array();

            for( var  i = 0; i < selects.length ; i ++ )
            {
                if ( 'visible' == selects[i].style.visibility || '' == selects[i].style.visibility )
                {
                    this._masked.push( selects[i] );
                    selects[i].style.visibility = 'hidden';
                }
            }
        }

        var docMasker = Element.extend( document.createElement( 'div' ) );

        docMasker.addClassName( 'masker' );
        docMasker.style.float = "left";
        docMasker.style.position = "absolute";

        docMasker.style.top = rect.top + 'px';
        docMasker.style.left = rect.left + 'px';
        docMasker.style.width = rect.width + 'px';
        docMasker.style.height = rect.height + 'px';

        document.body.appendChild( docMasker );
        docMasker.show();
        
        this._masker = docMasker;

    }

    // Computes the position to center the window
    this._Center = function()
    {
        if ( this.IsAutoSize() ) return; // Can't center an autosized object
        var rect = PageLayers.GetClientRect();


        var x = rect.left + ( rect.width  - this.GetWidth()  ) / 2;
        var y = rect.top  + ( rect.height - this.GetHeight() ) / 2;

        this.SetX( x > 0 ? x : 0 );
        this.SetY( y > 0 ? y : 0 );
    }

    // Create the page container object and add it to the page
    this._CreatePage = function()
    {
        var docHolder = Element.extend( document.createElement( 'div' ) );
        docHolder.addClassName( 'newPage' );
        docHolder.setAttribute( 'id', 'newPage_' + this.GetIndex() );

        this._page = docHolder;
        this._SetStyle();

        document.body.appendChild( docHolder );
        docHolder.show();
    }

    // Create the content inside the page or reset it if already created)
    this._CreateContent = function() 
    {
        if ( this._content )
        {
            if ( !Prototype.Browser.IE )
            {
                this._content.remove();
            }
            else
            {
                this._page.removeChild( document.getElementById( this._content.id ) );
            }
        }

        var docContent = Element.extend( document.createElement( 'div' ) );
        docContent.setAttribute( 'id', 'content_' + this.GetIndex() );
        this._page.appendChild( docContent );

        if (! this.IsAutoSize() )
        {
            docContent.style.position = "absolute";
            Position.clone( this._page, docContent );
        }

        this._content = docContent;
        this._content.show();

        if (this.IsModal() ) this._page.focus();
    }
    
    // Adjust the size to fit in the window 
    this._AdjustSize = function()
    {
        if ( this.IsFixedSize() || this.IsAutoSize() ) return;

        var viewport = PageLayers.GetClientRect();
        if ( this.GetWidth() > viewport.width )   this.SetWidth( viewport.width );
        if ( this.GetHeight() > viewport.height ) this.SetHeight( viewport.height );
    }

    // Check if the page fits the window
    this.FitsInWindow = function ()
    {
        var viewport = PageLayers.GetClientRect();
        
        if ( this.GetX() < 0 ) return false;
        if ( this.GetY() < 0 ) return false;
        if ( this.GetWidth() + this.GetX() > viewport.width ) return false;
        if ( this.GetHeight() + this.GetY() > viewport.height ) return false;

        return true;
    }

    // resize the page
    this.Resize = function( w, h )
    {
        this.SetWidth( w );
        this.SetHeight( h );

        this._AdjustSize();

        if ( this.IsCentered() ) this._Center();
        this._SetStyle();
    }
    
    // Used by the PageLayers class to check if the object needs to be notified on
    // window resize
    this.NeedResizeCallback = function ()
    { 
        return this.IsModal() || this.IsCentered();
    }

    this._GetValue = function( table, key, deft )
    {
        if ( 'undefined' == typeof table[key] )  return deft;
        return table[key];
    }

    // Basic accessors
    this.SetIndex   = function( idx ) { this._idx = idx; }
    this.GetIndex   = function()      { return this._idx; }

    this.GetX       = function()      { return this._GetValue( this._options, 'x', 0 ); }
    this.SetX       = function( x )   { this._options.x = x; }
    this.GetY       = function()      { return this._GetValue( this._options, 'y', 0 ); }
    this.SetY       = function( y )   { this._options.y = y; }

    this.GetWidth   = function()      { return this._GetValue( this._options, 'width', 800 ); }
    this.SetWidth   = function( w )   { this._options.width = w; }

    this.GetHeight  = function()      { return this._GetValue( this._options, 'height', 600 ); }
    this.SetHeight  = function( h )   { this._options.height = h; }

    this.IsModal    = function()      { return this._GetValue( this._options, 'modal', false     ); }
    this.IsCentered = function()      { return this._GetValue( this._options, 'centered', false  ); }
    this.ScrollType = function()      { return this._GetValue( this._options, 'scroll', 'auto'   ); }
    this.IsAutoSize = function()      { return this._GetValue( this._options, 'autosize', false  ); }
    this.IsFixedSize= function()      { return this._GetValue( this._options, 'fixedsize', false ); }

    this.IsAutoClose= function()      { return this._GetValue( this._options, 'autoclose', false ); }
    this.NoLoading  = function()      { return this._GetValue( this._options, 'noloading', false ); }



    //--------------------------------------------------------------------------
    // Constructor:                                                           //
    //--------------------------------------------------------------------------

    // First store the pageObject/masker extended by Prototype for later

    this._options = options;
    this.SetIndex( PageLayers.ReferenceMe( this ) );
    this._masker = null;
    this._page = null;
    this._content = null;
    this._oldBodyScroll = $( document.body ).getStyle( 'overflow' );
    this._oldIEScroll = document.body.scroll;
    
    if ( !this._options.toolmenu ) this._options.toolmenu = {};

    // Apply options:
    this._AdjustSize();

    if ( this.IsModal() )    this._MakeMasker();
    if ( this.IsCentered() ) this._Center();

    this._CreatePage();


    if ( !this.NoLoading() ) this._CreateLoading();
}

// static class used for holding layers:
var PageLayers = 
{
    layers: new Array(), // Containing layer PageHolder

    loadingImg: new Image(),

    Init: function()
    {
        PageLayers.loadingImg.src = '/images/design/loading.gif';
    },

    ImgPopup: function( url, options )
    {
        // create a holding page

        var page = new PageHolder( options );

        page.FinishImgLoad = function( url )
        {
            // This function will be set in the page, and
            // called after img loading
            var page = this;
            var options = this._options;
            var img = page.imgOnLoading;

            if ( !img.complete )
            {
                window.setTimeout( 'PageLayers.GetLayer(' + page.GetIndex() + ').FinishImgLoad(\'' + url + '\')', 100);
                return;
            }

            page.Resize( img.width, img.height );

            if ( !page.GetWidth() * page.GetHeight() * img.width * img.height )
            {   
                page.Close();
                return;
            }

            var ratio = img.width / img.height;
            
            // Now create a dom element:
            var domImg = $( document.createElement( 'img' ) );
            domImg.setAttribute( 'src', url );

            if ( !options.noclickclose )
            {
                // page index is in the closure
                var index = page.GetIndex();
                closeCode = function onclick() { PageLayers.GetLayer( index ).Close(); };

                domImg.onclick = closeCode;
                
                if ( Prototype.Browser.IE )
                {
                    page._page.onclick = closeCode;
                }
            }

            if ( !options.fixedsize && !options.autosize )
            {
                // Resize the image/page to fit constraints:
                if ( img.height != page.GetHeight() || img.width != page.GetWidth() )
                {
                    var h, w;

                    // apply the ratio here!
                    if ( options.noratio )
                    {
                        w = page.GetWidth();
                        h = page.GetHeight();
                    }
                    if ( page.GetWidth() > ratio * page.GetHeight() )
                    {
                        h = page.GetHeight();
                        w = h * ratio;
                    }
                    else
                    {
                        w = page.GetWidth();
                        h = w / ratio;
                    }

                    page.Resize( w, h );
                    domImg.setStyle( { width: w, height: h } );
                }
            }
            page.SetContent( domImg );

            // Clean up objects:
            delete page.imgOnLoading;
            page.imgOnLoading = undefined;
            page.FinishImgLoad = undefined;
        }

        // Load the image
        img = new Image();
        page.imgOnLoading = img;
        img.onerror = function onerror() { PageLayers.GetLayer( page.GetIndex() ).Close(); }; // Closure rocks!
        img.onabort = function onabort() { PageLayers.GetLayer( page.GetIndex() ).Close(); }; // Closure rocks!
        img.src = url;

        window.setTimeout( 'PageLayers.GetLayer(' + page.GetIndex() + ').FinishImgLoad(\'' + url + '\')', 100); // Should use a closure ?
    
        // prevent href to load:
        return false;
    },

    // Open an 'ajax popup containing the url
    AjaxPopup: function( url, options )
    {
        var page = new PageHolder( options );
        page.LoadUrl( url );
        return false; // prevent page reloading :)
    },

    // Find the page containing elt, returns null if no page
    FindPageFor: function( elt )
    {
        for ( var i = 0; i < PageLayers.layers.length; ++i )
        {
            if ( PageLayers.layers[i] && PageLayers.layers[i].IsInPage( elt ) )
            {
                return PageLayers.layers[i]; // an element can only be in one page
            }
        }
        return null;
    },

    // This function returns the client visible rect (compatible IE/NS)
    GetClientRect: function ()
    {
        var x, y, width, height;

        if ( window.innerWidth ) // NS
        {
            x =      window.pageXOffset;
            y =      window.pageYOffset;
            width  = window.innerWidth;
            height = window.innerHeight;
        }
        else // IE
        {
            x =      document.documentElement.scrollLeft;
            y =      document.documentElement.scrollTop;
            width  = document.documentElement.clientWidth;
            height = document.documentElement.clientHeight;
        }

        return { left: x, top: y, width: width, height: height };
    },

    GetLayer: function( idx ) { return PageLayers.layers[idx]; },

    // Autoclose feature:
    autoCloseStarted: false,

    StartAutoClose: function() 
    { 
        if ( PageLayers.autoCloseStarted ) return;
        if ( Prototype.Browser.IE )
        {
            PageLayers.ignoreClose = 1;
        }
        Event.observe( document, 'click', PageLayers.OnClick, true ); 
        PageLayers.autoCloseStarted = true;
    },
    
    // Called on click on the page
    OnClick: function ( evt )
    {
        // Since IE triggers the click directly, we have to ignore it ( yes that's ugly :( )
        if ( Prototype.Browser.IE )
        {
            if ( PageLayers.ignoreClose )
            {
                PageLayers.ignoreClose --;
                return;
            }
        }

        var elem = Event.element( evt );
        var page = null;

        if ( elem ) page = PageLayers.FindPageFor( elem );

        for ( var i = 0; i < PageLayers.layers.length; ++i )
        {
            var layer = PageLayers.layers[i];
            if ( layer && layer.IsAutoClose() )
            {
                if (layer != page ) layer.Close();
            }
        }

        // Now see if we are still in use here

        PageLayers.StopAutoClose();

    },
    
    // Stop the click listener if no more autoclose page are open
    StopAutoClose: function()
    {
        if ( !this.autoCloseStarted ) return;

        for ( var i = 0; i < PageLayers.layers.length; ++i )
        {
            var layer = PageLayers.layers[i];
            if ( layer && layer.IsAutoClose() ) return
        }       

        Event.stopObserving( document, 'click', PageLayers.OnClick, true ); 
        PageLayers.autoCloseStarted = false;
    },

    // Window resizing system
    resizeObserve: false,

    // Start the resize observer
    ObserveResize: function()
    {
        if ( PageLayers.resizeObserve ) return;
        PageLayers.resizeObserve = true;
        Event.observe( window, 'resize', PageLayers.OnWindowResize );
    },

    // Resize callback
    OnWindowResize: function( evt )
    {
        for ( var i = 0; i < PageLayers.layers.length; ++i )
        {
            var layer = PageLayers.layers[i];
            if ( layer && layer.NeedResizeCallback() ) layer.OnWindowResize();
        }
    },

    StopObserveResize: function()
    {
        if ( !PageLayers.resizeObserve ) return;

        for ( var i = 0; i < PageLayers.layers.length; ++i )
        {
            var layer = PageLayers.layers[i];
            if (layer && layer.NeedResizeCallback() ) return;
        }

        Event.stopObserving( window, 'resize', PageLayers.OnResize );
        PageLayers.resizeObserve = false;
    },

    // Reference holding (only called by PageHolder):
    UnReferenceMe: function( idx ) 
    { 
        PageLayers.layers[idx] = null; 
        PageLayers.StopAutoClose(); 
        PageLayers.StopObserveResize();
    },
    
    ReferenceMe: function( holder ) 
    { 
        PageLayers.layers.push( holder );
        if ( holder.IsAutoClose() )        PageLayers.StartAutoClose();
        if ( holder.NeedResizeCallback() ) PageLayers.ObserveResize();

        return PageLayers.layers.length - 1; 
    }
}





// Code after this point is deprecated !
// Maximize the current window                                                 
function MaximizeWindow() 
{
    // TODO: change this function to take care of the status bar and such ... ??
    window.moveTo( 0, 0);
    window.resizeTo( screen.availWidth, screen.availHeight );
}

// Open a window with x and y size and win as title                            
function OpenWin( win, x, y)
{
    var param = 'scrollbars=yes,resizable=yes,height='+ y +',width=' + x+ ', top=100, left=0';
    var w = window.open(win,'ww',param);
}


PageLayers.Init();




