/**
 * This script basculates (hides/shows/toggles) sets of elements.
 * It requires Prototype to be loaded.
 */

// This is the main function. It takes as parameter an object whose
// members indicate the options as follows:
//   selector: string (mandatory) The CSS selector that will identify the set.
//   parent: element (optional) Only search in this element. Needs to be Prototype-extended!
//   openClass: string (optional) Apply this class to an element after showing it.
//   closeClass: string (optional) Apply this class to an element after hiding it.
//   hardStyle: boolean (optional) If given hide/show will be done by setting .style.display
//      to block/none instead of calling Prototype Element.show()/hide().
//   force: boolean (optional) Will force elements that are already visible to be opened and
//       elements that are not to be closed. By default there's no redundant enforcement.
// The following options are all optional, but at least one must be given
// in order for the function to do anything. If more than one is supplied,
// only the first one (in the order below) will be acted upon.
//   closeElement: element Hide this element only, ignore the others.
//   openElement: element Show this element only, ignore the others.
//   toggleElement: element Toggle this element only, ignore the others.
//   closeAll: boolean Hide all elements.
//   openAll: boolean Show all elements.
//   closeAllExcept: element Show the given element, hide all others.
//   closeAllExceptFirst: boolean Show the first element, hide all others.
function basculate_elements(params) {
    // we MUST have a selector
    if (!params.selector) return;
    // if a parent element was provided, search only in it;
    // otherwise search the entire document
    var nodes = (params.parent ? params.parent.getElementsBySelector(params.selector) : $$(params.selector));
    // cycle through the nodes
    var first = true;
    nodes.each(function (e) {
        // close one element
        if (params.closeElement && e == params.closeElement) basculate_close_element(e, params);
        else {
            // open one element
            if (params.openElement && e == params.openElement) basculate_open_element(e, params);
            else {
                // toggle one element
                if (params.toggleElement && e == params.toggleElement) basculate_toggle_element(e, params);
                else {
                    // close all elements
                    if (params.closeAll) basculate_close_element(e, params);
                    else {
                        // open all elements
                        if (params.openAll) basculate_open_element(e, params);
                        else {
                            // close all elements except one
                            if (params.closeAllExcept) {
                                // open that one
                                if (e == params.closeAllExcept) basculate_open_element(e, params);
                                else basculate_close_element(e, params);
                            }
                            else {
                                // close all elements except 1st one
                                if (params.closeAllExceptFirst) {
                                    if (first) basculate_open_element(e, params);
                                    else basculate_close_element(e, params);
                                }
                            }
                        }
                    }
                }
            }
        }
        // update first marker
        first = false;
    });
}

// show an element and apply certain other changes
function basculate_open_element(e, params) {
    Element.extend(e);
    if (params && params.openHook && typeof(params.openHook)=='function') params.openHook(e, params);
    if (e.visible() && params && !params.force) return;
    if (params && params.hardStyle) e.style.display='block'; else e.show();
    if (params && params.openClass) e.addClassName(params.openClass);
    if (params && params.closedClass) e.removeClassName(params.closedClass);
}

// hide an element and apply certain other changes
function basculate_close_element(e, params) {
    Element.extend(e);
    if (params && params.closeHook && typeof(params.closeHook)=='function') params.closeHook(e, params);
    if (!e.visible() && params && !params.force) return;
    if (params && params.hardStyle) e.style.display='none'; else e.hide();
    if (params && params.openClass) e.removeClassName(params.openClass);
    if (params && params.closedClass) e.addClassName(params.closedClass);
}

// toggle an element and apply certain other changes
function basculate_toggle_element(e, params) {
    Element.extend(e);
    if (params && params.hardStyle) e.style.display = e.visible() ? 'none' : 'block';
    else e.toggle();
    if (params && params.openClass) e.toggleClassName(params.openClass);
    if (params && params.closedClass) e.toggleClassName(params.closedClass);
    if (params && params.toggleHook && typeof(params.toggleHook)=='function') params.toggleHook(e, params);
    if (e.visible() && params && params.openHook && typeof(params.openHook)=='function') params.openHook(e, params);
    else if (!e.visible() && params && params.closeHook && typeof(params.closeHook)=='function') params.closeHook(e, params);
}
