root / drupal7 / sites / all / modules / jquery_update / replace / misc / jquery.form.js @ 27945136
1 | 85ad3d82 | Assos Assos | /*!
|
---|---|---|---|
2 | * jQuery Form Plugin
|
||
3 | * version: 2.69 (06-APR-2011)
|
||
4 | * @requires jQuery v1.3.2 or later
|
||
5 | *
|
||
6 | * Examples and documentation at: http://malsup.com/jquery/form/
|
||
7 | * Dual licensed under the MIT and GPL licenses:
|
||
8 | * http://www.opensource.org/licenses/mit-license.php
|
||
9 | * http://www.gnu.org/licenses/gpl.html
|
||
10 | */
|
||
11 | ;(function($) { |
||
12 | |||
13 | /*
|
||
14 | Usage Note:
|
||
15 | -----------
|
||
16 | Do not use both ajaxSubmit and ajaxForm on the same form. These
|
||
17 | functions are intended to be exclusive. Use ajaxSubmit if you want
|
||
18 | to bind your own submit handler to the form. For example,
|
||
19 | |||
20 | $(document).ready(function() {
|
||
21 | $('#myForm').bind('submit', function(e) {
|
||
22 | e.preventDefault(); // <-- important
|
||
23 | $(this).ajaxSubmit({
|
||
24 | target: '#output'
|
||
25 | });
|
||
26 | });
|
||
27 | });
|
||
28 | |||
29 | Use ajaxForm when you want the plugin to manage all the event binding
|
||
30 | for you. For example,
|
||
31 | |||
32 | $(document).ready(function() {
|
||
33 | $('#myForm').ajaxForm({
|
||
34 | target: '#output'
|
||
35 | });
|
||
36 | });
|
||
37 | |||
38 | When using ajaxForm, the ajaxSubmit function will be invoked for you
|
||
39 | at the appropriate time.
|
||
40 | */
|
||
41 | |||
42 | /**
|
||
43 | * ajaxSubmit() provides a mechanism for immediately submitting
|
||
44 | * an HTML form using AJAX.
|
||
45 | */
|
||
46 | $.fn.ajaxSubmit = function(options) { |
||
47 | // fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
|
||
48 | if (!this.length) { |
||
49 | log('ajaxSubmit: skipping submit process - no element selected');
|
||
50 | return this; |
||
51 | } |
||
52 | |||
53 | if (typeof options == 'function') { |
||
54 | options = { success: options };
|
||
55 | } |
||
56 | |||
57 | var action = this.attr('action'); |
||
58 | var url = (typeof action === 'string') ? $.trim(action) : ''; |
||
59 | if (url) {
|
||
60 | // clean url (don't include hash vaue)
|
||
61 | url = (url.match(/^([^#]+)/)||[])[1]; |
||
62 | } |
||
63 | url = url || window.location.href || '';
|
||
64 | |||
65 | options = $.extend(true, { |
||
66 | url: url,
|
||
67 | success: $.ajaxSettings.success, |
||
68 | type: this[0].getAttribute('method') || 'GET', // IE7 massage (see issue 57) |
||
69 | iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank' |
||
70 | }, options); |
||
71 | |||
72 | // hook for manipulating the form data before it is extracted;
|
||
73 | // convenient for use with rich editors like tinyMCE or FCKEditor
|
||
74 | var veto = {};
|
||
75 | this.trigger('form-pre-serialize', [this, options, veto]); |
||
76 | if (veto.veto) {
|
||
77 | log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
|
||
78 | return this; |
||
79 | } |
||
80 | |||
81 | // provide opportunity to alter form data before it is serialized
|
||
82 | if (options.beforeSerialize && options.beforeSerialize(this, options) === false) { |
||
83 | log('ajaxSubmit: submit aborted via beforeSerialize callback');
|
||
84 | return this; |
||
85 | } |
||
86 | |||
87 | var n,v,a = this.formToArray(options.semantic); |
||
88 | if (options.data) {
|
||
89 | options.extraData = options.data; |
||
90 | for (n in options.data) { |
||
91 | if(options.data[n] instanceof Array) { |
||
92 | for (var k in options.data[n]) { |
||
93 | a.push( { name: n, value: options.data[n][k] } ); |
||
94 | } |
||
95 | } |
||
96 | else {
|
||
97 | v = options.data[n]; |
||
98 | v = $.isFunction(v) ? v() : v; // if value is fn, invoke it |
||
99 | a.push( { name: n, value: v } ); |
||
100 | } |
||
101 | } |
||
102 | } |
||
103 | |||
104 | // give pre-submit callback an opportunity to abort the submit
|
||
105 | if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) { |
||
106 | log('ajaxSubmit: submit aborted via beforeSubmit callback');
|
||
107 | return this; |
||
108 | } |
||
109 | |||
110 | // fire vetoable 'validate' event
|
||
111 | this.trigger('form-submit-validate', [a, this, options, veto]); |
||
112 | if (veto.veto) {
|
||
113 | log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
|
||
114 | return this; |
||
115 | } |
||
116 | |||
117 | var q = $.param(a); |
||
118 | |||
119 | if (options.type.toUpperCase() == 'GET') { |
||
120 | options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q; |
||
121 | options.data = null; // data is null for 'get' |
||
122 | } |
||
123 | else {
|
||
124 | options.data = q; // data is the query string for 'post'
|
||
125 | } |
||
126 | |||
127 | var $form = this, callbacks = []; |
||
128 | if (options.resetForm) {
|
||
129 | callbacks.push(function() { $form.resetForm(); }); |
||
130 | } |
||
131 | if (options.clearForm) {
|
||
132 | callbacks.push(function() { $form.clearForm(); }); |
||
133 | } |
||
134 | |||
135 | // perform a load on the target only if dataType is not provided
|
||
136 | if (!options.dataType && options.target) {
|
||
137 | var oldSuccess = options.success || function(){}; |
||
138 | callbacks.push(function(data) {
|
||
139 | var fn = options.replaceTarget ? 'replaceWith' : 'html'; |
||
140 | $(options.target)[fn](data).each(oldSuccess, arguments); |
||
141 | }); |
||
142 | } |
||
143 | else if (options.success) { |
||
144 | callbacks.push(options.success); |
||
145 | } |
||
146 | |||
147 | options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg |
||
148 | var context = options.context || options; // jQuery 1.4+ supports scope context |
||
149 | for (var i=0, max=callbacks.length; i < max; i++) { |
||
150 | callbacks[i].apply(context, [data, status, xhr || $form, $form]); |
||
151 | } |
||
152 | }; |
||
153 | |||
154 | // are there files to upload?
|
||
155 | var fileInputs = $('input:file', this).length > 0; |
||
156 | var mp = 'multipart/form-data'; |
||
157 | var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp); |
||
158 | |||
159 | // options.iframe allows user to force iframe mode
|
||
160 | // 06-NOV-09: now defaulting to iframe mode if file input is detected
|
||
161 | if (options.iframe !== false && (fileInputs || options.iframe || multipart)) { |
||
162 | // hack to fix Safari hang (thanks to Tim Molendijk for this)
|
||
163 | // see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
|
||
164 | if (options.closeKeepAlive) {
|
||
165 | $.get(options.closeKeepAlive, fileUpload);
|
||
166 | } |
||
167 | else {
|
||
168 | fileUpload(); |
||
169 | } |
||
170 | } |
||
171 | else {
|
||
172 | $.ajax(options);
|
||
173 | } |
||
174 | |||
175 | // fire 'notify' event
|
||
176 | this.trigger('form-submit-notify', [this, options]); |
||
177 | return this; |
||
178 | |||
179 | |||
180 | // private function for handling file uploads (hat tip to YAHOO!)
|
||
181 | function fileUpload() { |
||
182 | var form = $form[0]; |
||
183 | |||
184 | if ($(':input[name=submit],:input[id=submit]', form).length) { |
||
185 | // if there is an input with a name or id of 'submit' then we won't be
|
||
186 | // able to invoke the submit fn on the form (at least not x-browser)
|
||
187 | alert('Error: Form elements must not have name or id of "submit".');
|
||
188 | return;
|
||
189 | } |
||
190 | |||
191 | var s = $.extend(true, {}, $.ajaxSettings, options); |
||
192 | s.context = s.context || s; |
||
193 | var id = 'jqFormIO' + (new Date().getTime()), fn = '_'+id; |
||
194 | var $io = $('<iframe id="' + id + '" name="' + id + '" src="'+ s.iframeSrc +'" />'); |
||
195 | var io = $io[0]; |
||
196 | |||
197 | $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' }); |
||
198 | |||
199 | var xhr = { // mock object |
||
200 | aborted: 0, |
||
201 | responseText: null, |
||
202 | responseXML: null, |
||
203 | status: 0, |
||
204 | statusText: 'n/a', |
||
205 | getAllResponseHeaders: function() {}, |
||
206 | getResponseHeader: function() {}, |
||
207 | setRequestHeader: function() {}, |
||
208 | abort: function() { |
||
209 | log('aborting upload...');
|
||
210 | var e = 'aborted'; |
||
211 | this.aborted = 1; |
||
212 | $io.attr('src', s.iframeSrc); // abort op in progress |
||
213 | xhr.error = e; |
||
214 | s.error && s.error.call(s.context, xhr, 'error', e);
|
||
215 | g && $.event.trigger("ajaxError", [xhr, s, e]); |
||
216 | s.complete && s.complete.call(s.context, xhr, 'error');
|
||
217 | } |
||
218 | }; |
||
219 | |||
220 | var g = s.global;
|
||
221 | // trigger ajax global events so that activity/block indicators work like normal
|
||
222 | if (g && ! $.active++) { |
||
223 | $.event.trigger("ajaxStart"); |
||
224 | } |
||
225 | if (g) {
|
||
226 | $.event.trigger("ajaxSend", [xhr, s]); |
||
227 | } |
||
228 | |||
229 | if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) { |
||
230 | if (s.global) {
|
||
231 | $.active--;
|
||
232 | } |
||
233 | return;
|
||
234 | } |
||
235 | if (xhr.aborted) {
|
||
236 | return;
|
||
237 | } |
||
238 | |||
239 | var timedOut = 0; |
||
240 | |||
241 | // add submitting element to data if we know it
|
||
242 | var sub = form.clk;
|
||
243 | if (sub) {
|
||
244 | var n = sub.name;
|
||
245 | if (n && !sub.disabled) {
|
||
246 | s.extraData = s.extraData || {}; |
||
247 | s.extraData[n] = sub.value; |
||
248 | if (sub.type == "image") { |
||
249 | s.extraData[n+'.x'] = form.clk_x;
|
||
250 | s.extraData[n+'.y'] = form.clk_y;
|
||
251 | } |
||
252 | } |
||
253 | } |
||
254 | |||
255 | // take a breath so that pending repaints get some cpu time before the upload starts
|
||
256 | function doSubmit() { |
||
257 | // make sure form attrs are set
|
||
258 | var t = $form.attr('target'), a = $form.attr('action'); |
||
259 | |||
260 | // update form attrs in IE friendly way
|
||
261 | form.setAttribute('target',id);
|
||
262 | if (form.getAttribute('method') != 'POST') { |
||
263 | form.setAttribute('method', 'POST'); |
||
264 | } |
||
265 | if (form.getAttribute('action') != s.url) { |
||
266 | form.setAttribute('action', s.url);
|
||
267 | } |
||
268 | |||
269 | // ie borks in some cases when setting encoding
|
||
270 | if (! s.skipEncodingOverride) {
|
||
271 | $form.attr({
|
||
272 | encoding: 'multipart/form-data', |
||
273 | enctype: 'multipart/form-data' |
||
274 | }); |
||
275 | } |
||
276 | |||
277 | // support timout
|
||
278 | if (s.timeout) {
|
||
279 | setTimeout(function() { timedOut = true; cb(); }, s.timeout); |
||
280 | } |
||
281 | |||
282 | // add "extra" data to form if provided in options
|
||
283 | var extraInputs = [];
|
||
284 | try {
|
||
285 | if (s.extraData) {
|
||
286 | for (var n in s.extraData) { |
||
287 | extraInputs.push( |
||
288 | $('<input type="hidden" name="'+n+'" value="'+s.extraData[n]+'" />') |
||
289 | .appendTo(form)[0]);
|
||
290 | } |
||
291 | } |
||
292 | |||
293 | // add iframe to doc and submit the form
|
||
294 | $io.appendTo('body'); |
||
295 | io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false); |
||
296 | form.submit(); |
||
297 | } |
||
298 | finally {
|
||
299 | // reset attrs and remove "extra" input elements
|
||
300 | form.setAttribute('action',a);
|
||
301 | if(t) {
|
||
302 | form.setAttribute('target', t);
|
||
303 | } else {
|
||
304 | $form.removeAttr('target'); |
||
305 | } |
||
306 | $(extraInputs).remove();
|
||
307 | } |
||
308 | } |
||
309 | |||
310 | if (s.forceSync) {
|
||
311 | doSubmit(); |
||
312 | } |
||
313 | else {
|
||
314 | setTimeout(doSubmit, 10); // this lets dom updates render |
||
315 | } |
||
316 | |||
317 | var data, doc, domCheckCount = 50; |
||
318 | |||
319 | function cb() { |
||
320 | if (xhr.aborted) {
|
||
321 | return;
|
||
322 | } |
||
323 | |||
324 | var doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;
|
||
325 | if (!doc || doc.location.href == s.iframeSrc) {
|
||
326 | // response not received yet
|
||
327 | if (!timedOut)
|
||
328 | return;
|
||
329 | } |
||
330 | io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false); |
||
331 | |||
332 | var ok = true; |
||
333 | try {
|
||
334 | if (timedOut) {
|
||
335 | throw 'timeout'; |
||
336 | } |
||
337 | |||
338 | var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc); |
||
339 | log('isXml='+isXml);
|
||
340 | if (!isXml && window.opera && (doc.body == null || doc.body.innerHTML == '')) { |
||
341 | if (--domCheckCount) {
|
||
342 | // in some browsers (Opera) the iframe DOM is not always traversable when
|
||
343 | // the onload callback fires, so we loop a bit to accommodate
|
||
344 | log('requeing onLoad callback, DOM not available');
|
||
345 | setTimeout(cb, 250);
|
||
346 | return;
|
||
347 | } |
||
348 | // let this fall through because server response could be an empty document
|
||
349 | //log('Could not access iframe DOM after mutiple tries.');
|
||
350 | //throw 'DOMException: not available';
|
||
351 | } |
||
352 | |||
353 | //log('response detected');
|
||
354 | xhr.responseText = doc.body ? doc.body.innerHTML : doc.documentElement ? doc.documentElement.innerHTML : null;
|
||
355 | xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc; |
||
356 | xhr.getResponseHeader = function(header){ |
||
357 | var headers = {'content-type': s.dataType}; |
||
358 | return headers[header];
|
||
359 | }; |
||
360 | |||
361 | var scr = /(json|script)/.test(s.dataType); |
||
362 | if (scr || s.textarea) {
|
||
363 | // see if user embedded response in textarea
|
||
364 | var ta = doc.getElementsByTagName('textarea')[0]; |
||
365 | if (ta) {
|
||
366 | xhr.responseText = ta.value; |
||
367 | } |
||
368 | else if (scr) { |
||
369 | // account for browsers injecting pre around json response
|
||
370 | var pre = doc.getElementsByTagName('pre')[0]; |
||
371 | var b = doc.getElementsByTagName('body')[0]; |
||
372 | if (pre) {
|
||
373 | xhr.responseText = pre.textContent; |
||
374 | } |
||
375 | else if (b) { |
||
376 | xhr.responseText = b.innerHTML; |
||
377 | } |
||
378 | } |
||
379 | } |
||
380 | else if (s.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) { |
||
381 | xhr.responseXML = toXml(xhr.responseText); |
||
382 | } |
||
383 | |||
384 | data = httpData(xhr, s.dataType, s); |
||
385 | } |
||
386 | catch(e){
|
||
387 | log('error caught:',e);
|
||
388 | ok = false;
|
||
389 | xhr.error = e; |
||
390 | s.error && s.error.call(s.context, xhr, 'error', e);
|
||
391 | g && $.event.trigger("ajaxError", [xhr, s, e]); |
||
392 | } |
||
393 | |||
394 | if (xhr.aborted) {
|
||
395 | log('upload aborted');
|
||
396 | ok = false;
|
||
397 | } |
||
398 | |||
399 | // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
|
||
400 | if (ok) {
|
||
401 | s.success && s.success.call(s.context, data, 'success', xhr);
|
||
402 | g && $.event.trigger("ajaxSuccess", [xhr, s]); |
||
403 | } |
||
404 | |||
405 | g && $.event.trigger("ajaxComplete", [xhr, s]); |
||
406 | |||
407 | if (g && ! --$.active) { |
||
408 | $.event.trigger("ajaxStop"); |
||
409 | } |
||
410 | |||
411 | s.complete && s.complete.call(s.context, xhr, ok ? 'success' : 'error'); |
||
412 | |||
413 | // clean up
|
||
414 | setTimeout(function() {
|
||
415 | $io.removeData('form-plugin-onload'); |
||
416 | $io.remove();
|
||
417 | xhr.responseXML = null;
|
||
418 | }, 100);
|
||
419 | } |
||
420 | |||
421 | var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+) |
||
422 | if (window.ActiveXObject) {
|
||
423 | doc = new ActiveXObject('Microsoft.XMLDOM'); |
||
424 | doc.async = 'false';
|
||
425 | doc.loadXML(s); |
||
426 | } |
||
427 | else {
|
||
428 | doc = (new DOMParser()).parseFromString(s, 'text/xml'); |
||
429 | } |
||
430 | return (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc : null; |
||
431 | }; |
||
432 | var parseJSON = $.parseJSON || function(s) { |
||
433 | return window['eval']('(' + s + ')'); |
||
434 | }; |
||
435 | |||
436 | var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4 |
||
437 | var ct = xhr.getResponseHeader('content-type') || '', |
||
438 | xml = type === 'xml' || !type && ct.indexOf('xml') >= 0, |
||
439 | data = xml ? xhr.responseXML : xhr.responseText; |
||
440 | |||
441 | if (xml && data.documentElement.nodeName === 'parsererror') { |
||
442 | $.error && $.error('parsererror'); |
||
443 | } |
||
444 | if (s && s.dataFilter) {
|
||
445 | data = s.dataFilter(data, type); |
||
446 | } |
||
447 | if (typeof data === 'string') { |
||
448 | if (type === 'json' || !type && ct.indexOf('json') >= 0) { |
||
449 | data = parseJSON(data); |
||
450 | } else if (type === "script" || !type && ct.indexOf("javascript") >= 0) { |
||
451 | $.globalEval(data);
|
||
452 | } |
||
453 | } |
||
454 | return data;
|
||
455 | }; |
||
456 | } |
||
457 | }; |
||
458 | |||
459 | /**
|
||
460 | * ajaxForm() provides a mechanism for fully automating form submission.
|
||
461 | *
|
||
462 | * The advantages of using this method instead of ajaxSubmit() are:
|
||
463 | *
|
||
464 | * 1: This method will include coordinates for <input type="image" /> elements (if the element
|
||
465 | * is used to submit the form).
|
||
466 | * 2. This method will include the submit element's name/value data (for the element that was
|
||
467 | * used to submit the form).
|
||
468 | * 3. This method binds the submit() method to the form for you.
|
||
469 | *
|
||
470 | * The options argument for ajaxForm works exactly as it does for ajaxSubmit. ajaxForm merely
|
||
471 | * passes the options argument along after properly binding events for submit elements and
|
||
472 | * the form itself.
|
||
473 | */
|
||
474 | $.fn.ajaxForm = function(options) { |
||
475 | // in jQuery 1.3+ we can fix mistakes with the ready state
|
||
476 | if (this.length === 0) { |
||
477 | var o = { s: this.selector, c: this.context }; |
||
478 | if (!$.isReady && o.s) { |
||
479 | log('DOM not ready, queuing ajaxForm');
|
||
480 | $(function() { |
||
481 | $(o.s,o.c).ajaxForm(options);
|
||
482 | }); |
||
483 | return this; |
||
484 | } |
||
485 | // is your DOM ready? http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
|
||
486 | log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)')); |
||
487 | return this; |
||
488 | } |
||
489 | |||
490 | return this.ajaxFormUnbind().bind('submit.form-plugin', function(e) { |
||
491 | if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed |
||
492 | e.preventDefault(); |
||
493 | $(this).ajaxSubmit(options); |
||
494 | } |
||
495 | }).bind('click.form-plugin', function(e) { |
||
496 | var target = e.target;
|
||
497 | var $el = $(target); |
||
498 | if (!($el.is(":submit,input:image"))) { |
||
499 | // is this a child element of the submit el? (ex: a span within a button)
|
||
500 | var t = $el.closest(':submit'); |
||
501 | if (t.length == 0) { |
||
502 | return;
|
||
503 | } |
||
504 | target = t[0];
|
||
505 | } |
||
506 | var form = this; |
||
507 | form.clk = target; |
||
508 | if (target.type == 'image') { |
||
509 | if (e.offsetX != undefined) { |
||
510 | form.clk_x = e.offsetX; |
||
511 | form.clk_y = e.offsetY; |
||
512 | } else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin |
||
513 | var offset = $el.offset(); |
||
514 | form.clk_x = e.pageX - offset.left; |
||
515 | form.clk_y = e.pageY - offset.top; |
||
516 | } else {
|
||
517 | form.clk_x = e.pageX - target.offsetLeft; |
||
518 | form.clk_y = e.pageY - target.offsetTop; |
||
519 | } |
||
520 | } |
||
521 | // clear form vars
|
||
522 | setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100); |
||
523 | }); |
||
524 | }; |
||
525 | |||
526 | // ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
|
||
527 | $.fn.ajaxFormUnbind = function() { |
||
528 | return this.unbind('submit.form-plugin click.form-plugin'); |
||
529 | }; |
||
530 | |||
531 | /**
|
||
532 | * formToArray() gathers form element data into an array of objects that can
|
||
533 | * be passed to any of the following ajax functions: $.get, $.post, or load.
|
||
534 | * Each object in the array has both a 'name' and 'value' property. An example of
|
||
535 | * an array for a simple login form might be:
|
||
536 | *
|
||
537 | * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
|
||
538 | *
|
||
539 | * It is this array that is passed to pre-submit callback functions provided to the
|
||
540 | * ajaxSubmit() and ajaxForm() methods.
|
||
541 | */
|
||
542 | $.fn.formToArray = function(semantic) { |
||
543 | var a = [];
|
||
544 | if (this.length === 0) { |
||
545 | return a;
|
||
546 | } |
||
547 | |||
548 | var form = this[0]; |
||
549 | var els = semantic ? form.getElementsByTagName('*') : form.elements; |
||
550 | if (!els) {
|
||
551 | return a;
|
||
552 | } |
||
553 | |||
554 | var i,j,n,v,el,max,jmax;
|
||
555 | for(i=0, max=els.length; i < max; i++) { |
||
556 | el = els[i]; |
||
557 | n = el.name; |
||
558 | if (!n) {
|
||
559 | continue;
|
||
560 | } |
||
561 | |||
562 | if (semantic && form.clk && el.type == "image") { |
||
563 | // handle image inputs on the fly when semantic == true
|
||
564 | if(!el.disabled && form.clk == el) {
|
||
565 | a.push({name: n, value: $(el).val()}); |
||
566 | a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y}); |
||
567 | } |
||
568 | continue;
|
||
569 | } |
||
570 | |||
571 | v = $.fieldValue(el, true); |
||
572 | if (v && v.constructor == Array) {
|
||
573 | for(j=0, jmax=v.length; j < jmax; j++) { |
||
574 | a.push({name: n, value: v[j]}); |
||
575 | } |
||
576 | } |
||
577 | else if (v !== null && typeof v != 'undefined') { |
||
578 | a.push({name: n, value: v}); |
||
579 | } |
||
580 | } |
||
581 | |||
582 | if (!semantic && form.clk) {
|
||
583 | // input type=='image' are not found in elements array! handle it here
|
||
584 | var $input = $(form.clk), input = $input[0]; |
||
585 | n = input.name; |
||
586 | if (n && !input.disabled && input.type == 'image') { |
||
587 | a.push({name: n, value: $input.val()}); |
||
588 | a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y}); |
||
589 | } |
||
590 | } |
||
591 | return a;
|
||
592 | }; |
||
593 | |||
594 | /**
|
||
595 | * Serializes form data into a 'submittable' string. This method will return a string
|
||
596 | * in the format: name1=value1&name2=value2
|
||
597 | */
|
||
598 | $.fn.formSerialize = function(semantic) { |
||
599 | //hand off to jQuery.param for proper encoding
|
||
600 | return $.param(this.formToArray(semantic)); |
||
601 | }; |
||
602 | |||
603 | /**
|
||
604 | * Serializes all field elements in the jQuery object into a query string.
|
||
605 | * This method will return a string in the format: name1=value1&name2=value2
|
||
606 | */
|
||
607 | $.fn.fieldSerialize = function(successful) { |
||
608 | var a = [];
|
||
609 | this.each(function() { |
||
610 | var n = this.name; |
||
611 | if (!n) {
|
||
612 | return;
|
||
613 | } |
||
614 | var v = $.fieldValue(this, successful); |
||
615 | if (v && v.constructor == Array) {
|
||
616 | for (var i=0,max=v.length; i < max; i++) { |
||
617 | a.push({name: n, value: v[i]}); |
||
618 | } |
||
619 | } |
||
620 | else if (v !== null && typeof v != 'undefined') { |
||
621 | a.push({name: this.name, value: v}); |
||
622 | } |
||
623 | }); |
||
624 | //hand off to jQuery.param for proper encoding
|
||
625 | return $.param(a); |
||
626 | }; |
||
627 | |||
628 | /**
|
||
629 | * Returns the value(s) of the element in the matched set. For example, consider the following form:
|
||
630 | *
|
||
631 | * <form><fieldset>
|
||
632 | * <input name="A" type="text" />
|
||
633 | * <input name="A" type="text" />
|
||
634 | * <input name="B" type="checkbox" value="B1" />
|
||
635 | * <input name="B" type="checkbox" value="B2"/>
|
||
636 | * <input name="C" type="radio" value="C1" />
|
||
637 | * <input name="C" type="radio" value="C2" />
|
||
638 | * </fieldset></form>
|
||
639 | *
|
||
640 | * var v = $(':text').fieldValue();
|
||
641 | * // if no values are entered into the text inputs
|
||
642 | * v == ['','']
|
||
643 | * // if values entered into the text inputs are 'foo' and 'bar'
|
||
644 | * v == ['foo','bar']
|
||
645 | *
|
||
646 | * var v = $(':checkbox').fieldValue();
|
||
647 | * // if neither checkbox is checked
|
||
648 | * v === undefined
|
||
649 | * // if both checkboxes are checked
|
||
650 | * v == ['B1', 'B2']
|
||
651 | *
|
||
652 | * var v = $(':radio').fieldValue();
|
||
653 | * // if neither radio is checked
|
||
654 | * v === undefined
|
||
655 | * // if first radio is checked
|
||
656 | * v == ['C1']
|
||
657 | *
|
||
658 | * The successful argument controls whether or not the field element must be 'successful'
|
||
659 | * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
|
||
660 | * The default value of the successful argument is true. If this value is false the value(s)
|
||
661 | * for each element is returned.
|
||
662 | *
|
||
663 | * Note: This method *always* returns an array. If no valid value can be determined the
|
||
664 | * array will be empty, otherwise it will contain one or more values.
|
||
665 | */
|
||
666 | $.fn.fieldValue = function(successful) { |
||
667 | for (var val=[], i=0, max=this.length; i < max; i++) { |
||
668 | var el = this[i]; |
||
669 | var v = $.fieldValue(el, successful); |
||
670 | if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) { |
||
671 | continue;
|
||
672 | } |
||
673 | v.constructor == Array ? $.merge(val, v) : val.push(v);
|
||
674 | } |
||
675 | return val;
|
||
676 | }; |
||
677 | |||
678 | /**
|
||
679 | * Returns the value of the field element.
|
||
680 | */
|
||
681 | $.fieldValue = function(el, successful) { |
||
682 | var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
|
||
683 | if (successful === undefined) { |
||
684 | successful = true;
|
||
685 | } |
||
686 | |||
687 | if (successful && (!n || el.disabled || t == 'reset' || t == 'button' || |
||
688 | (t == 'checkbox' || t == 'radio') && !el.checked || |
||
689 | (t == 'submit' || t == 'image') && el.form && el.form.clk != el || |
||
690 | tag == 'select' && el.selectedIndex == -1)) { |
||
691 | return null; |
||
692 | } |
||
693 | |||
694 | if (tag == 'select') { |
||
695 | var index = el.selectedIndex;
|
||
696 | if (index < 0) { |
||
697 | return null; |
||
698 | } |
||
699 | var a = [], ops = el.options;
|
||
700 | var one = (t == 'select-one'); |
||
701 | var max = (one ? index+1 : ops.length); |
||
702 | for(var i=(one ? index : 0); i < max; i++) { |
||
703 | var op = ops[i];
|
||
704 | if (op.selected) {
|
||
705 | var v = op.value;
|
||
706 | if (!v) { // extra pain for IE... |
||
707 | v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value; |
||
708 | } |
||
709 | if (one) {
|
||
710 | return v;
|
||
711 | } |
||
712 | a.push(v); |
||
713 | } |
||
714 | } |
||
715 | return a;
|
||
716 | } |
||
717 | return $(el).val(); |
||
718 | }; |
||
719 | |||
720 | /**
|
||
721 | * Clears the form data. Takes the following actions on the form's input fields:
|
||
722 | * - input text fields will have their 'value' property set to the empty string
|
||
723 | * - select elements will have their 'selectedIndex' property set to -1
|
||
724 | * - checkbox and radio inputs will have their 'checked' property set to false
|
||
725 | * - inputs of type submit, button, reset, and hidden will *not* be effected
|
||
726 | * - button elements will *not* be effected
|
||
727 | */
|
||
728 | $.fn.clearForm = function() { |
||
729 | return this.each(function() { |
||
730 | $('input,select,textarea', this).clearFields(); |
||
731 | }); |
||
732 | }; |
||
733 | |||
734 | /**
|
||
735 | * Clears the selected form elements.
|
||
736 | */
|
||
737 | $.fn.clearFields = $.fn.clearInputs = function() { |
||
738 | return this.each(function() { |
||
739 | var t = this.type, tag = this.tagName.toLowerCase(); |
||
740 | if (t == 'text' || t == 'password' || tag == 'textarea') { |
||
741 | this.value = ''; |
||
742 | } |
||
743 | else if (t == 'checkbox' || t == 'radio') { |
||
744 | this.checked = false; |
||
745 | } |
||
746 | else if (tag == 'select') { |
||
747 | this.selectedIndex = -1; |
||
748 | } |
||
749 | }); |
||
750 | }; |
||
751 | |||
752 | /**
|
||
753 | * Resets the form data. Causes all form elements to be reset to their original value.
|
||
754 | */
|
||
755 | $.fn.resetForm = function() { |
||
756 | return this.each(function() { |
||
757 | // guard against an input with the name of 'reset'
|
||
758 | // note that IE reports the reset function as an 'object'
|
||
759 | if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) { |
||
760 | this.reset();
|
||
761 | } |
||
762 | }); |
||
763 | }; |
||
764 | |||
765 | /**
|
||
766 | * Enables or disables any matching elements.
|
||
767 | */
|
||
768 | $.fn.enable = function(b) { |
||
769 | if (b === undefined) { |
||
770 | b = true;
|
||
771 | } |
||
772 | return this.each(function() { |
||
773 | this.disabled = !b;
|
||
774 | }); |
||
775 | }; |
||
776 | |||
777 | /**
|
||
778 | * Checks/unchecks any matching checkboxes or radio buttons and
|
||
779 | * selects/deselects and matching option elements.
|
||
780 | */
|
||
781 | $.fn.selected = function(select) { |
||
782 | if (select === undefined) { |
||
783 | select = true;
|
||
784 | } |
||
785 | return this.each(function() { |
||
786 | var t = this.type; |
||
787 | if (t == 'checkbox' || t == 'radio') { |
||
788 | this.checked = select;
|
||
789 | } |
||
790 | else if (this.tagName.toLowerCase() == 'option') { |
||
791 | var $sel = $(this).parent('select'); |
||
792 | if (select && $sel[0] && $sel[0].type == 'select-one') { |
||
793 | // deselect all other options
|
||
794 | $sel.find('option').selected(false); |
||
795 | } |
||
796 | this.selected = select;
|
||
797 | } |
||
798 | }); |
||
799 | }; |
||
800 | |||
801 | // helper fn for console logging
|
||
802 | // set $.fn.ajaxSubmit.debug to true to enable debug logging
|
||
803 | function log() { |
||
804 | if ($.fn.ajaxSubmit.debug) { |
||
805 | var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,''); |
||
806 | if (window.console && window.console.log) {
|
||
807 | window.console.log(msg); |
||
808 | } |
||
809 | else if (window.opera && window.opera.postError) { |
||
810 | window.opera.postError(msg); |
||
811 | } |
||
812 | } |
||
813 | }; |
||
814 | |||
815 | })(jQuery); |