From 875a60dba09cf984e84c1531254d2c11dc0fe1ac Mon Sep 17 00:00:00 2001 From: Matěj Cepl Date: Wed, 13 Jan 2010 00:21:23 +0100 Subject: New version of form-serialization code --- offline-submit/form-serialization.js | 144 ++++++++++++++++++++++++++++------- 1 file changed, 118 insertions(+), 26 deletions(-) (limited to 'offline-submit') diff --git a/offline-submit/form-serialization.js b/offline-submit/form-serialization.js index 70c9ae0..d7c4d07 100644 --- a/offline-submit/form-serialization.js +++ b/offline-submit/form-serialization.js @@ -1,37 +1,129 @@ +/* ------------------------------------------------------------------ */ + /** - * (C) Thomas 'PointedEars' Lahn, 2009, released under GPLv3 - * - * Retrieves the data to send in the request, and optionally the request - * method, from an (X)HTML form. TODO: select[multiple] elements - * - * @param f : HTMLFormElement - * @param bUseFormMethod: optional boolean - * If true, the form's request method becomes the - * HTTPRequest object's request method. The default - * is false. - * @return boolean + * @param f : Form|HTMLFormElement + * @return string */ -getDataFromForm = function(f, bUseFormMethod) { - var result = false, es, len; +function serializeForm(f) +{ + var gotSubmit = false; - if (f && (es = f.elements) && (len = es.length)) + /** + * @param o + */ + function serializeControl(o) { - if (bUseFormMethod) this.method = f.method; - - var aData = []; - - for (var i = 0; i < len; i++) + /* HTML 4.01: Controls that are disabled cannot be successful. */ + if (!o.disabled) { - var o = es[i]; - if (o.name) + /* + * If a form contains more than one submit button, + * only the activated submit button is successful. + * (here: the first one) + */ + var isSubmit = /(^|\s)(submit|image)(\s|$)/i.test(o.type); + if (!gotSubmit || !isSubmit) { - aData.push(esc(o.name) + "=" + esc(o.value != "" ? o.value : "")); + if (isSubmit) gotSubmit = true; + + /* + * For menus, the control name is provided by a SELECT element + * and values are provided by OPTION elements. Only selected + * options may be successful. When no options are selected, + * the control is not successful and neither the name nor any + * values are submitted to the server when the form is submitted. + */ + var m = /(^|\s)(select(-one)?|undefined)(\s|$)/i.exec(o.type); + if (m) + { + /* select-one */ + if (m[3]) + { + if (o.selectedIndex > -1) + { + items.add(o.name, o.options[o.selectedIndex].value); + } + } + + /* select */ + else if (m[2]) + { + for (var i = 0, opts = o.options, len = opts && opts.length; + i < len; i++) + { + var opt = opts[i]; + if (opt.selected) + { + items.add(o.name, opt.value); + } + } + } + } + + /* + * All "on" checkboxes may be successful. + * For radio buttons that share the same value of the + * name attribute, only the "on" radio button may be successful. + */ + else if (!/(^|\s)file|reset(\s|$)/i.test(o.type) + && !(/(^|\s)object(\s|$)/i.test(o.tagName) && o.declare) + && !/(^|\s)(checkbox|radio)(\s|$)/i.test(o.type) + || o.checked) + { + items.add(o.name, o.value); + } } } + } - this.data = aData.join("&"); - result = true; + var es = getFeature(f, "elements"); + if (es) + { + var items = []; + + items.add = function(sName, sValue) { + var s = esc(sName) + "=" + esc(sValue); + this.push(s); + }; + + if (!isMethod(items, "push")) + { + items.push = function() { + for (var i = 0, len = arguments.length; i < len; i++) + { + items[items.length] = arguments[i]; + } + }; + } + + for (var i = 0, len = es.length; i < len; i++) + { + var e = es[i]; + + /* + * Elements with the same name create a NodeList object, + * however options of select objects are also indexable in Gecko. + */ + if (typeof e[0] != "undefined" && typeof e.options == "undefined") + { + for (var j = 0, len2 = e.length; j < len2; j++) + { + serializeControl(e[j]); + } + } + else + { + serializeControl(e); + } + } + + return items.join("&"); } + + return ""; +} + +/* ------------------------------------------------------------------ */ - return result; -}; +// esc(), getFeature() and isMethod() are user-defined, of course, but you +// probably get the idea.. -- cgit