//
// formrequest.js - DOM-based dynamic form requests
//
// Copyright (c) 2006, 2007 Brian Katzung, Kappa Computer Solutions, LLC
//
//   This program is free software; you can redistribute it and/or
//   modify it under the terms of the GNU General Public License as
//   published by the Free Software Foundation; either version 2 of
//   the License, or (at your option) any later version.
//
//   This program is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   GNU General Public License for more details.
//
//   You should have received a copy of the GNU General Public License
//   along with this program; if not, write to the Free Software
//   Foundation, Inc., 59 Temple Place, Suite 330, Boston,
//   MA 02111-1307 USA
//
// For more information, contact:
//
//	Kappa Computer Solutions, LLC
//	655 Deerfield Rd Ste 100 PMB 407
//	Deerfield, IL 60015-3241
//	877.367.8837 (US) or 781.370.1093
//	http://www.kappacs.com/
//
// 2007-12-14	Added support for (=)enctype
// 2006-03-25	Created by Brian Katzung, Kappa Computer Solutions, LLC

//======================================================================

// frInfo is used to restore any previous form changes
var frInfo = new Object

//======================================================================

//----------------------------------------------------------------------
// formRequest([HTMLFormElement form,] [Object params[, ...]])
//
// The form parameter, if provided, specifies which form to process and
// submit. If omitted, the first document form is used.
//
// If one or more parameter objects are provided, the parameters are
// appended to the form as hidden inputs before it is submitted.
//
// Arrays passed as parameter objects are interpreted as a collection
// of (name, value) pairs. Otherwise, the object's attributes are
// enumerated to generate (name, value) pairs.
//
// Special names =action, =enctype, =method, and =target can be used to
// alter the form action, enctype, method, and target attributes for a
// specific request. Special name =confirm, when present, prompts the user
// to confirm (with the value as the prompt) before submitting the form.
//
// All other parameters may be multi-valued directly in array parameters
// (e.g. [ "name", "value1", "name", "value2" ]) or by using an array for
// the values (e.g. { "name": [ "value1", "value2" ] }) for either array
// or object parameters.

function formRequest ()
{
	var form

	// Prevent effects from previous formRequests from accumulating
	undoFormRequest()

	if (formRequest.arguments.length && formRequest.arguments[0].submit)
	{
		// The caller specified a form to use
		form = formRequest.arguments[0]
	}
	else
	{
		// Default to the first document form
		form = document.forms[0]
	}

	// Set up for subsequent undo
	frInfo.form = form
	frInfo.action = form.action
	frInfo.enctype = form.enctype
	frInfo.method = form.method
	frInfo.target = form.target
	frInfo.children = new Array()

	// Process any parameter objects that may have been provided
	for (var index = 0; index < formRequest.arguments.length; ++index)
	{
		formRequestParams(formRequest.arguments[index])
	}

	if (!frInfo.confirm || confirm(frInfo.confirm))
	{
		form.submit()
	}
}

//----------------------------------------------------------------------
// formRequestParams(Object params)
// Helper function to process one formRequest parameter object
// (Object or Array)

function formRequestParams (params)
{
	if (params.submit)
	{
		// Nevermind--it's the form
		return
	}

	if (!params.pop)
	{
		//
		// Convert a non-Array object to an Array by attribute
		// enumeration.
		//
		var obj = params

		params = new Array()
		for (var key in obj)
		{
			params.push(key, obj[key])
		}
	}

	// Now process each (name, value) pair from the object
	for (var index = 1; index < params.length; index += 2)
	{
		var key = params[index - 1]
		var value = params[index]

		switch (key)
		{
		case "=action":
			frInfo.form.action = value
			break

		case "=confirm":
			frInfo.confirm = value
			break

		case "=enctype":
			frInfo.form.enctype = value
			break

		case "=method":
			frInfo.form.method = value
			break

		case "=target":
			frInfo.form.target = value
			break

		default:
			if (!value.pop)
			{
				//
				// To simplify coding, just process a
				// scalar value as an array with one
				// value.
				//
				value = [ value ]
			}

			// Now add the hidden input(s)
			for (var vindex = 0; vindex < value.length; ++vindex)
			{
				var inp = document.createElement("input")

				inp.setAttribute("name", key)
				inp.setAttribute("value", value[vindex])
				inp.setAttribute("type", "hidden")
				frInfo.children.push(inp)
				frInfo.form.appendChild(inp)
			}
		}
	}
}

//----------------------------------------------------------------------
// undoFormRequest()
// Undo all changes from a previous formRequest. This keeps DOM changes
// from accumulating when forms target another window.

function undoFormRequest ()
{
	if (!frInfo.form)
	{
		//
		// 99.99% of the time there's nothing to do.
		// Either we haven't done a formRequest yet, or
		// the request reloaded the document and we're
		// starting from scratch anyway.
		//
		return
	}

	// Restore original attributes
	frInfo.form.action = frInfo.action
	frInfo.form.enctype = frInfo.enctype
	frInfo.form.method = frInfo.method
	frInfo.form.target = frInfo.target

	// Remove any added parameters
	var childCount = frInfo.children.length
	while (--childCount >= 0)
	{
		frInfo.form.removeChild(frInfo.children[childCount])
	}

	frInfo.children = null
	frInfo.confirm = null
	frInfo.form = null
}

// END
