PageSourceSearch

https://defmin.fi/o/frontend-js-jquery-web/jquery/form.js

js defmin.fi collected 2026-10-02 04:15:52 UTC 44,102 bytes, 1,283 lines download raw bytes

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

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.