PageSourceSearch

https://www.championmicro.com.tw/js/jquery.form.js

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

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.