/**
    Copyright © 2003-2006 Jeff Watkins <http://newburyportion.com/>
    
    Except where otherwise noted, this software is licensed under the Creative
    Commons Attribution License. To view a copy of this license, visit
    http://creativecommons.org/licenses/by/2.5/ or send a letter to
    Creative Commons, 543 Howard Street, 5th Floor, San Francisco,
    California, 94105, USA.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-
    INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
    ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
    CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    SOFTWARE.
 **/

function bind( fn, obj )
{
    if (!obj)
        return null;
    if ("string"===typeof(fn))
        fn= obj[fn];
    if (!fn)
        return null;
        
    function bound()
    {
        return fn.apply(obj, arguments);
    }
    return bound;
}

function center(element)
{
    try
    {
        if ("string"==typeof(element))
            element= document.getElementById(element);
    }
    catch(e)
    {
        return;
    }

    var documentWidth= 0;
    var documentHeight= 0;

    if (typeof(window.innerWidth) == 'number')
    {
        documentWidth= window.innerWidth;
        documentHeight= window.innerHeight;
    }
    else if (document.documentElement && 
             (document.documentElement.clientWidth ||
              document.documentElement.clientHeight))
    {
        documentWidth= document.documentElement.clientWidth;
        documentHeight= document.documentElement.clientHeight;
    }
    else if (document.body && 
            (document.body.clientWidth || document.body.clientHeight))
    {
        documentWidth= document.body.clientWidth;
        documentHeight= document.body.clientHeight;
    }

    element.style.position= 'absolute';
    element.style.zIndex= 99;

    var scrollY= 0;

    if (document.documentElement && document.documentElement.scrollTop)
    {
        scrollY= document.documentElement.scrollTop;
    }
    else if (document.body && document.body.scrollTop)
    {
        scrollY= document.body.scrollTop;
    }
    else if (window.pageYOffset)
    {
        scrollY= window.pageYOffset;
    }
    else if (window.scrollY)
    {
        scrollY= window.scrollY;
    }

    var w;
    var h;
    
    if ('none'==element.style.display)
    {
        var old_pos= element.style.position;
        var old_vis= element.style.visibility;
        element.style.position= "absolute";
        element.style.visibility= "hidden";
        element.style.display= "block";
        w= element.scrollWidth;
        h= element.scrollHeight;
        element.style.display= "none";
        element.style.visibility= old_vis;
        element.style.position= old_pos;
    }
    else
    {
        w= element.scrollWidth;
        h= element.scrollHeight;
    }

    var setX = (documentWidth - w) / 2;
    var setY = (documentHeight - h) / 2 + scrollY;

    setX = (setX < 0) ? 0 : setX;
    setY = (setY < 0) ? 0 : setY;

    element.style.left= setX + "px";
    element.style.top= setY + "px";
}

function addEvent( obj, type, fn, useCapture )
{
	var preserveThisFn= function() { fn.call( obj, window.event ); }
    useCapture= useCapture||false;
	if (obj.addEventListener)
	{
		obj.addEventListener( type, preserveThisFn, useCapture );
		eventCache.add( obj, type, preserveThisFn, useCapture );
	}
	else if (obj.attachEvent)
	{
		obj.attachEvent( "on"+type, preserveThisFn );
		eventCache.add( obj, type, preserveThisFn, useCapture );
	}
}

function EventCache()
{
    this.events= [];
}
EventCache.prototype.add= function( node, eventName, handler, useCapture )
{
    this.events.push( {node:node, eventName:eventName, handler:handler,
                       useCapture:useCapture} );
}
EventCache.prototype.flush= function()
{
    var i;
    var item;
    var onEventName;
    
    for (i=this.events.length-1; i>=0; --i)
    {
        item= this.events[i];
        onEventName= "on"+item.eventName;
        if (item.node.removeEventListener)
            item.node.removeEventListener( item.eventName, item.handler,
                                           item.useCapture );
        else if (item.node.detachEvent)
            item.node.detachEvent( onEventName, item.handler );
    }
}
var eventCache= new EventCache();    
addEvent( window, 'unload', function(){ eventCache.flush(); } );

function addUnloadHandler( fn )
{
    Event.observe( window, "unload", fn );
}

var hasDocumentLoaded= false;
Event.observe( window, "load", function(){ hasDocumentLoaded= true; } );

function addLoadHandler( fn )
{
    //  If the document has already loaded, call the function immediately.
    if (hasDocumentLoaded)
    {
        fn.call( window, null );
        return;
    }
    Event.observe( window, "load", fn );
}



var kScriptTagWithSrc= /<script.*?src="(.*?)".*?>/g;
var _loadedScripts;

/** Return the initial set of scripts that were loaded with this document. This
    will not include any scripts that may have been loaded subsequently via
    loadScript.
 **/
function getLoadedScripts()
{
    if (_loadedScripts)
        return _loadedScripts;
        
    var head= document.getElementsByTagName("head")[0];
    var scripts= head.getElementsByTagName("script");
    var loaded= _loadedScripts || {};
    var i;
    var src;
    var href= document.location.protocol + "//" + document.location.host + "/";
    var len= href.length;
    
    for (i=0; i<scripts.length; ++i)
        if (scripts[i].src)
        {
            src= scripts[i].src;
            if (href==src.substr( 0, len ))
                src= src.substr( len-1 );
            loaded[src]= true;
        }
    
    _loadedScripts= loaded;
    return loaded;
}

addLoadHandler( getLoadedScripts );

/** Load a script file into the document.
    @param src  the URL of the script to load.
 **/
function loadScript( src )
{
    var script= document.createElement( "script" );
    script.src= src;
    script.type="text/javascript";
    script.language= "javascript";
    document.getElementsByTagName("head")[0].appendChild(script);
}

function loadScriptsInFragment( fragment )
{
    var scripts= getLoadedScripts();
    var result;
    
    while (null!==(result=kScriptTagWithSrc.exec(fragment)))
    {
        //  Skip scripts that have already been loaded into this document
        if (result[1] in scripts)
            continue;
        loadScript(result[1]);
    }
}
