// Dependências: util.js e forms.js;
//
// Classe para saltar para uma página/script e ao mesmo tempo passar-lhe parâmetros.
//

// Constructor.
derive (WebMsg, Object)
function WebMsg (optForm, optDoc) {
	this.doc = optDoc || document
	this.frm = optForm ? (optForm.substr ? elmx (optForm) : optForm) : this._newForm ()
	this.frm._wmObj = this
	this.itemCount = 0
	this.found = false
}

// Carrega os campos de 'frm' para este objecto. Veja a descrição de 'optForce' em 'newItem'.
proto.load = function (frm, optForce) {
	frm.substr && (frm = elmnx (frm))
	var rdbs = new Array, self = this
	// Carregar campos. 'Radio's e 'CheckBox'es ficam para depois.

	enumFields (frm, function loadField (el) {
		if (!el.name && !(el.name = el.id)) return

		var t = el.type ? el.type.toLowerCase () : ""
		switch (t) {
		case "":
			break;
		case "radio":
		case "checkbox":
			rdbs.push (el)
			break
		case "file":
			break
		default:
			self.newItem (el.name, el.value, optForce)
		}
	})
	// Carregar e 'Radio's e 'CheckBox'es. Estes têm um tratamento diferente devido à propriedade 'checked' e porque os 'Radio's de um
	// o nome de um grupo deles é o mesmo mas só interessa
	// mesmo grupo tem todos o mesmo nome.
	if (rdbs.length) {
		for (var i = 0; i < rdbs.length; ++i) {
			var rb = rdbs [i]
			rb.checked && this.newItem (rb.name, rb.value, optForce)
		}
	}
	return this
}

// Cria um novo item na mensagem. Esse chamar-se-á 'nm' e terá o valor 'vl'. 'optForce' controla se se pode ignorar quando 'vl' é nulo.
proto.newItem = function (nm, vl, optForce) {
	if (!optForce && (vl == null || (vl.substr && !vl))) return this

	var h = this.lastItem = this.doc.createElement ("input")
	h.type = "hidden"
	h.name = nm
	h.value = vl
	this.frm.appendChild (h)

	++this.itemCount

	return this
}

// Substítui o valor do item 'nm' por 'vl', ou então cria esse item. O uso dste método só é aconselhável quando há a probabilidade de 
// 'nm' já existir, pois é mais lento do que 'newItem'. Veja a descrição de 'optForce' em 'newItem'.
proto.setItem = function (nm, vl, optForce) {
	var el
	if (el = this.lastItem = this.getItem (nm)) {
		if (!optForce && (vl == "" || vl == null))
			return this.removeItem (nm)
		el.value = vl
		return this
	}
	return this.newItem (nm, vl, optForce)
}

// Remove __todos__ os itens chamados 'nm'.
proto.removeItem = function (nm, optAll) {
	var el, i = 0, n = optAll ? 65535 : 1
	this.found = false
	while ((el = this.getItem (nm)) && ++i <= n) {
		removeElm (el)
		this.found = true
	}
	return this
}

// Retorna o item 'nm'.
proto.getItem = function (nm) {	
	var res
	enumFields (this.frm, function (el) {
		if (el.name == nm) {
			res = el
			return false
		}
	})

	return res
}

// Aplica 'f' a todos os itens do objecto.
proto.enumFields = function (f) {	enumFields (this.frm, f)	}

// Enviar a mensagem. Essa poderá seguir para a página/script 'optAction' e os seus resultados colocados em 'optTarget'.
proto.send = function (optAction, optTarget) {
	var frm = this.frm, origfrm = this.frm, f
	// "Script" e objecto destino.
	frm.action = optAction == null ? (frm.action || this.doc.location.href) : optAction
	frm.target = optTarget == null ? frm.target : optTarget
	// O form não funciona como mensagem, tendo a codificação "multipart/form-data" e não tendo ficheiros seleccionados para carregar!
	if (frm.encoding == "multipart/form-data" && !hasFilesToUpl (frm)) {
		frm = this.frm = this._newForm ()
		fireOnSubmit (origfrm)	// Simular o despacho, para depois se fazer a cópia do form.

		this.load (origfrm)
		frm.action = origfrm.action
		frm.target = origfrm.target
	}
	// Enviar.
	(isIE ? frm.parentElement : frm.parentNode) || this.doc.body.appendChild (frm)
	frm.submit ()
	this.frm = origfrm
}

// Retorna um novo form.
proto._newForm = function () {
	var frm = this.doc.createElement ("form")
	frm.method = "post"
	frm.style.display = "none"
	return frm
}