home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Blogs / wordpress2.6.exe / wordpress2.6 / wp-includes / js / jquery / jquery.form.js < prev    next >
Encoding:
JavaScript  |  2008-03-03  |  30.7 KB  |  873 lines

  1. /*
  2.  * jQuery Form Plugin
  3.  * version: 2.02 (12/16/2007)
  4.  * @requires jQuery v1.1 or later
  5.  *
  6.  * Examples at: http://malsup.com/jquery/form/
  7.  * Dual licensed under the MIT and GPL licenses:
  8.  *   http://www.opensource.org/licenses/mit-license.php
  9.  *   http://www.gnu.org/licenses/gpl.html
  10.  *
  11.  * Revision: $Id$
  12.  */
  13.  (function($) {
  14. /**
  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
  178.  */
  179. $.fn.ajaxSubmit = function(options) {
  180.     if (typeof options == 'function')
  181.         options = { success: options };
  182.  
  183.     options = $.extend({
  184.         url:  this.attr('action') || window.location.toString(),
  185.         type: this.attr('method') || 'GET'
  186.     }, options || {});
  187.  
  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;
  193.  
  194.     var a = this.formToArray(options.semantic);
  195.     if (options.data) {
  196.         for (var n in options.data)
  197.             a.push( { name: n, value: options.data[n] } );
  198.     }
  199.  
  200.     // give pre-submit callback an opportunity to abort the submit
  201.     if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) return this;
  202.  
  203.     // fire vetoable 'validate' event
  204.     $.event.trigger('form.submit.validate', [a, this, options, veto]);
  205.     if (veto.veto) return this;
  206.  
  207.     var q = $.param(a);//.replace(/%20/g,'+');
  208.  
  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'
  215.  
  216.     var $form = this, callbacks = [];
  217.     if (options.resetForm) callbacks.push(function() { $form.resetForm(); });
  218.     if (options.clearForm) callbacks.push(function() { $form.clearForm(); });
  219.  
  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);
  232.  
  233.     options.success = function(data, status) {
  234.         for (var i=0, max=callbacks.length; i < max; i++)
  235.             callbacks[i](data, status, $form);
  236.     };
  237.  
  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;
  244.  
  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);
  256.  
  257.     // fire 'notify' event
  258.     $.event.trigger('form.submit.notify', [this, options]);
  259.     return this;
  260.  
  261.  
  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);
  266.  
  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' });
  273.  
  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.         };
  283.  
  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]);
  288.  
  289.         var cbInvoked = 0;
  290.         var timedOut = 0;
  291.  
  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';
  303.  
  304.             // support timout
  305.             if (opts.timeout)
  306.                 setTimeout(function() { timedOut = true; cb(); }, opts.timeout);
  307.  
  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);
  314.  
  315.         function cb() {
  316.             if (cbInvoked++) return;
  317.  
  318.             io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false);
  319.  
  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;
  328.  
  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.             }
  350.  
  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');
  359.  
  360.             // clean up
  361.             setTimeout(function() {
  362.                 $io.remove();
  363.                 xhr.responseXML = null;
  364.             }, 100);
  365.         };
  366.  
  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.     };
  378. };
  379. $.fn.ajaxSubmit.counter = 0; // used to create unique iframe ids
  380.  
  381. /**
  382.  * ajaxForm() provides a mechanism for fully automating form submission.
  383.  *
  384.  * The advantages of using this method instead of ajaxSubmit() are:
  385.  *
  386.  * 1: This method will include coordinates for <input type="image" /> elements (if the element
  387.  *    is used to submit the form).
  388.  * 2. This method will include the submit element's name/value data (for the element that was
  389.  *    used to submit the form).
  390.  * 3. This method binds the submit() method to the form for you.
  391.  *
  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.  *
  395.  * The options argument for ajaxForm works exactly as it does for ajaxSubmit.  ajaxForm merely
  396.  * 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
  438.  */
  439. $.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.     });
  446. };
  447.  
  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.  */
  487. $.fn.ajaxFormUnbind = function() {
  488.     this.unbind('submit', submitHandler);
  489.     return this.each(function() {
  490.         $(":submit,input:image", this).unbind('click', clickHandler);
  491.     });
  492.  
  493. };
  494.  
  495. /**
  496.  * formToArray() gathers form element data into an array of objects that can
  497.  * be passed to any of the following ajax functions: $.get, $.post, or load.
  498.  * Each object in the array has both a 'name' and 'value' property.  An example of
  499.  * an array for a simple login form might be:
  500.  *
  501.  * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
  502.  *
  503.  * It is this array that is passed to pre-submit callback functions provided to the
  504.  * 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
  520.  */
  521. $.fn.formToArray = function(semantic) {
  522.     var a = [];
  523.     if (this.length == 0) return a;
  524.  
  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;
  532.  
  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.         }
  539.  
  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.     }
  548.  
  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;
  560. };
  561.  
  562.  
  563. /**
  564.  * Serializes form data into a 'submittable' string. This method will return a string
  565.  * in the format: name1=value1&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
  580.  */
  581. $.fn.formSerialize = function(semantic) {
  582.     //hand off to jQuery.param for proper encoding
  583.     return $.param(this.formToArray(semantic));
  584. };
  585.  
  586.  
  587. /**
  588.  * Serializes all field elements in the jQuery object into a query string.
  589.  * This method will return a string in the format: name1=value1&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
  614.  */
  615. $.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);
  630. };
  631.  
  632.  
  633. /**
  634.  * Returns the value(s) of the element in the matched set.  For example, consider the following form:
  635.  *
  636.  *  <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" />
  643.  *  </fieldset></form>
  644.  *
  645.  *  var v = $(':text').fieldValue();
  646.  *  // if no values are entered into the text inputs
  647.  *  v == ['','']
  648.  *  // if values entered into the text inputs are 'foo' and 'bar'
  649.  *  v == ['foo','bar']
  650.  *
  651.  *  var v = $(':checkbox').fieldValue();
  652.  *  // if neither checkbox is checked
  653.  *  v === undefined
  654.  *  // if both checkboxes are checked
  655.  *  v == ['B1', 'B2']
  656.  *
  657.  *  var v = $(':radio').fieldValue();
  658.  *  // if neither radio is checked
  659.  *  v === undefined
  660.  *  // if first radio is checked
  661.  *  v == ['C1']
  662.  *
  663.  * The successful argument controls whether or not the field element must be 'successful'
  664.  * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
  665.  * The default value of the successful argument is true.  If this value is false the value(s)
  666.  * for each element is returned.
  667.  *
  668.  * 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
  694.  */
  695. $.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;
  704. };
  705.  
  706. /**
  707.  * 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
  726.  */
  727. $.fieldValue = function(el, successful) {
  728.     var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
  729.     if (typeof successful == 'undefined') successful = true;
  730.  
  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;
  736.  
  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;
  755. };
  756.  
  757.  
  758. /**
  759.  * Clears the form data.  Takes the following actions on the form's input fields:
  760.  *  - input text fields will have their 'value' property set to the empty string
  761.  *  - select elements will have their 'selectedIndex' property set to -1
  762.  *  - checkbox and radio inputs will have their 'checked' property set to false
  763.  *  - inputs of type submit, button, reset, and hidden will *not* be effected
  764.  *  - 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
  772.  */
  773. $.fn.clearForm = function() {
  774.     return this.each(function() {
  775.         $('input,select,textarea', this).clearFields();
  776.     });
  777. };
  778.  
  779. /**
  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
  793.  */
  794. $.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.     });
  804. };
  805.  
  806.  
  807. /**
  808.  * 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
  816.  */
  817. $.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.     });
  824. };
  825.  
  826.  
  827. /**
  828.  * 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
  836.  */
  837. $.fn.enable = function(b) { 
  838.     if (b == undefined) b = true;
  839.     return this.each(function() { 
  840.         this.disabled = !b 
  841.     });
  842. };
  843.  
  844. /**
  845.  * Checks/unchecks any matching checkboxes or radio buttons and
  846.  * 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
  854.  */
  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.     });
  870. };
  871.  
  872. })(jQuery);
  873.