5194d6fa2c5d6c90e0debf05afc457a74f6c1827
[jquery.git] / form / form.js
1 /**\r
2  * A method for submitting an HTML form using AJAX, as opposed to the\r
3  * standard page-load way.\r
4  *\r
5  * This method attempts to mimic the functionality of the original form\r
6  * as best as possible (duplicating the method, action, and exact contents\r
7  * of the form).\r
8  *\r
9  * There are three different resulting operations that can occur, after\r
10  * your form has been submitted.\r
11  *\r
12  * 1. The form is submitted and a callback is fired, letting you know\r
13  *    when it's done:\r
14  *    $("form").ajaxSubmit(function(){\r
15  *      alert("all done!");\r
16  *    });\r
17  *\r
18  * 2. The form is submitted and the resulting HTML contents are injected\r
19  *    into the page, at your specified location.\r
20  *    $("form").ajaxSubmit("#destination");\r
21  *\r
22  * 3. The form is submitted and the results returned from the server are\r
23  *    automatically executed (useful for having the server return more\r
24  *    Javascript commands to execute).\r
25  *    $("form").ajaxSubmit();\r
26  *\r
27  * Additionally, an optional pre-submit callback can be provided. If it,\r
28  * when called with the contents of the form, returns false, the form will\r
29  * not be submitted.\r
30  *\r
31  * Finally, both the URL and method of the form submission can be\r
32  * overidden using the 'url' and 'mth' arguments.\r
33  *\r
34  * @param target   arg for the target id element to render\r
35  * @param post_cb  callback after any results are returned\r
36  * @param pre_cb   callback function before submission\r
37  * @param url      form action override\r
38  * @param mth      form method override\r
39  * @return         "this" object\r
40  * @see            ajaxForm(), serialize(), load(), $.ajax()\r
41  * @author         Mark Constable (markc@renta.net)\r
42  * @author         G. vd Hoven, Mike Alsup, Sam Collett, John Resig\r
43  */\r
44 $.fn.ajaxSubmit = function(target, post_cb, pre_cb, url, mth) {\r
45         if ( !this.vars ) this.serialize();\r
46         \r
47         if (pre_cb && pre_cb.constructor == Function)\r
48                 if (pre_cb(this.vars) === false) return;\r
49 \r
50         var f = this.get(0);\r
51         var url = url || f.action || '';\r
52         var mth = mth || f.method || 'POST';\r
53 \r
54         if (target && target.constructor == Function) {\r
55                 $.ajax(mth, url, $.param(this.vars), target);\r
56         } else if (target && target.constructor == String) {\r
57                 $(target).load(url, this.vars, post_cb);\r
58         } else {\r
59                 this.vars.push({name: 'evaljs', value: 1});\r
60                 $.ajax(mth, url, $.param(this.vars), function(r) {\r
61                         eval(r.responseText);\r
62                 });\r
63         }\r
64 \r
65         return this;\r
66 };\r
67 \r
68 /**\r
69  * This function can be used to turn any HTML form into a form\r
70  * that submits using AJAX only.\r
71  *\r
72  * The purpose of using this method, instead of the ajaxSubmit()\r
73  * and submit() methods, is to make absolutely sure that the\r
74  * coordinates of <input type="image"/> elements are transmitted\r
75  * correctly OR figuring out exactly which <input type="submit"/>\r
76  * element was clicked to submit the form.\r
77  *\r
78  * If neither of the above points are important to you, then you'll\r
79  * probably just want to stick with the simpler ajaxSubmit() function.\r
80  *\r
81  * Usage examples, similar to ajaxSubmit():\r
82  *\r
83  * 1. Just eval the results returned from the backend.\r
84  *    $('#form-id').ajaxForm();\r
85  *\r
86  * 2. Render backend results directly to target ID (expects (x)HTML).\r
87  *    $('#form-id').ajaxForm('#target-id');\r
88  *\r
89  * 3. Submit to backend URL (form action) then call this function.\r
90  *    $('#form-id').ajaxForm(post_callback);\r
91  *\r
92  * 4. Load target ID with backend results then call a function.\r
93  *    $('#form-id').ajaxForm('#target-id', post_callback);\r
94  *\r
95  * 5. Call a browser function (for validation) and then (optionally)\r
96  *    load server results to target ID.\r
97  *    $('#form-id').ajaxForm('#target-id', null, pre_callback);\r
98  *\r
99  * 6. Call validation function first then load server results to\r
100  *    target ID and then also call a browser function.\r
101  *    $('#form-id').ajaxForm('#target-id', post_callback, pre_callback);\r
102  *\r
103  * @param target   arg for the target id element to render\r
104  * @param post_cb  callback after any results are returned\r
105  * @param pre_cb   callback function before submission\r
106  * @return         the jQuery Object\r
107  * @see            serialize(), ajaxSubmit()\r
108  * @author         Mark Constable (markc@renta.net)\r
109  * @author         G. vd Hoven, Mike Alsup, Sam Collett, John Resig\r
110  */\r
111 $.fn.ajaxForm = function(target, post_cb, pre_cb) {\r
112         return this.each(function(){\r
113                 $('input[@type="submit"],input[@type="image"]', this).click(function(ev){\r
114                         this.form.clicked = this;\r
115                         if (ev.offsetX != undefined) {\r
116                                 this.form.clicked_x = ev.offsetX;\r
117                                 this.form.clicked_y = ev.offsetY;\r
118                         } else {\r
119                                 this.form.clicked_x = ev.pageX - this.offsetLeft;\r
120                                 this.form.clicked_y = ev.pageY - this.offsetTop;\r
121                         }\r
122                 });\r
123         }).submit(function(e){\r
124                 e.preventDefault();\r
125                 $(this).ajaxSubmit(target, post_cb, pre_cb);\r
126                 return false;\r
127         });\r
128 };\r
129 \r
130 /**\r
131  * A simple wrapper function that sits around the .serialize()\r
132  * method, allowing you to easily extract the data stored within\r
133  * a form.\r
134  *\r
135  * Usage examples:\r
136  *\r
137  * 1. Serialize the contents of a form to a & and = delmited string:\r
138  *    $.param( $("form").formdata() );\r
139  *\r
140  * @return         An array of name/value pairs representing the form\r
141  * @see            serialize()\r
142  # @author         John Resig\r
143  */\r
144 $.fn.formdata = function(){\r
145         this.serialize();\r
146         return this.vars;\r
147 };\r
148 \r
149 /**\r
150  * This function gathers form element variables into an array that\r
151  * is embedded into the current "this" variable as "this.vars". It\r
152  * is normally used in conjunction with formdata() or ajaxSubmit() but can\r
153  * be used standalone as long as you don't need the x and y coordinates\r
154  * associated with an <input type="image"/> element..\r
155  *\r
156  * Standalone usage examples:\r
157  *\r
158  * 1. Gather form vars and return array to LHS variable.\r
159  *    var myform = $('#form-id').serialize();\r
160  *\r
161  * 2. Provide a serialized URL-ready string (after 1. above).\r
162  *    var mystring = $.param(myform.vars);\r
163  *\r
164  * 3. Gather form vars and send to RHS plugin via "this.vars".\r
165  *    $('#form-id').serialize().some_other_plugin();\r
166  *\r
167  * @return         the jQuery Object\r
168  * @see            ajaxForm(), ajaxSubmit()\r
169  * @author         Mark Constable (markc@renta.net)\r
170  * @author         G. vd Hoven, Mike Alsup, Sam Collett, John Resig\r
171  */\r
172 $.fn.serialize = function() {\r
173         var a = [];\r
174         var ok = {INPUT:true, TEXTAREA:true, OPTION:true};\r
175 \r
176         $('*', this).each(function() {\r
177                 if (this.disabled || this.type == 'reset' || \r
178                         (this.type == 'checkbox' && !this.checked) || \r
179                         (this.type == 'radio' && !this.checked)) return;\r
180 \r
181                 if (this.type == 'submit' || this.type == 'image') {\r
182                         if (this.form.clicked != this) return;\r
183 \r
184                         if (this.type == 'image') {\r
185                                 if (this.form.clicked_x) {\r
186                                         a.push({name: this.name+'_x', value: this.form.clicked_x});\r
187                                         a.push({name: this.name+'_y', value: this.form.clicked_y});\r
188                                         return;\r
189                                 }\r
190                         }\r
191                 }\r
192 \r
193                 if (!ok[this.nodeName.toUpperCase()])\r
194                         return;\r
195 \r
196                 var par = this.parentNode;\r
197                 var p = par.nodeName.toUpperCase();\r
198                 if ((p == 'SELECT' || p == 'OPTGROUP') && !this.selected) return;\r
199 \r
200                 var n = this.name;\r
201                 if (!n) n = (p == 'OPTGROUP') ? par.parentNode.name : (p == 'SELECT') ? par.name : this.name;\r
202                 if (n == undefined) return;\r
203 \r
204                 a.push({name: n, value: this.value});\r
205         });\r
206         \r
207         this.vars = a;\r
208 \r
209         return this;\r
210 };\r