/**
 * jquery.expose 1.0.0 - Make HTML elements stand out
 * 
 * Copyright (c) 2009 Tero Piirainen
 * http://flowplayer.org/tools/expose.html
 *
 * Dual licensed under MIT and GPL 2+ licenses
 * http://www.opensource.org/licenses
 *
 * Launch  : June 2008
 * Version : 1.0.0 - Sun Feb 15 2009 13:55:51 GMT-0000 (GMT+00:00)
 */
(function($) {  

        function fireEvent(opts, name, self) {
                var fn = opts[name];
                
                if ($.isFunction(fn)) {
                        
                        try {  
                                return fn.call(self);
                                
                        } catch (error) {
                                if (opts.alert) {
                                        alert("Error calling expose." + name + ": " + error);
                                } else {
                                        throw error;            
                                }
                                return false;
                        }                       
                }
                return true;                    
        }
        
        // mask instance (singleton)
        var mask = null;        
        

        // exposed elements
        var exposed, conf = null;

        
        // global methods
        $.expose = {            
                
                getVersion: function() {
                        return [1, 0, 0];       
                },
                
                getMask: function() {
                        return mask;    
                },
                
                getExposed: function() {
                        return exposed; 
                },
                
                getConf: function() {
                        return conf;    
                },              
                
                isLoaded: function() {
                        return mask && mask.is(":visible");     
                },
                
                load: function(els, opts) { 
                        
                        // already loaded ?
                        if (this.isLoaded()) { return this;     }

                        if (els) {
                                exposed = els;
                                conf = opts;                                    
                        } else {
                                els = exposed;
                                opts = conf;
                        } 

                        if (!els || !els.length) { return this; }
                                
                        // setup mask if not already done
                        if (!mask) {
        
                                mask = $('<div id="' + opts.maskId + '"></div>').css({                          
                                        position:'absolute',
                                        top:0,
                                        left:0,
                                        width:'100%',
                                        height:$(document).height(),
                                        display:'none',
                                        opacity: 0,                                                     
                                        zIndex:opts.zIndex      
                                });
                                                
                                
                                $("body").append(mask);
                                
                                
                                // esc button closes all instances
                                $(document).bind("keypress.unexpose", function(evt) {
                                        if (evt.keyCode == 27) {
                                                $.expose.close();       
                                        }               
                                });                     
                                
                                // clicking on the mask closes all
                                if (opts.closeOnClick) {
                                        mask.bind("click.unexpose", function()  {
                                                $.expose.close();               
                                        });                                     
                                } 
                        }

                        
                        // onBeforeLoad
                        if (fireEvent(opts, "onBeforeLoad", this) === false) {
                                return this;    
                        }                               
                        
                        // make sure element is positioned absolutely or relatively
                        $.each(els, function() {
                                var el = $(this);
                                if (!/relative|absolute/i.test(el.css("position"))) {
                                        el.css("position", "relative");         
                                }                                       
                        });
                 
                        // make elements sit on top of the mask
                        els.css({zIndex:opts.zIndex + 1});                              
                         

                        // background color of the mask
                        if (opts.color) {
                                mask.css("backgroundColor", opts.color);        
                        } 
                        
                        // reveal mask
                        if (!this.isLoaded()) {                                 
                                mask.css({opacity: 0, display: 'block'}).fadeTo(opts.loadSpeed, opts.opacity, function()  {
                                        fireEvent(opts, "onLoad", $.expose);                                            
                                });                                     
                        }

                        return this;
                }, 
                
                
                close: function() {
                        
                        var self = this;
                        
                        if (!this.isLoaded()) { return self; }   
                        
                        if (fireEvent(conf, "onBeforeClose", self) === false) {
                                return self;   
                        } 
                        
                        mask.fadeOut(conf.closeSpeed, function() {          
                                exposed.css({zIndex:conf.zIndex -1});
                                fireEvent(conf, "onClose", self);               
                        });                                     
                }
                
        };
        
        // jQuery plugin initialization
        $.prototype.expose = function(conf) {

                // no elements to expose
                if (!this.length)  {
                        return this;    
                }
                
                var opts = {
                        /*
                        CALLBACKS: 
                         - onBeforeLoad 
                         - onLoad
                         - onBeforeClose 
                         - onClose 
                        */              
                        alert: true,

                        // mask settings
                        maskId: 'exposeMask',
                        loadSpeed: 'slow',
                        closeSpeed: 'fast',
                        closeOnClick: true,
                        
                        // css settings
                        zIndex: 9998,
                        opacity: 0.8,
                        color: '#333'
                };
                
                if (typeof conf == 'string') {
                        conf = {color: conf};
                }
                
                $.extend(opts, conf);
                
                // call expose function         
                $.expose.load(this, opts);
                
                // return jQuery object
                return this;
                
        }; 


})(jQuery);
