﻿var loading_reference = 0;
var show_debug_info = false;
var start, timer = null, period = 5, time_left, session_time = 30 * 60, warning_time = 121;

var site_name = "";

var _search_parameters = new Array();    // BE WARNED: Indexing MUST be an integer, or a string - other keys DON'T WORK! (http://www.timdown.co.uk/jshashtable/)
var _start_record = new Array();         // BE WARNED: Indexing MUST be an integer, or a string - other keys DON'T WORK! (http://www.timdown.co.uk/jshashtable/)
var _search_window = new Array();        // BE WARNED: Indexing MUST be an integer, or a string - other keys DON'T WORK! (http://www.timdown.co.uk/jshashtable/)
var _sort_column = new Array();          // BE WARNED: Indexing MUST be an integer, or a string - other keys DON'T WORK! (http://www.timdown.co.uk/jshashtable/)

// ---------------------------------------------------------------------------
// Return true if the Enter key was pressed
// Read here about keycodes: http://unixpapa.com/js/key.html
// (javascript keyboard event key codes)
// ---------------------------------------------------------------------------
function keyCode(e) {
    if (e) return (e.keyCode);
    if (event) {
        if (event.which) return (event.which);
        if (event.charCode) return (event.charCode);
    }
    return (0);
}

// ---------------------------------------------------------------------------
// Return true if the Enter key was pressed
// ---------------------------------------------------------------------------
function checkEnter(e) {
    return (keyCode(e) == 13);
}

// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// Return the extended element. If the element cannot be found, throw error.
// ---------------------------------------------------------------------------
function get_element(elm_id) {
    var elm = $(elm_id);
    if (elm == null) throw "'" + elm_id + "' not found";
    return (elm);
}

// ---------------------------------------------------------------------------
// Fire an event (http://jehiah.cz/archive/firing-javascript-events-properly)
// ---------------------------------------------------------------------------
function fireEvent(element, event) {
    var this_module = "fireEvent()";
    try {
        if (document.createEvent) {
            // dispatch for firefox + others
            var evt = document.createEvent("HTMLEvents");
            evt.initEvent(event, true, true); // event type,bubbling,cancelable
            result = !element.dispatchEvent(evt);
            return (result);
        }
        else {
            // dispatch for IE
            var evt = document.createEventObject();
            result = element.fireEvent('on' + event, evt)
            return (result);
        }
    } catch (ex) {
        alert(this_module + ": " + ex);
    }
}

// ---------------------------------------------------------------------------
// Execute the action element's "onclick" code if Enter is pressed
// ---------------------------------------------------------------------------
function fire_onclick_on_enter(e, action_elm) {
    if (checkEnter(e)) {
        fireEvent($(action_elm), 'click');
        return (false);
    }
    return (true);
}

// ---------------------------------------------------------------------------
// Prevent form submission when enter is pressed
// (link to the onKeyPress event)
// ---------------------------------------------------------------------------
function dont_submit_on_enter(e) {
    if (checkEnter(e)) {
        return (false);
    }
}

// ---------------------------------------------------------------------------
// Do the default search
// ---------------------------------------------------------------------------
function default_search(target_id, search_url, search_text_id, json) {
    var this_module = "default_search()";
    try {
        var target_elm = $(target_id);
        target_id = target_elm.id;
        var guid = get_guid_from_target_id(target_id);

        var elm_id = search_url + guid;
        var elm = $(elm_id);
        if (elm != null) {
            $('debug_info').innerHTML = $F(elm);

            json = append_json(json, "\"default_search_text\" : \"" + encodeURIComponent($F(search_text_id + guid)) + "\"");

            _search_parameters[target_id] = json;
            _start_record[target_id] = 0;

            // If the sort order is found at the client side, submit it to the page
            if (_sort_column[target_id] != null) {
                json = append_json(json, "\"sort_column\" : \"" + _sort_column[target_id]) + "\"";
            }

            json = append_json(json, "\"start_record\" : 0");

            // Check if there is form data that we could pass on automatically.
            // For this, there must be a form with ID="frm"+target_id
            var frm = $('frm' + guid);
            if (frm != null) {
                json = append_json(json, "\"frm\" : \"" + encodeURIComponent("frm" + guid) + "\"");
                // Add its inputs to the JSON
                json = get_form_values(frm.id, json);
            } else {
                json = append_json(json, "\"frm\" : \"" + encodeURIComponent("'frm" + guid + "' not found") + "\"");
            }

            // function general_click(target_id, url, json, insertion, async)
            general_click(target_id, $F(search_url + guid), json, null);
        } else {
            throw ("'" + elm_id + "' not found");
            disable_search(guid);
        }
    } catch (ex) {
        alert(this_module + ": " + ex);
    }
    return (false);
}

// ---------------------------------------------------------------------------
// Do the advanced search
// ---------------------------------------------------------------------------
function advanced_search(target_id, form_id, search_url, json) {
    var this_module = "advanced_search()";
    try {
        var target_elm = $(target_id);
        target_id = target_elm.id;
        var guid = get_guid_from_target_id(target_id);

        if ($(search_url + guid) != null) {
            $('debug_info').innerHTML = $F(search_url + guid);

            json = get_form_values(form_id, json);

            _search_parameters[target_id] = json;
            _start_record[target_id] = 0;

            json = append_json(json, "\"start_record\" : 0");
            json = append_json(json, "\"show_advanced_search\" : true");

            // If the sort order is found at the client side, submit it to the page
            if (_sort_column[target_id] != null) {
                json = append_json(json, "\"sort_column\" : \"" + _sort_column[target_id]) + "\"";
            }

            // Check if there is form data that we could pass on automatically.
            // For this, there must be a form with ID="frm"+target_id
            var frm = $(form_id);
            if (frm != null) {
                json = append_json(json, "\"frm\" : \"" + encodeURIComponent(form_id) + "\"");
                // Add its inputs to the JSON
                json = get_form_values(frm.id, json);
            } else {
                json = append_json(json, "\"frm\" : \"" + encodeURIComponent("'" + form_id + "' not found") + "\"");
            }

            // function general_click(target_id, url, json, insertion, async)
            general_click(target_id, $F(search_url + guid), json, null);
        } else {
            disable_search(guid);
        }
    } catch (ex) {
        alert(this_module + ": " + ex);
    }
    return (false);
}

// ---------------------------------------------------------------------------
// Show the advanced search controls
// ---------------------------------------------------------------------------
function show_advanced_search(target_id) {
    var this_module = "show_advanced_search()";
    try {
        var target_elm = $(target_id);
        target_id = target_elm.id;
        var guid = get_guid_from_target_id(target_id);

        $('default_search_div' + guid).setStyle({
            visibility: 'hidden'
        });
        $('adv_srch' + guid).setStyle({
            display: 'block'
        });
        _search_window[target_id] = false;
    } catch (ex) {
        alert(this_module + ": " + ex);
    }
    return (false);
}

// ---------------------------------------------------------------------------
// Hide the advanced search controls
// ---------------------------------------------------------------------------
function hide_advanced_search(target_id) {
    var this_module = "hide_advanced_search()";
    try {
        var target_elm = $(target_id);
        target_id = target_elm.id;
        var guid = get_guid_from_target_id(target_id);

        var elm, elm_id;
        elm_id = 'default_search_div' + guid;
        elm = $(elm_id);
        if (elm == null) throw "'" + elm_id + "' not found";
        elm.setStyle({
            visibility: 'visible'
        });
        elm_id = 'adv_srch' + guid;
        elm = $(elm_id);
        if (elm == null) throw "'" + elm_id + "' not found";
        elm.setStyle({
            display: 'none'
        });
        _search_window[target_id] = true;
    } catch (ex) {
        alert(this_module + ": " + ex);
    }
    return (false);
}

// ---------------------------------------------------------------------------
// Get the GUID from the target ID
// ---------------------------------------------------------------------------
function get_guid_from_target_id(target_id) {
    var this_module = "get_guid_from_target_id()";
    var guid = "";
    if (target_id != null) {
        var pos_dash = target_id.lastIndexOf('-');
        while (pos_dash >= 0) {
            guid = target_id.substr(pos_dash, 4) + guid;
            pos_dash -= 4;
            if (pos_dash >= 0) {
                //alert(this_module + ": " + "pos_dash: '" + pos_dash + "', target_id[pos_dash]: '" + target_id.substr(pos_dash, 1) + "'");
                if (target_id.substr(pos_dash, 1) != '-') break;
            }
        }
    } else {
        target_id = "(null)";
    }
    //alert(this_module + ": " + "target_id: '" + target_id + "', guid: '" + guid + "'");
    return (guid);
}

// ---------------------------------------------------------------------------
// Perform actions required after AJAX call completed
// ---------------------------------------------------------------------------
function check_advanced_search_view_state(target_id) {
    var this_module = "check_advanced_search_view_state()";
    try {
        var target_elm = $(target_id);
        target_id = target_elm.id;
        var guid = get_guid_from_target_id(target_id);

        // Is there an advanced search DIV?
        if ($('adv_srch' + guid) != null) {
            //alert(_search_window[target_id]);
            if (_search_window[target_id] != false) {
                $('adv_srch' + guid).setStyle({
                    display: 'none'
                });
            }
        }
    } catch (ex) {
        alert(this_module + ": " + ex);
    }
}

// ---------------------------------------------------------------------------
// Toggle the plus/minus in a child list header.
// If there is a search or an advanced search, then hide them
// ---------------------------------------------------------------------------
function header_toggle_plus_minus(img_elm, div_elm_id, target_id, javascript) {
    var this_module = "header_toggle_plus_minus()";
    try {
        var target_elm = $(target_id);
        target_id = target_elm.id;
        var guid = get_guid_from_target_id(target_id);

        var img = $(img_elm);
        var img_src_dir = getDirectory(img.src);

        var elm = $(div_elm_id);

        if (elm == null) throw "'" + elm_id + "' not found";
        if (elm.style.display == 'none') {
            // the element is collapsed. expand it.
            elm.style.display = 'block';
            img.src = img_src_dir + 'minus.gif';
            if (_search_window[target_id] != false) {
                $('default_search_div' + guid).setStyle({
                    visibility: 'visible'
                });
            }
            if (javascript != null) {
                // Set a new "onclick" handler for the plus/minus image that does not have a javascript
                // This way, the child screen isn't re-loaded every time the child screen is expanded
                img.onclick = function () { header_toggle_plus_minus(img_elm.id, div_elm_id, target_id, null) };
                eval(javascript);
            }
        } else {
            // the element is not collapsed. collapse it.
            elm.style.display = 'none';
            img.src = img_src_dir + 'plus.gif';
            if (_search_window[target_id] != false) {
                $('default_search_div' + guid).setStyle({
                    visibility: 'hidden'
                });
            }
        }
    } catch (ex) {
        alert(this_module + ": " + ex);
    }
}


// ---------------------------------------------------------------------------
// Expand the plus/minus in a child list header.
// ---------------------------------------------------------------------------
function header_expand(img_elm, div_elm_id, target_id, javascript) {
    $(div_elm_id).style.display = 'none';
    header_toggle_plus_minus(img_elm, div_elm_id, target_id, javascript);
}


// ---------------------------------------------------------------------------
// Collapse the plus/minus in a child list header.
// ---------------------------------------------------------------------------
function header_collapse(img_elm, div_elm_id, target_id, javascript) {
    $(div_elm_id).style.display = 'block';
    header_toggle_plus_minus(img_elm, div_elm_id, target_id, javascript);
}

// ---------------------------------------------------------------------------
// Enable the default search controls
// ---------------------------------------------------------------------------
function enable_search(target_id, enabled_advanced_search) {
    var this_module = "enable_search()";
    try {
        var target_elm = $(target_id);
        target_id = target_elm.id;
        var guid = get_guid_from_target_id(target_id);

        //alert(this_module + ": " + "guid=[" + guid + "], enabled_advanced_search=[" + enabled_advanced_search + "]");
        if (_search_window[target_id] != false) {
            var default_search_div_elm = $('default_search_div' + guid);
            if (default_search_div_elm == null) {
                throw ("'default_search_div" + guid + "' not found");
            }
            default_search_div_elm.setStyle({
                visibility: 'visible'
            });
        }
        var show_adv_srch_elm = $('show_adv_srch' + guid);
        if (show_adv_srch_elm == null) {
            throw ("'show_adv_srch" + guid + "' not found");
        }
        show_adv_srch_elm.setStyle({
            display: enabled_advanced_search ? 'inline' : 'none'
        });
    } catch (ex) {
        alert(this_module + ": " + ex);
    }
    return (false);
}

// ---------------------------------------------------------------------------
// Disable the default search controls
// ---------------------------------------------------------------------------
function disable_search(target_id) {
    var this_module = "disable_search()";
    try {
        var target_elm = $(target_id);
        target_id = target_elm.id;
        var guid = get_guid_from_target_id(target_id);

        var default_search_div_elm = $('default_search_div' + guid);
//        if (default_search_div_elm == null) {
//            throw ("'default_search_div" + guid + "' not found");
        //        }
        if (default_search_div_elm) {
            default_search_div_elm.setStyle({
                visibility: 'hidden'
            });
        }
    } catch (ex) {
        alert(this_module + ": " + ex);
    }
    return (false);
}

// Perform actions required after AJAX call completed
// ---------------------------------------------------------------------------
function on_ajax_complete(target_id, response_text) {
    var this_module = "on_ajax_complete()";
    try {
        var target_elm = $(target_id);
        if (target_elm == null) throw "Element with ID '" + target_id + "' not found";
        target_id = target_elm.id;
        if (window.DPC_autoInit) {
            DPC_autoInit();
            if (window.validate_date_from_to) {
                DatePickerControl.onSelect = validate_date_from_to;
            }
        }
        check_advanced_search_view_state(target_id);
        decrement_loading_reference();
        check_debug_info('hid_debug_info', 'debug_info');
        //$('debug_info').innerHTML += response_text.escapeHTML();
    } catch (ex) {
        alert(this_module + ": " + ex);
    }
}

// ---------------------------------------------------------------------------
// Increment the reference to the "busy loading" image div
// ---------------------------------------------------------------------------
function increment_loading_reference() {
    var this_module = "increment_loading_reference()";
    try {
        if (loading_reference == 0) {
            $('div_loading').setStyle({
                display: '',
                zIndex: 1000
            });
        }
        loading_reference++;
    } catch (ex) {
        alert(this_module + ": " + ex);
    }
}

// ---------------------------------------------------------------------------
// Decrement the reference to the "busy loading" image div
// ---------------------------------------------------------------------------
function decrement_loading_reference() {
    var this_module = "decrement_loading_reference()";
    try {
        if (loading_reference > 0) {
            loading_reference--;
        }
        if (loading_reference == 0) {
            $('div_loading').setStyle({
                display: 'none'
            });
        }
    } catch (ex) {
        alert(this_module + ": " + ex);
    }
}

// ---------------------------------------------------------------------------
// Decrement the reference to the "busy loading" image div
// ---------------------------------------------------------------------------
function ajax_error_occurred(ajax_object, ev) {
    decrement_loading_reference();
    alert('Ajax error : ' + ev);
}

// ---------------------------------------------------------------------------
// Check if debug info was returned, and if so, display in the target frame
// ---------------------------------------------------------------------------
function check_debug_info(returned_info_id, target_frame_id) {
    var this_module = "check_debug_info()";
    try {
        var returned_info = $(returned_info_id);
        var target_frame = $(target_frame_id);

        // There's no point if the target frame does not exist
        if (target_frame != null) {
            if (!show_debug_info) {
                target_frame.setStyle({
                    display: 'none'
                });
                return;
            }
            var currentTime = new Date();
            var hours = currentTime.getHours();
            var minutes = currentTime.getMinutes();
            var seconds = currentTime.getSeconds();
            if (minutes < 10) {
                minutes = "0" + minutes;
            }
            if (seconds < 10) {
                seconds = "0" + seconds;
            }
            var end = new Date().getTime();
            var time = end - start;

            target_frame.setStyle({
                display: ''
            });
            debug.clear();
            target_frame.innerHTML += hours + ":" + minutes + ":" + seconds;
            if (time >= 0) target_frame.innerHTML += ' AJAX call execution time: ' + time + 'ms';
            target_frame.innerHTML += "<br />";
            if (returned_info != null) {
                target_frame.innerHTML += returned_info.value;
                returned_info_parent = returned_info.parentNode;
                if (returned_info_parent != null) {
                    returned_info_parent.removeChild(returned_info);
                    target_frame.innerHTML += "<br />(removed '" + returned_info_id + "')<br />";
                } else {
                    target_frame.innerHTML += "<br />(could not find parent for '" + returned_info_id + "')<br />";
                }
            } else {
                target_frame.innerHTML += "(no debug info)<br />";
            }
        }
    } catch (ex) {
        alert(this_module + ": " + ex);
    }
}

// ---------------------------------------------------------------------------
// Navigation click handler
// This handler re-posts any search parameters that apply
// ---------------------------------------------------------------------------
function navigation_click(target_id, url, json, start_record, insertion) {
    var this_module = "navigation_click()";
    try {
        var target_elm = $(target_id);
        target_id = target_elm.id;
        var guid = get_guid_from_target_id(target_id);

        if (_search_parameters[target_id] != null) {
            json = append_json(json, _search_parameters[target_id]);
        }
        // If no start record is supplied, get the one stored at the client side (it could be null too)
        if (start_record != null) {
            _start_record[target_id] = start_record;
        } else {
            start_record = _start_record[target_id];
        }
        // If the start record is supplied, or was found at the client side, submit it to the page
        if (start_record != null) {
            json = append_json(json, "\"start_record\" : " + start_record);
        }
        // If the sort order is found at the client side, submit it to the page
        if (_sort_column[target_id] != null) {
            json = append_json(json, "\"sort_column\" : \"" + _sort_column[target_id]) + "\"";
        }
        if (_search_window[target_id] != null) {
            json = append_json(json, "\"show_advanced_search\" : " + _search_window[target_id]);
        }
        // function general_click(target_id, url, json, insertion, async)
        general_click(target_id, url, json, insertion);
    } catch (ex) {
        alert(this_module + ": " + ex);
    }
    return (false);
}

// ---------------------------------------------------------------------------
// Sort-column click handler
// This handler re-posts any search parameters that apply
// ---------------------------------------------------------------------------
function sort_column_click(target_id, url, json, sort_column, insertion) {
    var this_module = "sort_column_click()";
    try {
        var target_elm = $(target_id);
        target_id = target_elm.id;

        if (_search_parameters[target_id] != null) {
            json = append_json(json, _search_parameters[target_id]);
        }
        // If no start record is supplied, get the one stored at the client side (it could be null too)
        if (sort_column != null) {
            _sort_column[target_id] = sort_column;
        } else {
            sort_column = _sort_column[target_id];
        }
        // If the start record is supplied, or was found at the client side, submit it to the page
        if (sort_column != null) {
            json = append_json(json, "\"sort_column\" : \"" + sort_column + "\"");
        }
        _start_record[target_id] = 0;
        json = append_json(json, "\"start_record\" : 0");
        if (_search_window[target_id] != null) {
            json = append_json(json, "\"show_advanced_search\" : " + _search_window[target_id]);
        }
        // function general_click(target_id, url, json, insertion, async)
        general_click(target_id, url, json, insertion);
    } catch (ex) {
        alert(this_module + ": " + ex);
    }
    return (false);
}

// ---------------------------------------------------------------------------
// Menu-item click handler
// This handler clears all the search parameters
// ---------------------------------------------------------------------------
function menu_click(target_id, url, json, title, insertion) {
    var this_module = "menu_click()";

    var target_elm = $(target_id);
    target_id = target_elm.id;

    _search_parameters = new Array();
    _start_record = new Array();
    _search_window = new Array();
    _sort_column = new Array();

    // function general_click(target_id, url, json, insertion, async)
    general_click(target_id, url, json, insertion);
    try {
        if (target_id.substr(0, 2) == "MC") {
            if (title != null) {
                if (title.length > 0) {
                    var title_contents = $('title_contents');
                    if (title_contents != null) {
                        title_contents.innerHTML = site_name + " : " + title;
                    }
                }
            }
        }
    } catch (ex) {
        alert(this_module + ": " + ex);
    }
    return (false);
}

// ---------------------------------------------------------------------------
// General click handler with a confirm box
// ---------------------------------------------------------------------------
function confirm_click(message, target_id, url_id, form_id, json, insertion) {
    var answer = confirm(message);
    if (answer) {
        // function form_post(target_id, url_id, form_id, json, insertion) {
        return (form_post(target_id, url_id, form_id, json, insertion));

    }
    return (false);
}

// ---------------------------------------------------------------------------
// General click handler
// insertion: null, 'top', 'bottom', 'before', 'after'
// async: null, true, false
// ---------------------------------------------------------------------------
function general_click(target_id, url, json, insertion, async, method) {
    var this_method = "general_click()";
    if (async == null) async = true;
    if (method == null) method = 'post';
    try {
        var target_elm = $(target_id);
        target_id = target_elm.id;
        var guid = get_guid_from_target_id(target_id);

        clean_target(target_elm, target_id, guid);

        // Make an Ajax query
        start = new Date().getTime();

        json = append_json(json, "\"target_element\":\"" + target_id + "\"");
        if (json.length > 0) json = "{" + json + "}";

        new Ajax.Updater(
            target_id,
            url,
            {
                onCreate: function () {
                    increment_loading_reference();
                },
                onComplete: function (transport) {
                    on_ajax_complete(target_id, transport.responseText);
                    if (window.initialise_form) {
                        initialise_form.defer();
                    }
                    //alert(transport.responseText);
                },
                onFailure: function (transport) {
                    decrement_loading_reference();
                },
                onException: ajax_error_occurred,
                parameters: {
                    json: json
                },
                evalScripts: true,
                insertion: insertion,
                asynchronous: async,
                method: method
            }
        );
    } catch (ex) {
        alert(this_method + ":" + ex);
    }
    return (false);
}

// ---------------------------------------------------------------------------
// Clean controls in the target element
// ---------------------------------------------------------------------------
function clean_target(target_elm, target_id, guid) {
    // Look for tinyMCE editors and terminate them
    var forms = target_elm.select('FORM');
    if (forms.length > 0) {
        for (var form_index = 0; form_index < forms.length; form_index++) {
            var form_inputs = forms[form_index].getElements();
            for (index = 0; index < form_inputs.length; index++) {
                var form_input = form_inputs[index];
                var id = form_input.id;
                // Check if the input is a tinyMCE editor
                if (window.tinyMCE) {
                    var tiny_mce_editor = tinyMCE.editors[id];
                    if (tiny_mce_editor != null) {
                        //alert('Removing tinyMCE[' + id + ']');
                        tiny_mce_editor.remove();
                    }
                }
            }
        }
    }
}

// ---------------------------------------------------------------------------
// Append values of input elements on a form to a JSON string
// ---------------------------------------------------------------------------
function append_json(json, text) {
    if (json == null) json = '';
    if (json.length > 0) json += ", ";
    return (json + text);
}

// ---------------------------------------------------------------------------
// Append values of input elements on a form to a JSON string
// ---------------------------------------------------------------------------
function get_form_values(form_id, json) {
    if (json == null) json = '';
    var form_inputs = $(form_id).getElements();
    if (form_inputs.length == 0) {
        alert('Form [' + form_id + '] has no elements');
    } else {
        for (index = 0; index < form_inputs.length; index++) {
            var form_input = form_inputs[index];
            var id = form_input.id;
            if (!id.startsWith('_')) {
                // Check for a group of radio buttons for boolean
                // Yes-->"True", No-->"False", Either-->"Either"
                if (id.endsWith('_yes') || id.endsWith('_no') || id.endsWith('_either')) {
                    if (id.endsWith('_yes')) {
                        id = id.substr(0, id.length - 4);
                        var box, value;
                        box = $(id + '_yes'); if (box != null) { if (box.checked) value = "True"; }
                        box = $(id + '_no'); if (box != null) { if (box.checked) value = "False"; }
                        box = $(id + '_either'); if (box != null) { if (box.checked) value = "Either"; }
                        json = append_json(json, "\"" + id + "\":" + "\"" + encodeURIComponent(value) + "\"");
                    }
                } else {
                    var json_pair = "\"" + form_input.name + "\":";

                    if (form_input.type == "checkbox") {
                        json_pair += form_input.checked;
                    } else {
                        // Check if the input is a tinyMCE editor
                        var tiny_mce_editor = null;
                        if (window.tinyMCE) {
                            tiny_mce_editor = tinyMCE.editors[id];
                        }
                        var is_tiny_mce = (tiny_mce_editor != null);
                        if (is_tiny_mce) {
                            //alert(form_input.id + ' is TinyMCE');
                            json_pair += "\"" + encodeURIComponent(tiny_mce_editor.getContent()) + "\"";
                        } else {
                            json_pair += "\"" + encodeURIComponent(form_input.value) + "\"";
                        }
                    }
                    json = append_json(json, json_pair);
                }
            }
        }
    }
    return (json);
}

// ---------------------------------------------------------------------------
// General form poster
//   The Listview form must supply these hidden fields:
//          hid_XXX_url : the url to call
//   target_id : the name of the container whose contents are to be replaced
//   url_id : the id of a hidden variable that holds the url (e.g. 'hid_XXX_url')
//   form_id : the id of the form for who to post all input values too
//   json : json that isn't dynamic content from the form
// ---------------------------------------------------------------------------
function form_post(target_id, url_id, form_id, json, insertion) {
    var this_module = "form_post()";
    try {
        var target_elm = $(target_id);
        target_id = target_elm.id;
        var guid = get_guid_from_target_id(target_id);

        var form_elm = $(form_id + guid);
        var url_elm = $(url_id + guid);
        if (form_elm == null) {
            throw ('Could not find form [' + form_id + guid + ']');
        }
        if (url_elm == null) {
            throw ('Could not find URL input [' + url_id + guid + ']');
        }
        var json_form = get_form_values(form_elm, json);
        general_click(target_id, $F(url_elm), json_form, insertion);
    } catch (ex) {
        alert(this_module + ": " + ex);
    }
    return (false);
}

// ---------------------------------------------------------------------------
// Initialise the Google Maps API
// ---------------------------------------------------------------------------
var geocoder = null;
var _found = false;
var _street, _suburb, _town, _postal_code, _country, _was_trying;
var _previous_address = "";

// ---------------------------------------------------------------------------
// Show the address on the map
// ---------------------------------------------------------------------------
function try_google_maps(target_id, notification_id) {
    var full_address = "";

    var target_elm = $(target_id);
    target_id = target_elm.id;
    var guid = get_guid_from_target_id(target_id);

    if (_was_trying == 1) {
        // Try it with everything we have
        if (_street.length > 0) {
            if (full_address.length > 0) full_address += ', ';
            full_address += _street;
        }
        if (_suburb.length > 0) {
            if (full_address.length > 0) full_address += ', ';
            full_address += _suburb;
        }
        if (_town.length > 0) {
            if (full_address.length > 0) full_address += ', ';
            full_address += _town;
        }
        if (_postal_code.length > 0) {
            if (full_address.length > 0) full_address += ', ';
            full_address += _postal_code;
        }
        if (_country.length > 0) {
            if (full_address.length > 0) full_address += ', ';
            full_address += _country;
        }
    }

    if (_was_trying == 2) {
        // Try it without the suburb
        if (_street.length > 0 && _town.length > 0 && _postal_code.length > 0 && _country.length > 0) {
            full_address = _street + ', ' + _town + ', ' + _postal_code + ', ' + _country;
        } else {
            _was_trying++;
        }
    }

    if (_was_trying == 3) {
        // Try it without the postal code
        if (_street.length > 0 && _suburb.length > 0 && _town.length > 0 && _country.length > 0) {
            full_address = _street + ', ' + _suburb + ', ' + _town + ', ' + _country;
        } else {
            _was_trying++;
        }
    }

    if (_was_trying == 4) {
        // Try it without the postal code and the suburb
        if (_street.length > 0 && _town.length > 0 && _country.length > 0) {
            full_address = _street + ', ' + _town + ', ' + _country;
        } else {
            _was_trying++;
        }
    }

    if ((full_address.length > 0) && (full_address != _previous_address)) {
        if (notification_id != null) {
            notification_id = $(notification_id);
            var notification_text = notification_id.innerHTML;
            if (notification_text.length > 0) {
                notification_text += "<br />";
                notification_id.update(notification_text);
            }
        }

        var geocoder = new google.maps.Geocoder();
        geocoder.geocode({ address: full_address }, function (results, status) {
            if (status == google.maps.GeocoderStatus.OK && results.length) {
                if (results.length != 1) {
                    var message = "<span style='color:#484;'>Google found [" + results.length + "] results for [" + full_address + "]<br />";
                    for (index = 0; index < results.length; index++) {
                        message += "<b>" + results[index].formatted_address + "</b><br />";
                    }
                    message += "</span>";
                } else {
                    message = "<span style='color:#000;'><b>" + results[0].formatted_address + "</b></span>";
                }
                if (notification_id != null) {
                    notification_id.update(notification_id.innerHTML + message);
                }
                // You should always check that a result was returned, as it is
                // possible to return an empty results object.
                var myOptions = {
                    zoom: 16,
                    center: results[0].geometry.location,
                    mapTypeId: google.maps.MapTypeId.ROADMAP,
                    navigationControl: true,
                    navigationControlOptions: { style: google.maps.NavigationControlStyle.ZOOM_PAN, position: google.maps.ControlPosition.TOP_LEFT },
                    scaleControl: true,
                    scaleControlOptions: { position: google.maps.ControlPosition.TOP }
                };
                var map = new google.maps.Map(target_elm, myOptions);
                var marker = new google.maps.Marker({
                    position: results[0].geometry.location,
                    map: map
                });
                _found = true;
            } else {
                message = "<span style='color:#844;'>" + _was_trying + ": Geocode of [" + full_address + "] failed:\n";
                if (status == "ZERO_RESULTS") {
                    message += "Google could not find this address.";
                } else {
                    message += status;
                }
                message += "</span>";
                if (notification_id != null) {
                    notification_id.update(notification_id.innerHTML + message);
                } else {
                    alert(message);
                }
                if (_was_trying < 4) {
                    _was_trying++;
                    _previous_address = full_address;
                    try_google_maps(target_id, notification_id);
                } else {
                    target_elm.setStyle({ display: 'none' });
                }
            }
        });
    } else {
        if (_was_trying < 4) {
            _was_trying++;
            _previous_address = full_address;
            try_google_maps(target_id, notification_id);
        } else {
            target_elm.setStyle({ display: 'none' });
        }
    }
}

// ---------------------------------------------------------------------------
// Show the address on the map
// ---------------------------------------------------------------------------
function showAddress(target_id, street, suburb, town, postal_code, country, notification_id, count) {
    if (window.google) {
        if (window.google.maps) {
            if (window.google.maps.Geocoder) {
                // Try the most complete address first
                _was_trying = 1;
                _found = false;
                _previous_address = "";
                _street = street;
                _suburb = suburb;
                _town = town;
                _postal_code = postal_code;
                _country = country;
                try_google_maps(target_id, notification_id);
                // The rest of the search combinations will be tried when Google maps answers (this process is ASYNCHRONOUS)
                return;
            }
        }
    }
    if (count == null) {
        count = 0;
        //alert("showAddress: 'waiting for google script to load.");
    }
    if (count < 25) {
        showAddress.delay(0.5, target_id, street, suburb, town, postal_code, country, notification_id, count + 1);
    } else {
        alert("showAddress: gave up after " + count + " tries.");
    }
}

// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// Run form initialisation code
// ---------------------------------------------------------------------------
function initialise_form() {
    if (window.form_initialiser) {
        debug.write_line('form_initialiser exists - calling it now ...');
        form_initialiser();
        form_initialiser = null;
    } else {
        debug.write_line('form_initialiser does NOT exist.');
    }
}

// ---------------------------------------------------------------------------
// Set input value, if the element exists
// If [value] is not supplied, the input is cleared
// ---------------------------------------------------------------------------
function clear_input(elm_id, value) {
    var this_module = "clear_input()";
    try {
        if (value == null) value = "";
        var elm = $(elm_id);
        if (elm != null) {
            elm.value = value;
        }
    } catch (ex) {
        alert(this_module + ": " + ex);
    }
}

// ---------------------------------------------------------------------------
// Class for debug functions
// ---------------------------------------------------------------------------
var DiagDebug = Class.create(
    {
        last_clear: null,

        // ---------------------------------------------------------------------------
        // Initialise the object
        // ---------------------------------------------------------------------------
        initialize: function () {
        },

        // ---------------------------------------------------------------------------
        // Initialise the object
        // ---------------------------------------------------------------------------
        debug_info_container: function () {
            return ($('debug_info'));
        },

        // ---------------------------------------------------------------------------
        // Clear the debug area
        // ---------------------------------------------------------------------------
        clear: function () {
            var d = this.debug_info_container();
            if (d != null) {
                var end = new Date().getTime();
                var time = end - this.last_clear;
                if (time > 2000) {
                    d.innerHTML = "";
                    this.last_clear = end;
                }
            }
        },

        // ---------------------------------------------------------------------------
        // Write a variable
        // ---------------------------------------------------------------------------
        htmlEncode: function (s) {
            return s.replace(/&(?!\w+([;\s]|$))/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
        },

        // ---------------------------------------------------------------------------
        // Write a line of text
        // ---------------------------------------------------------------------------
        write_line: function (text) {
            var d = this.debug_info_container();
            if (text == null) text = '';
            if (d != null) {
                d.innerHTML += this.htmlEncode(text) + "<br />";
            }
        },

        // ---------------------------------------------------------------------------
        // Write a variable
        // ---------------------------------------------------------------------------
        write_variable: function (text, value) {
            var d = this.debug_info_container();
            if (d != null) {
                if (value == null) { value = "(null)"; }
                d.innerHTML += this.htmlEncode(text) + ": " + this.htmlEncode(value.toString()) + "<br />";
            }
        }

    }
);

var debug = new DiagDebug();
debug.last_clear = new Date().getTime();

