PageSourceSearch

https://yeskey.or.kr/resources/js/lib/jquery.form.js

js yeskey.or.kr collected 2026-10-02 08:34:10 UTC 45,620 bytes, 1,299 lines download raw bytes

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

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.