PageSourceSearch

https://www.happycampus.com/js/jquery/plugins/jquery.form.js?jsVer=20260921.1

js happycampus.com collected 2026-09-24 09:09:16 UTC 39,553 bytes, 1,132 lines download raw bytes

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

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