function deferJS( src )
{
    var js, head;
    js = document.createElement( 'script' );
    js.src = src;
    head = document.getElementsByTagName( 'head' )[ 0 ];
    head.appendChild( js );
}

//  Return descendent elements that have the attribute set to a true value.
document.getElementsWithAttribute = function( attrName, parentElement )
{
    var i, elems, ret;
    elems = ($(parentElement) || document.body).getElementsByTagName( '*' );
    ret   = new Array;
    for( i = 0; i < elems.length; i++ )
        if( elems[ i ].getAttribute( attrName ) )
            ret[ ret.length ] = elems[ i ];
    return( ret );
};

function closePanes( group )
{
    var i, elems;

    elems = $(group).select('.pane');
    for( i = 0; i < elems.length; i++ )
        Element.hide( elems[ i ] );
}

function closePane( group, pane )
{
    Element.hide( $(group + '-' + pane) );
}

function openPane( group, pane )
{
    var i, elems;

    closePanes( group );
    Element.show( $(group + '-' + pane) );
    //  Autofocus form fields.
    elems = $(group).getElementsByTagName( 'input' );
    for( i = 0; i < elems.length; i++ )
    {
        if( !elems[ i ].getAttribute( 'mgns:autofocus' ) )
            continue;
        elems[ i ].focus();
        break;
    }
}


function swapPane( viewId, fromPane, toPane )
{
    Element.hide( $(viewId + '-' + fromPane) );
    Element.show( $(viewId + '-' + toPane) );
}

function scanForHighlightables()
{
    var i, els;

    els = $$('.highlightable');
    for( i = 0; i < els.length; i++ )
    {
        var el = els[ i ];
        Event.observe( el, 'mouseover',
            function() { Element.addClassName( this, 'highlight' ); }.bind( el ),
            false );
        Event.observe( el, 'mouseout',
            function() { Element.removeClassName( this, 'highlight' ); }.bind( el ),
            false );
    }
}

Event.observe( document, 'dom:loaded', scanForHighlightables, false );

/*  Element#up() is seriously slow on IE and Safari, use this until then  */
function findMatchingAncestor( el, expression )
{
    var parentNode;

    while( ( parentNode = el.parentNode ) && parentNode != document )
    {
        if( $(parentNode).match( expression ) )
            return( parentNode );
        el = parentNode;
    }
    return( null );
}

function showInlineEdit( el )
{
    var editContainer, currentContainer, editField;

//    if( !( editContainer = $(el).up( '.inline-edit' ) ) )
    if( !( editContainer = findMatchingAncestor( el, '.inline-edit' ) ) )
        return;

    currentContainer = editContainer.down( '.inline-edit-current' );
    editField        = editContainer.down( '.inline-edit-edit' );

    if( !currentContainer || !editField )
        return;

    /*  Copy existing value over to our edit field  */
    $(editField).value = currentContainer.innerHTML;

    /*  Swap visibility of the panes  */
    editContainer.select( '.inline-edit-current-block' ).each(
        function( el ) { el.hide() } );
    editContainer.select( '.inline-edit-edit-block' ).each(
        function( el ) { el.show() } );
    $(editField).activate();
}

function revertInlineEdit( el )
{
    var editContainer, editField;

//    if( !( editContainer = $(el).up( '.inline-edit' ) ) )
    if( !( editContainer = findMatchingAncestor( el, '.inline-edit' ) ) )
        return;

    editField = editContainer.down( '.inline-edit-edit' );

    if( !editField )
        return;

    /*  Clear our edit field  */
    $(editField).value = '';

    /*  Swap visibility of the panes  */
    editContainer.select( '.inline-edit-current-block' ).each(
        function( el ) { el.show() } );
    editContainer.select( '.inline-edit-edit-block' ).each(
        function( el ) { el.hide() } );
}

function swapPaneSet( el, paneSetName, showPaneName, matchDimensions )
{
    var paneSet, hidePane, showPane, field;

//alert('swapPaneSet(' + el + ', ' + paneSetName + ', ' + showPaneName + ')');

//    paneSet = $(el).up( '.paneset-' + paneSetName );
//    hidePane = $(el).up( '[class*="pane-' + paneSetName + '-"]' );
    paneSet = findMatchingAncestor( el, '.paneset-' + paneSetName );
    hidePane = findMatchingAncestor( el, '[class*="pane-' + paneSetName + '-"]' );
    showPane = $(paneSet).down( '.pane-' + paneSetName + '-' + showPaneName );

//alert('paneSet: '+paneSet+', hidePane: '+hidePane+', showPane: '+showPane);
//alert( 'all done' );

    if( !hidePane || !showPane )
        return;

    if( hidePane == showPane )
    {
        /*  Assume they want to hide all currently visible panes instead  */
        var visiblePanes;

        visiblePanes =
            $A(paneSet.select('[class*="pane-' + paneSetName + '-"]')).select(
                function (el) { return( $(el).visible() ); } );

        visiblePanes.each( function (el) { $(el).hide(); } );
        hidePane = visiblePanes.first();
    }

    if( matchDimensions )
    {
        var dimensions = hidePane.getDimensions();
        showPane.setStyle( {
            height: dimensions.height + 'px',
            width: dimensions.width + 'px'
            } );
    }

    hidePane.hide();
    showPane.show();

    if( field = showPane.down( 'INPUT[mgns:autofocus]' ) )
        field.focus();
}
