
/* Global variables holding the error message and header.
 */
var errorMsg;
var errorHeader = "";


/* Language to use. Default is English
 */
var language  = "nl";

var cssURL    = "";
var errWindow = null;


var dict = new Array();

dict["en"] = new Array(5);
dict["nl"] = new Array(5);

dict["en"]["header"]   = "This form was not submitted because of the errors listed.";
dict["en"]["required"] = " is required ";
dict["en"]["requires"] = " requires ";
dict["en"]["nomatch"]  = " doesn't match ";
dict["en"]["close"]    = "Close";

dict["nl"]["header"]     = "Formulier niet verstuurd vanwege de volgende fouten:";
dict["nl"]["required"]   = " is verplicht ";
dict["nl"]["requires"]   = " veronderstelt ";
dict["nl"]["nomatch"]    = " voldoet niet aan ";
dict["nl"]["close"]      = "Sluiten";

/**
 * Verify the complete form for all values.
 * Synopsis: verify(form)
 */
 
function verify(form) {

    errorMsg = "<UL>\n";

    var formOK   = true;

    for (var i= 0; i < form.length; i++) {

	var elt = form.elements[i];

	verifyField(elt) || (formOK = false);
    }

    errorMsg += "</UL>\n";

    if (! formOK) {
	showErrWindow(errorMsg);
    }

    return formOK;
}


/**
 * Verification dispatcher
 */
function verifyField(elt) {

    /* Now do some element specific thingies
     */
    switch(elt.type) {
	
    case "text":
	return verifyText(elt);
    case "password":
	return verifyText(elt);
    case "hidden":
	return verifyText(elt);
    case "textarea":
	return verifyText(elt);
    case "radio":
	return  verifyRadio(elt);
    case "checkbox":
	return  verifyCheckbox(elt);
    case "select-one":
	return verifySelect(elt);
    case "select-multiple":
	return verifySelect(elt);
    default:
	return true;
    }
}


/**
 * Verification of a select element. The element is ok-ed when the 
 * value of the option is not empty.
 */
function verifySelect(elt) {
    
    var required = elt.getAttribute("required");

    if (required != null && isEmpty(elt.value)) {
	errorMsg += "<LI>" + elt.name + dict[language]["required"] + "</LI>\n";
	return false;
    }

    return true;
}


/**
 * Dispatch to verifyRadio.
 */
function verifyCheckbox(elt) {
    return verifyRadio(elt);
}


/**
 * Verification of a radio checks for dependent field, and checks those accordingly.
 */
function verifyRadio(elt) {

    var ok = true;

    var requires = elt.getAttribute("requires");
    var check    = elt.getAttribute("check");
    var required = elt.getAttribute("required");

    if (elt.checked && check != null) {

	var err = eval(check + "()");

	if (err != 0) {
	    errorMsg += "<LI>" + elt.name + ": " + err + "</LI>\n";
	    ok = false;
	}
    }

    if (requires != null && elt.checked) {
	
	var requiredFields = requires.split(',');
	
	for (var j= 0; j < requiredFields.length; j++) {

	    if (isEmpty(elt.form.elements[requiredFields[j]].value)) {

		errorMsg += "<LI>" + elt.name + dict[language]["requires"] + requiredFields[j] + "</LI>\n";
		ok = false;
	    }
	}
    }

    // Now check if the radio group itself is required
    if (required != null) {

	var noneOK = true;

	for (var i= 0; i < elt.form.elements[elt.name].length; i++) {
	    if (elt.form.elements[elt.name][i].checked) {
		noneOK = false;
		break;
	    }
	}

	if (noneOK) {
	    errorMsg += "<LI>" + elt.name + dict[language]["required"] + "</LI>\n";
	}

	ok = ! noneOK;
    }
    
    return ok;
}


/**
 * Verify a text field. The field is OK if one of the following conditions is true:
 * 1. it's not required and empty;
 * 2. it's not empty and doesn't have a mask specified;
 * 3. it's not empty and satisfies it's specified mask.
 */
function verifyText(elt) {

    var ok = true;

    var check    = elt.getAttribute("check");
    var mask     = elt.getAttribute("mask");
    var required = elt.getAttribute("required");

    if (! isEmpty(elt.value) && mask != null && ! verifyMask(elt.value, mask)) {
	ok = false;
	errorMsg += "<LI>" + elt.name + ": " + elt.value + dict[language]["nomatch"] + mask + "</LI>\n";
    }

    if (! isEmpty(elt.value) && check != null) {

	var err = eval(check + "('" + elt.value + "')");

	if (err != 0) {
	    errorMsg += "<LI>" + elt.name + ": " + err + "</LI>\n";
	    ok = false;
	}
    }
    
    if (required != null && isEmpty(elt.value)) {
	ok = false;
	errorMsg += "<LI>" + elt.name + dict[language]["required"] + "</LI>\n";
    }

    return ok;
}


/**
 * The text element may have a mask specified. This should take the form of a
 * regular expression. If the element doesn't match the mask, false is returned.
 */
function verifyMask(value, mask) {

    exp = new RegExp(mask);
    return exp.test(value);
}


/**
 * Determine whether a value is empty. This is true when all characters in the
 * value are one of "\n, \t, ' '".
 */
function isEmpty(value) {
    
    for (var i= 0; i < value.length; i++) {
	var c = value.charAt(i);

	if ((c != ' ') && (c != '\n') && (c != '\t')) return false;
    }

    return true;
}


function requiresHandler(e) {

    var form;

    if (e.target != null) {
	form = e.target.form;
    }
    else {
	form = e.srcElement.form;
    }


    /* Find all fields that require other fields
     */
    for (var i= 0; i < form.length; i++) {

	var elt = form.elements[i];
	var requires          = elt.getAttribute("requires");
	var requiresHandler   = elt.getAttribute("requireshandler");
	var unrequiresHandler = elt.getAttribute("unrequireshandler");

	if (elt.checked && requires != null) {

	    if (requiresHandler != null) {
		eval(requiresHandler);;
	    }
	}
	else if (requires != null) {

	    if (unrequiresHandler != null) {
		eval(unrequiresHandler);;
	    }
	}
    }

    e.cancelBubble= true;
}



/**
 * Popup the error window if it's not already there, and write the errors.
 */ 
function showErrWindow(message) {
	alert('Formulier is niet volledig ingevuld!\nAlle velden met een * zijn verplicht');
	return false;
	/*
    if ( (errWindow != null && errWindow.closed) || (errWindow == null ) ) {
	errWindow = open("", "errors", "width=400,height=500,resizeable=no,menubar=no,locationbar=no,statusbar=no");
    }
    else {
	errWindow.focus();
    }

    errWindow.document.open();
    errWindow.document.write("<HTML>\n<HEAD>\n");

    if (cssURL != "") {
    	errWindow.document.write("<LINK REL=\"stylesheet\" TYPE=\"text/css\" HREF=\"" + cssURL + "\">\n");
    }

    errWindow.document.write("</HEAD>\n<BODY CLASS=\"vfErrMsg\">\n");

    if (errorHeader != "") {
    	errWindow.document.write("<P>" + errorHeader+ "</P>");
    }
    else {
    	errWindow.document.write("<P>" + dict[language]["header"] + "</P>");
    }

    errWindow.document.write("<P>" + message + "</P>");
    errWindow.document.write("<TABLE><TR><TD><FORM>\n");
    errWindow.document.write("<INPUT TYPE=\"button\" NAME=\"\" VALUE=\"" + dict[language]["close"] + "\" ONCLICK=\"window.close();\">");
    errWindow.document.write("</TR></TD></TABLE></FORM>");
    errWindow.document.write("</BODY>\n</HTML>\n");
    errWindow.document.close();
    */
}


/*******************************************************************************
 *
 * BEGIN User functions to customize behaviour.
 *
 ******************************************************************************/


/**
 * Create an event listener for the form, that listens to changes, and applies the
 * required class to new required fields.
 */
function setRequiresHandler(form) {

    for (var i = 0; i < form.length; i++) {
	form.elements[i].onclick = requiresHandler;
    }
}


/**
 * Set you own error header
 */
function setErrorHeader(header) {
    errorHeader = header;
}


/**
 * Set the stylesheet to use for the error window.
 */
function setStylesheet(url) {
    cssURL = url;
}


/**
 * Set the language to use
 */
function setLanguage(lang) {

    if (dict[lang] != null) {
	language = lang;
    }
}

