aboutsummaryrefslogtreecommitdiffstats
path: root/offline-submit/form-serialization.js
blob: d7c4d074ff187349fcfab8dc9ab59bea3d2d5db0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/* ------------------------------------------------------------------ */

/**
 * @param f : Form|HTMLFormElement
 * @return string
 */
function serializeForm(f)
{
  var gotSubmit = false;

  /**
   * @param o
   */
  function serializeControl(o)
  {
    /* HTML 4.01: Controls that are disabled cannot be successful. */
    if (!o.disabled)
    {
      /*
       * 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)
      {
        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);
        }
      }
    }
  }

  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 "";
}

/* ------------------------------------------------------------------ */

// esc(), getFeature() and isMethod() are user-defined, of course, but you 
// probably get the idea..