13b513b4ca414dbf1bfe987e0b099877b781e600
[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 && pre_cb(this.vars) === false) return;\r
48 \r
49         var f = this.get(0);\r
50         var url = url || f.action || '';\r
51         var mth = mth || f.method || 'POST';\r
52 \r
53         if (target && target.constructor == Function)\r
54                 $.ajax(mth, url, $.param(this.vars), target);\r
55         else if (target && target.constructor == String)\r
56                 $(target).load(url, this.vars, post_cb);\r
57         else {\r
58                 this.vars.push({name: 'evaljs', value: 1});\r
59                 $.ajax(mth, url, $.param(this.vars), function(r) {\r
60                         eval(r.responseText);\r
61                 });\r
62         }\r
63 \r
64         return this;\r
65 };\r
66 \r
67 /**\r
68  * This function can be used to turn any HTML form into a form\r
69  * that submits using AJAX only.\r
70  *\r
71  * The purpose of using this method, instead of the ajaxSubmit()\r
72  * and submit() methods, is to make absolutely sure that the\r
73  * coordinates of <input type="image"/> elements are transmitted\r
74  * correctly OR figuring out exactly which <input type="submit"/>\r
75  * element was clicked to submit the form.\r
76  *\r
77  * If neither of the above points are important to you, then you'll\r
78  * probably just want to stick with the simpler ajaxSubmit() function.\r
79  *\r
80  * Usage examples, similar to ajaxSubmit():\r
81  *\r
82  * 1. Just eval the results returned from the backend.\r
83  *    $('#form-id').ajaxForm();\r
84  *\r
85  * 2. Render backend results directly to target ID (expects (x)HTML).\r
86  *    $('#form-id').ajaxForm('#target-id');\r
87  *\r
88  * 3. Submit to backend URL (form action) then call this function.\r
89  *    $('#form-id').ajaxForm(post_callback);\r
90  *\r
91  * 4. Load target ID with backend results then call a function.\r
92  *    $('#form-id').ajaxForm('#target-id', post_callback);\r
93  *\r
94  * 5. Call a browser function (for validation) and then (optionally)\r
95  *    load server results to target ID.\r
96  *    $('#form-id').ajaxForm('#target-id', null, pre_callback);\r
97  *\r
98  * 6. Call validation function first then load server results to\r
99  *    target ID and then also call a browser function.\r
100  *    $('#form-id').ajaxForm('#target-id', post_callback, pre_callback);\r
101  *\r
102  * @param target   arg for the target id element to render\r
103  * @param post_cb  callback after any results are returned\r
104  * @param pre_cb   callback function before submission\r
105  * @return         the jQuery Object\r
106  * @type jQuery\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                 $(this).ajaxSubmit(target, post_cb, pre_cb);\r
125                 return false;\r
126         });\r
127 };\r
128 \r
129 /**\r
130  * A simple wrapper function that sits around the .serialize()\r
131  * method, allowing you to easily extract the data stored within\r
132  * a form.\r
133  *\r
134  * Usage examples:\r
135  *\r
136  * 1. Serialize the contents of a form to a & and = delmited string:\r
137  *    $.param( $("form").formdata() );\r
138  *\r
139  * @return         An array of name/value pairs representing the form\r
140  * @type Array<Object>\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  * @return jQuery\r
169  * @see            ajaxForm(), ajaxSubmit()\r
170  * @author         Mark Constable (markc@renta.net)\r
171  * @author         G. vd Hoven, Mike Alsup, Sam Collett, John Resig\r
172  */\r
173 $.fn.serialize = function() {\r
174         var a = [];\r
175         var ok = {INPUT:true, TEXTAREA:true, OPTION:true};\r
176 \r
177         $('*', this).each(function() {\r
178                 var par = this.parentNode;\r
179                 var p = par.nodeName.toUpperCase();\r
180                 var n = this.name || p == 'OPTGROUP' && par.parentNode.name || p == 'SELECT' && par.name || this.id;\r
181 \r
182                 if ( !n || this.disabled || this.type == 'reset' || \r
183                         (this.type == 'checkbox' || this.type == 'radio') && !this.checked || \r
184                         !ok[this.nodeName.toUpperCase()] ||\r
185                         (this.type == 'submit' || this.type == 'image') && this.form.clicked != this ||\r
186                         (p == 'SELECT' || p == 'OPTGROUP') && !this.selected ) return;\r
187 \r
188                 if (this.type == 'image' && this.form.clicked_x)\r
189                         return a.push(\r
190                                 {name: this.name+'_x', value: this.form.clicked_x},\r
191                                 {name: this.name+'_y', value: this.form.clicked_y}\r
192                         );\r
193 \r
194                 a.push({name: n, value: this.value});\r
195         });\r
196         \r
197         this.vars = a;\r
198 \r
199         return this;\r
200 };\r