PageSourceSearch

https://mamco.ch/jsc/jquery.form.js

js mamco.ch collected 2026-10-02 06:07:07 UTC 44,399 bytes, 1,293 lines download raw bytes

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

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.