aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--offline-submit/form-serialization.js144
1 files changed, 118 insertions, 26 deletions
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 <code>true</code>, the form's request method becomes the
- * <code>HTTPRequest</code> object's request method. The default
- * is <code>false</code>.
- * @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..