/**
 * An edit panel
 *
 * This panel requires Prototype javascript framework and scriptaculous effects
 * library.
 *
 * To use the panel, first include this script in the head of the document:
 * <script src="panel.js" type="text/javascript"></script>
 *
 * To add an open link to open the panel add an anchor to the DOM with the
 * attribute rel set to panel:
 * <a href="javascript:{};" rel="panel">Open Panel</a>
 *
 * You can also call the panel by defining your own onclick functionality
 * <a href="javascript:{};" onclick="javascript:myPanel.open();" />Open</a>
 *
 *
 *
 * The panel has configuration that at this time can be set and passed at the
 * bottom of this file.  The following options are available
 *
 * height - integer - default null
 *    height of the panel, can be controlled through css as well by defining a
 *    height for #panel
 * width - integer - default null
 *    width of the panel, can be controlled through css as well by defining a
 *    width for #panel
 * noresize - If set to true the box will not be resizable
 *
 * overlay - options for the overlay backdrop behind the panel
 * overlayClickExit - boolean - default true
 *    defines whether the backdrop exits the panel when clicked
 * overlayDuration - integer - default 1
 *    defines the duration in seconds of the overlay open or close effect
 * overlayDurationFrom - float - default 0.0
 *    defines the start opacity for the overlay effect
 * overlayDurationTo - float - default 0.8
 *    defines the end opacity for the overlay effect
 *
 * open - options for the open of the panel
 * openEffect - string - default 'Appear'
 *    defines the scriptaculous effect to use to open the panel
 * openOptions - JS object
 *    defines the options to pass to the scriptaculous effect
 *
 * close - options for the close of the panel
 * closeEffect - string - default 'Fade'
 *    defines the scriptaculous effect to use to close the panel
 * closeOptions - JS object
 *    defines the options to pass to the scriptaculous effect
 *
 *
 * @category
 * @package
 * @author      Joshua Ross <joshualross@gmail.com>
 * @author      Chuck Neal <chuck@mediamacros.com>
 * @copyright   Copyright (C) MediaMacros, Inc. All rights reserved.
 * @version     $'id': $
 * @revision    $LastChangedRevision: $
 * @date        $LastChangedDate: 5/28/2008$
 * @file        $HeadURL: $
 * @link
 * @since       File available since release 0.1
 */

//this is temporary, we need to check both that scriptaculous is available
//as well as prototype
if (typeof Prototype=='undefined')
  throw("panel.js requires the Prototype JavaScript framework >= 1.6.0");
if (typeof Effect=='undefined')
  throw("panel.js requires script.aculo.us' effects.js library");
if (typeof Resizable=='undefined')
  throw("panel.js requires resizable.js effect library");

/**
 * An edit Panel
 *
 * @author      Joshua Ross <joshualross@gmail.com>
 * @author      Chuck Neal <chuck@mediamacros.com>
 * @package
 * @subpackage
 * @copyright   Copyright (C) MediaMacros, Inc. All rights reserved.
 */
var Panel = Class.create();
Panel.prototype = {

    DefaultOptions: {
        overlayClickExit:       true,
        overlayDuration:        .5, //seconds
        overlayDurationFrom:    0.0, //opacity
        overlayDurationTo:      0.5,  //opacity
        openEffect:             'Appear',
        openOptions:            {duration: .5}, //seconds
        closeEffect:            'Fade',
        closeOptions:           {duration: .5}, //second
        height:                 null,
        width:                  null
    },

    /**
     * Scriptaculous Draggable object
     *
     * @var Draggable
     * @access private
     */
    _draggable: null,

    /**
     * The panel title
     * @var string
     * @access private
     */
    _title: '',

    /**
     * The panel subtitle
     * @var string
     * @access private
     */
    _subtitle: '',

    /**
     * The panel body
     * @var string
     * @access private
     */
    _body: '',

    /**
     * The panel body header
     * @var string
     * @access private
     */
    _header: '',

    /**
     * The panel body footer
     * @var string
     * @access private
     */
    _footer: '',

    /**
     *
     * @var Object
     * @access private
     */
    _options: {},


    /**
     *
     * @var string
     * @access private
     */
    _name : "",
    _objectName : "",
    /**
     * This method is a private static initializer(constructor).
     *
     * The first part of this method loops through the DOM looking for
     * references to panel in an anchor tag.  When it finds one it adds the
     * onclick functionality to it.  The second part creates the panel
     * by appending the DOM elements to the document.body
     *
     * @todo accept configuration/parameters
     * @access private
     * @return void
     */
    initialize: function(name, options) {
        this._name = name + "_";
        this._objectName = name;
        this._options = Object.extend(Object.extend({ },this.DefaultOptions), options || { });

        // loop through all anchor tags and add open event
        $$('a').each(function(a){
            if ($(a).hasAttribute('rel') && $(a).readAttribute('rel').match('panel')) {
                $(a).observe('click', this.open.bindAsEventListener(this));
            }
        });


        /*
            <div id="overlay"></div>
            <div id="panel" style="display:none">
                <div id="panelControl">
                    <a id="panelClose" href="javascript:{};" onclick="javascript:panel.close()">x</a>
                    <div id="panelTitle"></div>
                    <div id="panelSubtitle"></div>
                </div>
                <div id="panelHeader"></div>
                <div id="panelBody"></div>
                <div id="panelFooter"></div>
            </div>
        */
        $(document.body).appendChild(
            Builder.node('div',{
                'id':this._name+'overlay',
                'class':'overlay',
                'style':'display:none;position:absolute;top:0;left:0;width:100%;z-index:900;'
            })
        );

        if (true==this._options.overlayClickExit) {
            $(this._name+'overlay').observe('click',this.close.bindAsEventListener(this));
        }

        $(document.body).appendChild(
            Builder.node('div', {'id':this._name+'panel', 'class':'panel','style':'display:none;z-index:1000'},[
                Builder.node('div',{
                        'id':this._name+'panelClose',
                        'class':'panelClose',
                        //href:'javascript:{};',
                        'onclick':this._objectName+'.close();',
                        'style':''
                    }, 'x'),
                Builder.node('div',{
                        'id':this._name+'panelResizer',
                        'class':'panelResizer',
                        'style':'position:absolute;bottom:2px;right:2px'
                    }),
                Builder.node('div',{'id':this._name+'panelControl', 'class':'panelControl'},[
                    Builder.node('div',{'id':this._name+'panelTitle', 'class':'panelTitle headding'}, [
                        this._title
                    ]),
                    Builder.node('div',{'id':this._name+'panelSubtitle', 'class':'panelSubtitle'},this._subtitle)
                ]),
                Builder.node('div',{'id':this._name+'panelHeader', 'class':'panelHeader headding'},this._header),
                Builder.node('div',{'id':this._name+'panelBody', 'class':'panelBody'},this._body),
                Builder.node('div',{'id':this._name+'panelFooter', 'class':'panelFooter'},this._footer)
            ])
        );

        if (null!=this._options.height) {
            $(this._name+'panel').setStyle({height:this._options.height+'px'});
        }

        if (null!=this._options.width) {
            $(this._name+'panel').setStyle({width:this._options.width+'px'});
        }

        //resizable
        if(this._options.noresize != true){
            new Resizable(this._name+'panel',{handle:this._name+'panelResizer',minWidth:100,minHeight:100});
        }
    },

    /**
     * Hides the panel
     *
     * This method uses the optional parameter for close effect to hide the
     * panel
     *
     * @return void
     */
    close: function() {

        if (typeof Effect[this._options.closeEffect]=='undefined')
            throw('Invalid close effect');
         Event.stopObserving(window, "resize", this.recenterEx);
        new Effect[this._options.closeEffect](this._name+'panel', this._options.closeOptions);

       // this.draggable.destroy();
        this.unoverlay();
    },

    /**
     * Displays the panel
     *
     * This method uses prototype's show method to display the panel.  It also
     * adds the
     *
     * @todo accept a animation effect to use when we open
     * @access public
     * @return void
     */
    open: function() {
        //center it l-r
       this.recenter();
        
        if (typeof Effect[this._options.openEffect]=='undefined')
            throw('Invalid open effect');
            
        this.recenterEx = this.recenter.bindAsEventListener(this);
        Event.observe(window, "resize", this.recenterEx);
        new Effect[this._options.openEffect](this._name+'panel', this._options.openOptions);
       //this.draggable = new Draggable($(this._name+'panel'),{revert:false, handle:'panelControl'});
        this.overlay();

    },


    recenter: function(){
    viewWidth = document.viewport.getWidth();
         p = $(this._name+'panel')
        areaWidth = p.getWidth();
        p.setStyle("left:"+((viewWidth - areaWidth)/2)+"px;position:absolute;");
    }, 
    
    /**
     *
     * This method uses the element name to get the innerHTML for editing
     *
     * @accept string id of the element to edit
     * @access public
     * @return void
     */
    edit: function(value) {
        if (typeof value == 'string'){
            this.setBodyRaw(value);
        } else if (typeof value == 'object'){
            this.setBodyElement(value);
        } else {
            return;
        }
        this.open();


    },

    /**
     * This method hides select boxes and flash elements and then fades the
     * overlay in.
     *
     * @access public
     * @return void
     */
    overlay: function() {
    
        $$('object', 'embed', 'select').each(function(e){
            ancestors = $(e).ancestors();
            if(ancestors.indexOf($(this._name+'panel'))==-1){
                $(e).setStyle({visibility:'hidden'});
            }
        });

        bars = Array('page_content', 'home_page');
        bars.each(function(bar){
           e = $(bar);
            if(e != undefined){
           /*      if(Prototype.Browser.Gecko == true){
                    e.setStyle({visibility:'hidden', overflow:'hidden'});
                }else{
                    e.setStyle({visibility:'hidden'});
                }
            }
            */
             new Effect.Fade(bar,{duration: .5 });
             }
       });
        
        $(this._name+'overlay').setStyle({height:document.viewport.getHeight()+'px'});
        new Effect.Appear(this._name+'overlay', {
            duration:   this._options.overlayDuration,
            from:       this._options.overlayDurationFrom,
            to:         this._options.overlayDurationTo
        });
    },

    /**
     * This method fades out the overlay and then unhides select boxes and
     * flash elements
     *
     * @access public
     * @return void
     */
    unoverlay: function() {
        new Effect.Fade(this._name+'overlay',{
            duration:   this._options.overlayDuration
        });
        $$('object', 'embed', 'select').each(function(e){
            $(e).setStyle({visibility:'visible'});
        });
       
        bars = Array('page_content', 'home_page');
        bars.each(function(bar){
            e = $(bar);
            if(e != undefined){
               /* if(Prototype.Browser.Gecko == true){
                    e.setStyle({visibility:'visible', overflow:'auto'});
                }else{
                    e.setStyle({visibility:'visible'});
                }
                */
                 new Effect.Appear(bar, {duration: .5});
             }
        });
        
      
    },

    /**
     * Returns a property
     *
     * @todo disallow private variable access
     * @param string name
     * @return mixed
     */
    get: function(name) {
        return this.name;
    },

    /**
     * Sets the property name to value
     *
     * @todo disallow private variable access
     * @param string name
     * @param mixed value
     * @return void
     */
    set: function(name, value) {
        this.name = value;
    },

    /**
     * Returns the title
     *
     * @access public
     * @return string
     */
    getTitle: function() {
        return this._title;
    },

    /**
     * Sets the title to value
     *
     * @param string value
     * @return void
     */
    setTitle: function(value) {
        this._title = value;
        e = $(this._name+'panelTitle');
        if(e != undefined){
            e.innerHTML = this._title;
        }
    },

    /**
     * Returns the subtitle
     *
     * @access public
     * @return string
     */
    getSubtitle: function() {
        return this._subtitle;
    },

    /**
     * Sets the subtitle to value
     *
     * @param string value
     * @return void
     */
    setSubtitle: function(value) {
        this._subtitle = value;
    },

    /**
     * Returns the body
     *
     * @access public
     * @return string
     */
    getBody: function() {
        return this._body;
    },

    /**
     * Sets the body to value.  Value is expected to be an id of a DOM element
     *
     * @param string value
     * @return void
     */
    setBodyElement: function(value) {
        this._body = new Element('div',{}).update($(value).innerHTML);
        $(this._name+'panelBody').update(this._body);
    },

    /**
     * Sets the body to the raw value
     *
     * @param string value
     * @return void
     */
    setBodyRaw: function(value) {
        this._body = new Element('div',{}).update(value);
        $(this._name+'panelBody').update(this._body);
    },

    /**
     * Returns the body header
     *
     * @access public
     * @return string
     */
    getHeader: function() {
        return this._header;
    },

    /**
     * Sets the body header to value
     *
     * @param string value
     * @return void
     */
    setHeader: function(value) {
        this._header = value;
        $(this._name+'panelHeader').insert(this._header);
    },

    /**
     * Returns the body footer
     *
     * @access public
     * @return string
     */
    getFooter: function() {
        return this._footer;
    },

    /**
     * Sets the body footer to value
     *
     * @param string value
     * @return void
     */
    setFooter: function(value) {
        this._footer = value;
        $(this._name+'panelFooter').insert(this._footer);
    }



};

