console.log("yop!");

// Enhance html list elements with collapsibility.
// ken dot manheimer at gmail dot com $revision$

// Including this script on a web page makes list items on that page
// "collapsable", so clicking on the item bullet or text hides any lists
// contained within that item.  Below are details about the features,
// followed by hook-up instructions, and then the code.
//
// Features:
//
// - Click on affected item bullet or body text to toggle exposure of subitems
//   - You can still select body text (by dragging across it) or click
//     on contained buttons or text areas without toggling.
//   - Clicking anywhere in the item (except subitems) and holding for 3
//     seconds (see COLL.holdClickSecs) will toggle - so you can toggle
//     items that are links without following the links.
//   - Clicking on an empty item toggles the exposure of its container, if any.
// - A special bullet indicates that an item is expanded or collapsed.
//   (Empty items have their default bullets.)
// - During mouseover a light box is drawn around the item that would be
//   affected.  Eg, the item and its contents if it has any, else the
//   item's container, if any.
// - The body of collapsed items is highlighted with an unobtrusive color -
//   specified by 'COLL.closed_color'.
// - Ctrl-click will toggle exposure of the item and subitems.  For
//   example, expanding items that have been collapsed this way will show
//   collapsed subitems.
// - You can control the initial default exposure of all affected items, and
//   that of specific items, by including "directive" elements in your html.
//   See the comments at the top of the coll_apply_directives() function.
// - Affected items and some behaviors are configurable - see the COLL
//   structure and the hook-up instructions.
//
// Hook-Up:
//
// To hook up the script, include it somewhere on your site as
// "collapsible.js" and something like the following fragment in web pages
// you want to enable, adjusting the "src=" path to the location of the
// script:
//
//    <script type="text/javascript" src=http://your.site/path/collapsible.js">
//    </script>
//
//  By default, the script will enhance all <LI> elements in the page
//  <BODY>.  You can restrict the attention to the contents of some
//  specific element by setting a global javascript variable
//  'local_content_well' to the preferred element before including the
//  script.  Eg, with some lines before the above fragment like:
//
//    <script type="text/javascript">
//       local_content_well = document.getElementById("region-content");
//    </script>
//
// You can add "directives" to adjust the initial exposure of specific
// items in your document, or of all items.  See the comments at the top of
// the coll_apply_directives() function.

COLL = {"default_exposure": "collapsed", // "collapsed" or "open"
        // "hold-click" after mouse button held for this number milliseconds:
        "holdClickSecs": 3000,
        "cursor": "crosshair",
        "opened_color": "",
        "closed_color": "", //floralwhite,oldlace,seashell,lightcyan,honeydew
        "opened_icon": "url(angle_opened.png)",
        "closed_icon": "url(angle_closed.png)",
        "border_style": "gainsboro solid 1px",
        "collapsed_border_style": "gainsboro 1px dotted",
        // Wish i knew how to say this in a conventional, non-jargon way.
        // "recurse"
        "title": "".concat("Click to collapse/expand outline here,",
                          " ctrl-click cascades."),
        "drag_tolerance": 4,

        "expr_collapsed": /start-collapsed/,
        "expr_open": /start-open/,
        "expr_all_collapsed": /start-all-collapsed/,
        "expr_all_open": /start-all-open/,
        "expr_all_default": /start-all-default/,

        "END": 1  // to avoid problems w/extraneous trailling ",".
}
collPendingHoldClick = null;

function coll_wrap_onload(func) {
    // Add func to window.onload, preserving existing onload function if any.
    // Preexisting onload function is performed first.
    var wasOnload = window.onload;
    if (typeof wasOnload != 'function') {
        window.onload = func;
    } else {
        window.onload = function() {
            if (wasOnload) { wasOnload(); }
            func();
        }   }    }

function coll_get_content_well() {
    // Return the designated content well, defaulting to the document body.
    // Prefers the value of 'local_content_well', if set.
console.log(local_content_well);
    if ((typeof local_content_well != "undefined") && local_content_well) {
        return local_content_well;
    } else {
        return document.getElementsByTagName("BODY")[0];
  } }
function coll_target_lis() {
    // Return set of lis to be treated.  If there's an element that serves
    // as the content well, make this function return the elements within
    // it.
    return coll_get_content_well().getElementsByTagName("li");
}

function coll_equip() {
    // Instrument all list items for collapsibility.
    //
    var all_li = coll_target_lis();
        default_exposure = coll_get_default_exposure();
    for (var i=0; i < all_li.length; i++) {
        var element = all_li[i], populous = coll_has_sublists(element),
            exposure = populous ? default_exposure : "empty";
        // All items except top-level empties:
        if (populous || coll_get_containing_li(element)) {
            coll_adjust_sublists_exposure(element, exposure);
            element.onmousedown = coll_toggle_mouse_down;
            element.onmouseup = coll_toggle_mouse_up;
            element.style.cursor = COLL.cursor;
            var cur_ti = element.title;
            if (!cur_ti || cur_ti == "") {
                element.title = COLL.title;
            } else {
                element.title += " (" + COLL.title + ") ";
            }
            if (!element.onmouseover || element.onmouseover == "") {
                element.onmouseover = coll_highlight_collapsible;
            }
            if (!element.onmouseout || element.onmouseout == "") {
                element.onmouseout = coll_unhighlight_collapsible;
    }   }   }
    coll_apply_directives();
    var b = document.getElementById("buttoning");
    if (b) { b.onclick = buttoning; }
    if (document.addEventListener) {
        document.addEventListener("mousemove", coll_track_move, false); 
    } else { document.attachEvent("onmousemove", coll_track_move); }
    return true;
}

function coll_toggle_collapsible(e, subject) {
    var curstate = (subject && subject.getAttribute("collapsible"));
    var recursive = (e && e.ctrlKey);
    if (!subject) { return null;
    } else if (curstate == "collapsed") {
        coll_adjust_sublists_exposure(subject, "open", e, recursive);
    } else if (curstate == "open") {
        coll_adjust_sublists_exposure(subject, "collapsed", e, recursive);
    } else if (curstate == "empty") {
        coll_toggle_collapsible(e, coll_get_containing_li(subject));
    } }

function coll_adjust_sublists_exposure(element, exposure, e, recursive) {
    // Hide nearest-contained list subelements.
    // Optional event e presence determines whether element box is drawn.
    // If optional recursive is set, treat all contained lists, not
    // just nearest contained ones.
    // (We can't just use css because IE mostly doesn't respect it.)

    if (exposure != element.getAttribute("collapsible")) {
        element.setAttribute("collapsible", exposure);
        coll_decorate_li(element, e);
        if (exposure != "empty") {
            var hide = exposure == "collapsed";
            var subjects = recursive ? coll_get_all_sublists(element)
                                     : coll_get_nearest_sublists(element);
            for (var i in subjects) {
                if (subjects[i] && subjects[i].style) {
                    subjects[i].style.display = hide ? "none" : "block";
                    var parent = subjects[i].parentNode;
                    if ((parent.nodeName == "LI")
                        && (parent.getAttribute("collapsible") != exposure)) {
                        parent.setAttribute("collapsible", exposure);
                        coll_decorate_li(parent, recursive ? "" : e); }
                }
        } } } }

function coll_decorate_li(element, e) {
    // Put decorations on list element according to collapsibility state.
    var curstate = element.getAttribute("collapsible");
    if (curstate == "collapsed") {
        element.style.listStyleImage = COLL.closed_icon;
        element.style.background = COLL.closed_color;
        if (e) { coll_set_element_box(element, COLL.border_style); }
        else { coll_set_element_box(element, ""); }
    } else if (curstate == "open") {
        element.style.listStyleImage = COLL.opened_icon;
        element.style.background = COLL.opened_color;
        if (e) { coll_set_element_box(element, COLL.border_style); }
        else { coll_set_element_box(element, ""); }
    } else if (curstate == "empty") {
        element.style.listStyleImage = "none";
        var superior = coll_get_containing_li(element);
        if (superior) { return coll_decorate_li(superior, e); }
    } }

function coll_apply_directives() {
    // Abuse html items to provide initial outline exposure directives.
    // We use the contents of any tags (we suggest <APPLET>) with the name
    // "collapsible-directive" to qualify the initial exposure of the
    // most immediately containing <LI>, or, in the case of the "-all-"
    // forms, of the default exposure for all the <LI>s.  The
    // alternatives are:
    //
    // start-collapsed
    // start-open
    // start-all-collapsed
    // start-all-open
    // start-all-default
    //
    // These amend COLL.default_exposure for items contained within
    // the immediately following list, or, for the "-all-" forms, for all
    // items, instead of the default.  If there are multiple "-all-"
    // directives, the last one prevails.
    //
    // all-default cancels the effect of any previous "-all-" directive,
    // reinstating COLL.default_exposure as the default.
    var directives = document.getElementsByName("collapsible-directive"),
        pending = [];
    for (var i=0; i < directives.length; i++) {
        var text = directives[i].textContent, specific=null;
        if (text.match(COLL.expr_all_collapsed)) {
            collapsible_amended_exposure = "collapsed";}
        if (text.match(COLL.expr_all_open)) {
            collapsible_amended_exposure = "open";}
        if (text.match(COLL.expr_all_default)) {
            collapsible_amended_exposure = null; }
        if (text.match(COLL.expr_open)) { specific = "open"; }
        // collapsed wins, if both specifics are set:
        if (text.match(COLL.expr_collapsed)) { specific = "collapsed"; }
        if (specific) {
            var li = coll_get_containing_li(directives[i]);
            pending[pending.length] = [li, specific];
        }
    }
    // implement default exposure:
    var default_exposure = coll_get_default_exposure();
    if ((default_exposure == "collapsed")
        || ((typeof collapsible_amended_exposure != "undefined")
            && collapsible_amended_exposure)) {
        // get top-level LIs and collapse them.
        var all_li = coll_target_lis();
        for (var i=0; i<all_li.length; i++) {
            var element = all_li[i],
                collapsible = element.getAttribute("collapsible");
            if (collapsible
                && (collapsible != "")
                && (collapsible != "empty")
                && (! coll_get_containing_li(element))) {
                // Top-level populous items:
                coll_adjust_sublists_exposure(element,
                                              default_exposure,null,true);
            } } }
    // implement selective exposure:
    for (var i=0; i < pending.length; i++) {
        coll_adjust_sublists_exposure(pending[i][0], pending[i][1],
                                      null, true);
    }
}

function coll_set_element_box(element, setting) {
    // set border on element, preferring .outline when supported.
    if (element.style.outline || (element.style.outline == "")) {
        element.style.outline = setting || "";
    } else { element.style.border = setting || ""; } }

function coll_get_containing_li(element) {
    // Return li that contains this element.
    for (var ascend = element.parentNode; ascend; ascend = ascend.parentNode)
        if (ascend.nodeName == "LI") { return ascend; }
    return null; }

function coll_get_all_sublists(element) {
    // Return sublists which have element as their LI.
    var got = []
        nodeList = element.getElementsByTagName("UL");
    for (var i=0; i < nodeList.length; i++) {
        got[i] = nodeList[i]; }
    nodeList = element.getElementsByTagName("OL");
    for (var i=0; i < nodeList.length; i++) {
        got[got.length+i] = nodeList[i]; }
    return got; }

function coll_get_nearest_sublists(element) {
    // Return sublists which have element as their nearest containing LI.
    var got=[], sublists = coll_get_all_sublists(element);
    for (var i=0; i < sublists.length; i++) {
        var is_nearest_parent = true;
        var subl = sublists[i];
        if (subl.parentNode) {
            var ascend = subl.parentNode;
            while (ascend) {
                if (ascend.nodeName == "LI") {
                    if (ascend != element) { is_nearest_parent = false; }
                    break;
                }
                ascend = ascend.parentNode
                    }
            if (is_nearest_parent) { got[got.length] = subl; }
        } }
    return got;
}

function coll_has_sublists(li) {
    return (li.getElementsByTagName("UL").length != 0)
        || (li.getElementsByTagName("OL").length != 0);
}

function coll_highlight_collapsible(e, override) {
    var subject = override || this;
    if (subject.getAttribute("collapsible") == "empty") {
        var superior = coll_get_containing_li(subject);
        if (superior) { return coll_highlight_collapsible(e, superior);
        } else { return true; }
    }
    if (override || coll_is_event_for_object(e, subject)) {
        coll_set_element_box(subject, COLL.border_style);
        if (subject.getAttribute("collapsible") == "open") {
            subject.style.background = COLL.opened_color; } } }
function coll_unhighlight_collapsible(e, override) {
    var subject = override || this;
    if (subject.getAttribute("collapsible") == "empty") {
        var superior = coll_get_containing_li(subject);
        if (superior) { return coll_unhighlight_collapsible(e, superior);
        } else { return true; }
    }
    if (override || coll_is_event_for_object(e, subject)) {
        var state = subject.getAttribute("collapsible");
        coll_set_element_box(subject, "");
        subject.style.background = (state == "collapsed") ? COLL.closed_color
                                                          : ""
        } }

function buttoning(e) {
    var target = e ? e.target : window.event.srcElement
        document.createNodeIterator();
    var span = document.getElementById("thespan");
    var c = span.firstChild.nextSibling;
    global_c = c;
    alert(target);
}

function coll_toggle_mouse_down(event) {
    if (!event) { event = window.event; }
    // We need to preserve the values, because the event changes over time?
    event.stopPropagation ? event.stopPropagation()
                          : event.cancelBubble = true;
    toggle_down_event = [event.screenX, event.screenY,
                         event.target || event.srcElement];
    collPendingHoldClick = [setTimeout("coll_hold_click()",
                                       COLL["holdClickSecs"]),
                            event.currentTarget || event.target
                            || event.srcElement,
                            null];
}
function coll_toggle_mouse_up(event) {
    // If mouse is near where it was during mouse_down, act on this event.
    // (We avoid onmousemove 'cause it's expensive in some browser ie.
    if (!event) { event = window.event; }
    if (collPendingHoldClick) {
        var hold_click_fired = collPendingHoldClick[2];
        clearTimeout(collPendingHoldClick[0]);
        if (hold_click_fired) { return true; }
    }
    // Disregard if there was a drag, to allow for text selection.
    if ((coll_is_event_for_object(event, this))
        && !event.shiftKey && !event.altKey) {
        var X = toggle_down_event[0] - event.screenX,
            Y = toggle_down_event[1] - event.screenY,
            target = event.target || event.srcElement;
        if (Math.sqrt((X*X) + (Y*Y)) < COLL.drag_tolerance) {
            coll_toggle_collapsible(event, this);
        }
    } }

function coll_track_move(event) {
    // register mouse motion so we can disqualify toggles.
    if (!event) { event = window.event; }
    
}

function coll_hold_click() {
    // Process a "hold click", where the mouse button was held for long enough.
    // This is useful for those cases where the entire LI is covered by, eg,
    // some other clickable.
    if (! collPendingHoldClick) { return null; }
    var target = collPendingHoldClick[1];
    if (!target) { return null; }
    if (target.tagName != "LI") {
        target = coll_get_containing_li(target); }
    coll_toggle_collapsible(null, target);
    collPendingHoldClick[2] = true; }

function coll_is_event_for_object(event, object) {
    // true if event is on object or event is on an object with no click
    // provisions of its own.
    if (!event) { event = window.event; }
    // Stop bubbling:
    event.stopPropagation ? event.stopPropagation()
                          : event.cancelBubble = true;
    var target = event.target || event.srcElement;
    if ((object == target)
        || ((!target.onclick && !target.onMouseDown && !target.onMouseUp)
            && target.nodeName != "A"
            && target.nodeName != "INPUT"
            && target.nodeName != "SELECT"
            && target.nodeName != "TEXTAREA"
            && target.nodeName != "BUTTON"
            && target.nodeName != "APPLET"
            && target.nodeName != "FRAME"
            && target.nodeName != "FRAMESET"
            && target.nodeName != "IFRAME"
            && target.nodeName != "AREA"
            && target.nodeName != "OBJECT" )) {
        return true;
    } else { return false; }
}

function coll_get_default_exposure() {
    // return locally amended default exposure setting or builtin default.
    return (typeof collapsible_amended_exposure != "undefined")
           ? (collapsible_amended_exposure || COLL.default_exposure)
           : COLL.default_exposure; }

coll_wrap_onload(coll_equip);
