PageSourceSearch

https://lindsdalsif.se/js/jquery.form.js?12444

js lindsdalsif.se collected 2026-09-25 09:49:15 UTC 39,525 bytes, 1,132 lines download raw bytes

1/*!
2 * jQuery Form Plugin
3 * version: 3.28.0-2013.02.06
4 * @requires jQuery v1.5 or later
5 *
6 * Examples and documentation at: http://malsup.com/jquery/form/
7 * Project repository: https://github.com/malsup/form
8 * Dual licensed under the MIT and GPL licenses:
9 *    http://malsup.github.com/mit-license.txt
10 *    http://malsup.github.com/gpl-license-v2.txt
11 */
12/*global ActiveXObject alert */
13;(function($) {
14"use strict";
15
16/*
17    Usage Note:
18    -----------
19    Do not use both ajaxSubmit and ajaxForm on the same form.  These
20    functions are mutually exclusive.  Use ajaxSubmit if you want
21    to bind your own submit handler to the form.  For example,
22
23    $(document).ready(function() {
24        $('#myForm').on('submit', function(e) {
25            e.preventDefault(); // <-- important
26            $(this).ajaxSubmit({
27                target: '#output'
28            });
29        });
30    });
31
32    Use ajaxForm when you want the plugin to manage all the event binding
33    for you.  For example,
34
35    $(document).ready(function() {
36        $('#myForm').ajaxForm({
37            target: '#output'
38        });
39    });
40
41    You can also use ajaxForm with delegation (requires jQuery v1.7+), so the
42    form does not have to exist when you invoke ajaxForm:
43
44    $('#myForm').ajaxForm({
45        delegation: true,
46        target: '#output'
47    });
48
49    When using ajaxForm, the ajaxSubmit function will be invoked for you
50    at the appropriate time.
51*/
52
53/**
54 * Feature detection
55 */
56var feature = {};
57feature.fileapi = $("<input type='file'/>").get(0).files !== undefined;
58feature.formdata = window.FormData !== undefined;
59
60/**
61 * ajaxSubmit() provides a mechanism for immediately submitting
62 * an HTML form using AJAX.
63 */
64$.fn.ajaxSubmit = function(options) {
65    /*jshint scripturl:true */
66
67    // fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
68    if (!this.length) {
69        log('ajaxSubmit: skipping submit process - no element selected');
70        return this;
71    }
72
73    var method, action, url, $form = this;
74
75    if (typeof options == 'function') {
76        options = { success: options };
77    }
78
79    method = this.attr('method');
80    action = this.attr('action');
81    url = (typeof action === 'string') ? $.trim(action) : '';
82    url = url || window.location.href || '';
83    if (url) {
84        // clean url (don't include hash vaue)
85        url = (url.match(/^([^#]+)/)||[])[1];
86    }
87
88    options = $.extend(true, {
89        url:  url,
90        success: $.ajaxSettings.success,
91        type: method || 'GET',
92        iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
93    }, options);
94
95    // hook for manipulating the form data before it is extracted;
96    // convenient for use with rich editors like tinyMCE or FCKEditor
97    var veto = {};
98    this.trigger('form-pre-serialize', [this, options, veto]);
99    if (veto.veto) {
100        log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
101        return this;
102    }
103
104    // provide opportunity to alter form data before it is serialized
105    if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
106        log('ajaxSubmit: submit aborted via beforeSerialize callback');
107        return this;
108    }
109
110    var traditional = options.traditional;
111    if ( traditional === undefined ) {
112        traditional = $.ajaxSettings.traditional;
113    }
114
115    var elements = [];
116    var qx, a = this.formToArray(options.semantic, elements);
117    if (options.data) {
118        options.extraData = options.data;
119        qx = $.param(options.data, traditional);
120    }
121
122    // give pre-submit callback an opportunity to abort the submit
123    if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
124        log('ajaxSubmit: submit aborted via beforeSubmit callback');
125        return this;
126    }
127
128    // fire vetoable 'validate' event
129    this.trigger('form-submit-validate', [a, this, options, veto]);
130    if (veto.veto) {
131        log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
132        return this;
133    }
134
135    var q = $.param(a, traditional);
136    if (qx) {
137        q = ( q ? (q + '&' + qx) : qx );
138    }
139    if (options.type.toUpperCase() == 'GET') {
140        options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
141        options.data = null;  // data is null for 'get'
142    }
143    else {
144        options.data = q; // data is the query string for 'post'
145    }
146
147    var callbacks = [];
148    if (options.resetForm) {
149        callbacks.push(function() { $form.resetForm(); });
150    }
151    if (options.clearForm) {
152        callbacks.push(function() { $form.clearForm(options.includeHidden); });
153    }
154
155    // perform a load on the target only if dataType is not provided
156    if (!options.dataType && options.target) {
157        var oldSuccess = options.success || function(){};
158        callbacks.push(function(data) {
159            var fn = options.replaceTarget ? 'replaceWith' : 'html';
160            $(options.target)[fn](data).each(oldSuccess, arguments);
161        });
162    }
163    else if (options.success) {
164        callbacks.push(options.success);
165    }
166
167    options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
168        var context = options.context || this ;    // jQuery 1.4+ supports scope context
169        for (var i=0, max=callbacks.length; i < max; i++) {
170            callbacks[i].apply(context, [data, status, xhr || $form, $form]);
171        }
172    };
173
174    // are there files to upload?
175
176    // [value] (issue #113), also see comment:
177    // https://github.com/malsup/form/commit/588306aedba1de01388032d5f42a60159eea9228#commitcomment-2180219
178    var fileInputs = $('input[type=file]:enabled[value!=""]', this);
179
180    var hasFileInputs = fileInputs.length > 0;
181    var mp = 'multipart/form-data';
182    var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
183
184    var fileAPI = feature.fileapi && feature.formdata;
185    log("fileAPI :" + fileAPI);
186    var shouldUseFrame = (hasFileInputs || multipart) && !fileAPI;
187
188    var jqxhr;
189
190    // options.iframe allows user to force iframe mode
191    // 06-NOV-09: now defaulting to iframe mode if file input is detected
192    if (options.iframe !== false && (options.iframe || shouldUseFrame)) {
193        // hack to fix Safari hang (thanks to Tim Molendijk for this)
194        // see:  http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
195        if (options.closeKeepAlive) {
196            $.get(options.closeKeepAlive, function() {
197                jqxhr = fileUploadIframe(a);
198            });
199        }
200        else {
201            jqxhr = fileUploadIframe(a);
202        }
203    }
204    else if ((hasFileInputs || multipart) && fileAPI) {
205        jqxhr = fileUploadXhr(a);
206    }
207    else {
208        jqxhr = $.ajax(options);
209    }
210
211    $form.removeData('jqxhr').data('jqxhr', jqxhr);
212
213    // clear element array
214    for (var k=0; k < elements.length; k++)
215        elements[k] = null;
216
217    // fire 'notify' event
218    this.trigger('form-submit-notify', [this, options]);
219    return this;
220
221    // utility fn for deep serialization
222    function deepSerialize(extraData){
223        var serialized = $.param(extraData).split('&');
224        var len = serialized.length;
225        var result = [];
226        var i, part;
227        for (i=0; i < len; i++) {
228            // #252; undo param space replacement
229            serialized[i] = serialized[i].replace(/\+/g,' ');
230            part = serialized[i].split('=');
231            // #278; use array instead of object storage, favoring array serializations
232            result.push([decodeURIComponent(part[0]), decodeURIComponent(part[1])]);
233        }
234        return result;
235    }
236
237     // XMLHttpRequest Level 2 file uploads (big hat tip to francois2metz)
238    function fileUploadXhr(a) {
239        var formdata = new FormData();
240
241        for (var i=0; i < a.length; i++) {
242            formdata.append(a[i].name, a[i].value);
243        }
244
245        if (options.extraData) {
246            var serializedData = deepSerialize(options.extraData);
247            for (i=0; i < serializedData.length; i++)
248                if (serializedData[i])
249                    formdata.append(serializedData[i][0], serializedData[i][1]);
250        }
251
252        options.data = null;
253
254        var s = $.extend(true, {}, $.ajaxSettings, options, {
255            contentType: false,
256            processData: false,
257            cache: false,
258            type: method || 'POST'
259        });
260
261        if (options.uploadProgress) {
262            // workaround because jqXHR does not expose upload property
263            s.xhr = function() {
264                var xhr = jQuery.ajaxSettings.xhr();
265                if (xhr.upload) {
266                    xhr.upload.addEventListener('progress', function(event) {
267                        var percent = 0;
268                        var position = event.loaded || event.position; /*event.position is deprecated*/
269                        var total = event.total;
270                        if (event.lengthComputable) {
271                            percent = Math.ceil(position / total * 100);
272                        }
273                        options.uploadProgress(event, position, total, percent);
274                    }, false);
275                }
276                return xhr;
277            };
278        }
279
280        s.data = null;
281            var beforeSend = s.beforeSend;
282            s.beforeSend = function(xhr, o) {
283                o.data = formdata;
284                if(beforeSend)
285                    beforeSend.call(this, xhr, o);
286        };
287        return $.ajax(s);
288    }
289
290    // private function for handling file uploads (hat tip to YAHOO!)
291    function fileUploadIframe(a) {
292        var form = $form[0], el, i, s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle;
293        var useProp = !!$.fn.prop;
294        var deferred = $.Deferred();
295
296        if (a) {
297            // ensure that every serialized input is still enabled
298            for (i=0; i < elements.length; i++) {
299                el = $(elements[i]);
300                if ( useProp )
301                    el.prop('disabled', false);
302                else
303                    el.removeAttr('disabled');
304            }
305        }
306
307        s = $.extend(true, {}, $.ajaxSettings, options);
308        s.context = s.context || s;
309        id = 'jqFormIO' + (new Date().getTime());
310        if (s.iframeTarget) {
311            $io = $(s.iframeTarget);
312            n = $io.attr('name');
313            if (!n)
314                 $io.attr('name', id);
315            else
316                id = n;
317        }
318        else {
319            $io = $('<iframe name="' + id + '" src="'+ s.iframeSrc +'" />');
320            $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
321        }
322        io = $io[0];
323
324
325        xhr = { // mock object
326            aborted: 0,
327            responseText: null,
328            responseXML: null,
329            status: 0,
330            statusText: 'n/a',
331            getAllResponseHeaders: function() {},
332            getResponseHeader: function() {},
333            setRequestHeader: function() {},
334            abort: function(status) {
335                var e = (status === 'timeout' ? 'timeout' : 'aborted');
336                log('aborting upload... ' + e);
337                this.aborted = 1;
338
339                try { // #214, #257
340                    if (io.contentWindow.document.execCommand) {
341                        io.contentWindow.document.execCommand('Stop');
342                    }
343                }
344                catch(ignore) {}
345
346                $io.attr('src', s.iframeSrc); // abort op in progress
347                xhr.error = e;
348                if (s.error)
349                    s.error.call(s.context, xhr, e, status);
350                if (g)
351                    $.event.trigger("ajaxError", [xhr, s, e]);
352                if (s.complete)
353                    s.complete.call(s.context, xhr, e);
354            }
355        };
356
357        g = s.global;
358        // trigger ajax global events so that activity/block indicators work like normal
359        if (g && 0 === $.active++) {
360            $.event.trigger("ajaxStart");
361        }
362        if (g) {
363            $.event.trigger("ajaxSend", [xhr, s]);
364        }
365
366        if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
367            if (s.global) {
368                $.active--;
369            }
370            deferred.reject();
371            return deferred;
372        }
373        if (xhr.aborted) {
374            deferred.reject();
375            return deferred;
376        }
377
378        // add submitting element to data if we know it
379        sub = form.clk;
380        if (sub) {
381            n = sub.name;
382            if (n && !sub.disabled) {
383                s.extraData = s.extraData || {};
384                s.extraData[n] = sub.value;
385                if (sub.type == "image") {
386                    s.extraData[n+'.x'] = form.clk_x;
387                    s.extraData[n+'.y'] = form.clk_y;
388                }
389            }
390        }
391
392        var CLIENT_TIMEOUT_ABORT = 1;
393        var SERVER_ABORT = 2;
394
395        function getDoc(frame) {
396            var doc = frame.contentWindow ? frame.contentWindow.document : frame.contentDocument ? frame.contentDocument : frame.document;
397            return doc;
398        }
399
400        // Rails CSRF hack (thanks to Yvan Barthelemy)
401        var csrf_token = $('meta[name=csrf-token]').attr('content');
402        var csrf_param = $('meta[name=csrf-param]').attr('content');
403        if (csrf_param && csrf_token) {
404            s.extraData = s.extraData || {};
405            s.extraData[csrf_param] = csrf_token;
406        }
407
408        // take a breath so that pending repaints get some cpu time before the upload starts
409        function doSubmit() {
410            // make sure form attrs are set
411            var t = $form.attr('target'), a = $form.attr('action');
412
413            // update form attrs in IE friendly way
414            form.setAttribute('target',id);
415            if (!method) {
416                form.setAttribute('method', 'POST');
417            }
418            if (a != s.url) {
419                form.setAttribute('action', s.url);
420            }
421
422            // ie borks in some cases when setting encoding
423            if (! s.skipEncodingOverride && (!method || /post/i.test(method))) {
424                $form.attr({
425                    encoding: 'multipart/form-data',
426                    enctype:  'multipart/form-data'
427                });
428            }
429
430            // support timout
431            if (s.timeout) {
432                timeoutHandle = setTimeout(function() { timedOut = true; cb(CLIENT_TIMEOUT_ABORT); }, s.timeout);
433            }
434
435            // look for server aborts
436            function checkState() {
437                try {
438                    var state = getDoc(io).readyState;
439                    log('state = ' + state);
440                    if (state && state.toLowerCase() == 'uninitialized')
441                        setTimeout(checkState,50);
442                }
443                catch(e) {
444                    log('Server abort: ' , e, ' (', e.name, ')');
445                    cb(SERVER_ABORT);
446                    if (timeoutHandle)
447                        clearTimeout(timeoutHandle);
448                    timeoutHandle = undefined;
449                }
450            }
451
452            // add "extra" data to form if provided in options
453            var extraInputs = [];
454            try {
455                if (s.extraData) {
456                    for (var n in s.extraData) {
457                        if (s.extraData.hasOwnProperty(n)) {
458                           // if using the $.param format that allows for multiple values with the same name
459                           if($.isPlainObject(s.extraData[n]) && s.extraData[n].hasOwnProperty('name') && s.extraData[n].hasOwnProperty('value')) {
460                               extraInputs.push(
461                               $('<input type="hidden" name="'+s.extraData[n].name+'">').val(s.extraData[n].value)
462                                   .appendTo(form)[0]);
463                           } else {
464                               extraInputs.push(
465                               $('<input type="hidden" name="'+n+'">').val(s.extraData[n])
466                                   .appendTo(form)[0]);
467                           }
468                        }
469                    }
470                }
471
472                if (!s.iframeTarget) {
473                    // add iframe to doc and submit the form
474                    $io.appendTo('body');
475                    if (io.attachEvent)
476                        io.attachEvent('onload', cb);
477                    else
478                        io.addEventListener('load', cb, false);
479                }
480                setTimeout(checkState,15);
481
482                try {
483                    form.submit();
484                } catch(err) {
485                    // just in case form has element with name/id of 'submit'
486                    var submitFn = document.createElement('form').submit;
487                    submitFn.apply(form);
488                }
489            }
490            finally {
491                // reset attrs and remove "extra" input elements
492                form.setAttribute('action',a);
493                if(t) {
494                    form.setAttribute('target', t);
495                } else {
496                    $form.removeAttr('target');
497                }
498                $(extraInputs).remove();
499            }
500        }
501
502        if (s.forceSync) {
503            doSubmit();
504        }
505        else {
506            setTimeout(doSubmit, 10); // this lets dom updates render
507        }
508
509        var data, doc, domCheckCount = 50, callbackProcessed;
510
511        function cb(e) {
512            if (xhr.aborted || callbackProcessed) {
513                return;
514            }
515            try {
516                doc = getDoc(io);
517            }
518            catch(ex) {
519                log('cannot access response document: ', ex);
520                e = SERVER_ABORT;
521            }
522            if (e === CLIENT_TIMEOUT_ABORT && xhr) {
523                xhr.abort('timeout');
524                deferred.reject(xhr, 'timeout');
525                return;
526            }
527            else if (e == SERVER_ABORT && xhr) {
528                xhr.abort('server abort');
529                deferred.reject(xhr, 'error', 'server abort');
530                return;
531            }
532
533            if (!doc || doc.location.href == s.iframeSrc) {
534                // response not received yet
535                if (!timedOut)
536                    return;
537            }
538            if (io.detachEvent)
539                io.detachEvent('onload', cb);
540            else
541                io.removeEventListener('load', cb, false);
542
543            var status = 'success', errMsg;
544            try {
545                if (timedOut) {
546                    throw 'timeout';
547                }
548
549                var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
550                log('isXml='+isXml);
551                if (!isXml && window.opera && (doc.body === null || !doc.body.innerHTML)) {
552                    if (--domCheckCount) {
553                        // in some browsers (Opera) the iframe DOM is not always traversable when
554                        // the onload callback fires, so we loop a bit to accommodate
555                        log('requeing onLoad callback, DOM not available');
556                        setTimeout(cb, 250);
557                        return;
558                    }
559                    // let this fall through because server response could be an empty document
560                    //log('Could not access iframe DOM after mutiple tries.');
561                    //throw 'DOMException: not available';
562                }
563
564                //log('response detected');
565                var docRoot = doc.body ? doc.body : doc.documentElement;
566                xhr.responseText = docRoot ? docRoot.innerHTML : null;
567                xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
568                if (isXml)
569                    s.dataType = 'xml';
570                xhr.getResponseHeader = function(header){
571                    var headers = {'content-type': s.dataType};
572                    return headers[header];
573                };
574                // support for XHR 'status' & 'statusText' emulation :
575                if (docRoot) {
576                    xhr.status = Number( docRoot.getAttribute('status') ) || xhr.status;
577                    xhr.statusText = docRoot.getAttribute('statusText') || xhr.statusText;
578                }
579
580                var dt = (s.dataType || '').toLowerCase();
581                var scr = /(json|script|text)/.test(dt);
582                if (scr || s.textarea) {
583                    // see if user embedded response in textarea
584                    var ta = doc.getElementsByTagName('textarea')[0];
585                    if (ta) {
586                        xhr.responseText = ta.value;
587                        // support for XHR 'status' & 'statusText' emulation :
588                        xhr.status = Number( ta.getAttribute('status') ) || xhr.status;
589                        xhr.statusText = ta.getAttribute('statusText') || xhr.statusText;
590                    }
591                    else if (scr) {
592                        // account for browsers injecting pre around json response
593                        var pre = doc.getElementsByTagName('pre')[0];
594                        var b = doc.getElementsByTagName('body')[0];
595                        if (pre) {
596                            xhr.responseText = pre.textContent ? pre.textContent : pre.innerText;
597                        }
598                        else if (b) {
599                            xhr.responseText = b.textContent ? b.textContent : b.innerText;
600                        }
601                    }
602                }
603                else if (dt == 'xml' && !xhr.responseXML && xhr.responseText) {
604                    xhr.responseXML = toXml(xhr.responseText);
605                }
606
607                try {
608                    data = httpData(xhr, dt, s);
609                }
610                catch (err) {
611                    status = 'parsererror';
612                    xhr.error = errMsg = (err || status);
613                }
614            }
615            catch (err) {
616                log('error caught: ',err);
617                status = 'error';
618                xhr.error = errMsg = (err || status);
619            }
620
621            if (xhr.aborted) {
622                log('upload aborted');
623                status = null;
624            }
625
626            if (xhr.status) { // we've set xhr.status
627                status = (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) ? 'success' : 'error';
628            }
629
630            // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
631            if (status === 'success') {
632                if (s.success)
633                    s.success.call(s.context, data, 'success', xhr);
634                deferred.resolve(xhr.responseText, 'success', xhr);
635                if (g)
636                    $.event.trigger("ajaxSuccess", [xhr, s]);
637            }
638            else if (status) {
639                if (errMsg === undefined)
640                    errMsg = xhr.statusText;
641                if (s.error)
642                    s.error.call(s.context, xhr, status, errMsg);
643                deferred.reject(xhr, 'error', errMsg);
644                if (g)
645                    $.event.trigger("ajaxError", [xhr, s, errMsg]);
646            }
647
648            if (g)
649                $.event.trigger("ajaxComplete", [xhr, s]);
650
651            if (g && ! --$.active) {
652                $.event.trigger("ajaxStop");
653            }
654
655            if (s.complete)
656                s.complete.call(s.context, xhr, status);
657
658            callbackProcessed = true;
659            if (s.timeout)
660                clearTimeout(timeoutHandle);
661
662            // clean up
663            setTimeout(function() {
664                if (!s.iframeTarget)
665                    $io.remove();
666                xhr.responseXML = null;
667            }, 100);
668        }
669
670        var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+)
671            if (window.ActiveXObject) {
672                doc = new ActiveXObject('Microsoft.XMLDOM');
673                doc.async = 'false';
674                doc.loadXML(s);
675            }
676            else {
677                doc = (new DOMParser()).parseFromString(s, 'text/xml');
678            }
679            return (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc : null;
680        };
681        var parseJSON = $.parseJSON || function(s) {
682            /*jslint evil:true */
683            return window['eval']('(' + s + ')');
684        };
685
686        var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4
687
688            var ct = xhr.getResponseHeader('content-type') || '',
689                xml = type === 'xml' || !type && ct.indexOf('xml') >= 0,
690                data = xml ? xhr.responseXML : xhr.responseText;
691
692            if (xml && data.documentElement.nodeName === 'parsererror') {
693                if ($.error)
694                    $.error('parsererror');
695            }
696            if (s && s.dataFilter) {
697                data = s.dataFilter(data, type);
698            }
699            if (typeof data === 'string') {
700                if (type === 'json' || !type && ct.indexOf('json') >= 0) {
701                    data = parseJSON(data);
702                } else if (type === "script" || !type && ct.indexOf("javascript") >= 0) {
703                    $.globalEval(data);
704                }
705            }
706            return data;
707        };
708
709        return deferred;
710    }
711};
712
713/**
714 * ajaxForm() provides a mechanism for fully automating form submission.
715 *
716 * The advantages of using this method instead of ajaxSubmit() are:
717 *
718 * 1: This method will include coordinates for <input type="image" /> elements (if the element
719 *    is used to submit the form).
720 * 2. This method will include the submit element's name/value data (for the element that was
721 *    used to submit the form).
722 * 3. This method binds the submit() method to the form for you.
723 *
724 * The options argument for ajaxForm works exactly as it does for ajaxSubmit.  ajaxForm merely
725 * passes the options argument along after properly binding events for submit elements and
726 * the form itself.
727 */
728$.fn.ajaxForm = function(options) {
729    options = options || {};
730    options.delegation = options.delegation && $.isFunction($.fn.on);
731
732    // in jQuery 1.3+ we can fix mistakes with the ready state
733    if (!options.delegation && this.length === 0) {
734        var o = { s: this.selector, c: this.context };
735        if (!$.isReady && o.s) {
736            log('DOM not ready, queuing ajaxForm');
737            $(function() {
738                $(o.s,o.c).ajaxForm(options);
739            });
740            return this;
741        }
742        // is your DOM ready?  http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
743        log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
744        return this;
745    }
746
747    if ( options.delegation ) {
748        $(document)
749            .off('submit.form-plugin', this.selector, doAjaxSubmit)
750            .off('click.form-plugin', this.selector, captureSubmittingElement)
751            .on('submit.form-plugin', this.selector, options, doAjaxSubmit)
752            .on('click.form-plugin', this.selector, options, captureSubmittingElement);
753        return this;
754    }
755
756    return this.ajaxFormUnbind()
757        .bind('submit.form-plugin', options, doAjaxSubmit)
758        .bind('click.form-plugin', options, captureSubmittingElement);
759};
760
761// private event handlers
762function doAjaxSubmit(e) {
763    /*jshint validthis:true */
764    var options = e.data;
765    if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
766        e.preventDefault();
767        $(this).ajaxSubmit(options);
768    }
769}
770
771function captureSubmittingElement(e) {
772    /*jshint validthis:true */
773    var target = e.target;
774    var $el = $(target);
775    if (!($el.is("[type=submit],[type=image]"))) {
776        // is this a child element of the submit el?  (ex: a span within a button)
777        var t = $el.closest('[type=submit]');
778        if (t.length === 0) {
779            return;
780        }
781        target = t[0];
782    }
783    var form = this;
784    form.clk = target;
785    if (target.type == 'image') {
786        if (e.offsetX !== undefined) {
787            form.clk_x = e.offsetX;
788            form.clk_y = e.offsetY;
789        } else if (typeof $.fn.offset == 'function') {
790            var offset = $el.offset();
791            form.clk_x = e.pageX - offset.left;
792            form.clk_y = e.pageY - offset.top;
793        } else {
794            form.clk_x = e.pageX - target.offsetLeft;
795            form.clk_y = e.pageY - target.offsetTop;
796        }
797    }
798    // clear form vars
799    setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
800}
801
802
803// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
804$.fn.ajaxFormUnbind = function() {
805    return this.unbind('submit.form-plugin click.form-plugin');
806};
807
808/**
809 * formToArray() gathers form element data into an array of objects that can
810 * be passed to any of the following ajax functions: $.get, $.post, or load.
811 * Each object in the array has both a 'name' and 'value' property.  An example of
812 * an array for a simple login form might be:
813 *
814 * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
815 *
816 * It is this array that is passed to pre-submit callback functions provided to the
817 * ajaxSubmit() and ajaxForm() methods.
818 */
819$.fn.formToArray = function(semantic, elements) {
820    var a = [];
821    if (this.length === 0) {
822        return a;
823    }
824
825    var form = this[0];
826    var els = semantic ? form.getElementsByTagName('*') : form.elements;
827    if (!els) {
828        return a;
829    }
830
831    var i,j,n,v,el,max,jmax;
832    for(i=0, max=els.length; i < max; i++) {
833        el = els[i];
834        n = el.name;
835        if (!n) {
836            continue;
837        }
838
839        if (semantic && form.clk && el.type == "image") {
840            // handle image inputs on the fly when semantic == true
841            if(!el.disabled && form.clk == el) {
842                a.push({name: n, value: $(el).val(), type: el.type });
843                a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
844            }
845            continue;
846        }
847
848        v = $.fieldValue(el, true);
849        if (v && v.constructor == Array) {
850            if (elements)
851                elements.push(el);
852            for(j=0, jmax=v.length; j < jmax; j++) {
853                a.push({name: n, value: v[j]});
854            }
855        }
856        else if (feature.fileapi && el.type == 'file' && !el.disabled) {
857            if (elements)
858                elements.push(el);
859            var files = el.files;
860            if (files.length) {
861                for (j=0; j < files.length; j++) {
862                    a.push({name: n, value: files[j], type: el.type});
863                }
864            }
865            else {
866                // #180
867                a.push({ name: n, value: '', type: el.type });
868            }
869        }
870        else if (v !== null && typeof v != 'undefined') {
871            if (elements)
872                elements.push(el);
873            a.push({name: n, value: v, type: el.type, required: el.required});
874        }
875    }
876
877    if (!semantic && form.clk) {
878        // input type=='image' are not found in elements array! handle it here
879        var $input = $(form.clk), input = $input[0];
880        n = input.name;
881        if (n && !input.disabled && input.type == 'image') {
882            a.push({name: n, value: $input.val()});
883            a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
884        }
885    }
886    return a;
887};
888
889/**
890 * Serializes form data into a 'submittable' string. This method will return a string
891 * in the format: name1=value1&amp;name2=value2
892 */
893$.fn.formSerialize = function(semantic) {
894    //hand off to jQuery.param for proper encoding
895    return $.param(this.formToArray(semantic));
896};
897
898/**
899 * Serializes all field elements in the jQuery object into a query string.
900 * This method will return a string in the format: name1=value1&amp;name2=value2
901 */
902$.fn.fieldSerialize = function(successful) {
903    var a = [];
904    this.each(function() {
905        var n = this.name;
906        if (!n) {
907            return;
908        }
909        var v = $.fieldValue(this, successful);
910        if (v && v.constructor == Array) {
911            for (var i=0,max=v.length; i < max; i++) {
912                a.push({name: n, value: v[i]});
913            }
914        }
915        else if (v !== null && typeof v != 'undefined') {
916            a.push({name: this.name, value: v});
917        }
918    });
919    //hand off to jQuery.param for proper encoding
920    return $.param(a);
921};
922
923/**
924 * Returns the value(s) of the element in the matched set.  For example, consider the following form:
925 *
926 *  <form><fieldset>
927 *      <input name="A" type="text" />
928 *      <input name="A" type="text" />
929 *      <input name="B" type="checkbox" value="B1" />
930 *      <input name="B" type="checkbox" value="B2"/>
931 *      <input name="C" type="radio" value="C1" />
932 *      <input name="C" type="radio" value="C2" />
933 *  </fieldset></form>
934 *
935 *  var v = $('input[type=text]').fieldValue();
936 *  // if no values are entered into the text inputs
937 *  v == ['','']
938 *  // if values entered into the text inputs are 'foo' and 'bar'
939 *  v == ['foo','bar']
940 *
941 *  var v = $('input[type=checkbox]').fieldValue();
942 *  // if neither checkbox is checked
943 *  v === undefined
944 *  // if both checkboxes are checked
945 *  v == ['B1', 'B2']
946 *
947 *  var v = $('input[type=radio]').fieldValue();
948 *  // if neither radio is checked
949 *  v === undefined
950 *  // if first radio is checked
951 *  v == ['C1']
952 *
953 * The successful argument controls whether or not the field element must be 'successful'
954 * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
955 * The default value of the successful argument is true.  If this value is false the value(s)
956 * for each element is returned.
957 *
958 * Note: This method *always* returns an array.  If no valid value can be determined the
959 *    array will be empty, otherwise it will contain one or more values.
960 */
961$.fn.fieldValue = function(successful) {
962    for (var val=[], i=0, max=this.length; i < max; i++) {
963        var el = this[i];
964        var v = $.fieldValue(el, successful);
965        if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {
966            continue;
967        }
968        if (v.constructor == Array)
969            $.merge(val, v);
970        else
971            val.push(v);
972    }
973    return val;
974};
975
976/**
977 * Returns the value of the field element.
978 */
979$.fieldValue = function(el, successful) {
980    var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
981    if (successful === undefined) {
982        successful = true;
983    }
984
985    if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
986        (t == 'checkbox' || t == 'radio') && !el.checked ||
987        (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
988        tag == 'select' && el.selectedIndex == -1)) {
989            return null;
990    }
991
992    if (tag == 'select') {
993        var index = el.selectedIndex;
994        if (index < 0) {
995            return null;
996        }
997        var a = [], ops = el.options;
998        var one = (t == 'select-one');
999        var max = (one ? index+1 : ops.length);
1000        for(var i=(one ? index : 0); i < max; i++) {
1001            var op = ops[i];
1002            if (op.selected) {
1003                var v = op.value;
1004                if (!v) { // extra pain for IE...
1005                    v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
1006                }
1007                if (one) {
1008                    return v;
1009                }
1010                a.push(v);
1011            }
1012        }
1013        return a;
1014    }
1015    return $(el).val();
1016};
1017
1018/**
1019 * Clears the form data.  Takes the following actions on the form's input fields:
1020 *  - input text fields will have their 'value' property set to the empty string
1021 *  - select elements will have their 'selectedIndex' property set to -1
1022 *  - checkbox and radio inputs will have their 'checked' property set to false
1023 *  - inputs of type submit, button, reset, and hidden will *not* be effected
1024 *  - button elements will *not* be effected
1025 */
1026$.fn.clearForm = function(includeHidden) {
1027    return this.each(function() {
1028        $('input,select,textarea', this).clearFields(includeHidden);
1029    });
1030};
1031
1032/**
1033 * Clears the selected form elements.
1034 */
1035$.fn.clearFields = $.fn.clearInputs = function(includeHidden) {
1036    var re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i; // 'hidden' is not in this list
1037    return this.each(function() {
1038        var t = this.type, tag = this.tagName.toLowerCase();
1039        if (re.test(t) || tag == 'textarea') {
1040            this.value = '';
1041        }
1042        else if (t == 'checkbox' || t == 'radio') {
1043            this.checked = false;
1044        }
1045        else if (tag == 'select') {
1046            this.selectedIndex = -1;
1047        }
1048		else if (t == "file") {
1049			if (/MSIE/.test(navigator.userAgent)) {
1050				$(this).replaceWith($(this).clone());
1051			} else {
1052				$(this).val('');
1053			}
1054		}
1055        else if (includeHidden) {
1056            // includeHidden can be the value true, or it can be a selector string
1057            // indicating a special test; for example:
1058            //  $('#myForm').clearForm('.special:hidden')
1059            // the above would clean hidden inputs that have the class of 'special'
1060            if ( (includeHidden === true && /hidden/.test(t)) ||
1061                 (typeof includeHidden == 'string' && $(this).is(includeHidden)) )
1062                this.value = '';
1063        }
1064    });
1065};
1066
1067/**
1068 * Resets the form data.  Causes all form elements to be reset to their original value.
1069 */
1070$.fn.resetForm = function() {
1071    return this.each(function() {
1072        // guard against an input with the name of 'reset'
1073        // note that IE reports the reset function as an 'object'
1074        if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) {
1075            this.reset();
1076        }
1077    });
1078};
1079
1080/**
1081 * Enables or disables any matching elements.
1082 */
1083$.fn.enable = function(b) {
1084    if (b === undefined) {
1085        b = true;
1086    }
1087    return this.each(function() {
1088        this.disabled = !b;
1089    });
1090};
1091
1092/**
1093 * Checks/unchecks any matching checkboxes or radio buttons and
1094 * selects/deselects and matching option elements.
1095 */
1096$.fn.selected = function(select) {
1097    if (select === undefined) {
1098        select = true;
1099    }
1100    return this.each(function() {
1101        var t = this.type;
1102        if (t == 'checkbox' || t == 'radio') {
1103            this.checked = select;
1104        }
1105        else if (this.tagName.toLowerCase() == 'option') {
1106            var $sel = $(this).parent('select');
1107            if (select && $sel[0] && $sel[0].type == 'select-one') {
1108                // deselect all other options
1109                $sel.find('option').selected(false);
1110            }
1111            this.selected = select;
1112        }
1113    });
1114};
1115
1116// expose debug var
1117$.fn.ajaxSubmit.debug = false;
1118
1119// helper fn for console logging
1120function log() {
1121    if (!$.fn.ajaxSubmit.debug)
1122        return;
1123    var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
1124    if (window.console && window.console.log) {
1125        window.console.log(msg);
1126    }
1127    else if (window.opera && window.opera.postError) {
1128        window.opera.postError(msg);
1129    }
1130}
1131
1132})(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.