PageSourceSearch

https://mickeyfix.com/wp-content/plugins/contact-form-7/jquery.form.js

js mickeyfix.com collected 2026-10-05 18:35:06 UTC 37,156 bytes, 1,070 lines download raw bytes

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