
//var RTEFields = new Array();

function get_html_translation_table (table, quote_style) {
    // Returns the internal translation table used by htmlspecialchars and htmlentities  
    // 
    // version: 1103.1210
    // discuss at: http://phpjs.org/functions/get_html_translation_table
    // +   original by: Philip Peterson
    // +    revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   bugfixed by: noname
    // +   bugfixed by: Alex
    // +   bugfixed by: Marco
    // +   bugfixed by: madipta
    // +   improved by: KELAN
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Brett Zamir (http://brett-zamir.me)
    // +      input by: Frank Forte
    // +   bugfixed by: T.Wild
    // +      input by: Ratheous
    // %          note: It has been decided that we're not going to add global
    // %          note: dependencies to php.js, meaning the constants are not
    // %          note: real constants, but strings instead. Integers are also supported if someone
    // %          note: chooses to create the constants themselves.
    // *     example 1: get_html_translation_table('HTML_SPECIALCHARS');
    // *     returns 1: {'"': '&quot;', '&': '&amp;', '<': '&lt;', '>': '&gt;'}
    var entities = {},
        hash_map = {},
        decimal = 0,
        symbol = '';
    var constMappingTable = {},
        constMappingQuoteStyle = {};
    var useTable = {},
        useQuoteStyle = {};
 
    // Translate arguments
    constMappingTable[0] = 'HTML_SPECIALCHARS';
    constMappingTable[1] = 'HTML_ENTITIES';
    constMappingQuoteStyle[0] = 'ENT_NOQUOTES';
    constMappingQuoteStyle[2] = 'ENT_COMPAT';
    constMappingQuoteStyle[3] = 'ENT_QUOTES';
 
    useTable = !isNaN(table) ? constMappingTable[table] : table ? table.toUpperCase() : 'HTML_SPECIALCHARS';
    useQuoteStyle = !isNaN(quote_style) ? constMappingQuoteStyle[quote_style] : quote_style ? quote_style.toUpperCase() : 'ENT_COMPAT';
 
    if (useTable !== 'HTML_SPECIALCHARS' && useTable !== 'HTML_ENTITIES') {
        throw new Error("Table: " + useTable + ' not supported');
        // return false;
    }
 
    entities['38'] = '&amp;';
    if (useTable === 'HTML_ENTITIES') {
        entities['160'] = '&nbsp;';
        entities['161'] = '&iexcl;';
        entities['162'] = '&cent;';
        entities['163'] = '&pound;';
        entities['164'] = '&curren;';
        entities['165'] = '&yen;';
        entities['166'] = '&brvbar;';
        entities['167'] = '&sect;';
        entities['168'] = '&uml;';
        entities['169'] = '&copy;';
        entities['170'] = '&ordf;';
        entities['171'] = '&laquo;';
        entities['172'] = '&not;';
        entities['173'] = '&shy;';
        entities['174'] = '&reg;';
        entities['175'] = '&macr;';
        entities['176'] = '&deg;';
        entities['177'] = '&plusmn;';
        entities['178'] = '&sup2;';
        entities['179'] = '&sup3;';
        entities['180'] = '&acute;';
        entities['181'] = '&micro;';
        entities['182'] = '&para;';
        entities['183'] = '&middot;';
        entities['184'] = '&cedil;';
        entities['185'] = '&sup1;';
        entities['186'] = '&ordm;';
        entities['187'] = '&raquo;';
        entities['188'] = '&frac14;';
        entities['189'] = '&frac12;';
        entities['190'] = '&frac34;';
        entities['191'] = '&iquest;';
        entities['192'] = '&Agrave;';
        entities['193'] = '&Aacute;';
        entities['194'] = '&Acirc;';
        entities['195'] = '&Atilde;';
        entities['196'] = '&Auml;';
        entities['197'] = '&Aring;';
        entities['198'] = '&AElig;';
        entities['199'] = '&Ccedil;';
        entities['200'] = '&Egrave;';
        entities['201'] = '&Eacute;';
        entities['202'] = '&Ecirc;';
        entities['203'] = '&Euml;';
        entities['204'] = '&Igrave;';
        entities['205'] = '&Iacute;';
        entities['206'] = '&Icirc;';
        entities['207'] = '&Iuml;';
        entities['208'] = '&ETH;';
        entities['209'] = '&Ntilde;';
        entities['210'] = '&Ograve;';
        entities['211'] = '&Oacute;';
        entities['212'] = '&Ocirc;';
        entities['213'] = '&Otilde;';
        entities['214'] = '&Ouml;';
        entities['215'] = '&times;';
        entities['216'] = '&Oslash;';
        entities['217'] = '&Ugrave;';
        entities['218'] = '&Uacute;';
        entities['219'] = '&Ucirc;';
        entities['220'] = '&Uuml;';
        entities['221'] = '&Yacute;';
        entities['222'] = '&THORN;';
        entities['223'] = '&szlig;';
        entities['224'] = '&agrave;';
        entities['225'] = '&aacute;';
        entities['226'] = '&acirc;';
        entities['227'] = '&atilde;';
        entities['228'] = '&auml;';
        entities['229'] = '&aring;';
        entities['230'] = '&aelig;';
        entities['231'] = '&ccedil;';
        entities['232'] = '&egrave;';
        entities['233'] = '&eacute;';
        entities['234'] = '&ecirc;';
        entities['235'] = '&euml;';
        entities['236'] = '&igrave;';
        entities['237'] = '&iacute;';
        entities['238'] = '&icirc;';
        entities['239'] = '&iuml;';
        entities['240'] = '&eth;';
        entities['241'] = '&ntilde;';
        entities['242'] = '&ograve;';
        entities['243'] = '&oacute;';
        entities['244'] = '&ocirc;';
        entities['245'] = '&otilde;';
        entities['246'] = '&ouml;';
        entities['247'] = '&divide;';
        entities['248'] = '&oslash;';
        entities['249'] = '&ugrave;';
        entities['250'] = '&uacute;';
        entities['251'] = '&ucirc;';
        entities['252'] = '&uuml;';
        entities['253'] = '&yacute;';
        entities['254'] = '&thorn;';
        entities['255'] = '&yuml;';
    }
 
    if (useQuoteStyle !== 'ENT_NOQUOTES') {
        entities['34'] = '&quot;';
    }
    if (useQuoteStyle === 'ENT_QUOTES') {
        entities['39'] = '&#39;';
    }
    entities['60'] = '&lt;';
    entities['62'] = '&gt;';
 
 
    // ascii decimals to real symbols
    for (decimal in entities) {
        symbol = String.fromCharCode(decimal);
        hash_map[symbol] = entities[decimal];
    }
 
    return hash_map;
}

function htmlentities (string, quote_style) {
    // Convert all applicable characters to HTML entities  
    // 
    // version: 1103.1210
    // discuss at: http://phpjs.org/functions/htmlentities
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +    revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: nobbler
    // +    tweaked by: Jack
    // +   bugfixed by: Onno Marsman
    // +    revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +    bugfixed by: Brett Zamir (http://brett-zamir.me)
    // +      input by: Ratheous
    // -    depends on: get_html_translation_table
    // *     example 1: htmlentities('Kevin & van Zonneveld');
    // *     returns 1: 'Kevin &amp; van Zonneveld'
    // *     example 2: htmlentities("foo'bar","ENT_QUOTES");
    // *     returns 2: 'foo&#039;bar'
    var hash_map = {},
        symbol = '',
        tmp_str = '',
        entity = '';
    tmp_str = string.toString();
 
    if (false === (hash_map = this.get_html_translation_table('HTML_ENTITIES', quote_style))) {
        return false;
    }
    hash_map["'"] = '&#039;';
    for (symbol in hash_map) {
        entity = hash_map[symbol];
        tmp_str = tmp_str.split(symbol).join(entity);
    }
 
    return tmp_str;
}

function html_entity_decode (string, quote_style) {
    // Convert all HTML entities to their applicable characters  
    // 
    // version: 1103.1210
    // discuss at: http://phpjs.org/functions/html_entity_decode
    // +   original by: john (http://www.jd-tech.net)
    // +      input by: ger
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +    revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   bugfixed by: Onno Marsman
    // +   improved by: marc andreu
    // +    revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: Ratheous
    // +   bugfixed by: Brett Zamir (http://brett-zamir.me)
    // +      input by: Nick Kolosov (http://sammy.ru)
    // +   bugfixed by: Fox
    // -    depends on: get_html_translation_table
    // *     example 1: html_entity_decode('Kevin &amp; van Zonneveld');
    // *     returns 1: 'Kevin & van Zonneveld'
    // *     example 2: html_entity_decode('&amp;lt;');
    // *     returns 2: '&lt;'
    var hash_map = {},
        symbol = '',
        tmp_str = '',
        entity = '';
    tmp_str = string.toString();
 
    if (false === (hash_map = this.get_html_translation_table('HTML_ENTITIES', quote_style))) {
        return false;
    }
 
    // fix &amp; problem
    // http://phpjs.org/functions/get_html_translation_table:416#comment_97660
    delete(hash_map['&']);
    hash_map['&'] = '&amp;';
 
    for (symbol in hash_map) {
        entity = hash_map[symbol];
        tmp_str = tmp_str.split(entity).join(symbol);
    }
    tmp_str = tmp_str.split('&#039;').join("'");
 
    return tmp_str;
}




var tabSwitchBlock = false;
function switchTab(tabID) {
    if (!document.getElementById(tabID)) {
        alert("Invalid tab: " + tabID);
        return;
    }
    
    if (tabSwitchBlock) {
        // RTE's are being rendered, have to wait to avoid a ffx exception
        return;
    }
    
    // Un-highlight all tabs and hide all content
    var tabContainer = document.getElementById('tabButtonContainer');
    for (i = 0; i < tabContainer.childNodes.length; i++) {
        // Get the parts of the id (in the form class_tabID)
        if (!tabContainer.childNodes[i].id) continue; // wrong kind of node

        var parts = tabContainer.childNodes[i].id.split("_");

        if (parts[1] == tabID) {
            // Make this active
            tabContainer.childNodes[i].className = parts[0] + "Act"; // append Act to the classname
        } else {
            // Make this inactive
            tabContainer.childNodes[i].className = parts[0];
        }
    }
    
    // Hide all section elements
    var formbox = document.getElementById("tabbox");
    for (i = 0; i < formbox.childNodes.length; i++) {
        if (!formbox.childNodes[i].style) continue; // wrong kind of element
        formbox.childNodes[i].style.display = "none";
    }
    
    // Add the section we want
    document.getElementById(tabID).style.display = "block";
    
    // Enable any un-enabled RTE fields (this has to be done while they're visible to get the
    // size right)
    tabSwitchBlock = true;
    var textAreas = document.getElementById(tabID).getElementsByTagName('textarea');
    for (i = 0; i < textAreas.length; i++) {
        if (textAreas[i].className == "formRTETextArea") {
            if (!textAreas[i].rteEnabled) {
                var rte = new HTMLArea(textAreas[i].id);
                rte.config.toolbar = new Array(
                    new Array('bold', 'italic', 'insertunorderedlist')
                );
                rte.config.statusBar = false;
                textAreas[i].rteEnabled = true;
                
                rte.generate();
                
                textAreas[i].rteObj = rte;
            }
        }
    }
    tabSwitchBlock = false;
}

function removeTabFor(id) {
    // Hide the left, middle and right of that tab
    var tabBar = document.getElementById("tabButtonContainer");
    tabBar.removeChild(document.getElementById("buttonLeft_" + id));
    tabBar.removeChild(document.getElementById("buttonMid_" + id));
    tabBar.removeChild(document.getElementById("buttonRight_" + id));
}

function setTitleBar(text) {
    var titlebar = document.getElementById("titleBar").firstChild;
    if (titlebar.nodeValue != text) {
        titlebar.nodeValue = text;
    }
}

// Pass in an img element to have popup-able
function enablePopup(element, filename) {
    element.currentImage = "uploads/tx_remalsdb/" + filename;
    addEvent(element, 'click', function(event) {
        imageWindow(event.target.currentImage);
        }, false);
    element.style.cursor = "pointer";
}

function imageWindow(url) {
    window.open(url, 'imagepopup');
}

/* Worker functions */

// gFF = getFormField
function gFF(field) {
    if (!document.getElementById(field)) alert("Invalid form field: " + field);
    return document.getElementById(field);
}

function emptyNode(id) {
    // empties out all children of a given node
    var parent = document.getElementById(id);
    try {
        while (true) {
            parent.removeChild(parent.firstChild);
        }
    } catch (e) {}
}

// Validation functions

function markGood(field) {
    // Remove  any red border around a field
    gFF(field).style.borderColor = '';
}

function markBad(field) {
    gFF(field).style.borderColor = "red";
}

function hideElement(id) {
    if (gFF(id).style.display != "none") {
        gFF(id).style.display = "none";
    }
}

function showElement(id) {
    if (gFF(id).style.display != "block") {
        gFF(id).style.display = "block";
    }
}

function toggleElement(id, idPlus, idMinus) {
  if (gFF(id).style.display == "none") {
	gFF(id).style.display = "block";
  } else {
	gFF(id).style.display = "none";
  }
  if (gFF(idPlus).style.display == "none") {
	gFF(idPlus).style.display = "inline";
  } else {
	gFF(idPlus).style.display = "none";
  }
  if (gFF(idMinus).style.display == "none") {
	gFF(idMinus).style.display = "inline";
  } else {
	gFF(idMinus).style.display = "none";
  }
}

function isNumeric(value, allowDecimal) {
    var regexp = null;
    if (allowDecimal) {
        regexp = new RegExp(/^[0-9]*(\.\d+)?$/);
    } else {
        regexp = new RegExp(/^[0-9]*$/);
    }

    if (regexp.exec(value)) {
        return true; // nothing illegal found
    } else {
        return false; // some illegal string
    }
}

function processTerm(id) {
    if (!isNumeric(gFF(id + "INPUT").value, false)) {
        markBad(id + "INPUT");
        return false;
    } else {
        gFF(id).value = (gFF(id + "INPUT").value) * (gFF(id + "SELECT").options[gFF(id + "SELECT").selectedIndex].value);
        markGood(id + "INPUT");
        return true;
    }
}

function processDateChange(calendar, date) {
    if (calendar.dateClicked) {
        calendar.belongsTo.value = Date.parse(calendar.date.toLocaleDateString()) / 10000;
        // alert(calendar.belongsTo.value)
   	}
}

function selectInSelectBox(selectid, selectedvalue) {
    if (!selectedvalue) return; // just default to whatever
    var selectBox = gFF(selectid);
    for (i = 0; i < selectBox.options.length; i++) {
        if (selectBox.options[i].value == selectedvalue) {
            selectBox.options[i].selected = true;
            return;
        }
    }
    //alert("Error: Option '" + selectedvalue + "' in '" + selectid + "' is not available");
}

function getSelectedValue(id) {
    if (gFF(id).selectedIndex == -1) {
        return null;
    }
    return gFF(id).options[gFF(id).selectedIndex].value;   
}

// gfv = get field value
function gfv(id) {
    // Works out how to deal with the field based on the class
    var field = gFF(id);
    switch(field.className) {
        case 'formTextField': return htmlentities(field.value, 'ENT_QUOTES');
        case 'formTextHidden': return field.value;
        case 'formPasswordField': return field.value;
        case 'formTextArea': return htmlentities(field.value, 'ENT_QUOTES');
        case 'formRTETextArea':
            if (field.rteEnabled) {
                // Is a special RTE object
                return htmlentities(field.rteObj.getHTML(), 'ENT_QUOTES');
            } else {
                // Is just a textarea
                return htmlentities(field.value, 'ENT_QUOTES');
            }
        case 'formSelect': return getSelectedValue(id);
        case 'formTermSelect': return field.value;
        case 'formDateSelect': return field.value;
        case 'formCheckBoxList':
            // Iterate through all children producing a comma-separated list of selected values
            var selectedValues = new Array();
            var subnodes = field.childNodes;
            for (i = 0; i < subnodes.length; i++) {
                if (subnodes[i].className == 'formCheckBox') {
                    if (subnodes[i].checked) {
                        selectedValues.push(subnodes[i].value);
                    }
                }
            }
            return selectedValues.join(',');
        case 'formCheckBox': return field.checked; break;
        default: alert("Don't know how to deal with this class: " + field.className + "\nOn formid " + id);
    }
}

// sfv = set form value
function sfv(id, value) {
    if (typeof value == "undefined") {
        alert("Warning! sfv() asked to set " + id + " to undefined");
        return;
    }
    var field = gFF(id);
    switch(field.className) {
        case 'formTextField': field.value = html_entity_decode(value, 'ENT_QUOTES'); break;
        case 'formTextHidden': field.value = value; break;
        case 'formPasswordField': field.value = value; break;
        case 'formTextArea': field.value = html_entity_decode(value, 'ENT_QUOTES'); break;
        case 'formRTETextArea': field.value = html_entity_decode(value, 'ENT_QUOTES'); break
        case 'formSelect': selectInSelectBox(id, value); break;
        case 'formTermSelect': setTermSelect(id, value); break;
        case 'formDateSelect': 
            
            /*
            // NO idea why "date.setTime(value * 1000);"????
            var date = new Date();
            date.setTime(value * 1000); //convert to milliseconds from seconds (epoch)
            field.calendarObj.setDate(date);
            break;*/
            
        case 'listingCompletedDate':
           	field.calendarObj.setDate(value);
        	break;
        case 'formCheckBoxList':
            if (!value) return; // new listing
            var selectedValues = value.split(',');
            var subnodes = field.childNodes;
            for (i = 0; i < subnodes.length; i++) {
                if (subnodes[i].className == 'formCheckBox') {
                    for (j= 0; j < selectedValues.length; j++) {
                        if (selectedValues[j] == subnodes[i].value) {
                            subnodes[i].checked = true;
                            break;
                        }
                    }
                }
            }
            break;
        case 'formCheckBox': field.checked = value; break;
        default: alert("Don't know how to deal with this class: " + field.className);
    }
}

function setTermSelect(baseid, months) {
    gFF(baseid).value = months;
    gFF(baseid + "INPUT").value = months;
    selectInSelectBox(baseid + "SELECT", "1"); // select months
}



/*** XMLHttpRequest wrapper for multiple simultaneous requests ***/
var requestObjects = Array();
function RemoteRequest(type, action, uid, decodeReturn) {

    // Method declarations
    this.sendAndLoad = function(sendObj) {
        if (!this.callback) {
            alert("Attempted sendAndLoad with no callback registered!");
            return;
        }
        
        // Serialise the object
	var serialised = JSON.stringify(sendObj);
        var serialised = "data=" + URLEncode(serialised);
        this.reqObj.open("POST", this.url, true);
        this.reqObj.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
        /* Where (in theory) the submission to RealENZ should take place. */
        this.reqObj.send(serialised);
    }
    this.get = function() {
        if (!this.callback) {
            alert("Attempted get with no callback registered!");
            return;
        } 
        this.reqObj.open("GET", this.url, true);
        this.reqObj.send("");
    }
    
    
    // Constructor stuff
    this.type = type;
    this.action = action;
    this.uid = uid;
    
    if (window.XMLHttpRequest) {
        try {
            this.reqObj = new XMLHttpRequest();
        } catch(e) {
            this.reqObj = null;
        }
    } else if (window.ActiveXObject) {
        // try IE
        try {
            this.reqObj = new ActiveXObject("Microsoft.XMLHTTP");
        } catch(e) {
            this.reqObj = null;
        }
    } else {
        this.reqObj = null;
    }
    if (this.reqObj == null) {
        alert("Failed to initialise XMLHttpRequest!");
        return;
    }
    
    this.reqObj.onreadystatechange = requestStateChange;
    this.callback = null;
    this.decodeReturnedObject = decodeReturn;
    if (window.location.href.indexOf("static") != -1) {
        var path = "../../../";
    } else {
        var path = "";
    }
    this.url = path + "index.php?responder&tx_remalsinterface_pi1[type]=" + this.type + "&tx_remalsinterface_pi1[action]=" + this.action + (this.uid ? "&tx_remalsinterface_pi1[uid]=" + this.uid : "");

    // Push ourselves on to the array to prevent us being destructed
    requestObjects.push(this);
    //alert("new intiialise " + action);
}

function requestStateChange() {

    // Loop through pending requests looking for ready ones
    for (i = 0; i < requestObjects.length; i++) {
        if (requestObjects[i].reqObj.readyState == 4) {
            // Remove the object from the waiting array
            var cur = requestObjects[i];
            requestObjects.splice(i, 1);
            //alert("found ready\n" + cur.reqObj.responseText);
            
            if (cur.decodeReturnedObject) {
                // Attempt to deserialise the JSON object
                try {
                    var responseObj = JSON.parse(cur.reqObj.responseText);
                    cur.callback(responseObj);
                } catch (e) {
                    alert("Error! " + e);
                    //alert("Could not parse returning object: " + e);
                    //popUpProperties(e);
                    //alert(cur.reqObj.responseText);
                    return;
                }
            } else {
                // Return the response text plain
                cur.callback(cur.reqObj.responseText);
            }
            
            // Start the loop again
            i = -1;
        }
    }
}


function setBusyCursor() {
    document.getElementsByTagName('body')[0].style.cursor = 'wait';
}

function clearBusyCursor() {
    document.getElementsByTagName('body')[0].style.cursor = 'default';
}

function getVar(name) {
    if (!piVars) {
        alert("piVars not available!");
        return null;
    } else if (typeof piVars[name] == "undefined") {
        return null;
    } else {
        return piVars[name];
    }
}


/** SEARCH **/

function SearchObject(type) {
    this.type = type;
    this.requestObject = Object();
    this.requestObject.pageNum = 1;
    this.callback = function(responseObj) {
        emptyNode(this.type + "SearchResultsContainer");
        
        var resultsDiv = document.getElementById(this.type + "SearchResultsContainer");
        if (responseObj.numresults == 0) {
            resultsDiv.innerHTML = '<span class="searchNoResults">Sorry, there were no results for your search</span>';
            clearBusyCursor();
			return;
        }
        var results = responseObj.results;
        for (i = 0; i < results.length; i++) {
            var resultContainer = document.createElement("div");
            resultContainer.className = "searchTeaserContainer " + "teaser-" + results[i].type;
            resultContainer.reqObj = this;
            resultContainer.style.cursor = 'pointer';
            // pass the click handler function down to the div so we can access it in the onClick handler
            resultContainer.clickHandler = this.clickHandler;
            resultContainer.uid = results[i].uid;
            resultContainer.remalsType = results[i].type;
            addEvent(resultContainer, "click", function(evt) {
                // evt is the item that's clicked on, not necessarily the container div
                if (evt.target) {
                    var curNode = evt.target; // good browsers
                } else if (evt.srcElement) {
                    var curNode = evt.srcElement; // IE
                } else {
                    alert("Can't find target for click");
                }

                while (typeof curNode.uid == 'undefined') {
                    curNode = curNode.parentNode;
                }
                curNode.clickHandler(curNode.uid);
            }, true);
            
            resultContainer.innerHTML = results[i].html;
            
            resultsDiv.appendChild(resultContainer);
            searchTeaserCallback(resultContainer);
        }
        
        // Append the navigation
        if (responseObj.navhtml.length > 0) {
            var resultsNav = document.createElement('div');
            resultsNav.className = this.type + 'SearchResultsNav';
            resultsNav.innerHTML = responseObj.navhtml;
            resultsDiv.appendChild(resultsNav);
        }
        setContentHeight(); // resize the background (unrelated function to remals)
        clearBusyCursor();
    }
    this.doSearch = function() {
        // (called on clicking search button)
        this.fieldCopy();
        this.requestObject.pageNum = 1;
        this.doSend();
    }
    this.doSend = function() {
        setBusyCursor();
        var rr = new RemoteRequest(this.type, "search", null, true);
        rr.callback = this.callback;
        // register our click handler with the request object so it can pass it on
        rr.clickHandler = this.resultClicked;
        rr.sendAndLoad(this.requestObject);
		var resultsDiv = document.getElementById(this.type + "SearchResultsContainer");
        resultsDiv.innerHTML = '<div align="center" style="font-size: 2em">Searching...</div>';
    }
    this.doSearchAlternate = function() {
        // (called on clicking search button)
        this.fieldCopy();
        this.requestObject.pageNum = 1;
        this.doSendAlternate();
    }
    this.doSendAlternate = function() {
        setBusyCursor();
        var rr = new RemoteRequest(this.type, "searchAlternate", null, true);
        rr.callback = this.callback;
        // register our click handler with the request object so it can pass it on
        rr.clickHandler = this.resultClicked;
        rr.sendAndLoad(this.requestObject);
		var resultsDiv = document.getElementById(this.type + "SearchResultsContainer");
        resultsDiv.innerHTML = '<div align="center" style="font-size: 2em">Searching...</div>';
    }
    this.resultClicked = function(uid) {
        alert("Clicked on " + uid + " in prefix " + this.fieldPrefix + ", no defined handler");
    }
    this.fieldCopy = function() {
        alert("On submit method not defined yet");
    }
    
    this.nextSearchResultPage = function() {
        this.requestObject.pageNum++;
        this.doSend();
    }
    this.previousSearchResultPage = function() {
        this.requestObject.pageNum--;
        this.doSend();
    }
    this.goToSearchResultPage = function(num) {
        this.requestObject.pageNum = num;
        this.doSend();
    }
    
    this.nextSearchResultPageAlternate = function() {
        this.requestObject.pageNum++;
        this.doSendAlternate();
    }
    this.previousSearchResultPageAlternate = function() {
        this.requestObject.pageNum--;
        this.doSendAlternate();
    }
    this.goToSearchResultPageAlternate = function(num) {
        this.requestObject.pageNum = num;
        this.doSendAlternate();
    }
}

function searchTeaserCallback(teaser) {
    // intended to be overridden
}

function doFinish(uid) {
    // Redirect to whereever we were asked to go
    var nextType = getVar('nextType');
    var nextAction = getVar('nextAction');
    var nextGoTo = getVar('nextGoTo');
    
    var nextType2 = getVar('nextType2');
    var nextAction2 = getVar('nextAction2');
    var nextGoTo2 = getVar('nextGoTo2');
    
    if (nextType2 && nextAction2) {
        var nextPart = "&tx_remalsinterface_pi1[nextType]=" + nextType2 + "&tx_remalsinterface_pi1[nextAction]=" + nextAction2 + ((nextGoTo2) ? "&tx_remalsinterface_pi1[nextGoTo]=" + nextGoTo2 : "");
    } else {
        var nextPart = "";
    }
    
    if (!nextType || !nextAction) {
        alert("Cannot complete - No nextType or nextAction specified");
        return;
    }
    
    var url = "index.php?responder&tx_remalsinterface_pi1[type]=" + nextType + "&tx_remalsinterface_pi1[action]=" + nextAction + "&tx_remalsinterface_pi1[uid]=" + uid + ((nextGoTo) ? ("&tx_remalsinterface_pi1[goTo]=" + nextGoTo) : "") + nextPart;
    
	if (nextAction == 'delete') {
		if (!confirm("Are you sure you want to delete this " + nextType + "?")) return;
	}
	location.href = url;
}

function csvContains(list, uid) {
    if (list == null) return false;
    var parts = list.split(',');
    for (i = 0; i < parts.length; i++) {
        if (parts[i] == uid) return true;
    }
    return false;
}

function csvAdd(list, uid) {
    if (!list || list.length == 0) list = "" + uid; // cast to string
    else list = list + "," + uid;
    return list;
}

function csvDelete(list, uid) {
    var splitted = list.split(',');
    var output = new Array();
    for (i = 0; i < splitted.length; i++) {
        if (splitted[i] != uid) output.push(splitted[i]);
    }
    return output.join(',');
}

/****** SUPPORT FUNCTIONS (not by me) ******/

function addEvent(obj, evType, fn, useCapture){
  if (obj.addEventListener){
    obj.addEventListener(evType, fn, useCapture);
    return true;
  } else if (obj.attachEvent){
    var r = obj.attachEvent("on"+evType, fn);
    return r;
  } else {
    alert("Handler could not be attached");
  }
}

function popUpProperties(inobj) {
	op = window.open();
	op.document.open('text/plain');
	for (objprop in inobj) {
	op.document.write(objprop + ' => ' + inobj[objprop] + '\n');
	}
	op.document.close();
}

/* URL encode script */

// ====================================================================
//       URLEncode and URLDecode functions
//
// Copyright Albion Research Ltd. 2002
// http://www.albionresearch.com/
//
// You may copy these functions providing that 
// (a) you leave this copyright notice intact, and 
// (b) if you use these functions on a publicly accessible
//     web site you include a credit somewhere on the web site 
//     with a link back to http://www.albionresarch.com/
//
// If you find or fix any bugs, please let us know at albionresearch.com
//
// SpecialThanks to Neelesh Thakur for being the first to
// report a bug in URLDecode() - now fixed 2003-02-19.
// ====================================================================
function URLEncode(plaintext)
{
	// The Javascript escape and unescape functions do not correspond
	// with what browsers actually do...
	var SAFECHARS = "0123456789" +					// Numeric
					"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +	// Alphabetic
					"abcdefghijklmnopqrstuvwxyz" +
					"-_.!~*'()";					// RFC2396 Mark characters
	var HEX = "0123456789ABCDEF";

	var encoded = "";
	for (var i = 0; i < plaintext.length; i++ ) {
		var ch = plaintext.charAt(i);
	    if (ch == " ") {
		    encoded += "+";				// x-www-urlencoded, rather than %20
		} else if (SAFECHARS.indexOf(ch) != -1) {
		    encoded += ch;
		} else {
		    var charCode = ch.charCodeAt(0);
			if (charCode > 255) {
			    alert( "Unicode Character '" 
                        + ch 
                        + "' cannot be encoded using standard URL encoding.\n" +
				          "(URL encoding only supports 8-bit characters.)\n" +
						  "A space (+) will be substituted." );
				encoded += "+";
			} else {
				encoded += "%";
				encoded += HEX.charAt((charCode >> 4) & 0xF);
				encoded += HEX.charAt(charCode & 0xF);
			}
		}
	} // for

	return encoded;
};


/*
Copyright (c) 2005 JSON.org

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The Software shall be used for Good, not Evil.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

Array.prototype.______array = '______array';

var JSON = {
    org: 'http://www.JSON.org',
    copyright: '(c)2005 JSON.org',
    license: 'http://www.crockford.com/JSON/license.html',

    stringify: function (arg) {
        var c, i, l, s = '', v;

        switch (typeof arg) {
        case 'object':
            if (arg) {
                if (arg.______array == '______array') {
                    for (i = 0; i < arg.length; ++i) {
                        v = this.stringify(arg[i]);
                        if (s) {
                            s += ',';
                        }
                        s += v;
                    }
                    return '[' + s + ']';
                } else if (typeof arg.toString != 'undefined') {
                    for (i in arg) {
                        v = arg[i];
                        if (typeof v != 'undefined' && typeof v != 'function') {
                            v = this.stringify(v);
                            if (s) {
                                s += ',';
                            }
                            s += this.stringify(i) + ':' + v;
                        }
                    }
                    return '{' + s + '}';
                }
            }
            return 'null';
        case 'number':
            return isFinite(arg) ? String(arg) : 'null';
        case 'string':
            l = arg.length;
            s = '"';
            for (i = 0; i < l; i += 1) {
                c = arg.charAt(i);
                if (c >= ' ') {
                    if (c == '\\' || c == '"') {
                        s += '\\';
                    }
                    s += c;
                } else {
                    switch (c) {
                        case '\b':
                            s += '\\b';
                            break;
                        case '\f':
                            s += '\\f';
                            break;
                        case '\n':
                            s += '\\n';
                            break;
                        case '\r':
                            s += '\\r';
                            break;
                        case '\t':
                            s += '\\t';
                            break;
                        default:
                            c = c.charCodeAt();
                            s += '\\u00' + Math.floor(c / 16).toString(16) +
                                (c % 16).toString(16);
                    }
                }
            }
            return s + '"';
        case 'boolean':
            return String(arg);
        default:
            return 'null';
        }
    },
    parse: function (text) {
        var at = 0;
        var ch = ' ';

        function error(m) {
            throw {
                name: 'JSONError',
                message: m,
                at: at - 1,
                text: text
            };
        }

        function next() {
            ch = text.charAt(at);
            at += 1;
            return ch;
        }

        function white() {
            while (ch !== '' && ch <= ' ') {
                next();
            }
        }

        function str() {
            var i, s = '', t, u;

            if (ch == '"') {
outer:          while (next()) {
                    if (ch == '"') {
                        next();
                        return s;
                    } else if (ch == '\\') {
                        switch (next()) {
                        case 'b':
                            s += '\b';
                            break;
                        case 'f':
                            s += '\f';
                            break;
                        case 'n':
                            s += '\n';
                            break;
                        case 'r':
                            s += '\r';
                            break;
                        case 't':
                            s += '\t';
                            break;
                        case 'u':
                            u = 0;
                            for (i = 0; i < 4; i += 1) {
                                t = parseInt(next(), 16);
                                if (!isFinite(t)) {
                                    break outer;
                                }
                                u = u * 16 + t;
                            }
                            s += String.fromCharCode(u);
                            break;
                        default:
                            s += ch;
                        }
                    } else {
                        s += ch;
                    }
                }
            }
            error("Bad string");
        }

        function arr() {
            var a = [];

            if (ch == '[') {
                next();
                white();
                if (ch == ']') {
                    next();
                    return a;
                }
                while (ch) {
                    a.push(val());
                    white();
                    if (ch == ']') {
                        next();
                        return a;
                    } else if (ch != ',') {
                        break;
                    }
                    next();
                    white();
                }
            }
            error("Bad array");
        }

        function obj() {
            var k, o = {};

            if (ch == '{') {
                next();
                white();
                if (ch == '}') {
                    next();
                    return o;
                }
                while (ch) {
                    k = str();
                    white();
                    if (ch != ':') {
                        break;
                    }
                    next();
                    o[k] = val();
                    white();
                    if (ch == '}') {
                        next();
                        return o;
                    } else if (ch != ',') {
                        break;
                    }
                    next();
                    white();
                }
            }
            error("Bad object");
        }

        function num() {
            var n = '', v;
            if (ch == '-') {
                n = '-';
                next();
            }
            while (ch >= '0' && ch <= '9') {
                n += ch;
                next();
            }
            if (ch == '.') {
                n += '.';
                while (next() && ch >= '0' && ch <= '9') {
                    n += ch;
                }
            }
            if (ch == 'e' || ch == 'E') {
                n += 'e';
                next();
                if (ch == '-' || ch == '+') {
                    n += ch;
                    next();
                }
                while (ch >= '0' && ch <= '9') {
                    n += ch;
                    next();
                }
            }
            v = +n;
            if (!isFinite(v)) {
                error("Bad number");
            } else {
                return v;
            }
        }

        function word() {
            switch (ch) {
                case 't':
                    if (next() == 'r' && next() == 'u' && next() == 'e') {
                        next();
                        return true;
                    }
                    break;
                case 'f':
                    if (next() == 'a' && next() == 'l' && next() == 's' &&
                            next() == 'e') {
                        next();
                        return false;
                    }
                    break;
                case 'n':
                    if (next() == 'u' && next() == 'l' && next() == 'l') {
                        next();
                        return null;
                    }
                    break;
            }
            error("Syntax error");
        }

        function val() {
            white();
            switch (ch) {
                case '{':
                    return obj();
                case '[':
                    return arr();
                case '"':
                    return str();
                case '-':
                    return num();
                default:
                    return ch >= '0' && ch <= '9' ? num() : word();
            }
        }

        return val();
    }
};


function blurLink(foo) {
}

