WordPress.org

Make WordPress Core

Ticket #15909: jquery.form.2.73.diff

File jquery.form.2.73.diff, 50.9 KB (added by duck_, 4 years ago)

2.73 released 3 May 2011

  • wp-includes/js/jquery/jquery.form.dev.js

     
    1 /* 
     1/*! 
    22 * jQuery Form Plugin 
    3  * version: 2.02 (12/16/2007) 
    4  * @requires jQuery v1.1 or later 
     3 * version: 2.73 (03-MAY-2011) 
     4 * @requires jQuery v1.3.2 or later 
    55 * 
    6  * Examples at: http://malsup.com/jquery/form/ 
     6 * Examples and documentation at: http://malsup.com/jquery/form/ 
    77 * Dual licensed under the MIT and GPL licenses: 
    88 *   http://www.opensource.org/licenses/mit-license.php 
    99 *   http://www.gnu.org/licenses/gpl.html 
    10  * 
    11  * Revision: $Id$ 
    1210 */ 
    13  (function($) { 
     11;(function($) { 
     12 
     13/* 
     14        Usage Note: 
     15        ----------- 
     16        Do not use both ajaxSubmit and ajaxForm on the same form.  These 
     17        functions are intended to be exclusive.  Use ajaxSubmit if you want 
     18        to bind your own submit handler to the form.  For example, 
     19 
     20        $(document).ready(function() { 
     21                $('#myForm').bind('submit', function(e) { 
     22                        e.preventDefault(); // <-- important 
     23                        $(this).ajaxSubmit({ 
     24                                target: '#output' 
     25                        }); 
     26                }); 
     27        }); 
     28 
     29        Use ajaxForm when you want the plugin to manage all the event binding 
     30        for you.  For example, 
     31 
     32        $(document).ready(function() { 
     33                $('#myForm').ajaxForm({ 
     34                        target: '#output' 
     35                }); 
     36        }); 
     37 
     38        When using ajaxForm, the ajaxSubmit function will be invoked for you 
     39        at the appropriate time. 
     40*/ 
     41 
    1442/** 
    15  * ajaxSubmit() provides a mechanism for submitting an HTML form using AJAX. 
    16  * 
    17  * ajaxSubmit accepts a single argument which can be either a success callback function 
    18  * or an options Object.  If a function is provided it will be invoked upon successful 
    19  * completion of the submit and will be passed the response from the server. 
    20  * If an options Object is provided, the following attributes are supported: 
    21  * 
    22  *  target:   Identifies the element(s) in the page to be updated with the server response. 
    23  *            This value may be specified as a jQuery selection string, a jQuery object, 
    24  *            or a DOM element. 
    25  *            default value: null 
    26  * 
    27  *  url:      URL to which the form data will be submitted. 
    28  *            default value: value of form's 'action' attribute 
    29  * 
    30  *  type:     The method in which the form data should be submitted, 'GET' or 'POST'. 
    31  *            default value: value of form's 'method' attribute (or 'GET' if none found) 
    32  * 
    33  *  data:     Additional data to add to the request, specified as key/value pairs (see $.ajax). 
    34  * 
    35  *  beforeSubmit:  Callback method to be invoked before the form is submitted. 
    36  *            default value: null 
    37  * 
    38  *  success:  Callback method to be invoked after the form has been successfully submitted 
    39  *            and the response has been returned from the server 
    40  *            default value: null 
    41  * 
    42  *  dataType: Expected dataType of the response.  One of: null, 'xml', 'script', or 'json' 
    43  *            default value: null 
    44  * 
    45  *  semantic: Boolean flag indicating whether data must be submitted in semantic order (slower). 
    46  *            default value: false 
    47  * 
    48  *  resetForm: Boolean flag indicating whether the form should be reset if the submit is successful 
    49  * 
    50  *  clearForm: Boolean flag indicating whether the form should be cleared if the submit is successful 
    51  * 
    52  * 
    53  * The 'beforeSubmit' callback can be provided as a hook for running pre-submit logic or for 
    54  * validating the form data.  If the 'beforeSubmit' callback returns false then the form will 
    55  * not be submitted. The 'beforeSubmit' callback is invoked with three arguments: the form data 
    56  * in array format, the jQuery object, and the options object passed into ajaxSubmit. 
    57  * The form data array takes the following form: 
    58  * 
    59  *     [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ] 
    60  * 
    61  * If a 'success' callback method is provided it is invoked after the response has been returned 
    62  * from the server.  It is passed the responseText or responseXML value (depending on dataType). 
    63  * See jQuery.ajax for further details. 
    64  * 
    65  * 
    66  * The dataType option provides a means for specifying how the server response should be handled. 
    67  * This maps directly to the jQuery.httpData method.  The following values are supported: 
    68  * 
    69  *      'xml':    if dataType == 'xml' the server response is treated as XML and the 'success' 
    70  *                   callback method, if specified, will be passed the responseXML value 
    71  *      'json':   if dataType == 'json' the server response will be evaluted and passed to 
    72  *                   the 'success' callback, if specified 
    73  *      'script': if dataType == 'script' the server response is evaluated in the global context 
    74  * 
    75  * 
    76  * Note that it does not make sense to use both the 'target' and 'dataType' options.  If both 
    77  * are provided the target will be ignored. 
    78  * 
    79  * The semantic argument can be used to force form serialization in semantic order. 
    80  * This is normally true anyway, unless the form contains input elements of type='image'. 
    81  * If your form must be submitted with name/value pairs in semantic order and your form 
    82  * contains an input of type='image" then pass true for this arg, otherwise pass false 
    83  * (or nothing) to avoid the overhead for this logic. 
    84  * 
    85  * 
    86  * When used on its own, ajaxSubmit() is typically bound to a form's submit event like this: 
    87  * 
    88  * $("#form-id").submit(function() { 
    89  *     $(this).ajaxSubmit(options); 
    90  *     return false; // cancel conventional submit 
    91  * }); 
    92  * 
    93  * When using ajaxForm(), however, this is done for you. 
    94  * 
    95  * @example 
    96  * $('#myForm').ajaxSubmit(function(data) { 
    97  *     alert('Form submit succeeded! Server returned: ' + data); 
    98  * }); 
    99  * @desc Submit form and alert server response 
    100  * 
    101  * 
    102  * @example 
    103  * var options = { 
    104  *     target: '#myTargetDiv' 
    105  * }; 
    106  * $('#myForm').ajaxSubmit(options); 
    107  * @desc Submit form and update page element with server response 
    108  * 
    109  * 
    110  * @example 
    111  * var options = { 
    112  *     success: function(responseText) { 
    113  *         alert(responseText); 
    114  *     } 
    115  * }; 
    116  * $('#myForm').ajaxSubmit(options); 
    117  * @desc Submit form and alert the server response 
    118  * 
    119  * 
    120  * @example 
    121  * var options = { 
    122  *     beforeSubmit: function(formArray, jqForm) { 
    123  *         if (formArray.length == 0) { 
    124  *             alert('Please enter data.'); 
    125  *             return false; 
    126  *         } 
    127  *     } 
    128  * }; 
    129  * $('#myForm').ajaxSubmit(options); 
    130  * @desc Pre-submit validation which aborts the submit operation if form data is empty 
    131  * 
    132  * 
    133  * @example 
    134  * var options = { 
    135  *     url: myJsonUrl.php, 
    136  *     dataType: 'json', 
    137  *     success: function(data) { 
    138  *        // 'data' is an object representing the the evaluated json data 
    139  *     } 
    140  * }; 
    141  * $('#myForm').ajaxSubmit(options); 
    142  * @desc json data returned and evaluated 
    143  * 
    144  * 
    145  * @example 
    146  * var options = { 
    147  *     url: myXmlUrl.php, 
    148  *     dataType: 'xml', 
    149  *     success: function(responseXML) { 
    150  *        // responseXML is XML document object 
    151  *        var data = $('myElement', responseXML).text(); 
    152  *     } 
    153  * }; 
    154  * $('#myForm').ajaxSubmit(options); 
    155  * @desc XML data returned from server 
    156  * 
    157  * 
    158  * @example 
    159  * var options = { 
    160  *     resetForm: true 
    161  * }; 
    162  * $('#myForm').ajaxSubmit(options); 
    163  * @desc submit form and reset it if successful 
    164  * 
    165  * @example 
    166  * $('#myForm).submit(function() { 
    167  *    $(this).ajaxSubmit(); 
    168  *    return false; 
    169  * }); 
    170  * @desc Bind form's submit event to use ajaxSubmit 
    171  * 
    172  * 
    173  * @name ajaxSubmit 
    174  * @type jQuery 
    175  * @param options  object literal containing options which control the form submission process 
    176  * @cat Plugins/Form 
    177  * @return jQuery 
     43 * ajaxSubmit() provides a mechanism for immediately submitting 
     44 * an HTML form using AJAX. 
    17845 */ 
    17946$.fn.ajaxSubmit = function(options) { 
    180     if (typeof options == 'function') 
    181         options = { success: options }; 
     47        // fast fail if nothing selected (http://dev.jquery.com/ticket/2752) 
     48        if (!this.length) { 
     49                log('ajaxSubmit: skipping submit process - no element selected'); 
     50                return this; 
     51        } 
    18252 
    183     options = $.extend({ 
    184         url:  this.attr('action') || window.location.toString(), 
    185         type: this.attr('method') || 'GET' 
    186     }, options || {}); 
     53        if (typeof options == 'function') { 
     54                options = { success: options }; 
     55        } 
    18756 
    188     // hook for manipulating the form data before it is extracted; 
    189     // convenient for use with rich editors like tinyMCE or FCKEditor 
    190     var veto = {}; 
    191     $.event.trigger('form.pre.serialize', [this, options, veto]); 
    192     if (veto.veto) return this; 
     57        var action = this.attr('action'); 
     58        var url = (typeof action === 'string') ? $.trim(action) : ''; 
     59        if (url) { 
     60                // clean url (don't include hash vaue) 
     61                url = (url.match(/^([^#]+)/)||[])[1]; 
     62        } 
     63        url = url || window.location.href || ''; 
    19364 
    194     var a = this.formToArray(options.semantic); 
     65        options = $.extend(true, { 
     66                url:  url, 
     67                success: $.ajaxSettings.success, 
     68                type: this[0].getAttribute('method') || 'GET', // IE7 massage (see issue 57) 
     69                iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank' 
     70        }, options); 
     71 
     72        // hook for manipulating the form data before it is extracted; 
     73        // convenient for use with rich editors like tinyMCE or FCKEditor 
     74        var veto = {}; 
     75        this.trigger('form-pre-serialize', [this, options, veto]); 
     76        if (veto.veto) { 
     77                log('ajaxSubmit: submit vetoed via form-pre-serialize trigger'); 
     78                return this; 
     79        } 
     80 
     81        // provide opportunity to alter form data before it is serialized 
     82        if (options.beforeSerialize && options.beforeSerialize(this, options) === false) { 
     83                log('ajaxSubmit: submit aborted via beforeSerialize callback'); 
     84                return this; 
     85        } 
     86 
     87        var n,v,a = this.formToArray(options.semantic); 
    19588        if (options.data) { 
    196             for (var n in options.data) 
    197                 a.push( { name: n, value: options.data[n] } ); 
     89                options.extraData = options.data; 
     90                for (n in options.data) { 
     91                        if(options.data[n] instanceof Array) { 
     92                                for (var k in options.data[n]) { 
     93                                        a.push( { name: n, value: options.data[n][k] } ); 
     94                                } 
     95                        } 
     96                        else { 
     97                                v = options.data[n]; 
     98                                v = $.isFunction(v) ? v() : v; // if value is fn, invoke it 
     99                                a.push( { name: n, value: v } ); 
     100                        } 
     101                } 
    198102        } 
    199103 
    200     // give pre-submit callback an opportunity to abort the submit 
    201     if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) return this; 
     104        // give pre-submit callback an opportunity to abort the submit 
     105        if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) { 
     106                log('ajaxSubmit: submit aborted via beforeSubmit callback'); 
     107                return this; 
     108        } 
    202109 
    203     // fire vetoable 'validate' event 
    204     $.event.trigger('form.submit.validate', [a, this, options, veto]); 
    205     if (veto.veto) return this; 
     110        // fire vetoable 'validate' event 
     111        this.trigger('form-submit-validate', [a, this, options, veto]); 
     112        if (veto.veto) { 
     113                log('ajaxSubmit: submit vetoed via form-submit-validate trigger'); 
     114                return this; 
     115        } 
    206116 
    207     var q = $.param(a);//.replace(/%20/g,'+'); 
     117        var q = $.param(a); 
    208118 
    209     if (options.type.toUpperCase() == 'GET') { 
    210         options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q; 
    211         options.data = null;  // data is null for 'get' 
    212     } 
    213     else 
    214         options.data = q; // data is the query string for 'post' 
     119        if (options.type.toUpperCase() == 'GET') { 
     120                options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q; 
     121                options.data = null;  // data is null for 'get' 
     122        } 
     123        else { 
     124                options.data = q; // data is the query string for 'post' 
     125        } 
    215126 
    216     var $form = this, callbacks = []; 
    217     if (options.resetForm) callbacks.push(function() { $form.resetForm(); }); 
    218     if (options.clearForm) callbacks.push(function() { $form.clearForm(); }); 
     127        var $form = this, callbacks = []; 
     128        if (options.resetForm) { 
     129                callbacks.push(function() { $form.resetForm(); }); 
     130        } 
     131        if (options.clearForm) { 
     132                callbacks.push(function() { $form.clearForm(); }); 
     133        } 
    219134 
    220     // perform a load on the target only if dataType is not provided 
    221     if (!options.dataType && options.target) { 
    222         var oldSuccess = options.success || function(){}; 
    223         callbacks.push(function(data) { 
    224             if (this.evalScripts) 
    225                 $(options.target).attr("innerHTML", data).evalScripts().each(oldSuccess, arguments); 
    226             else // jQuery v1.1.4 
    227                 $(options.target).html(data).each(oldSuccess, arguments); 
    228         }); 
    229     } 
    230     else if (options.success) 
    231         callbacks.push(options.success); 
     135        // perform a load on the target only if dataType is not provided 
     136        if (!options.dataType && options.target) { 
     137                var oldSuccess = options.success || function(){}; 
     138                callbacks.push(function(data) { 
     139                        var fn = options.replaceTarget ? 'replaceWith' : 'html'; 
     140                        $(options.target)[fn](data).each(oldSuccess, arguments); 
     141                }); 
     142        } 
     143        else if (options.success) { 
     144                callbacks.push(options.success); 
     145        } 
    232146 
    233     options.success = function(data, status) { 
    234         for (var i=0, max=callbacks.length; i < max; i++) 
    235             callbacks[i](data, status, $form); 
    236     }; 
     147        options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg 
     148                var context = options.context || options;   // jQuery 1.4+ supports scope context  
     149                for (var i=0, max=callbacks.length; i < max; i++) { 
     150                        callbacks[i].apply(context, [data, status, xhr || $form, $form]); 
     151                } 
     152        }; 
    237153 
    238     // are there files to upload? 
    239     var files = $('input:file', this).fieldValue(); 
    240     var found = false; 
    241     for (var j=0; j < files.length; j++) 
    242         if (files[j]) 
    243             found = true; 
     154        // are there files to upload? 
     155        var fileInputs = $('input:file', this).length > 0; 
     156        var mp = 'multipart/form-data'; 
     157        var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp); 
    244158 
    245     // options.iframe allows user to force iframe mode 
    246    if (options.iframe || found) {  
    247        // hack to fix Safari hang (thanks to Tim Molendijk for this) 
    248        // see:  http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d 
    249        if ($.browser.safari && options.closeKeepAlive) 
    250            $.get(options.closeKeepAlive, fileUpload); 
    251        else 
    252            fileUpload(); 
    253        } 
    254    else 
    255        $.ajax(options); 
     159        // options.iframe allows user to force iframe mode 
     160        // 06-NOV-09: now defaulting to iframe mode if file input is detected 
     161   if (options.iframe !== false && (fileInputs || options.iframe || multipart)) { 
     162           // hack to fix Safari hang (thanks to Tim Molendijk for this) 
     163           // see:  http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d 
     164           if (options.closeKeepAlive) { 
     165                   $.get(options.closeKeepAlive, fileUpload); 
     166                } 
     167           else { 
     168                   fileUpload(); 
     169                } 
     170   } 
     171   else { 
     172                $.ajax(options); 
     173   } 
    256174 
    257     // fire 'notify' event 
    258     $.event.trigger('form.submit.notify', [this, options]); 
    259     return this; 
     175        // fire 'notify' event 
     176        this.trigger('form-submit-notify', [this, options]); 
     177        return this; 
    260178 
    261179 
    262     // private function for handling file uploads (hat tip to YAHOO!) 
    263     function fileUpload() { 
    264         var form = $form[0]; 
    265         var opts = $.extend({}, $.ajaxSettings, options); 
     180        // private function for handling file uploads (hat tip to YAHOO!) 
     181        function fileUpload() { 
     182                var form = $form[0]; 
    266183 
    267         var id = 'jqFormIO' + $.fn.ajaxSubmit.counter++; 
    268         var $io = $('<iframe id="' + id + '" name="' + id + '" />'); 
    269         var io = $io[0]; 
    270         var op8 = $.browser.opera && window.opera.version() < 9; 
    271         if ($.browser.msie || op8) io.src = 'javascript:false;document.write("");'; 
    272         $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' }); 
     184                if ($(':input[name=submit],:input[id=submit]', form).length) { 
     185                        // if there is an input with a name or id of 'submit' then we won't be 
     186                        // able to invoke the submit fn on the form (at least not x-browser) 
     187                        alert('Error: Form elements must not have name or id of "submit".'); 
     188                        return; 
     189                } 
     190                 
     191                var s = $.extend(true, {}, $.ajaxSettings, options); 
     192                s.context = s.context || s; 
     193                var id = 'jqFormIO' + (new Date().getTime()), fn = '_'+id; 
     194                var $io = $('<iframe id="' + id + '" name="' + id + '" src="'+ s.iframeSrc +'" />'); 
     195                var io = $io[0]; 
    273196 
    274         var xhr = { // mock object 
    275             responseText: null, 
    276             responseXML: null, 
    277             status: 0, 
    278             statusText: 'n/a', 
    279             getAllResponseHeaders: function() {}, 
    280             getResponseHeader: function() {}, 
    281             setRequestHeader: function() {} 
    282         }; 
     197                $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' }); 
    283198 
    284         var g = opts.global; 
    285         // trigger ajax global events so that activity/block indicators work like normal 
    286         if (g && ! $.active++) $.event.trigger("ajaxStart"); 
    287         if (g) $.event.trigger("ajaxSend", [xhr, opts]); 
     199                var xhr = { // mock object 
     200                        aborted: 0, 
     201                        responseText: null, 
     202                        responseXML: null, 
     203                        status: 0, 
     204                        statusText: 'n/a', 
     205                        getAllResponseHeaders: function() {}, 
     206                        getResponseHeader: function() {}, 
     207                        setRequestHeader: function() {}, 
     208                        abort: function(status) { 
     209                                var e = (status === 'timeout' ? 'timeout' : 'aborted'); 
     210                                log('aborting upload... ' + e); 
     211                                this.aborted = 1; 
     212                                $io.attr('src', s.iframeSrc); // abort op in progress 
     213                                xhr.error = e; 
     214                                s.error && s.error.call(s.context, xhr, e, e); 
     215                                g && $.event.trigger("ajaxError", [xhr, s, e]); 
     216                                s.complete && s.complete.call(s.context, xhr, e); 
     217                        } 
     218                }; 
    288219 
    289         var cbInvoked = 0; 
    290         var timedOut = 0; 
     220                var g = s.global; 
     221                // trigger ajax global events so that activity/block indicators work like normal 
     222                if (g && ! $.active++) { 
     223                        $.event.trigger("ajaxStart"); 
     224                } 
     225                if (g) { 
     226                        $.event.trigger("ajaxSend", [xhr, s]); 
     227                } 
    291228 
    292         // take a breath so that pending repaints get some cpu time before the upload starts 
    293         setTimeout(function() { 
    294             // make sure form attrs are set 
    295             var encAttr = form.encoding ? 'encoding' : 'enctype'; 
    296             var t = $form.attr('target'); 
    297             $form.attr({ 
    298                 target:   id, 
    299                 method:  'POST', 
    300                 action:   opts.url 
    301             }); 
    302             form[encAttr] = 'multipart/form-data'; 
     229                if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) { 
     230                        if (s.global) {  
     231                                $.active--; 
     232                        } 
     233                        return; 
     234                } 
     235                if (xhr.aborted) { 
     236                        return; 
     237                } 
    303238 
    304             // support timout 
    305             if (opts.timeout) 
    306                 setTimeout(function() { timedOut = true; cb(); }, opts.timeout); 
     239                var timedOut = 0, timeoutHandle; 
    307240 
    308             // add iframe to doc and submit the form 
    309             $io.appendTo('body'); 
    310             io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false); 
    311             form.submit(); 
    312             $form.attr('target', t); // reset target 
    313         }, 10); 
     241                // add submitting element to data if we know it 
     242                var sub = form.clk; 
     243                if (sub) { 
     244                        var n = sub.name; 
     245                        if (n && !sub.disabled) { 
     246                                s.extraData = s.extraData || {}; 
     247                                s.extraData[n] = sub.value; 
     248                                if (sub.type == "image") { 
     249                                        s.extraData[n+'.x'] = form.clk_x; 
     250                                        s.extraData[n+'.y'] = form.clk_y; 
     251                                } 
     252                        } 
     253                } 
    314254 
    315         function cb() { 
    316             if (cbInvoked++) return; 
     255                // take a breath so that pending repaints get some cpu time before the upload starts 
     256                function doSubmit() { 
     257                        // make sure form attrs are set 
     258                        var t = $form.attr('target'), a = $form.attr('action'); 
    317259 
     260                        // update form attrs in IE friendly way 
     261                        form.setAttribute('target',id); 
     262                        if (form.getAttribute('method') != 'POST') { 
     263                                form.setAttribute('method', 'POST'); 
     264                        } 
     265                        if (form.getAttribute('action') != s.url) { 
     266                                form.setAttribute('action', s.url); 
     267                        } 
     268 
     269                        // ie borks in some cases when setting encoding 
     270                        if (! s.skipEncodingOverride) { 
     271                                $form.attr({ 
     272                                        encoding: 'multipart/form-data', 
     273                                        enctype:  'multipart/form-data' 
     274                                }); 
     275                        } 
     276 
     277                        // support timout 
     278                        if (s.timeout) { 
     279                                timeoutHandle = setTimeout(function() { timedOut = true; cb(true); }, s.timeout); 
     280                        } 
     281 
     282                        // add "extra" data to form if provided in options 
     283                        var extraInputs = []; 
     284                        try { 
     285                                if (s.extraData) { 
     286                                        for (var n in s.extraData) { 
     287                                                extraInputs.push( 
     288                                                        $('<input type="hidden" name="'+n+'" value="'+s.extraData[n]+'" />') 
     289                                                                .appendTo(form)[0]); 
     290                                        } 
     291                                } 
     292 
     293                                // add iframe to doc and submit the form 
     294                                $io.appendTo('body'); 
     295                io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false); 
     296                                form.submit(); 
     297                        } 
     298                        finally { 
     299                                // reset attrs and remove "extra" input elements 
     300                                form.setAttribute('action',a); 
     301                                if(t) { 
     302                                        form.setAttribute('target', t); 
     303                                } else { 
     304                                        $form.removeAttr('target'); 
     305                                } 
     306                                $(extraInputs).remove(); 
     307                        } 
     308                } 
     309 
     310                if (s.forceSync) { 
     311                        doSubmit(); 
     312                } 
     313                else { 
     314                        setTimeout(doSubmit, 10); // this lets dom updates render 
     315                } 
     316         
     317                var data, doc, domCheckCount = 50, callbackProcessed; 
     318 
     319                function cb(e) { 
     320                        if (xhr.aborted || callbackProcessed) { 
     321                                return; 
     322                        } 
     323                        if (e === true && xhr) { 
     324                                xhr.abort('timeout'); 
     325                                return; 
     326                        } 
     327                         
     328                        var doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document; 
     329                        if (!doc || doc.location.href == s.iframeSrc) { 
     330                                // response not received yet 
     331                                if (!timedOut) 
     332                                        return; 
     333                        } 
    318334            io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false); 
    319335 
    320             var ok = true; 
    321             try { 
    322                 if (timedOut) throw 'timeout'; 
    323                 // extract the server response from the iframe 
    324                 var data, doc; 
    325                 doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document; 
    326                 xhr.responseText = doc.body ? doc.body.innerHTML : null; 
    327                 xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc; 
     336                        var ok = true; 
     337                        try { 
     338                                if (timedOut) { 
     339                                        throw 'timeout'; 
     340                                } 
    328341 
    329                 if (opts.dataType == 'json' || opts.dataType == 'script') { 
    330                     var ta = doc.getElementsByTagName('textarea')[0]; 
    331                     data = ta ? ta.value : xhr.responseText; 
    332                     if (opts.dataType == 'json') 
    333                         eval("data = " + data); 
    334                     else 
    335                         $.globalEval(data); 
    336                 } 
    337                 else if (opts.dataType == 'xml') { 
    338                     data = xhr.responseXML; 
    339                     if (!data && xhr.responseText != null) 
    340                         data = toXml(xhr.responseText); 
    341                 } 
    342                 else { 
    343                     data = xhr.responseText; 
    344                 } 
    345             } 
    346             catch(e){ 
    347                 ok = false; 
    348                 $.handleError(opts, xhr, 'error', e); 
    349             } 
     342                                var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc); 
     343                                log('isXml='+isXml); 
     344                                if (!isXml && window.opera && (doc.body == null || doc.body.innerHTML == '')) { 
     345                                        if (--domCheckCount) { 
     346                                                // in some browsers (Opera) the iframe DOM is not always traversable when 
     347                                                // the onload callback fires, so we loop a bit to accommodate 
     348                                                log('requeing onLoad callback, DOM not available'); 
     349                                                setTimeout(cb, 250); 
     350                                                return; 
     351                                        } 
     352                                        // let this fall through because server response could be an empty document 
     353                                        //log('Could not access iframe DOM after mutiple tries.'); 
     354                                        //throw 'DOMException: not available'; 
     355                                } 
    350356 
    351             // ordering of these callbacks/triggers is odd, but that's how $.ajax does it 
    352             if (ok) { 
    353                 opts.success(data, 'success'); 
    354                 if (g) $.event.trigger("ajaxSuccess", [xhr, opts]); 
    355             } 
    356             if (g) $.event.trigger("ajaxComplete", [xhr, opts]); 
    357             if (g && ! --$.active) $.event.trigger("ajaxStop"); 
    358             if (opts.complete) opts.complete(xhr, ok ? 'success' : 'error'); 
     357                                //log('response detected'); 
     358                                xhr.responseText = doc.body ? doc.body.innerHTML : doc.documentElement ? doc.documentElement.innerHTML : null;  
     359                                xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc; 
     360                                if (isXml) 
     361                                        s.dataType = 'xml'; 
     362                                xhr.getResponseHeader = function(header){ 
     363                                        var headers = {'content-type': s.dataType}; 
     364                                        return headers[header]; 
     365                                }; 
    359366 
    360             // clean up 
    361             setTimeout(function() { 
    362                 $io.remove(); 
    363                 xhr.responseXML = null; 
    364             }, 100); 
    365         }; 
     367                                var scr = /(json|script|text)/.test(s.dataType); 
     368                                if (scr || s.textarea) { 
     369                                        // see if user embedded response in textarea 
     370                                        var ta = doc.getElementsByTagName('textarea')[0]; 
     371                                        if (ta) { 
     372                                                xhr.responseText = ta.value; 
     373                                        } 
     374                                        else if (scr) { 
     375                                                // account for browsers injecting pre around json response 
     376                                                var pre = doc.getElementsByTagName('pre')[0]; 
     377                                                var b = doc.getElementsByTagName('body')[0]; 
     378                                                if (pre) { 
     379                                                        xhr.responseText = pre.textContent; 
     380                                                } 
     381                                                else if (b) { 
     382                                                        xhr.responseText = b.innerHTML; 
     383                                                } 
     384                                        }                          
     385                                } 
     386                                else if (s.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) { 
     387                                        xhr.responseXML = toXml(xhr.responseText); 
     388                                } 
     389                                 
     390                                data = httpData(xhr, s.dataType, s); 
     391                        } 
     392                        catch(e){ 
     393                                log('error caught:',e); 
     394                                ok = false; 
     395                                xhr.error = e; 
     396                                s.error && s.error.call(s.context, xhr, 'error', e); 
     397                                g && $.event.trigger("ajaxError", [xhr, s, e]); 
     398                        } 
     399                         
     400                        if (xhr.aborted) { 
     401                                log('upload aborted'); 
     402                                ok = false; 
     403                        } 
    366404 
    367         function toXml(s, doc) { 
    368             if (window.ActiveXObject) { 
    369                 doc = new ActiveXObject('Microsoft.XMLDOM'); 
    370                 doc.async = 'false'; 
    371                 doc.loadXML(s); 
    372             } 
    373             else 
    374                 doc = (new DOMParser()).parseFromString(s, 'text/xml'); 
    375             return (doc && doc.documentElement && doc.documentElement.tagName != 'parsererror') ? doc : null; 
    376         }; 
    377     }; 
     405                        // ordering of these callbacks/triggers is odd, but that's how $.ajax does it 
     406                        if (ok) { 
     407                                s.success && s.success.call(s.context, data, 'success', xhr); 
     408                                g && $.event.trigger("ajaxSuccess", [xhr, s]); 
     409                        } 
     410                         
     411                        g && $.event.trigger("ajaxComplete", [xhr, s]); 
     412 
     413                        if (g && ! --$.active) { 
     414                                $.event.trigger("ajaxStop"); 
     415                        } 
     416                         
     417                        s.complete && s.complete.call(s.context, xhr, ok ? 'success' : 'error'); 
     418 
     419                        callbackProcessed = true; 
     420                        if (s.timeout) 
     421                                clearTimeout(timeoutHandle); 
     422 
     423                        // clean up 
     424                        setTimeout(function() { 
     425                                $io.removeData('form-plugin-onload'); 
     426                                $io.remove(); 
     427                                xhr.responseXML = null; 
     428                        }, 100); 
     429                } 
     430 
     431                var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+) 
     432                        if (window.ActiveXObject) { 
     433                                doc = new ActiveXObject('Microsoft.XMLDOM'); 
     434                                doc.async = 'false'; 
     435                                doc.loadXML(s); 
     436                        } 
     437                        else { 
     438                                doc = (new DOMParser()).parseFromString(s, 'text/xml'); 
     439                        } 
     440                        return (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc : null; 
     441                }; 
     442                var parseJSON = $.parseJSON || function(s) { 
     443                        return window['eval']('(' + s + ')'); 
     444                }; 
     445                 
     446                var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4 
     447                        var ct = xhr.getResponseHeader('content-type') || '', 
     448                                xml = type === 'xml' || !type && ct.indexOf('xml') >= 0, 
     449                                data = xml ? xhr.responseXML : xhr.responseText; 
     450 
     451                        if (xml && data.documentElement.nodeName === 'parsererror') { 
     452                                $.error && $.error('parsererror'); 
     453                        } 
     454                        if (s && s.dataFilter) { 
     455                                data = s.dataFilter(data, type); 
     456                        } 
     457                        if (typeof data === 'string') { 
     458                                if (type === 'json' || !type && ct.indexOf('json') >= 0) { 
     459                                        data = parseJSON(data); 
     460                                } else if (type === "script" || !type && ct.indexOf("javascript") >= 0) { 
     461                                        $.globalEval(data); 
     462                                } 
     463                        } 
     464                        return data; 
     465                }; 
     466        } 
    378467}; 
    379 $.fn.ajaxSubmit.counter = 0; // used to create unique iframe ids 
    380468 
    381469/** 
    382470 * ajaxForm() provides a mechanism for fully automating form submission. 
     
    384472 * The advantages of using this method instead of ajaxSubmit() are: 
    385473 * 
    386474 * 1: This method will include coordinates for <input type="image" /> elements (if the element 
    387  *    is used to submit the form). 
     475 *      is used to submit the form). 
    388476 * 2. This method will include the submit element's name/value data (for the element that was 
    389  *    used to submit the form). 
     477 *      used to submit the form). 
    390478 * 3. This method binds the submit() method to the form for you. 
    391479 * 
    392  * Note that for accurate x/y coordinates of image submit elements in all browsers 
    393  * you need to also use the "dimensions" plugin (this method will auto-detect its presence). 
    394  * 
    395480 * The options argument for ajaxForm works exactly as it does for ajaxSubmit.  ajaxForm merely 
    396481 * passes the options argument along after properly binding events for submit elements and 
    397  * the form itself.  See ajaxSubmit for a full description of the options argument. 
    398  * 
    399  * 
    400  * @example 
    401  * var options = { 
    402  *     target: '#myTargetDiv' 
    403  * }; 
    404  * $('#myForm').ajaxSForm(options); 
    405  * @desc Bind form's submit event so that 'myTargetDiv' is updated with the server response 
    406  *       when the form is submitted. 
    407  * 
    408  * 
    409  * @example 
    410  * var options = { 
    411  *     success: function(responseText) { 
    412  *         alert(responseText); 
    413  *     } 
    414  * }; 
    415  * $('#myForm').ajaxSubmit(options); 
    416  * @desc Bind form's submit event so that server response is alerted after the form is submitted. 
    417  * 
    418  * 
    419  * @example 
    420  * var options = { 
    421  *     beforeSubmit: function(formArray, jqForm) { 
    422  *         if (formArray.length == 0) { 
    423  *             alert('Please enter data.'); 
    424  *             return false; 
    425  *         } 
    426  *     } 
    427  * }; 
    428  * $('#myForm').ajaxSubmit(options); 
    429  * @desc Bind form's submit event so that pre-submit callback is invoked before the form 
    430  *       is submitted. 
    431  * 
    432  * 
    433  * @name   ajaxForm 
    434  * @param  options  object literal containing options which control the form submission process 
    435  * @return jQuery 
    436  * @cat    Plugins/Form 
    437  * @type   jQuery 
     482 * the form itself. 
    438483 */ 
    439484$.fn.ajaxForm = function(options) { 
    440     return this.ajaxFormUnbind().submit(submitHandler).each(function() { 
    441         // store options in hash 
    442         this.formPluginId = $.fn.ajaxForm.counter++; 
    443         $.fn.ajaxForm.optionHash[this.formPluginId] = options; 
    444         $(":submit,input:image", this).click(clickHandler); 
    445     }); 
     485        // in jQuery 1.3+ we can fix mistakes with the ready state 
     486        if (this.length === 0) { 
     487                var o = { s: this.selector, c: this.context }; 
     488                if (!$.isReady && o.s) { 
     489                        log('DOM not ready, queuing ajaxForm'); 
     490                        $(function() { 
     491                                $(o.s,o.c).ajaxForm(options); 
     492                        }); 
     493                        return this; 
     494                } 
     495                // is your DOM ready?  http://docs.jquery.com/Tutorials:Introducing_$(document).ready() 
     496                log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)')); 
     497                return this; 
     498        } 
     499         
     500        return this.ajaxFormUnbind().bind('submit.form-plugin', function(e) { 
     501                if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed 
     502                        e.preventDefault(); 
     503                        $(this).ajaxSubmit(options); 
     504                } 
     505        }).bind('click.form-plugin', function(e) { 
     506                var target = e.target; 
     507                var $el = $(target); 
     508                if (!($el.is(":submit,input:image"))) { 
     509                        // is this a child element of the submit el?  (ex: a span within a button) 
     510                        var t = $el.closest(':submit'); 
     511                        if (t.length == 0) { 
     512                                return; 
     513                        } 
     514                        target = t[0]; 
     515                } 
     516                var form = this; 
     517                form.clk = target; 
     518                if (target.type == 'image') { 
     519                        if (e.offsetX != undefined) { 
     520                                form.clk_x = e.offsetX; 
     521                                form.clk_y = e.offsetY; 
     522                        } else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin 
     523                                var offset = $el.offset(); 
     524                                form.clk_x = e.pageX - offset.left; 
     525                                form.clk_y = e.pageY - offset.top; 
     526                        } else { 
     527                                form.clk_x = e.pageX - target.offsetLeft; 
     528                                form.clk_y = e.pageY - target.offsetTop; 
     529                        } 
     530                } 
     531                // clear form vars 
     532                setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100); 
     533        }); 
    446534}; 
    447535 
    448 $.fn.ajaxForm.counter = 1; 
    449 $.fn.ajaxForm.optionHash = {}; 
    450  
    451 function clickHandler(e) { 
    452     var $form = this.form; 
    453     $form.clk = this; 
    454     if (this.type == 'image') { 
    455         if (e.offsetX != undefined) { 
    456             $form.clk_x = e.offsetX; 
    457             $form.clk_y = e.offsetY; 
    458         } else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin 
    459             var offset = $(this).offset(); 
    460             $form.clk_x = e.pageX - offset.left; 
    461             $form.clk_y = e.pageY - offset.top; 
    462         } else { 
    463             $form.clk_x = e.pageX - this.offsetLeft; 
    464             $form.clk_y = e.pageY - this.offsetTop; 
    465         } 
    466     } 
    467     // clear form vars 
    468     setTimeout(function() { $form.clk = $form.clk_x = $form.clk_y = null; }, 10); 
    469 }; 
    470  
    471 function submitHandler() { 
    472     // retrieve options from hash 
    473     var id = this.formPluginId; 
    474     var options = $.fn.ajaxForm.optionHash[id]; 
    475     $(this).ajaxSubmit(options); 
    476     return false; 
    477 }; 
    478  
    479 /** 
    480  * ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm 
    481  * 
    482  * @name   ajaxFormUnbind 
    483  * @return jQuery 
    484  * @cat    Plugins/Form 
    485  * @type   jQuery 
    486  */ 
     536// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm 
    487537$.fn.ajaxFormUnbind = function() { 
    488     this.unbind('submit', submitHandler); 
    489     return this.each(function() { 
    490         $(":submit,input:image", this).unbind('click', clickHandler); 
    491     }); 
    492  
     538        return this.unbind('submit.form-plugin click.form-plugin'); 
    493539}; 
    494540 
    495541/** 
     
    502548 * 
    503549 * It is this array that is passed to pre-submit callback functions provided to the 
    504550 * ajaxSubmit() and ajaxForm() methods. 
    505  * 
    506  * The semantic argument can be used to force form serialization in semantic order. 
    507  * This is normally true anyway, unless the form contains input elements of type='image'. 
    508  * If your form must be submitted with name/value pairs in semantic order and your form 
    509  * contains an input of type='image" then pass true for this arg, otherwise pass false 
    510  * (or nothing) to avoid the overhead for this logic. 
    511  * 
    512  * @example var data = $("#myForm").formToArray(); 
    513  * $.post( "myscript.cgi", data ); 
    514  * @desc Collect all the data from a form and submit it to the server. 
    515  * 
    516  * @name formToArray 
    517  * @param semantic true if serialization must maintain strict semantic ordering of elements (slower) 
    518  * @type Array<Object> 
    519  * @cat Plugins/Form 
    520551 */ 
    521552$.fn.formToArray = function(semantic) { 
    522     var a = []; 
    523     if (this.length == 0) return a; 
     553        var a = []; 
     554        if (this.length === 0) { 
     555                return a; 
     556        } 
    524557 
    525     var form = this[0]; 
    526     var els = semantic ? form.getElementsByTagName('*') : form.elements; 
    527     if (!els) return a; 
    528     for(var i=0, max=els.length; i < max; i++) { 
    529         var el = els[i]; 
    530         var n = el.name; 
    531         if (!n) continue; 
     558        var form = this[0]; 
     559        var els = semantic ? form.getElementsByTagName('*') : form.elements; 
     560        if (!els) { 
     561                return a; 
     562        } 
     563         
     564        var i,j,n,v,el,max,jmax; 
     565        for(i=0, max=els.length; i < max; i++) { 
     566                el = els[i]; 
     567                n = el.name; 
     568                if (!n) { 
     569                        continue; 
     570                } 
    532571 
    533         if (semantic && form.clk && el.type == "image") { 
    534             // handle image inputs on the fly when semantic == true 
    535             if(!el.disabled && form.clk == el) 
    536                 a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y}); 
    537             continue; 
    538         } 
     572                if (semantic && form.clk && el.type == "image") { 
     573                        // handle image inputs on the fly when semantic == true 
     574                        if(!el.disabled && form.clk == el) { 
     575                                a.push({name: n, value: $(el).val()}); 
     576                                a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y}); 
     577                        } 
     578                        continue; 
     579                } 
    539580 
    540         var v = $.fieldValue(el, true); 
    541         if (v && v.constructor == Array) { 
    542             for(var j=0, jmax=v.length; j < jmax; j++) 
    543                 a.push({name: n, value: v[j]}); 
    544         } 
    545         else if (v !== null && typeof v != 'undefined') 
    546             a.push({name: n, value: v}); 
    547     } 
     581                v = $.fieldValue(el, true); 
     582                if (v && v.constructor == Array) { 
     583                        for(j=0, jmax=v.length; j < jmax; j++) { 
     584                                a.push({name: n, value: v[j]}); 
     585                        } 
     586                } 
     587                else if (v !== null && typeof v != 'undefined') { 
     588                        a.push({name: n, value: v}); 
     589                } 
     590        } 
    548591 
    549     if (!semantic && form.clk) { 
    550         // input type=='image' are not found in elements array! handle them here 
    551         var inputs = form.getElementsByTagName("input"); 
    552         for(var i=0, max=inputs.length; i < max; i++) { 
    553             var input = inputs[i]; 
    554             var n = input.name; 
    555             if(n && !input.disabled && input.type == "image" && form.clk == input) 
    556                 a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y}); 
    557         } 
    558     } 
    559     return a; 
     592        if (!semantic && form.clk) { 
     593                // input type=='image' are not found in elements array! handle it here 
     594                var $input = $(form.clk), input = $input[0]; 
     595                n = input.name; 
     596                if (n && !input.disabled && input.type == 'image') { 
     597                        a.push({name: n, value: $input.val()}); 
     598                        a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y}); 
     599                } 
     600        } 
     601        return a; 
    560602}; 
    561603 
    562  
    563604/** 
    564605 * Serializes form data into a 'submittable' string. This method will return a string 
    565606 * in the format: name1=value1&amp;name2=value2 
    566  * 
    567  * The semantic argument can be used to force form serialization in semantic order. 
    568  * If your form must be submitted with name/value pairs in semantic order then pass 
    569  * true for this arg, otherwise pass false (or nothing) to avoid the overhead for 
    570  * this logic (which can be significant for very large forms). 
    571  * 
    572  * @example var data = $("#myForm").formSerialize(); 
    573  * $.ajax('POST', "myscript.cgi", data); 
    574  * @desc Collect all the data from a form into a single string 
    575  * 
    576  * @name formSerialize 
    577  * @param semantic true if serialization must maintain strict semantic ordering of elements (slower) 
    578  * @type String 
    579  * @cat Plugins/Form 
    580607 */ 
    581608$.fn.formSerialize = function(semantic) { 
    582     //hand off to jQuery.param for proper encoding 
    583     return $.param(this.formToArray(semantic)); 
     609        //hand off to jQuery.param for proper encoding 
     610        return $.param(this.formToArray(semantic)); 
    584611}; 
    585612 
    586  
    587613/** 
    588614 * Serializes all field elements in the jQuery object into a query string. 
    589615 * This method will return a string in the format: name1=value1&amp;name2=value2 
    590  * 
    591  * The successful argument controls whether or not serialization is limited to 
    592  * 'successful' controls (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls). 
    593  * The default value of the successful argument is true. 
    594  * 
    595  * @example var data = $("input").formSerialize(); 
    596  * @desc Collect the data from all successful input elements into a query string 
    597  * 
    598  * @example var data = $(":radio").formSerialize(); 
    599  * @desc Collect the data from all successful radio input elements into a query string 
    600  * 
    601  * @example var data = $("#myForm :checkbox").formSerialize(); 
    602  * @desc Collect the data from all successful checkbox input elements in myForm into a query string 
    603  * 
    604  * @example var data = $("#myForm :checkbox").formSerialize(false); 
    605  * @desc Collect the data from all checkbox elements in myForm (even the unchecked ones) into a query string 
    606  * 
    607  * @example var data = $(":input").formSerialize(); 
    608  * @desc Collect the data from all successful input, select, textarea and button elements into a query string 
    609  * 
    610  * @name fieldSerialize 
    611  * @param successful true if only successful controls should be serialized (default is true) 
    612  * @type String 
    613  * @cat Plugins/Form 
    614616 */ 
    615617$.fn.fieldSerialize = function(successful) { 
    616     var a = []; 
    617     this.each(function() { 
    618         var n = this.name; 
    619         if (!n) return; 
    620         var v = $.fieldValue(this, successful); 
    621         if (v && v.constructor == Array) { 
    622             for (var i=0,max=v.length; i < max; i++) 
    623                 a.push({name: n, value: v[i]}); 
    624         } 
    625         else if (v !== null && typeof v != 'undefined') 
    626             a.push({name: this.name, value: v}); 
    627     }); 
    628     //hand off to jQuery.param for proper encoding 
    629     return $.param(a); 
     618        var a = []; 
     619        this.each(function() { 
     620                var n = this.name; 
     621                if (!n) { 
     622                        return; 
     623                } 
     624                var v = $.fieldValue(this, successful); 
     625                if (v && v.constructor == Array) { 
     626                        for (var i=0,max=v.length; i < max; i++) { 
     627                                a.push({name: n, value: v[i]}); 
     628                        } 
     629                } 
     630                else if (v !== null && typeof v != 'undefined') { 
     631                        a.push({name: this.name, value: v}); 
     632                } 
     633        }); 
     634        //hand off to jQuery.param for proper encoding 
     635        return $.param(a); 
    630636}; 
    631637 
    632  
    633638/** 
    634639 * Returns the value(s) of the element in the matched set.  For example, consider the following form: 
    635640 * 
    636641 *  <form><fieldset> 
    637  *      <input name="A" type="text" /> 
    638  *      <input name="A" type="text" /> 
    639  *      <input name="B" type="checkbox" value="B1" /> 
    640  *      <input name="B" type="checkbox" value="B2"/> 
    641  *      <input name="C" type="radio" value="C1" /> 
    642  *      <input name="C" type="radio" value="C2" /> 
     642 *        <input name="A" type="text" /> 
     643 *        <input name="A" type="text" /> 
     644 *        <input name="B" type="checkbox" value="B1" /> 
     645 *        <input name="B" type="checkbox" value="B2"/> 
     646 *        <input name="C" type="radio" value="C1" /> 
     647 *        <input name="C" type="radio" value="C2" /> 
    643648 *  </fieldset></form> 
    644649 * 
    645650 *  var v = $(':text').fieldValue(); 
     
    666671 * for each element is returned. 
    667672 * 
    668673 * Note: This method *always* returns an array.  If no valid value can be determined the 
    669  *       array will be empty, otherwise it will contain one or more values. 
    670  * 
    671  * @example var data = $("#myPasswordElement").fieldValue(); 
    672  * alert(data[0]); 
    673  * @desc Alerts the current value of the myPasswordElement element 
    674  * 
    675  * @example var data = $("#myForm :input").fieldValue(); 
    676  * @desc Get the value(s) of the form elements in myForm 
    677  * 
    678  * @example var data = $("#myForm :checkbox").fieldValue(); 
    679  * @desc Get the value(s) for the successful checkbox element(s) in the jQuery object. 
    680  * 
    681  * @example var data = $("#mySingleSelect").fieldValue(); 
    682  * @desc Get the value(s) of the select control 
    683  * 
    684  * @example var data = $(':text').fieldValue(); 
    685  * @desc Get the value(s) of the text input or textarea elements 
    686  * 
    687  * @example var data = $("#myMultiSelect").fieldValue(); 
    688  * @desc Get the values for the select-multiple control 
    689  * 
    690  * @name fieldValue 
    691  * @param Boolean successful true if only the values for successful controls should be returned (default is true) 
    692  * @type Array<String> 
    693  * @cat Plugins/Form 
     674 *         array will be empty, otherwise it will contain one or more values. 
    694675 */ 
    695676$.fn.fieldValue = function(successful) { 
    696     for (var val=[], i=0, max=this.length; i < max; i++) { 
    697         var el = this[i]; 
    698         var v = $.fieldValue(el, successful); 
    699         if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) 
    700             continue; 
    701         v.constructor == Array ? $.merge(val, v) : val.push(v); 
    702     } 
    703     return val; 
     677        for (var val=[], i=0, max=this.length; i < max; i++) { 
     678                var el = this[i]; 
     679                var v = $.fieldValue(el, successful); 
     680                if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) { 
     681                        continue; 
     682                } 
     683                v.constructor == Array ? $.merge(val, v) : val.push(v); 
     684        } 
     685        return val; 
    704686}; 
    705687 
    706688/** 
    707689 * Returns the value of the field element. 
    708  * 
    709  * The successful argument controls whether or not the field element must be 'successful' 
    710  * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls). 
    711  * The default value of the successful argument is true.  If the given element is not 
    712  * successful and the successful arg is not false then the returned value will be null. 
    713  * 
    714  * Note: If the successful flag is true (default) but the element is not successful, the return will be null 
    715  * Note: The value returned for a successful select-multiple element will always be an array. 
    716  * Note: If the element has no value the return value will be undefined. 
    717  * 
    718  * @example var data = jQuery.fieldValue($("#myPasswordElement")[0]); 
    719  * @desc Gets the current value of the myPasswordElement element 
    720  * 
    721  * @name fieldValue 
    722  * @param Element el The DOM element for which the value will be returned 
    723  * @param Boolean successful true if value returned must be for a successful controls (default is true) 
    724  * @type String or Array<String> or null or undefined 
    725  * @cat Plugins/Form 
    726690 */ 
    727691$.fieldValue = function(el, successful) { 
    728     var n = el.name, t = el.type, tag = el.tagName.toLowerCase(); 
    729     if (typeof successful == 'undefined') successful = true; 
     692        var n = el.name, t = el.type, tag = el.tagName.toLowerCase(); 
     693        if (successful === undefined) { 
     694                successful = true; 
     695        } 
    730696 
    731     if (successful && (!n || el.disabled || t == 'reset' || t == 'button' || 
    732         (t == 'checkbox' || t == 'radio') && !el.checked || 
    733         (t == 'submit' || t == 'image') && el.form && el.form.clk != el || 
    734         tag == 'select' && el.selectedIndex == -1)) 
    735             return null; 
     697        if (successful && (!n || el.disabled || t == 'reset' || t == 'button' || 
     698                (t == 'checkbox' || t == 'radio') && !el.checked || 
     699                (t == 'submit' || t == 'image') && el.form && el.form.clk != el || 
     700                tag == 'select' && el.selectedIndex == -1)) { 
     701                        return null; 
     702        } 
    736703 
    737     if (tag == 'select') { 
    738         var index = el.selectedIndex; 
    739         if (index < 0) return null; 
    740         var a = [], ops = el.options; 
    741         var one = (t == 'select-one'); 
    742         var max = (one ? index+1 : ops.length); 
    743         for(var i=(one ? index : 0); i < max; i++) { 
    744             var op = ops[i]; 
    745             if (op.selected) { 
    746                 // extra pain for IE... 
    747                 var v = $.browser.msie && !(op.attributes['value'].specified) ? op.text : op.value; 
    748                 if (one) return v; 
    749                 a.push(v); 
    750             } 
    751         } 
    752         return a; 
    753     } 
    754     return el.value; 
     704        if (tag == 'select') { 
     705                var index = el.selectedIndex; 
     706                if (index < 0) { 
     707                        return null; 
     708                } 
     709                var a = [], ops = el.options; 
     710                var one = (t == 'select-one'); 
     711                var max = (one ? index+1 : ops.length); 
     712                for(var i=(one ? index : 0); i < max; i++) { 
     713                        var op = ops[i]; 
     714                        if (op.selected) { 
     715                                var v = op.value; 
     716                                if (!v) { // extra pain for IE... 
     717                                        v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value; 
     718                                } 
     719                                if (one) { 
     720                                        return v; 
     721                                } 
     722                                a.push(v); 
     723                        } 
     724                } 
     725                return a; 
     726        } 
     727        return $(el).val(); 
    755728}; 
    756729 
    757  
    758730/** 
    759731 * Clears the form data.  Takes the following actions on the form's input fields: 
    760732 *  - input text fields will have their 'value' property set to the empty string 
     
    762734 *  - checkbox and radio inputs will have their 'checked' property set to false 
    763735 *  - inputs of type submit, button, reset, and hidden will *not* be effected 
    764736 *  - button elements will *not* be effected 
    765  * 
    766  * @example $('form').clearForm(); 
    767  * @desc Clears all forms on the page. 
    768  * 
    769  * @name clearForm 
    770  * @type jQuery 
    771  * @cat Plugins/Form 
    772737 */ 
    773738$.fn.clearForm = function() { 
    774     return this.each(function() { 
    775         $('input,select,textarea', this).clearFields(); 
    776     }); 
     739        return this.each(function() { 
     740                $('input,select,textarea', this).clearFields(); 
     741        }); 
    777742}; 
    778743 
    779744/** 
    780  * Clears the selected form elements.  Takes the following actions on the matched elements: 
    781  *  - input text fields will have their 'value' property set to the empty string 
    782  *  - select elements will have their 'selectedIndex' property set to -1 
    783  *  - checkbox and radio inputs will have their 'checked' property set to false 
    784  *  - inputs of type submit, button, reset, and hidden will *not* be effected 
    785  *  - button elements will *not* be effected 
    786  * 
    787  * @example $('.myInputs').clearFields(); 
    788  * @desc Clears all inputs with class myInputs 
    789  * 
    790  * @name clearFields 
    791  * @type jQuery 
    792  * @cat Plugins/Form 
     745 * Clears the selected form elements. 
    793746 */ 
    794747$.fn.clearFields = $.fn.clearInputs = function() { 
    795     return this.each(function() { 
    796         var t = this.type, tag = this.tagName.toLowerCase(); 
    797         if (t == 'text' || t == 'password' || tag == 'textarea') 
    798             this.value = ''; 
    799         else if (t == 'checkbox' || t == 'radio') 
    800             this.checked = false; 
    801         else if (tag == 'select') 
    802             this.selectedIndex = -1; 
    803     }); 
     748        return this.each(function() { 
     749                var t = this.type, tag = this.tagName.toLowerCase(); 
     750                if (t == 'text' || t == 'password' || tag == 'textarea') { 
     751                        this.value = ''; 
     752                } 
     753                else if (t == 'checkbox' || t == 'radio') { 
     754                        this.checked = false; 
     755                } 
     756                else if (tag == 'select') { 
     757                        this.selectedIndex = -1; 
     758                } 
     759        }); 
    804760}; 
    805761 
    806  
    807762/** 
    808763 * Resets the form data.  Causes all form elements to be reset to their original value. 
    809  * 
    810  * @example $('form').resetForm(); 
    811  * @desc Resets all forms on the page. 
    812  * 
    813  * @name resetForm 
    814  * @type jQuery 
    815  * @cat Plugins/Form 
    816764 */ 
    817765$.fn.resetForm = function() { 
    818     return this.each(function() { 
    819         // guard against an input with the name of 'reset' 
    820         // note that IE reports the reset function as an 'object' 
    821         if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) 
    822             this.reset(); 
    823     }); 
     766        return this.each(function() { 
     767                // guard against an input with the name of 'reset' 
     768                // note that IE reports the reset function as an 'object' 
     769                if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) { 
     770                        this.reset(); 
     771                } 
     772        }); 
    824773}; 
    825774 
    826  
    827775/** 
    828776 * Enables or disables any matching elements. 
    829  * 
    830  * @example $(':radio').enabled(false); 
    831  * @desc Disables all radio buttons 
    832  * 
    833  * @name select 
    834  * @type jQuery 
    835  * @cat Plugins/Form 
    836777 */ 
    837 $.fn.enable = function(b) {  
    838     if (b == undefined) b = true; 
    839     return this.each(function() {  
    840         this.disabled = !b  
    841     }); 
     778$.fn.enable = function(b) { 
     779        if (b === undefined) { 
     780                b = true; 
     781        } 
     782        return this.each(function() { 
     783                this.disabled = !b; 
     784        }); 
    842785}; 
    843786 
    844787/** 
    845788 * Checks/unchecks any matching checkboxes or radio buttons and 
    846789 * selects/deselects and matching option elements. 
    847  * 
    848  * @example $(':checkbox').selected(); 
    849  * @desc Checks all checkboxes 
    850  * 
    851  * @name select 
    852  * @type jQuery 
    853  * @cat Plugins/Form 
    854790 */ 
    855 $.fn.select = function(select) { 
    856     if (select == undefined) select = true; 
    857     return this.each(function() {  
    858         var t = this.type; 
    859         if (t == 'checkbox' || t == 'radio') 
    860             this.checked = select; 
    861         else if (this.tagName.toLowerCase() == 'option') { 
    862             var $sel = $(this).parent('select'); 
    863             if (select && $sel[0] && $sel[0].type == 'select-one') { 
    864                 // deselect all other options 
    865                 $sel.find('option').select(false); 
    866             } 
    867             this.selected = select; 
    868         } 
    869     }); 
     791$.fn.selected = function(select) { 
     792        if (select === undefined) { 
     793                select = true; 
     794        } 
     795        return this.each(function() { 
     796                var t = this.type; 
     797                if (t == 'checkbox' || t == 'radio') { 
     798                        this.checked = select; 
     799                } 
     800                else if (this.tagName.toLowerCase() == 'option') { 
     801                        var $sel = $(this).parent('select'); 
     802                        if (select && $sel[0] && $sel[0].type == 'select-one') { 
     803                                // deselect all other options 
     804                                $sel.find('option').selected(false); 
     805                        } 
     806                        this.selected = select; 
     807                } 
     808        }); 
    870809}; 
    871810 
     811// helper fn for console logging 
     812// set $.fn.ajaxSubmit.debug to true to enable debug logging 
     813function log() { 
     814        if ($.fn.ajaxSubmit.debug) { 
     815                var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,''); 
     816                if (window.console && window.console.log) { 
     817                        window.console.log(msg); 
     818                } 
     819                else if (window.opera && window.opera.postError) { 
     820                        window.opera.postError(msg); 
     821                } 
     822        } 
     823}; 
     824 
    872825})(jQuery);