/* Javascript utility functions for Multifilter */

var __mf_filters = new Array();
var __mf_timer = null;

/*
 * Called when a filter must be (re-)initialized.
 */
function multifilter_add_filter(filter_name, all_items, active_items, onchange_func, pre_onchange_func, display_style)
{
    if (!defined(filter_name) || !defined(all_items) || !defined(active_items) || !defined(onchange_func) || !defined(pre_onchange_func) || !defined(display_style)) {
        return false;
    }

    __mf_filters[filter_name] = new Array();
    __mf_filters[filter_name]["all"] = all_items;
    __mf_filters[filter_name]["active"] = active_items;
    __mf_filters[filter_name]["onchange"] = onchange_func;
    __mf_filters[filter_name]["pre_onchange"] = pre_onchange_func;
    __mf_filters[filter_name]["display_style"] = display_style;
}


/*
 * To be called when filter must become "dropdown" and just one option is selectable.
 * id is the id of the active filter element that will become selected in the dropdown
 * (i.e. the element the user clicked on in list mode)
 */
function multifilter_restrict_one(filter_name, id)
{
    if (!defined(filter_name) || !defined(id)) {
        return false;
    }

    var needs_update = false;
    if (__mf_filters[filter_name]["active"].length > 1) {
        __mf_call_pre_onchange(filter_name);
        __mf_stop_timer();

        __mf_filters[filter_name]["active"] = new Array(id);
        needs_update = true;
    }

    multifilter_update_drop(filter_name);
    multifilter_update_list(filter_name);
    multifilter_switch_display(filter_name);

    if (needs_update) {
        __mf_start_timer(filter_name, 1);
    }
}


/*
 * To be called when a checkbox is clicked.
 */
function multifilter_switch_item(filter_name, checkbox_obj, id)
{
    if (!defined(filter_name) || !defined(checkbox_obj) || !defined(id)) {
        return false;
    }

    __mf_stop_timer();

    var el_a = document.getElementById("link_" + filter_name + "_" + id);
    if (!el_a) {
        return false;
    }

    if (checkbox_obj.checked) {
        __mf_filters[filter_name]["active"].push(id);
        el_a.className = "multifilter_active_list_element";
    } else {
        //don't allow unchecking of the last checked item
        if (__mf_filters[filter_name]["active"].length == 1) {
            checkbox_obj.checked = true;
            return false;
        }
        var index = -1;
        for(var i = 0; i < __mf_filters[filter_name]["active"].length; i++) {
            if (__mf_filters[filter_name]["active"][i] == id) {
                index = i;
                break;
            }
        }
        if (index == -1) {
            checkbox_obj.checked = true;
            return false;
        }
        __mf_filters[filter_name]["active"].splice(index, 1);
        el_a.className = "multifilter_disabled_list_element";
    }

    __mf_call_pre_onchange(filter_name);
    __mf_start_timer(filter_name);
}


/*
 * ONCHANGE action for the filter in "drop" state.
 */
function multifilter_drop_change(filter_name)
{
    if (!defined(filter_name)) {
        return false;
    }

    __mf_call_pre_onchange(filter_name);
    __mf_stop_timer();

    var drop_sel_obj = document.getElementById(__mf_get_drop_select_name(filter_name));
    if (!drop_sel_obj) {
        return false;
    }

    var id = drop_sel_obj.options[drop_sel_obj.selectedIndex].value;
    if (!id) {
        return false;
    }

    __mf_filters[filter_name]["active"] = new Array(id);

    __mf_start_timer(filter_name, 1);
}


/*
 * Updates the list of active items for the specified filter, when in "list" mode
 */
function multifilter_update_list(filter_name)
{
    if (!defined(filter_name)) {
        return false;
    }

    var all_elems = __mf_filters[filter_name]["all"];
    var active_elems = __mf_filters[filter_name]["active"];

    var checked;
    var a_class;

    for(var i = 0; i < all_elems.length; i++) {
        var is_sel = false;
        for(var j = 0; j < active_elems.length; j++) {
            if (active_elems[j] == all_elems[i]) {
                is_sel = true;
                break;
            }
        }

        if (is_sel) {
            checked = true;
            a_class = "multifilter_active_list_element";
        } else {
            checked = false;
            a_class = "multifilter_disabled_list_element";
        }

        var el_c = document.getElementById("checkbox_" + filter_name + "_" + all_elems[i]);
        var el_a = document.getElementById("link_" + filter_name + "_" + all_elems[i]);
        if (el_c) {
            el_c.checked = checked;
        }
        if (el_a) {
            el_a.className = a_class;
        }
    }
}


/*
 * Used to update the invisible "drop" control before displaying it when the filter
 * switches from "list" to "drop" mode by clicking on one of the items.
 */
function multifilter_update_drop(filter_name)
{
    if (!defined(filter_name)) {
        return false;
    }

    var drop_sel_obj = document.getElementById(__mf_get_drop_select_name(filter_name));
    if (!drop_sel_obj) {
        return false;
    }

    var id = __mf_filters[filter_name]["active"][0];

    for (var i = 0; i < drop_sel_obj.options.length; i++) {
        if (drop_sel_obj.options[i].value == id) {
            drop_sel_obj.options[i].selected = true;
            break;
        }
    }
}


/*
 * Switches between the "list" and "drop" display modes
 * (hides the currently visible display mode and shows the invisible one)
 */
function multifilter_switch_display(filter_name)
{
    if (!defined(filter_name)) {
        return false;
    }

    var list_obj = document.getElementById(__mf_get_list_name(filter_name));
    var drop_obj = document.getElementById(__mf_get_drop_name(filter_name));

    if (!list_obj || !drop_obj) {
        return false;
    }

    var t = list_obj.style.display;
    list_obj.style.display = drop_obj.style.display;
    drop_obj.style.display = t;

    if (list_obj.style.display == "block") {
        __mf_filters[filter_name]["display_style"] = "list";
    } else {
        __mf_filters[filter_name]["display_style"] = "drop";
    }

    return true;
}


/*
 * Stops the timer started when an onchange event happens
 */
function __mf_stop_timer()
{
    if (__mf_timer) {
        self.clearTimeout(__mf_timer);
        __mf_timer = null;
    }
}


/*
 * Starts a timer that will call the user-defined onchange function after timeout (default: see below) ms.
 * Called when the "onchange" event occurs in one of the "drop" or "list" controls
 */
function __mf_start_timer(filter_name, timeout)
{
    if (!defined(filter_name)) {
        return false;
    }

    if (typeof(timeout) == "undefined") {
        timeout = 250;
    }

    __mf_stop_timer();

    filter_cats_timer = self.setTimeout(__mf_filters[filter_name]["onchange"] + "(__mf_filters);", timeout);
}


/*
 * Calls the user-defined pre-onchange function.
 * (i.e. a function that, for example, will display a loader when something changes in the filter state)
 * This is necessary to provide visual feedback for the user before the actual onchange function is called,
 * because that function is delayed to give the user a chance to adjust options (i.e. (de-)select
 * several items at the same time).
 */
function __mf_call_pre_onchange(filter_name)
{
    if (!defined(filter_name)) {
        return false;
    }

    if (__mf_filters[filter_name]["pre_onchange"] != "") {
        eval(__mf_filters[filter_name]["pre_onchange"]+"('" + filter_name + "');");
    }
}


/*
 * Returns the name of the list of items HTML div
 */
function __mf_get_list_name(filter_name)
{
    return "multi_" + filter_name + "_list";
}


/*
 * Returns the name of the dropdown HTML div
 */
function __mf_get_drop_name(filter_name)
{
    return "multi_" + filter_name + "_drop";
}


/*
 * Returns the name of the <select> HTML element containing the actual choices
 */
function __mf_get_drop_select_name(filter_name)
{
    return "multi_" + filter_name + "_drop_select";
}


/*
 * Returns true if variable is defined, false otherwise
 */
function defined(variable)
{
    return (typeof(variable) != "undefined");
}


function __see_all(element)
{
    if (typeof(element) == "undefined") {
        return false;
    }
    if (typeof(element.childNodes) == "undefined") {
        return false;
    }
    for (var i = 0; i < element.childNodes.length; i++) {
        if (element.childNodes[i].nodeType == 1 && element.childNodes[i].nodeName == 'LI' && element.childNodes[i].style) {
            element.childNodes[i].style.display = '';
        }
    }
}

function __see_less(element, n_items)
{
    if (typeof(element) == "undefined") {
        return false;
    }
    if (typeof(n_items) == "undefined") {
        return false;
    }
    if (typeof(element.childNodes) == "undefined") {
        return false;
    }
    var shown = 0;
    for (var i = 0; i < element.childNodes.length; i++) {
        if (element.childNodes[i].nodeType == 1 && element.childNodes[i].nodeName == 'LI' && element.childNodes[i].style) {
            shown++;
            if (shown > n_items) {
                element.childNodes[i].style.display = 'none';
            }
        }
    }
}
