PageSourceSearch

https://www.bjxkyy.cn/Scripts/Awesome/jquery.form.js

js bjxkyy.cn collected 2026-10-06 20:52:28 UTC 27,093 bytes, 675 lines download raw bytes

1/*!
2* jQuery Form Plugin
3* version: 2.43 (12-MAR-2010)
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() {
22    $(this).ajaxSubmit({
23    target: '#output'
24    });
25    return false; // <-- important!
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        var url = $.trim(this.attr('action'));
57        if (url) {
58            // clean url (don't include hash vaue)
59            url = (url.match(/^([^#]+)/) || [])[1];
60        }
61        url = url || window.location.href || '';
62
63        options = $.extend({
64            url: url,
65            type: this.attr('method') || 'GET',
66            iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
67        }, options || {});
68
69        // hook for manipulating the form data before it is extracted;
70        // convenient for use with rich editors like tinyMCE or FCKEditor
71        var veto = {};
72        this.trigger('form-pre-serialize', [this, options, veto]);
73        if (veto.veto) {
74            log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
75            return this;
76        }
77
78        // provide opportunity to alter form data before it is serialized
79        if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
80            log('ajaxSubmit: submit aborted via beforeSerialize callback');
81            return this;
82        }
83
84        var a = this.formToArray(options.semantic);
85        if (options.data) {
86            options.extraData = options.data;
87            for (var n in options.data) {
88                if (options.data[n] instanceof Array) {
89                    for (var k in options.data[n])
90                        a.push({ name: n, value: options.data[n][k] });
91                }
92                else
93                    a.push({ name: n, value: options.data[n] });
94            }
95        }
96
97        // give pre-submit callback an opportunity to abort the submit
98        if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
99            log('ajaxSubmit: submit aborted via beforeSubmit callback');
100            return this;
101        }
102
103        // fire vetoable 'validate' event
104        this.trigger('form-submit-validate', [a, this, options, veto]);
105        if (veto.veto) {
106            log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
107            return this;
108        }
109
110        var q = $.param(a);
111
112        if (options.type.toUpperCase() == 'GET') {
113            options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
114            options.data = null;  // data is null for 'get'
115        }
116        else
117            options.data = q; // data is the query string for 'post'
118
119        var $form = this, callbacks = [];
120        if (options.resetForm) callbacks.push(function () { $form.resetForm(); });
121        if (options.clearForm) callbacks.push(function () { $form.clearForm(); });
122
123        // perform a load on the target only if dataType is not provided
124        if (!options.dataType && options.target) {
125            var oldSuccess = options.success || function () { };
126            callbacks.push(function (data) {
127                var fn = options.replaceTarget ? 'replaceWith' : 'html';
128                $(options.target)[fn](data).each(oldSuccess, arguments);
129            });
130        }
131        else if (options.success)
132            callbacks.push(options.success);
133
134        options.success = function (data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
135            for (var i = 0, max = callbacks.length; i < max; i++)
136                callbacks[i].apply(options, [data, status, xhr || $form, $form]);
137        };
138
139        // are there files to upload?
140        var files = $('input:file', this).fieldValue();
141        var found = false;
142        for (var j = 0; j < files.length; j++)
143            if (files[j])
144                found = true;
145
146        var multipart = false;
147        //	var mp = 'multipart/form-data';
148        //	multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
149
150        // options.iframe allows user to force iframe mode
151        // 06-NOV-09: now defaulting to iframe mode if file input is detected
152        if ((files.length && options.iframe !== false) || options.iframe || found || multipart) {
153            // hack to fix Safari hang (thanks to Tim Molendijk for this)
154            // see:  http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
155            if (options.closeKeepAlive)
156                $.get(options.closeKeepAlive, fileUpload);
157            else
158                fileUpload();
159        }
160        else
161            $.ajax(options);
162
163        // fire 'notify' event
164        this.trigger('form-submit-notify', [this, options]);
165        return this;
166
167
168        // private function for handling file uploads (hat tip to YAHOO!)
169        function fileUpload() {
170            var form = $form[0];
171
172            if ($(':input[name=submit]', form).length) {
173                alert('Error: Form elements must not be named "submit".');
174                return;
175            }
176
177            var opts = $.extend({}, $.ajaxSettings, options);
178            var s = $.extend(true, {}, $.extend(true, {}, $.ajaxSettings), opts);
179
180            var id = 'jqFormIO' + (new Date().getTime());
181            var $io = $('<iframe id="' + id + '" name="' + id + '" src="' + opts.iframeSrc + '" onload="(jQuery(this).data(\'form-plugin-onload\'))()" />');
182            var io = $io[0];
183
184            $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
185
186            var xhr = { // mock object
187                aborted: 0,
188                responseText: null,
189                responseXML: null,
190                status: 0,
191                statusText: 'n/a',
192                getAllResponseHeaders: function () { },
193                getResponseHeader: function () { },
194                setRequestHeader: function () { },
195                abort: function () {
196                    this.aborted = 1;
197                    $io.attr('src', opts.iframeSrc); // abort op in progress
198                }
199            };
200
201            var g = opts.global;
202            // trigger ajax global events so that activity/block indicators work like normal
203            if (g && !$.active++) $.event.trigger("ajaxStart");
204            if (g) $.event.trigger("ajaxSend", [xhr, opts]);
205
206            if (s.beforeSend && s.beforeSend(xhr, s) === false) {
207                s.global && $.active--;
208                return;
209            }
210            if (xhr.aborted)
211                return;
212
213            var cbInvoked = false;
214            var timedOut = 0;
215
216            // add submitting element to data if we know it
217            var sub = form.clk;
218            if (sub) {
219                var n = sub.name;
220                if (n && !sub.disabled) {
221                    opts.extraData = opts.extraData || {};
222                    opts.extraData[n] = sub.value;
223                    if (sub.type == "image") {
224                        opts.extraData[n + '.x'] = form.clk_x;
225                        opts.extraData[n + '.y'] = form.clk_y;
226                    }
227                }
228            }
229
230            // take a breath so that pending repaints get some cpu time before the upload starts
231            function doSubmit() {
232                // make sure form attrs are set
233                var t = $form.attr('target'), a = $form.attr('action');
234
235                // update form attrs in IE friendly way
236                form.setAttribute('target', id);
237                if (form.getAttribute('method') != 'POST')
238                    form.setAttribute('method', 'POST');
239                if (form.getAttribute('action') != opts.url)
240                    form.setAttribute('action', opts.url);
241
242                // ie borks in some cases when setting encoding
243                if (!opts.skipEncodingOverride) {
244                    $form.attr({
245                        encoding: 'multipart/form-data',
246                        enctype: 'multipart/form-data'
247                    });
248                }
249
250                // support timout
251                if (opts.timeout)
252                    setTimeout(function () { timedOut = true; cb(); }, opts.timeout);
253
254                // add "extra" data to form if provided in options
255                var extraInputs = [];
256                try {
257                    if (opts.extraData)
258                        for (var n in opts.extraData)
259                            extraInputs.push(
260							$('<input type="hidden" name="' + n + '" value="' + opts.extraData[n] + '" />')
261								.appendTo(form)[0]);
262
263                    // add iframe to doc and submit the form
264                    $io.appendTo('body');
265                    $io.data('form-plugin-onload', cb);
266                    form.submit();
267                }
268                finally {
269                    // reset attrs and remove "extra" input elements
270                    form.setAttribute('action', a);
271                    t ? form.setAttribute('target', t) : $form.removeAttr('target');
272                    $(extraInputs).remove();
273                }
274            };
275
276            if (opts.forceSync)
277                doSubmit();
278            else
279                setTimeout(doSubmit, 10); // this lets dom updates render
280
281            var domCheckCount = 100;
282
283            function cb() {
284                if (cbInvoked)
285                    return;
286
287                var ok = true;
288                try {
289                    if (timedOut) throw 'timeout';
290                    // extract the server response from the iframe
291                    var data, doc;
292
293                    doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;
294
295                    var isXml = opts.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
296                    log('isXml=' + isXml);
297                    if (!isXml && (doc.body == null || doc.body.innerHTML == '')) {
298                        if (--domCheckCount) {
299                            // in some browsers (Opera) the iframe DOM is not always traversable when
300                            // the onload callback fires, so we loop a bit to accommodate
301                            log('requeing onLoad callback, DOM not available');
302                            setTimeout(cb, 250);
303                            return;
304                        }
305                        log('Could not access iframe DOM after 100 tries.');
306                        return;
307                    }
308
309                    log('response detected');
310                    cbInvoked = true;
311                    xhr.responseText = doc.body ? doc.body.innerHTML : null;
312                    xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
313                    xhr.getResponseHeader = function (header) {
314                        var headers = { 'content-type': opts.dataType };
315                        return headers[header];
316                    };
317
318                    if (opts.dataType == 'json' || opts.dataType == 'script') {
319                        // see if user embedded response in textarea
320                        var ta = doc.getElementsByTagName('textarea')[0];
321                        if (ta)
322                            xhr.responseText = ta.value;
323                        else {
324                            // account for browsers injecting pre around json response
325                            var pre = doc.getElementsByTagName('pre')[0];
326                            if (pre)
327                                xhr.responseText = pre.innerHTML;
328                        }
329                    }
330                    else if (opts.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) {
331                        xhr.responseXML = toXml(xhr.responseText);
332                    }
333                    data = $.httpData(xhr, opts.dataType);
334                }
335                catch (e) {
336                    log('error caught:', e);
337                    ok = false;
338                    xhr.error = e;
339                    $.handleError(opts, xhr, 'error', e);
340                }
341
342                // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
343                if (ok) {
344                    opts.success(data, 'success');
345                    if (g) $.event.trigger("ajaxSuccess", [xhr, opts]);
346                }
347                if (g) $.event.trigger("ajaxComplete", [xhr, opts]);
348                if (g && ! --$.active) $.event.trigger("ajaxStop");
349                if (opts.complete) opts.complete(xhr, ok ? 'success' : 'error');
350
351                // clean up
352                setTimeout(function () {
353                    $io.removeData('form-plugin-onload');
354                    $io.remove();
355                    xhr.responseXML = null;
356                }, 100);
357            };
358
359            function toXml(s, doc) {
360                if (window.ActiveXObject) {
361                    doc = new ActiveXObject('Microsoft.XMLDOM');
362                    doc.async = 'false';
363                    doc.loadXML(s);
364                }
365                else
366                    doc = (new DOMParser()).parseFromString(s, 'text/xml');
367                return (doc && doc.documentElement && doc.documentElement.tagName != 'parsererror') ? doc : null;
368            };
369        };
370    };
371
372    /**
373    * ajaxForm() provides a mechanism for fully automating form submission.
374    *
375    * The advantages of using this method instead of ajaxSubmit() are:
376    *
377    * 1: This method will include coordinates for <input type="image" /> elements (if the element
378    *	is used to submit the form).
379    * 2. This method will include the submit element's name/value data (for the element that was
380    *	used to submit the form).
381    * 3. This method binds the submit() method to the form for you.
382    *
383    * The options argument for ajaxForm works exactly as it does for ajaxSubmit.  ajaxForm merely
384    * passes the options argument along after properly binding events for submit elements and
385    * the form itself.
386    */
387    $.fn.ajaxForm = function (options) {
388        return this.ajaxFormUnbind().bind('submit.form-plugin', function (e) {
389            e.preventDefault();
390            $(this).ajaxSubmit(options);
391        }).bind('click.form-plugin', function (e) {
392            var target = e.target;
393            var $el = $(target);
394            if (!($el.is(":submit,input:image"))) {
395                // is this a child element of the submit el?  (ex: a span within a button)
396                var t = $el.closest(':submit');
397                if (t.length == 0)
398                    return;
399                target = t[0];
400            }
401            var form = this;
402            form.clk = target;
403            if (target.type == 'image') {
404                if (e.offsetX != undefined) {
405                    form.clk_x = e.offsetX;
406                    form.clk_y = e.offsetY;
407                } else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin
408                    var offset = $el.offset();
409                    form.clk_x = e.pageX - offset.left;
410                    form.clk_y = e.pageY - offset.top;
411                } else {
412                    form.clk_x = e.pageX - target.offsetLeft;
413                    form.clk_y = e.pageY - target.offsetTop;
414                }
415            }
416            // clear form vars
417            setTimeout(function () { form.clk = form.clk_x = form.clk_y = null; }, 100);
418        });
419    };
420
421    // ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
422    $.fn.ajaxFormUnbind = function () {
423        return this.unbind('submit.form-plugin click.form-plugin');
424    };
425
426    /**
427    * formToArray() gathers form element data into an array of objects that can
428    * be passed to any of the following ajax functions: $.get, $.post, or load.
429    * Each object in the array has both a 'name' and 'value' property.  An example of
430    * an array for a simple login form might be:
431    *
432    * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
433    *
434    * It is this array that is passed to pre-submit callback functions provided to the
435    * ajaxSubmit() and ajaxForm() methods.
436    */
437    $.fn.formToArray = function (semantic) {
438        var a = [];
439        if (this.length == 0) return a;
440
441        var form = this[0];
442        var els = semantic ? form.getElementsByTagName('*') : form.elements;
443        if (!els) return a;
444        for (var i = 0, max = els.length; i < max; i++) {
445            var el = els[i];
446            var n = el.name;
447            if (!n) continue;
448
449            if (semantic && form.clk && el.type == "image") {
450                // handle image inputs on the fly when semantic == true
451                if (!el.disabled && form.clk == el) {
452                    a.push({ name: n, value: $(el).val() });
453                    a.push({ name: n + '.x', value: form.clk_x }
453, { name: n + '.y', value: form.clk_y });
454                }
455                continue;
456            }
457
458            var v = $.fieldValue(el, true);
459            if (v && v.constructor == Array) {
460                for (var j = 0, jmax = v.length; j < jmax; j++)
461                    a.push({ name: n, value: v[j] });
462            }
463            else if (v !== null && typeof v != 'undefined')
464                a.push({ name: n, value: v });
465        }
466
467        if (!semantic && form.clk) {
468            // input type=='image' are not found in elements array! handle it here
469            var $input = $(form.clk), input = $input[0], n = input.name;
470            if (n && !input.disabled && input.type == 'image') {
471                a.push({ name: n, value: $input.val() });
472                a.push({ name: n + '.x', value: form.clk_x }, { name: n + '.y', value: form.clk_y });
473            }
474        }
475        return a;
476    };
477
478    /**
479    * Serializes form data into a 'submittable' string. This method will return a string
480    * in the format: name1=value1&amp;name2=value2
481    */
482    $.fn.formSerialize = function (semantic) {
483        //hand off to jQuery.param for proper encoding
484        return $.param(this.formToArray(semantic));
485    };
486
487    /**
488    * Serializes all field elements in the jQuery object into a query string.
489    * This method will return a string in the format: name1=value1&amp;name2=value2
490    */
491    $.fn.fieldSerialize = function (successful) {
492        var a = [];
493        this.each(function () {
494            var n = this.name;
495            if (!n) return;
496            var v = $.fieldValue(this, successful);
497            if (v && v.constructor == Array) {
498                for (var i = 0, max = v.length; i < max; i++)
499                    a.push({ name: n, value: v[i] });
500            }
501            else if (v !== null && typeof v != 'undefined')
502                a.push({ name: this.name, value: v });
503        });
504        //hand off to jQuery.param for proper encoding
505        return $.param(a);
506    };
507
508    /**
509    * Returns the value(s) of the element in the matched set.  For example, consider the following form:
510    *
511    *  <form><fieldset>
512    *	  <input name="A" type="text" />
513    *	  <input name="A" type="text" />
514    *	  <input name="B" type="checkbox" value="B1" />
515    *	  <input name="B" type="checkbox" value="B2"/>
516    *	  <input name="C" type="radio" value="C1" />
517    *	  <input name="C" type="radio" value="C2" />
518    *  </fieldset></form>
519    *
520    *  var v = $(':text').fieldValue();
521    *  // if no values are entered into the text inputs
522    *  v == ['','']
523    *  // if values entered into the text inputs are 'foo' and 'bar'
524    *  v == ['foo','bar']
525    *
526    *  var v = $(':checkbox').fieldValue();
527    *  // if neither checkbox is checked
528    *  v === undefined
529    *  // if both checkboxes are checked
530    *  v == ['B1', 'B2']
531    *
532    *  var v = $(':radio').fieldValue();
533    *  // if neither radio is checked
534    *  v === undefined
535    *  // if first radio is checked
536    *  v == ['C1']
537    *
538    * The successful argument controls whether or not the field element must be 'successful'
539    * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
540    * The default value of the successful argument is true.  If this value is false the value(s)
541    * for each element is returned.
542    *
543    * Note: This method *always* returns an array.  If no valid value can be determined the
544    *	   array will be empty, otherwise it will contain one or more values.
545    */
546    $.fn.fieldValue = function (successful) {
547        for (var val = [], i = 0, max = this.length; i < max; i++) {
548            var el = this[i];
549            var v = $.fieldValue(el, successful);
550            if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length))
551                continue;
552            v.constructor == Array ? $.merge(val, v) : val.push(v);
553        }
554        return val;
555    };
556
557    /**
558    * Returns the value of the field element.
559    */
560    $.fieldValue = function (el, successful) {
561        var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
562        if (typeof successful == 'undefined') successful = true;
563
564        if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
565		(t == 'checkbox' || t == 'radio') && !el.checked ||
566		(t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
567		tag == 'select' && el.selectedIndex == -1))
568            return null;
569
570        if (tag == 'select') {
571            var index = el.selectedIndex;
572            if (index < 0) return null;
573            var a = [], ops = el.options;
574            var one = (t == 'select-one');
575            var max = (one ? index + 1 : ops.length);
576            for (var i = (one ? index : 0); i < max; i++) {
577                var op = ops[i];
578                if (op.selected) {
579                    var v = op.value;
580                    if (!v) // extra pain for IE...
581                        v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
582                    if (one) return v;
583                    a.push(v);
584                }
585            }
586            return a;
587        }
588        return el.value;
589    };
590
591    /**
592    * Clears the form data.  Takes the following actions on the form's input fields:
593    *  - input text fields will have their 'value' property set to the empty string
594    *  - select elements will have their 'selectedIndex' property set to -1
595    *  - checkbox and radio inputs will have their 'checked' property set to false
596    *  - inputs of type submit, button, reset, and hidden will *not* be effected
597    *  - button elements will *not* be effected
598    */
599    $.fn.clearForm = function () {
600        return this.each(function () {
601            $('input,select,textarea', this).clearFields();
602        });
603    };
604
605    /**
606    * Clears the selected form elements.
607    */
608    $.fn.clearFields = $.fn.clearInputs = function () {
609        return this.each(function () {
610            var t = this.type, tag = this.tagName.toLowerCase();
611            if (t == 'text' || t == 'password' || tag == 'textarea')
612                this.value = '';
613            else if (t == 'checkbox' || t == 'radio')
614                this.checked = false;
615            else if (tag == 'select')
616                this.selectedIndex = -1;
617        });
618    };
619
620    /**
621    * Resets the form data.  Causes all form elements to be reset to their original value.
622    */
623    $.fn.resetForm = function () {
624        return this.each(function () {
625            // guard against an input with the name of 'reset'
626            // note that IE reports the reset function as an 'object'
627            if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType))
628                this.reset();
629        });
630    };
631
632    /**
633    * Enables or disables any matching elements.
634    */
635    $.fn.enable = function (b) {
636        if (b == undefined) b = true;
637        return this.each(function () {
638            this.disabled = !b;
639        });
640    };
641
642    /**
643    * Checks/unchecks any matching checkboxes or radio buttons and
644    * selects/deselects and matching option elements.
645    */
646    $.fn.selected = function (select) {
647        if (select == undefined) select = true;
648        return this.each(function () {
649            var t = this.type;
650            if (t == 'checkbox' || t == 'radio')
651                this.checked = select;
652            else if (this.tagName.toLowerCase() == 'option') {
653                var $sel = $(this).parent('select');
654                if (select && $sel[0] && $sel[0].type == 'select-one') {
655                    // deselect all other options
656                    $sel.find('option').selected(false);
657                }
658                this.selected = select;
659            }
660        });
661    };
662
663    // helper fn for console logging
664    // set $.fn.ajaxSubmit.debug to true to enable debug logging
665    function log() {
666        if ($.fn.ajaxSubmit.debug) {
667            var msg = '[jquery.form] ' + Array.prototype.join.call(arguments, '');
668            if (window.console && window.console.log)
669                window.console.log(msg);
670            else if (window.opera && window.opera.postError)
671                window.opera.postError(msg);
672        }
673    };
674
675})(jQuery);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.