/**
 * $Header: /home/mpdavig/proj/repository/html/home/work/company/ccib/library/lib/mpdAjax.js,v 1.8 2008/12/02 05:02:56 mpdavig Exp $
 *
 * COPYRIGHT:
 *
 * This software is Copyright (c) 2006-2008 Marc Davignon
 *                         <mpdavig@users.sourceforge.net>
 *
 * LICENSE:
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of Version 2 of the GNU General Public License as published by the
 * Free Software Foundation.
 */

/*
   Code to handle a single AJAX request in Mozilla
*/

/*
function handleHttpResponse(elementid) {
    if (http.readyState == 4) {
	results = http.responseText;
	document.getElementById(elementid).innerHTML = results;
    }
}


function getMoreFormValues(params, elementid) {
    var retrieveValue = document.getElementById("retrieveHTML").value;
    http.open("GET", "?" + params + "retrieve=" + escape(retrieveValue), true);
    http.onreadystatechange = function (){ handleHttpResponse(elementid) };
    http.send(null);
}

function getHTTPObject() {
    var xmlhttp;
    xmlhttp = new XMLHttpRequest();
    return xmlhttp;
}

var http = getHTTPObject()
*/


/*
   Code to handle multiple simultaneous AJAX requests in Mozilla and IE
   borrowed from http://www.drakware.com/?e=3
*/

var xmlreqs = new Array();


/**
 * Create a cross browser AJAX request object
 */
function CXMLReq(freed) {
    this.freed = freed;
    this.xmlhttp = false;
    if (window.XMLHttpRequest) {
	this.xmlhttp = new XMLHttpRequest();
    } else if (window.ActiveXObject) {
	this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
} // function CXMLReq(freed)


/**
 * OBSOLETE: Replaced with getFormValues
 */
function getMoreFormValues(params, elementid) {
    var pos = -1;
    for (var i=0; i<xmlreqs.length; i++) {
	if (xmlreqs[i].freed == 1) { pos = i; break; }
    }
    if (pos == -1) { pos = xmlreqs.length; xmlreqs[pos] = new CXMLReq(1); }
    if (xmlreqs[pos].xmlhttp) {
	xmlreqs[pos].freed = 0;
	var retrieveValue = document.getElementById('retrieveHTML').value;
	if (retrieveValue) {
	    xmlreqs[pos].xmlhttp.open("GET", "?" + params + "retrieve=" + escape(retrieveValue), true);
	    xmlreqs[pos].xmlhttp.onreadystatechange = function() {
		if (typeof(xmlhttpChange) != 'undefined') { xmlhttpChange(pos, elementid); }
	    }
	    if (window.XMLHttpRequest) {
		xmlreqs[pos].xmlhttp.send(null);
	    } else if (window.ActiveXObject) {
		xmlreqs[pos].xmlhttp.send();
	    }
	}
    }
} // function getMoreFormValues(params, elementid)


/**
 * OBSOLETE: Not used
 */
function dodacheck(val) {
    var mikExp = /[$\\@\\\#%\^\&\*\(\)\[\]\+\_\{\}\`\~\=\|]/;
    var strPass = val.value;
    var strLength = strPass.length;
    var lchar = val.value.charAt((strLength) - 1);
    if(lchar.search(mikExp) != -1) {
	var tst = val.value.substring(0, (strLength) - 1);
	val.value = tst;
    }
} // function dodacheck(val)


/**
 * This is the function directly called by scripts. Not the easiest function
 * to use since new Ajax features are always added on.
 *
 * @param string params Get values to be directly passed to the PHP script
 * @param string elementid Matching element id to pass the returned innerHTML data to
 * @param string arguments[2] optional Element id to retrieve a numerical value from, typically to generate a total to update elementid with
 * @param bool arguments[3] optional Set to true to use synchronous instead of asynchronous communication
 * @param string arguments[4] optional comma separated element id(s) to retrieve $limitArray data from
 * @param string arguments[5] optional element id to use instead of the default 'retrieveHTML'
 */
function getFormValues(params, elementid) {
    var pos = -1;
    for (var i=0; i<xmlreqs.length; i++) {
	if (xmlreqs[i].freed == 1) { pos = i; break; }
    }
    if (pos == -1) { pos = xmlreqs.length; xmlreqs[pos] = new CXMLReq(1); }
    if (xmlreqs[pos].xmlhttp) {
	xmlreqs[pos].freed = 0;
	var retrieveValue = "";
	var valueIdValue = "";

        /* Element id "retrieveHTML" usually contains the data type, sometimes
           this may be passed with "params" instead so make sure it exists
           first */
        if (document.getElementById('retrieveHTML')) {
            var retrieveElement = document.getElementById('retrieveHTML');
            retrieveValue = escape(retrieveElement.value);
	    //alert(retrieveValue);
	    // If "retrieveElement" is a span tag the value is usually hidden above
	    if (retrieveValue == 'undefined' && retrieveElement.nodeName.toLowerCase() == "span") {
		var hiddenElement = findPreviousSibling(retrieveElement);
		if (hiddenElement.nodeName.toLowerCase() == "input" && hiddenElement.type.toLowerCase() == "hidden") {
		    retrieveValue = escape(hiddenElement.value);
		}
	    }
        }

	if (arguments[2]) {
	    valueIdValue = document.getElementById(arguments[2]).value;
            /* strip non-digit characters, ^ means negative matching */
	    //document.getElementById(arguments[2]).value = document.getElementById(arguments[2]).value.replace(/[^\d]/g, '');
	}
        var asynchronous = (arguments[3]) ? false : true;

	var limitByValues = "";
	if (arguments[4]) {
	    var limitValues = arguments[4].split(',');
	    for (var i=0; i < limitValues.length; i++) {
		currentSource = limitValues[i].split('=');
		limitByValues += '&limitBy' + currentSource[1] + '=' + document.getElementById(currentSource[0] + 'Value').value;
	    }
	}

	if (arguments[5]) {
	    retrieveValue = escape(document.getElementById(arguments[5]).value);
	}

        // To change between synchronous (false) and asynchronous (true) change the 3rd parameter for .open
	xmlreqs[pos].xmlhttp.open("POST", "mpdAjax.php?retrieve=" + retrieveValue + "&" + params + "value=" + valueIdValue + "&elementid=" + elementid + limitByValues, asynchronous);

	xmlreqs[pos].xmlhttp.onreadystatechange = function() {
	    if (typeof(xmlhttpChange) != 'undefined') { xmlhttpChange(pos, elementid); }
	}
	if (window.XMLHttpRequest) {
	    xmlreqs[pos].xmlhttp.send(null);
	} else if (window.ActiveXObject) {
	    xmlreqs[pos].xmlhttp.send();
	}
    }
} // function getFormValues(params, elementid)


/**
 * Used? See library.xsl
 * Populates a form based on one tables data into another.
 */
function changeElementById(elementIdName, elementUniqueID, elementValue, elementDataType) {
    //alert("elementId: " + elementIdName + " elementUniqueID: " + elementUniqueID);
    if (document.getElementById(elementIdName)) {
	var retrieveElement = document.getElementById(elementIdName);
	if (retrieveElement.nodeName.toLowerCase() == "select") {
	    // Handle records with "$values"
	    //alert(retrieveElement.options.length);
	    for (i=0; i <= retrieveElement.options.length - 1; i++) {
		if (retrieveElement.options[i].value.match(elementUniqueID)) {
		    retrieveElement.value = retrieveElement.options[i].value;
		    // run the tag onchange event
		    runListenerEvents(retrieveElement);
		}
	    }
	} else if (retrieveElement.nodeName.toLowerCase() == "span") {
	    // Handle "view_only" records
	    var dbValue = elementValue + '>=<id=>' + elementUniqueID + '>=<xml=>' + elementDataType;
	    retrieveElement.innerHTML = elementValue;
	    retrieveElement.value = dbValue;
	    // run the tag onchange event
	    runListenerEvents(retrieveElement);
	    //alert('findPreviousSibling: ' + retrieveElement.id); // Testing

	    var hiddenElement = findPreviousSibling(retrieveElement);
	    //alert(hiddenElement.type);
	    if (hiddenElement.nodeName.toLowerCase() == "input" && hiddenElement.type.toLowerCase() == "hidden") {
		hiddenElement.value = dbValue;
	    }
	}
	scrollToPosition();
    }
} // function changeElementById(elementIdName, elementUniqueID, elementValue, elementDataType)


/**
 * Firefox, and most other browsers, will treat empty white-spaces or new lines
 * as text nodes, Internet Explorer will not.
 */
function findPreviousSibling(n) {
    x=n.previousSibling;
    while (x && x.nodeType != 1) {
      x=x.previousSibling;
    }
    return x;
} // function findPreviousSibling(n)


/**
 * Firefox, and most other browsers, will treat empty white-spaces or new lines
 * as text nodes, Internet Explorer will not.
 */
function findNextSibling(n) {
    x=n.nextSibling;
    while (x && x.nodeType != 1) {
	x=x.nextSibling;
    }
    return x;
} // function findNextSibling(n)


/**
 * Used to run onload AJAX requests
 */
function runRetrieveElement() {
    var retrieveElement = document.getElementById('retrieveHTML');
    runListenerEvents(retrieveElement);
} // function runRetrieveElement()


/**
 * Run listener events
 */
function runListenerEvents(n) {
    // run the input tag onchange event
    var attr = n.getAttribute('onchange');
    typeof attr == 'function' ? attr() : eval(attr);
} // function runListenerEvents(n)


/**
 * OBSOLETE: Handle AJAX post requests
 */
function xmlreqPOST(url,data) {
    var pos = -1;
    for (var i=0; i<xmlreqs.length; i++) {
	if (xmlreqs[i].freed == 1) { pos = i; break; }
    }
    if (pos == -1) { pos = xmlreqs.length; xmlreqs[pos] = new CXMLReq(1); }
    if (xmlreqs[pos].xmlhttp) {
	xmlreqs[pos].freed = 0;
	xmlreqs[pos].xmlhttp.open("POST",url,true);
	xmlreqs[pos].xmlhttp.onreadystatechange = function() {
	    if (typeof(xmlhttpChange) != 'undefined') { xmlhttpChange(pos); }
	}
	xmlreqs[pos].xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
	xmlreqs[pos].xmlhttp.send(data);
    }
} // function xmlreqPOST(url,data)


/**
 * Change HTML elements based on AJAX results
 */
function xmlhttpChange(pos, elementid) {
    //alert(elementid); // Testing
    if (typeof(xmlreqs[pos]) != 'undefined' && xmlreqs[pos].freed == 0 && xmlreqs[pos].xmlhttp.readyState == 4) {
	if (xmlreqs[pos].xmlhttp.status == 200 || xmlreqs[pos].xmlhttp.status == 304) {
	    var respText = xmlreqs[pos].xmlhttp.responseText;
	    runDirect = new RegExp("(updateDateInput)");
	    if ( runDirect.test(respText) )
		eval(respText);
	    else {
		/*handle_response(xmlreqs[pos].xmlhttp.responseXML);*/
		/* NEW: Always write to the parent? */
		// WARNING: Hack alert, should be fixed?
		//alert('Ajax updating id='+elementid); // Testing
		try {
		    opener.document.getElementById(elementid).innerHTML = respText;
		} catch(error) {
		    if (document.getElementById(elementid)) document.getElementById(elementid).innerHTML = respText;
		}
            }
	} else {
	    handle_error();
	}
	xmlreqs[pos].freed = 1;
    }
} // function xmlhttpChange(pos, elementid)


//////////////////////////////////////////////////
// QUERY BUILDER SPECIFIC FUNCTIONS //////////////
//////////////////////////////////////////////////
/**
 * Query Builder values each consist of 4 parts "Field", "Op", "Value" and "Attr"
 * Clear all Add Values
 */
function clearQueryBuilderAddValues(fieldcsv) {
    var fields = fieldcsv.split(',');
    for(var i=0; i < fields.length; i++) {
	// Reset the form values
	document.getElementById(fields[i]+'Value').value = '';
	if (document.getElementById(fields[i]+'ValueInput')) document.getElementById(fields[i]+'ValueInput').value = '';
	if (document.getElementById(fields[i]+'ValueDate')) document.getElementById(fields[i]+'ValueDate').value = '';

	if (document.getElementById('ignoremonths'+fields[i]+'Value')) document.getElementById('ignoremonths'+fields[i]+'Value').value = '';
	if (document.getElementById('ignoredays'+fields[i]+'Value')) document.getElementById('ignoredays'+fields[i]+'Value').value = '';
	if (document.getElementById('ignoreyears'+fields[i]+'Value')) document.getElementById('ignoreyears'+fields[i]+'Value').value = '';
    }
} // function clearQueryBuilderAddValues(fieldcsv)


/**
 * Query Builder values each consist of 4 parts "Field", "Op", "Value" and "Attr"
 */
function getQueryBuilderAddValue(postFix, keyValue) {
    var qbAgg,qbField,qbOp,qbValue;
    var aggs = document.getElementsByName('aggregator');
    for (var i=0; i < aggs.length; i++) {
	if (aggs[i].checked) qbAgg = aggs[i].value;
    }

    qbField = document.getElementById(keyValue+'Field'+postFix).value;
    qbOp = document.getElementById(keyValue+'Op'+postFix).value;
    // Be sure to only use the value (no attributes)
    qbValue = document.getElementById(keyValue+'Value'+postFix).value.split('>=<');
    qbValue = qbValue[0];
    qbAttr = document.getElementById(keyValue+'Attr'+postFix).value;

    // Add each query criteria
    if (qbField && qbOp && qbValue) {
	//alert(qbAgg+' '+qbField+' '+qbOp+' '+qbValue); // Testing
	if (qbOp == 'LIKE' || qbOp == 'NOT LIKE') qbValue = "%"+qbValue+"%";
	if (qbOp == '=' && qbAttr == 'values') { qbOp = 'LIKE'; qbValue = qbValue+"%"; }
	if (qbOp == '!=' && qbAttr == 'values') { qbOp = 'NOT LIKE'; qbValue = qbValue+"%"; }

	populateQueryContentList(qbAgg, qbField, qbOp, qbValue);
    }
} // function getQueryBuilderAddValue(postFix, keyValue)


/**
 * Store two versions of the query, one in a textfield, the other a multiple select list
 * Both should be able to be modified and update each other.
 */
function populateQueryContentList(qbAgg, qbField, qbOp, qbValue) {
    var qbQueryContentsList = document.getElementById('queryContentsList');

    // Escape problem characters with cookies (;), HTML (<>) and SQL (&quot;).
    // "_" matches one character, "%" zero or more
    qbValue = qbValue.replace(/(;|<|>)/g, "_");
    qbValue = qbValue.replace(/(")/g, "%");

    // Handle the very first element
    if (qbQueryContentsList.options.length == 0) {
	qbQuery = "( "+qbField+" "+qbOp+" '"+qbValue+"' )";
	//alert("'"+qbQuery+"'"); // Testing
	qbQueryContentsList.options[qbQueryContentsList.options.length] = new Option(addIndent(qbQuery), qbQuery, false, false);
    } else {
	// Store the current select list values
	var storageArray = [];
        for(var i=0; i < qbQueryContentsList.options.length; i++)  storageArray[i] = qbQueryContentsList.options[i].value;

	var qbi=0;
	var qbiprior=0;
	var match=0;


	// Add to the beggining of a group
	/*
        for (var i=0; i < storageArray.length; i++) {
	    findFieldRegExp = new RegExp("(\\w*)\\s*\\(\\s*"+qbField);
	    if ( findFieldRegExp.test(storageArray[i]) ) {
		qbQuery = RegExp.$1+" ( "+qbField+" "+qbOp+" '"+qbValue+"'";
		qbQueryContentsList.options[qbi] = new Option(addIndent(qbQuery), qbQuery, false, false);

		storageArray[i] = storageArray[i].replace(/\w*\s*\(/, "");
		storageArray[i] = qbAgg+" "+storageArray[i];
		qbi++;
		match=1;
	    }

	    qbQueryContentsList.options[qbi] = new Option(addIndent(storageArray[i]), storageArray[i], false, false);
	    qbi++;
        } // for (var i=0; i < storageArray.length; i++)
	*/

	// Add to the end of a group
        for (var i=0; i < storageArray.length; i++) {
	    findFieldRegExp = new RegExp("(\\w*)\\s*\\(*\\s*"+qbField+".*\\)$");
	    if ( findFieldRegExp.test(storageArray[i]) ) {
		qbi++;

		qbQuery = qbAgg+" "+qbField+" "+qbOp+" '"+qbValue+"' )";
		qbQueryContentsList.options[qbi] = new Option(addIndent(qbQuery), qbQuery, false, false);

		storageArray[i] = storageArray[i].replace(/\s*\)$/, "");
		match=1;
	    }

	    qbQueryContentsList.options[qbiprior] = new Option(addIndent(storageArray[i]), storageArray[i], false, false);

	    qbi++;
	    qbiprior=qbi;
        } // for (var i=0; i < storageArray.length; i++)


	if (match == 0) {
	    qbQuery = qbAgg+" ( "+qbField+" "+qbOp+" '"+qbValue+"' )";
	    qbQueryContentsList.options[qbQueryContentsList.options.length] = new Option(addIndent(qbQuery), qbQuery, false, false);
	}
    }
    populateQueryContent();
} // populateQueryContentList(qbAgg, qbField, qbOp, qbValue)


/**
 * Auto indent groups of objects
 */
function addIndent(qbQueryString) {
    // Keep displayed select values to 45 characters
    if ( qbQueryString.length > 45 ) {
	var reg = /(%*'\s*\)*)$/;
	reg.exec(qbQueryString);
	qbQueryString = qbQueryString.substr(0,45) + "..." + RegExp.$1;
    }

    var qbIndent = "";
    if (! qbQueryString.match(/^\w*\s*\(/)) qbIndent = "\u00a0\u00a0";
    return qbIndent+qbQueryString;
} // function addIndent(qbQueryString)


/**
 * Changes selected objects from AND to OR or vise versa
 */
function changeSelectedAndOr() {
    var qbQueryContentsList = document.getElementById('queryContentsList');
    for (var i=0; i < qbQueryContentsList.options.length; i++) {
	if (qbQueryContentsList.options[i].selected) {
	    qbQuery = qbQueryContentsList.options[i].value;

	    if (qbQueryContentsList.options[i].value.match(/^AND/)) {
		qbQuery = qbQueryContentsList.options[i].value.replace(/^AND/, "OR");
	    }
	    if (qbQueryContentsList.options[i].value.match(/^OR/)) {
		qbQuery = qbQueryContentsList.options[i].value.replace(/^OR/, "AND");
	    }

	    // Do the swap
	    // new Option([text], [value], [defaultSelected], [selected])
	    qbQueryContentsList.options[i] = new Option(addIndent(qbQuery), qbQuery, false, true);
	}
    }
    populateQueryContent();
} // function changeSelectedAndOr()


/**
 * Handle removing selected objects with parentheses support
 */
function clearSelectedValues() {
    var qbQueryContentsList = document.getElementById('queryContentsList');
    var qbQuery = "";
    var qbSelected = false;
    var qbi = 0;
    for (var i=0; i < qbQueryContentsList.options.length; i++) {
	if (qbQueryContentsList.options[i].selected) {
	    // Completely surrounded by parentheses can be safely deleted
	    if ( qbQueryContentsList.options[i].value.match(/^\w*\s*\(.*\)$/) ) {
		// Be sure to clear the Aggregator of the next object
		if (i == 0 && qbQueryContentsList.options.length > 1) {
		    qbi = i+1;
		    qbQuery = qbQueryContentsList.options[qbi].value;
		    qbSelected = qbQueryContentsList.options[qbi].selected;
		    qbQuery = qbQuery.replace(/^\w*\s*/, "");
		    qbQueryContentsList.options[qbi] = new Option(addIndent(qbQuery), qbQuery, false, qbSelected);
		}
		qbQueryContentsList.remove(i);
	    // Handle opening but no ending
	    } else if ( qbQueryContentsList.options[i].value.match(/^\w*\s*\(.*$/) ) {
		qbi = i+1;
		qbQuery = qbQueryContentsList.options[qbi].value;
		qbSelected = qbQueryContentsList.options[qbi].selected;
		if (i == 0) qbQuery = qbQuery.replace(/^(\w*\s*)/, "( ");
		else qbQuery = qbQuery.replace(/^(\w*\s*)/, "$1( ");
		qbQueryContentsList.options[qbi] = new Option(addIndent(qbQuery), qbQuery, false, qbSelected);
		qbQueryContentsList.remove(i);
	    // Handle ending but no opening
	    } else if ( qbQueryContentsList.options[i].value.match(/^\w*\s*.*\)$/) ) {
		qbi = i-1;
		qbQuery = qbQueryContentsList.options[qbi].value+" )";
		qbSelected = qbQueryContentsList.options[qbi].selected;
		qbQueryContentsList.options[qbi] = new Option(addIndent(qbQuery), qbQuery, false, qbSelected);
		qbQueryContentsList.remove(i);
	    // Handle no opening or ending
	    } else {
		qbQueryContentsList.remove(i);
	    }

	    clearSelectedValues();
	    break;
	}
    }
    populateQueryContent();
} // function clearSelectedValues()


/**
 * Rebuild the textarea content from the select list
 */
function populateQueryContent() {
    var qbQueryContents = document.getElementById('queryContents');
    var qbQueryContentsList = document.getElementById('queryContentsList');

    qbQueryContents.value = "";
    for (var i=0; i < qbQueryContentsList.options.length; i++) {
        // Old method of writing to a textarea field
        if (qbQueryContents.value == '') qbQueryContents.value = qbQueryContentsList.options[i].value;
        else qbQueryContents.value = qbQueryContents.value+" "+qbQueryContentsList.options[i].value;
    }
    createCookie('queryContents'+document.getElementsByName('xml')[0].value,qbQueryContents.value,1825);
} // function populateQueryContent()


/**
 * Add a single select list object from the textarea
 */
function populateQueryContentListFromText(qbQuery) {
    qbQuery = qbQuery.replace(/^\s+|\s+$/g, '');
    var qbQueryContentsList = document.getElementById('queryContentsList');
    qbQueryContentsList.options[qbQueryContentsList.options.length] = new Option(addIndent(qbQuery), qbQuery, false, false);
} // function populateQueryContentListFromText(qbAgg, qbQuery)


/**
 * Port the textarea query to the select list
 */
function queryContentTextToList() {
    var qbAgg = "";
    var qbQuery = "";

    var qbQueryContentsList = document.getElementById('queryContentsList');
    for (var i = qbQueryContentsList.options.length - 1; i >= 0; i--) {
	qbQueryContentsList.remove(i);
    }

    if (! document.getElementById('queryContents').value) return;

    var queryWords = document.getElementById('queryContents').value.split(' ');
    for(var i=0; i < queryWords.length; i++) {
	switch(queryWords[i]) {
	    case "AND":
		populateQueryContentListFromText(qbAgg+" "+qbQuery);
		qbAgg = "AND";
		qbQuery = "";
		break;
	    case "OR":
		populateQueryContentListFromText(qbAgg+" "+qbQuery);
		qbAgg = "OR";
		qbQuery = "";
		break;
	    default:
		if (qbQuery) qbQuery = qbQuery+" "+queryWords[i];
		else qbQuery = queryWords[i];
	}
    }

    populateQueryContentListFromText(qbAgg+" "+qbQuery);

    var qbQueryContents = document.getElementById('queryContents');
    createCookie('queryContents'+document.getElementsByName('xml')[0].value,qbQueryContents.value,1825);
} // function queryContentTextToList()


/**
 * Query Builder values each consist of 4 parts "Field", "Op", "Value" and "Attr"
 * Obsolete!
 */
function getQueryBuilderAddValues(fieldcsv) {
    var fields = fieldcsv.split(',');
    var qbAgg,qbField,qbOp,qbValue;
    var aggs = document.getElementsByName('aggregator');
    var qbQueryContents = document.getElementById('queryContents');
    for (var i=0; i < aggs.length; i++) {
	if (aggs[i].checked) qbAgg = aggs[i].value;
    }
    for(var i=0; i < fields.length; i++) {
	qbField = document.getElementById(fields[i]+'Field').value;
	qbOp = document.getElementById(fields[i]+'Op').value;
	qbValue = document.getElementById(fields[i]+'Value').value;
	qbAttr = document.getElementById(fields[i]+'Attr').value;

	// Add each query criteria
	if (qbField && qbOp && qbValue) {
	    //alert(qbAgg+' '+qbField+' '+qbOp+' '+qbValue); // Testing
	    if (qbOp == 'LIKE' || qbOp == 'NOT LIKE') qbValue = "%"+qbValue+"%";
	    if (qbOp == '=' && qbAttr == 'values') { qbOp = 'LIKE'; qbValue = qbValue+"%"; }
	    if (qbOp == '!=' && qbAttr == 'values') { qbOp = 'NOT LIKE'; qbValue = qbValue+"%"; }
	    // No '\n' is allowed in the query since this breaks cookie storage
	    if (qbQueryContents.value == '') qbQueryContents.value = qbField+" "+qbOp+" '"+qbValue+"'";
	    else qbQueryContents.value = qbQueryContents.value+" "+qbAgg+" "+qbField+" "+qbOp+" '"+qbValue+"'";
	}

	// Reset the form values
	document.getElementById(fields[i]+'Value').value = '';
	if (document.getElementById('ignoremonths'+fields[i]+'Value')) document.getElementById('ignoremonths'+fields[i]+'Value').value = '';
	if (document.getElementById('ignoredays'+fields[i]+'Value')) document.getElementById('ignoredays'+fields[i]+'Value').value = '';
	if (document.getElementById('ignoreyears'+fields[i]+'Value')) document.getElementById('ignoreyears'+fields[i]+'Value').value = '';
    }
    createCookie('queryContents'+document.getElementsByName('xml')[0].value,qbQueryContents.value,1825);
} // function getQueryBuilderAddValues(fieldcsv)


/**
 * Generic function for clearing cookies and HTML elements by ID
 */
function clearFieldValue(elementId) {
    eraseCookie(elementId+document.getElementsByName('xml')[0].value);
    document.getElementById(elementId).value = '';
    queryContentTextToList();
} // function clearFieldValue(elementId)


/**
 * Run the Query Builder created query
 */
function runQuery() {
    createCookie('queryContents'+document.getElementsByName('xml')[0].value,document.getElementById('queryContents').value,1825);
    submitform('searchform', 'Run Query', 'custom_query', document.getElementById('queryContents').value, 'custom_query_table', document.getElementsByName('xml')[0].value);
} // function runQuery()


/**
 * Load the selected/saved Query Builder query
 */
function loadQuery() {
    if (document.getElementById('queryLoad').value) {
        document.getElementById('queryContents').value = document.getElementById('queryLoad').value;
        createCookie('queryContents'+document.getElementsByName('xml')[0].value,document.getElementById('queryContents').value,1825);
    }
} // function runQuery()


/**
 * Unhide Query Builder and restore the last created query
 */
function useQueryBuilder() {
    //alert('queryContents'+document.getElementsByName('xml')[0].value); // Testing
    if (readCookie('queryContents'+document.getElementsByName('xml')[0].value)) document.getElementById('queryContents').value = readCookie('queryContents'+document.getElementsByName('xml')[0].value);
    queryContentTextToList();
    useSection('querybuilder');
}


/**
 * Hide Query Builder
 */
function closeQueryBuilder() { closeSection('querybuilder'); }
//////////////////////////////////////////////////
// END OF QUERY BUILDER SPECIFIC FUNCTIONS ///////
//////////////////////////////////////////////////
