/**
 * The FORMfields Library
 * The file contains a collection of JavaScript routines used by FORMfields.
 */

/**
 * Sets the current focus to the 1st element in the 1st form, if a form exists.
 * @since FORMfields v1.0
 */
function setFocus()
{
	if (document.forms.length > 0) {
		var form = document.forms[0];
		for (i = 0; i < form.length; i++) {
			if ( !form.elements[i].disabled
				&& ( (form.elements[i].type == "text") 
					|| (form.elements[i].type == "textarea")
					|| (form.elements[i].type == "select-one")
					|| (form.elements[i].type == "select-multiple")
					|| (form.elements[i].type == "radio")
					|| (form.elements[i].type == "checkbox")
					|| (form.elements[i].type == "password") ) ) {
				// Don't set the focus if there is an anchor in the URL
				var parts = window.location.href.split("#");
				if (parts.length == 1)
					document.forms[0].elements[i].focus();
				return;
			}
		}
	}
}

/**
 * Sets the current focus to the 1st text element in the 1st form, if a form exists.
 * @since FORMfields v1.0
 */
function setTextFocus()
{
	if (document.forms.length > 0) {
		var field = document.forms[0];
		for (i = 0; i < field.length; i++) {
			if ( !form.elements[i].disabled
				&& ( (field.elements[i].type == "text") 
					|| (field.elements[i].type == "textarea")
					|| (field.elements[i].type == "password") ) ) {
				// Don't set the focus if there is an anchor in the URL
				var parts = window.location.href.split("#");
				if (parts.length == 1)
					document.forms[0].elements[i].focus();
				return;
			}
		}
	}
}

/**
 * If id exists, sets the inner HTML. This is useful for dynamically populating
 * the content of an element.
 * @param string id the element id
 * @param string html the html to insert
 * @since FORMfields v1.0
 */
function setInnerHtml(id, html)
{
	if ( (elmnt = document.getElementById(id)) != null)
		elmnt.innerHTML = html;
}

/**
 * If id exists, clears the inner HTML. 
 * @param string id the element id
 * @since FORMfields v1.0
 */
function clearInnerHtml(id)
{
	setInnerHtml(id, '');
}

/**
 * Restricts the user from entering more than maxLen characters.
 * @param element cur the element to apply the restriction to
 * @param int maxLen the max length of characters permitted
 * @param string cntId the id of the element reporting the characters left count
 * @param event event the key press event
 * @since FORMfields v1.0
 */
function restrict(cur, maxLen, cntId, event)
{
	var keyCode = event.keyCode ? event.keyCode : event.which ? event.which : event.charCode;
	if (keyCode == 38 || keyCode == 40) // ignore up or down arrows
		return;
	charsLeft = (maxLen - cur.value.length);
	if (charsLeft < 0)
		charsLeft = 0;
	if ( (elmnt = document.getElementById(cntId)) != null)
		elmnt.innerHTML = charsLeft;
	if (cur.value.length > maxLen) {
		cur.value = cur.value.substr(0, maxLen);
	}
}

/**
 * Processes an enter event.
 * @param element field the element where the enter occured
 * @param event event the key press event
 * @since FORMfields v1.0
 */
function enterTabHandler(field, event)
{
	var keyCode = event.keyCode ? event.keyCode : event.which ? event.which : event.charCode;
	if (keyCode == 13) {
		for (j = 0; j < field.form.elements.length; j++) {
			if (field == field.form.elements[j]) {
				break;
			}
		}
		j = (j + 1) % field.form.elements.length;
		if (!field.form.elements[j].disabled && field.form.elements[j].type != 'hidden') {
			field.form.elements[j].focus();
		}
		return false;
	} else {
		return true;
	}
}

/**
 * Disables the default action associated with the user pressing enter.
 * @param event event the key press event
 * @since FORMfields v1.0
 */
function disableEnter(event)
{
	var keyCode = event.keyCode ? event.keyCode : event.which ? event.which : event.charCode;
	if (keyCode == 13) {
		return false;
	} else {
		return true;
	}
}

/**
 * Causes a submit button to be clicked when enter is pressed while editing a field.
 * @param event event the key press event
 * @param int sbId the ID of the submit button to submit with
 * @since FORMfields v3.0
 */
function enterSubmits(event, sbId)
{
	var keyCode = event.keyCode ? event.keyCode : event.which ? event.which : event.charCode;
	if (keyCode == 13) {
		sb = document.getElementById(sbId);
		if (sb != null) {
			sb.click();
		}
		return false;
	} else {
		return true;
	}
}

/**
 * Opens a new window for FORMfields calendar/date chooser.
 * @param string id the id of the form field associated with this calendar
 * @param string startYear a four digit year equal to the earliest year permitted by the calendar
 * @param string endYear a four digit year equal to the latest year permitted by the calendar
 * @param string calendarUrl the URL to the FORMfields calendar
 * @since FORMfields v2.0
 */
function showCalendar(id, startYear, endYear, calendarUrl)
{
	url = calendarUrl + "/calendar.php?id=" + id + "&year=" + document.getElementById(id + "_" + "year").value + "&month=" + document.getElementById(id + "_" + "month").value + "&startYear=" + startYear + "&endYear=" + endYear;
	window.open(url, "Calendar", "resizable=YES,height=280,width=450");
}

/**
 * Dynamically sets the date of a FORMfields date field.
 * @param string id the id of the calling form field
 * @param string year the four digit year
 * @param string month the two digit month
 * @param string day the two digit day
 * @since FORMfields v2.0
 */
function setDate(id, year, month, day)
{
	document.getElementById(id + "_" + "year").value = year;
	document.getElementById(id + "_" + "month").value = month;
	document.getElementById(id + "_" + "day").value = day;
	document.getElementById(id + "_" + "year").focus();
}

/**
 * Opens a new window for FORMfields palette/color chooser.
 * @param string id the id of the form field associated with this palette
 * @param string ffRootUrl the URL to the FORMfields root
 * @since FORMfields v2.0
 */
function showPalette(id, ffRootUrl)
{
	url = ffRootUrl + "/palette.php?id=" + id;
	window.open(url, "Calendar", "status=YES,resizable=YES,height=350,width=550");
}

/**
 * Used by the palette to set the color value of the ColorChooserField after a
 * color has been selected.
 * @param string id the id of the form field associated with the palette
 * @param string color the color picked by the user
 * @since FORMfields v2.0
 */
function setColor(id, color)
{
	document.getElementById(id).value = color;
	document.getElementById(id).focus();
}

/**
 * Used by fields that have refresh buttons to remove the anchor and add an
 * anchor to themselves so that the focus is set on the field that just
 * caused the refresh.
 * @param string url a URL
 * @since FORMfields v3.0
 */
function removeAnchor(url)
{
	parts = url.split("#");
	return parts[0];
}

// Enhancement: could use elmnt.tabIndex to simplify logic
/**
 * Returns the form element after the specified element or null if none exists.
 * @param element elmt an element
 * @return element the form element after the specified element or null if none exists
 * @since FORMfields v3.0
 */
function getNextElement(elmt) 
{
	// find i,j for the current element
	outer:
	for (i = 0; i < document.forms.length; i++) {
		for (j = 0; j < document.forms[i].elements.length; j++) {
			if (document.forms[i].elements[j] == elmt) {
				if (j < document.forms[i].elements.length - 1) { // not last elmt in form
					j++;
					break outer;
				} else if (i < document.forms.length - 1) { // go to 1st element of next form
					i++;
					j = 0;
					break outer;
				} else {
					return null;
				}
			}
		}
	}

	// legends appear to be elements, but they are undefined
	for (m = i; m < document.forms.length; m++) {
		for (n = j; n < document.forms[m].elements.length; n++) {
			if (document.forms[m].elements[n].name != undefined) {
				return document.forms[m].elements[n];
			}
		}
	}
	return null;
}

/**
 * Returns true if element e is contained in element a.
 * @param element a the container element
 * @param element e the contained element
 * @return boolean true if element e is contained in element a
 * @since FORMfields v3.0
 */
function containsElement(a, e) 
{
	for (i = 0; i < a.length; i++) {
		if (a[i] == e) {
			return true;
		}
	}
	return false;
}

/**
 * This function is used in debugging and prints an alert message of all the
 * elements on a page.
 * @since FORMfields v3.0
 */
function printElements() 
{
	str = "";
	for (i = 0; i < document.forms.length; i++) {
		for (j = 0; j < document.forms[i].elements.length; j++) {
			str = str + "document.forms[" + i + "].elements[" + j + "].name = " + document.forms[i].elements[j].name + "\n";
		}
	}
	alert(str);
}

/**
 * Automatically tabs to the next field when this field has been completely filled in.
 * @param element cur the element utilizing auto tab
 * @param event even the key press event
 * @since FORMfields v3.0
 */
function autoTab(cur, event) 
{
	// Make sure that we only autoTab when a printable char is entered, i.e. not on a tab
	// Key Codes for IE, FF, NS and Opera are the same:
	// - Back space: 8
	// - Tab: 9
	// - Shift: 16
	// - Ctrl: 17
	// - Alt: 18
	// - Caps lock: 20
	// - End: 35
	// - Home: 36
	// - Arrows: 37, 38, 39 , 40
	// - Delete: 46
	//alert(event.keyCode);
	var keyCode = event.keyCode ? event.keyCode : event.which ? event.which : event.charCode;
	var filter = [8, 9, 16, 17, 18, 20, 35, 36, 37, 38, 39, 40, 46];
	if (cur.value.length == cur.maxLength && !containsElement(filter, keyCode)) {
		next = getNextElement(cur);
		if (next != null)
			next.focus();
	}
}