PageSourceSearch

https://www.mountvernongrand.com/scripts/jquery.form.js

js mountvernongrand.com collected 2026-10-08 16:38:39 UTC 38,664 bytes, 1,103 lines download raw bytes

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