Made a bunch of changes to the way that the $() compatability code is handled.
[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 \r
132 $.ajax({\r
133         type: "POST",\r
134         url: "foo.cgi",\r
135         data: $.param( $("form").formdata() ),\r
136         success: function(){},\r
137         error: function(){},\r
138         complete: function(){}\r
139 });\r
140 \r
141  */\r
142 \r
143 /**\r
144  * A simple wrapper function that sits around the .serialize()\r
145  * method, allowing you to easily extract the data stored within\r
146  * a form.\r
147  *\r
148  * Usage examples:\r
149  *\r
150  * 1. Serialize the contents of a form to a & and = delmited string:\r
151  *    $.param( $("form").formdata() );\r
152  *\r
153  * @return         An array of name/value pairs representing the form\r
154  * @see            serialize()\r
155  # @author         John Resig\r
156  */\r
157 $.fn.formdata = function(){\r
158         this.serialize();\r
159         return this.vars;\r
160 };\r
161 \r
162 /**\r
163  * This function gathers form element variables into an array that\r
164  * is embedded into the current "this" variable as "this.vars". It\r
165  * is normally used in conjunction with formdata() or ajaxSubmit() but can\r
166  * be used standalone as long as you don't need the x and y coordinates\r
167  * associated with an <input type="image"/> element..\r
168  *\r
169  * Standalone usage examples:\r
170  *\r
171  * 1. Gather form vars and return array to LHS variable.\r
172  *    var myform = $('#form-id').serialize();\r
173  *\r
174  * 2. Provide a serialized URL-ready string (after 1. above).\r
175  *    var mystring = $.param(myform.vars);\r
176  *\r
177  * 3. Gather form vars and send to RHS plugin via "this.vars".\r
178  *    $('#form-id').serialize().some_other_plugin();\r
179  *\r
180  * @return         the jQuery Object\r
181  * @see            ajaxForm(), ajaxSubmit()\r
182  * @author         Mark Constable (markc@renta.net)\r
183  * @author         G. vd Hoven, Mike Alsup, Sam Collett, John Resig\r
184  */\r
185 $.fn.serialize = function() {\r
186         var a = [];\r
187         var ok = {INPUT:true, TEXTAREA:true, OPTION:true};\r
188 \r
189         $('*', this).each(function() {\r
190                 if (this.disabled || this.type == 'reset' || \r
191                         (this.type == 'checkbox' && !this.checked) || \r
192                         (this.type == 'radio' && !this.checked)) return;\r
193 \r
194                 if (this.type == 'submit' || this.type == 'image') {\r
195                         if (this.form.clicked != this) return;\r
196 \r
197                         if (this.type == 'image') {\r
198                                 if (this.form.clicked_x) {\r
199                                         a.push({name: this.name+'_x', value: this.form.clicked_x});\r
200                                         a.push({name: this.name+'_y', value: this.form.clicked_y});\r
201                                         return;\r
202                                 }\r
203                         }\r
204                 }\r
205 \r
206                 if (!ok[this.nodeName.toUpperCase()])\r
207                         return;\r
208 \r
209                 var par = this.parentNode;\r
210                 var p = par.nodeName.toUpperCase();\r
211                 if ((p == 'SELECT' || p == 'OPTGROUP') && !this.selected) return;\r
212 \r
213                 var n = this.name;\r
214                 if (!n) n = (p == 'OPTGROUP') ? par.parentNode.name : (p == 'SELECT') ? par.name : this.name;\r
215                 if (n == undefined) return;\r
216 \r
217                 a.push({name: n, value: this.value});\r
218         });\r
219         \r
220         this.vars = a;\r
221 \r
222         return this;\r
223 };\r