sphinx_django/static/jquery.form.js
changeset 3 de4a2ed2f34b
equal deleted inserted replaced
2:f5e18f8ed036 3:de4a2ed2f34b
       
     1 /*
       
     2  * jQuery Form Plugin
       
     3  * version: 2.28 (10-MAY-2009)
       
     4  * @requires jQuery v1.2.2 or later
       
     5  *
       
     6  * Examples and documentation 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 ;(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() {
       
    22             $(this).ajaxSubmit({
       
    23                 target: '#output'
       
    24             });
       
    25             return false; // <-- important!
       
    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 
       
    42 /**
       
    43  * ajaxSubmit() provides a mechanism for immediately submitting
       
    44  * an HTML form using AJAX.
       
    45  */
       
    46 $.fn.ajaxSubmit = function(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     }
       
    52 
       
    53     if (typeof options == 'function')
       
    54         options = { success: options };
       
    55 
       
    56     var url = $.trim(this.attr('action'));
       
    57     if (url) {
       
    58 	    // clean url (don't include hash vaue)
       
    59 	    url = (url.match(/^([^#]+)/)||[])[1];
       
    60    	}
       
    61    	url = url || window.location.href || ''
       
    62 
       
    63     options = $.extend({
       
    64         url:  url,
       
    65         type: this.attr('method') || 'GET'
       
    66     }, options || {});
       
    67 
       
    68     // hook for manipulating the form data before it is extracted;
       
    69     // convenient for use with rich editors like tinyMCE or FCKEditor
       
    70     var veto = {};
       
    71     this.trigger('form-pre-serialize', [this, options, veto]);
       
    72     if (veto.veto) {
       
    73         log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
       
    74         return this;
       
    75     }
       
    76 
       
    77     // provide opportunity to alter form data before it is serialized
       
    78     if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
       
    79         log('ajaxSubmit: submit aborted via beforeSerialize callback');
       
    80         return this;
       
    81     }
       
    82 
       
    83     var a = this.formToArray(options.semantic);
       
    84     if (options.data) {
       
    85         options.extraData = options.data;
       
    86         for (var n in options.data) {
       
    87           if(options.data[n] instanceof Array) {
       
    88             for (var k in options.data[n])
       
    89               a.push( { name: n, value: options.data[n][k] } );
       
    90           }
       
    91           else
       
    92              a.push( { name: n, value: options.data[n] } );
       
    93         }
       
    94     }
       
    95 
       
    96     // give pre-submit callback an opportunity to abort the submit
       
    97     if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
       
    98         log('ajaxSubmit: submit aborted via beforeSubmit callback');
       
    99         return this;
       
   100     }
       
   101 
       
   102     // fire vetoable 'validate' event
       
   103     this.trigger('form-submit-validate', [a, this, options, veto]);
       
   104     if (veto.veto) {
       
   105         log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
       
   106         return this;
       
   107     }
       
   108 
       
   109     var q = $.param(a);
       
   110 
       
   111     if (options.type.toUpperCase() == 'GET') {
       
   112         options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
       
   113         options.data = null;  // data is null for 'get'
       
   114     }
       
   115     else
       
   116         options.data = q; // data is the query string for 'post'
       
   117 
       
   118     var $form = this, callbacks = [];
       
   119     if (options.resetForm) callbacks.push(function() { $form.resetForm(); });
       
   120     if (options.clearForm) callbacks.push(function() { $form.clearForm(); });
       
   121 
       
   122     // perform a load on the target only if dataType is not provided
       
   123     if (!options.dataType && options.target) {
       
   124         var oldSuccess = options.success || function(){};
       
   125         callbacks.push(function(data) {
       
   126             $(options.target).html(data).each(oldSuccess, arguments);
       
   127         });
       
   128     }
       
   129     else if (options.success)
       
   130         callbacks.push(options.success);
       
   131 
       
   132     options.success = function(data, status) {
       
   133         for (var i=0, max=callbacks.length; i < max; i++)
       
   134             callbacks[i].apply(options, [data, status, $form]);
       
   135     };
       
   136 
       
   137     // are there files to upload?
       
   138     var files = $('input:file', this).fieldValue();
       
   139     var found = false;
       
   140     for (var j=0; j < files.length; j++)
       
   141         if (files[j])
       
   142             found = true;
       
   143 
       
   144 	var multipart = false;
       
   145 //	var mp = 'multipart/form-data';
       
   146 //	multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
       
   147 
       
   148     // options.iframe allows user to force iframe mode
       
   149    if (options.iframe || found || multipart) {
       
   150        // hack to fix Safari hang (thanks to Tim Molendijk for this)
       
   151        // see:  http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
       
   152        if (options.closeKeepAlive)
       
   153            $.get(options.closeKeepAlive, fileUpload);
       
   154        else
       
   155            fileUpload();
       
   156        }
       
   157    else
       
   158        $.ajax(options);
       
   159 
       
   160     // fire 'notify' event
       
   161     this.trigger('form-submit-notify', [this, options]);
       
   162     return this;
       
   163 
       
   164 
       
   165     // private function for handling file uploads (hat tip to YAHOO!)
       
   166     function fileUpload() {
       
   167         var form = $form[0];
       
   168 
       
   169         if ($(':input[name=submit]', form).length) {
       
   170             alert('Error: Form elements must not be named "submit".');
       
   171             return;
       
   172         }
       
   173 
       
   174         var opts = $.extend({}, $.ajaxSettings, options);
       
   175 		var s = $.extend(true, {}, $.extend(true, {}, $.ajaxSettings), opts);
       
   176 
       
   177         var id = 'jqFormIO' + (new Date().getTime());
       
   178         var $io = $('<iframe id="' + id + '" name="' + id + '" src="about:blank" />');
       
   179         var io = $io[0];
       
   180 
       
   181         $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
       
   182 
       
   183         var xhr = { // mock object
       
   184             aborted: 0,
       
   185             responseText: null,
       
   186             responseXML: null,
       
   187             status: 0,
       
   188             statusText: 'n/a',
       
   189             getAllResponseHeaders: function() {},
       
   190             getResponseHeader: function() {},
       
   191             setRequestHeader: function() {},
       
   192             abort: function() {
       
   193                 this.aborted = 1;
       
   194                 $io.attr('src','about:blank'); // abort op in progress
       
   195             }
       
   196         };
       
   197 
       
   198         var g = opts.global;
       
   199         // trigger ajax global events so that activity/block indicators work like normal
       
   200         if (g && ! $.active++) $.event.trigger("ajaxStart");
       
   201         if (g) $.event.trigger("ajaxSend", [xhr, opts]);
       
   202 
       
   203 		if (s.beforeSend && s.beforeSend(xhr, s) === false) {
       
   204 			s.global && $.active--;
       
   205 			return;
       
   206         }
       
   207         if (xhr.aborted)
       
   208             return;
       
   209 
       
   210         var cbInvoked = 0;
       
   211         var timedOut = 0;
       
   212 
       
   213         // add submitting element to data if we know it
       
   214         var sub = form.clk;
       
   215         if (sub) {
       
   216             var n = sub.name;
       
   217             if (n && !sub.disabled) {
       
   218                 options.extraData = options.extraData || {};
       
   219                 options.extraData[n] = sub.value;
       
   220                 if (sub.type == "image") {
       
   221                     options.extraData[name+'.x'] = form.clk_x;
       
   222                     options.extraData[name+'.y'] = form.clk_y;
       
   223                 }
       
   224             }
       
   225         }
       
   226 
       
   227         // take a breath so that pending repaints get some cpu time before the upload starts
       
   228         setTimeout(function() {
       
   229             // make sure form attrs are set
       
   230             var t = $form.attr('target'), a = $form.attr('action');
       
   231 
       
   232 			// update form attrs in IE friendly way
       
   233 			form.setAttribute('target',id);
       
   234 			if (form.getAttribute('method') != 'POST')
       
   235 				form.setAttribute('method', 'POST');
       
   236 			if (form.getAttribute('action') != opts.url)
       
   237 				form.setAttribute('action', opts.url);
       
   238 
       
   239             // ie borks in some cases when setting encoding
       
   240             if (! options.skipEncodingOverride) {
       
   241                 $form.attr({
       
   242                     encoding: 'multipart/form-data',
       
   243                     enctype:  'multipart/form-data'
       
   244                 });
       
   245             }
       
   246 
       
   247             // support timout
       
   248             if (opts.timeout)
       
   249                 setTimeout(function() { timedOut = true; cb(); }, opts.timeout);
       
   250 
       
   251             // add "extra" data to form if provided in options
       
   252             var extraInputs = [];
       
   253             try {
       
   254                 if (options.extraData)
       
   255                     for (var n in options.extraData)
       
   256                         extraInputs.push(
       
   257                             $('<input type="hidden" name="'+n+'" value="'+options.extraData[n]+'" />')
       
   258                                 .appendTo(form)[0]);
       
   259 
       
   260                 // add iframe to doc and submit the form
       
   261                 $io.appendTo('body');
       
   262                 io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false);
       
   263                 form.submit();
       
   264             }
       
   265             finally {
       
   266                 // reset attrs and remove "extra" input elements
       
   267 				form.setAttribute('action',a);
       
   268                 t ? form.setAttribute('target', t) : $form.removeAttr('target');
       
   269                 $(extraInputs).remove();
       
   270             }
       
   271         }, 10);
       
   272 
       
   273         var nullCheckFlag = 0;
       
   274 
       
   275         function cb() {
       
   276             if (cbInvoked++) return;
       
   277 
       
   278             io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false);
       
   279 
       
   280             var ok = true;
       
   281             try {
       
   282                 if (timedOut) throw 'timeout';
       
   283                 // extract the server response from the iframe
       
   284                 var data, doc;
       
   285 
       
   286                 doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;
       
   287 
       
   288                 if ((doc.body == null || doc.body.innerHTML == '') && !nullCheckFlag) {
       
   289                     // in some browsers (cough, Opera 9.2.x) the iframe DOM is not always traversable when
       
   290                     // the onload callback fires, so we give them a 2nd chance
       
   291                     nullCheckFlag = 1;
       
   292                     cbInvoked--;
       
   293                     setTimeout(cb, 100);
       
   294                     return;
       
   295                 }
       
   296 
       
   297                 xhr.responseText = doc.body ? doc.body.innerHTML : null;
       
   298                 xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
       
   299                 xhr.getResponseHeader = function(header){
       
   300                     var headers = {'content-type': opts.dataType};
       
   301                     return headers[header];
       
   302                 };
       
   303 
       
   304                 if (opts.dataType == 'json' || opts.dataType == 'script') {
       
   305                     var ta = doc.getElementsByTagName('textarea')[0];
       
   306                     xhr.responseText = ta ? ta.value : xhr.responseText;
       
   307                 }
       
   308                 else if (opts.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) {
       
   309                     xhr.responseXML = toXml(xhr.responseText);
       
   310                 }
       
   311                 data = $.httpData(xhr, opts.dataType);
       
   312             }
       
   313             catch(e){
       
   314                 ok = false;
       
   315                 $.handleError(opts, xhr, 'error', e);
       
   316             }
       
   317 
       
   318             // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
       
   319             if (ok) {
       
   320                 opts.success(data, 'success');
       
   321                 if (g) $.event.trigger("ajaxSuccess", [xhr, opts]);
       
   322             }
       
   323             if (g) $.event.trigger("ajaxComplete", [xhr, opts]);
       
   324             if (g && ! --$.active) $.event.trigger("ajaxStop");
       
   325             if (opts.complete) opts.complete(xhr, ok ? 'success' : 'error');
       
   326 
       
   327             // clean up
       
   328             setTimeout(function() {
       
   329                 $io.remove();
       
   330                 xhr.responseXML = null;
       
   331             }, 100);
       
   332         };
       
   333 
       
   334         function toXml(s, doc) {
       
   335             if (window.ActiveXObject) {
       
   336                 doc = new ActiveXObject('Microsoft.XMLDOM');
       
   337                 doc.async = 'false';
       
   338                 doc.loadXML(s);
       
   339             }
       
   340             else
       
   341                 doc = (new DOMParser()).parseFromString(s, 'text/xml');
       
   342             return (doc && doc.documentElement && doc.documentElement.tagName != 'parsererror') ? doc : null;
       
   343         };
       
   344     };
       
   345 };
       
   346 
       
   347 /**
       
   348  * ajaxForm() provides a mechanism for fully automating form submission.
       
   349  *
       
   350  * The advantages of using this method instead of ajaxSubmit() are:
       
   351  *
       
   352  * 1: This method will include coordinates for <input type="image" /> elements (if the element
       
   353  *    is used to submit the form).
       
   354  * 2. This method will include the submit element's name/value data (for the element that was
       
   355  *    used to submit the form).
       
   356  * 3. This method binds the submit() method to the form for you.
       
   357  *
       
   358  * The options argument for ajaxForm works exactly as it does for ajaxSubmit.  ajaxForm merely
       
   359  * passes the options argument along after properly binding events for submit elements and
       
   360  * the form itself.
       
   361  */
       
   362 $.fn.ajaxForm = function(options) {
       
   363     return this.ajaxFormUnbind().bind('submit.form-plugin',function() {
       
   364         $(this).ajaxSubmit(options);
       
   365         return false;
       
   366     }).each(function() {
       
   367         // store options in hash
       
   368         $(":submit,input:image", this).bind('click.form-plugin',function(e) {
       
   369             var form = this.form;
       
   370             form.clk = this;
       
   371             if (this.type == 'image') {
       
   372                 if (e.offsetX != undefined) {
       
   373                     form.clk_x = e.offsetX;
       
   374                     form.clk_y = e.offsetY;
       
   375                 } else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin
       
   376                     var offset = $(this).offset();
       
   377                     form.clk_x = e.pageX - offset.left;
       
   378                     form.clk_y = e.pageY - offset.top;
       
   379                 } else {
       
   380                     form.clk_x = e.pageX - this.offsetLeft;
       
   381                     form.clk_y = e.pageY - this.offsetTop;
       
   382                 }
       
   383             }
       
   384             // clear form vars
       
   385             setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 10);
       
   386         });
       
   387     });
       
   388 };
       
   389 
       
   390 // ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
       
   391 $.fn.ajaxFormUnbind = function() {
       
   392     this.unbind('submit.form-plugin');
       
   393     return this.each(function() {
       
   394         $(":submit,input:image", this).unbind('click.form-plugin');
       
   395     });
       
   396 
       
   397 };
       
   398 
       
   399 /**
       
   400  * formToArray() gathers form element data into an array of objects that can
       
   401  * be passed to any of the following ajax functions: $.get, $.post, or load.
       
   402  * Each object in the array has both a 'name' and 'value' property.  An example of
       
   403  * an array for a simple login form might be:
       
   404  *
       
   405  * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
       
   406  *
       
   407  * It is this array that is passed to pre-submit callback functions provided to the
       
   408  * ajaxSubmit() and ajaxForm() methods.
       
   409  */
       
   410 $.fn.formToArray = function(semantic) {
       
   411     var a = [];
       
   412     if (this.length == 0) return a;
       
   413 
       
   414     var form = this[0];
       
   415     var els = semantic ? form.getElementsByTagName('*') : form.elements;
       
   416     if (!els) return a;
       
   417     for(var i=0, max=els.length; i < max; i++) {
       
   418         var el = els[i];
       
   419         var n = el.name;
       
   420         if (!n) continue;
       
   421 
       
   422         if (semantic && form.clk && el.type == "image") {
       
   423             // handle image inputs on the fly when semantic == true
       
   424             if(!el.disabled && form.clk == el) {
       
   425             	a.push({name: n, value: $(el).val()});
       
   426                 a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
       
   427             }
       
   428             continue;
       
   429         }
       
   430 
       
   431         var v = $.fieldValue(el, true);
       
   432         if (v && v.constructor == Array) {
       
   433             for(var j=0, jmax=v.length; j < jmax; j++)
       
   434                 a.push({name: n, value: v[j]});
       
   435         }
       
   436         else if (v !== null && typeof v != 'undefined')
       
   437             a.push({name: n, value: v});
       
   438     }
       
   439 
       
   440     if (!semantic && form.clk) {
       
   441         // input type=='image' are not found in elements array! handle it here
       
   442         var $input = $(form.clk), input = $input[0], n = input.name;
       
   443         if (n && !input.disabled && input.type == 'image') {
       
   444         	a.push({name: n, value: $input.val()});
       
   445             a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
       
   446         }
       
   447     }
       
   448     return a;
       
   449 };
       
   450 
       
   451 /**
       
   452  * Serializes form data into a 'submittable' string. This method will return a string
       
   453  * in the format: name1=value1&amp;name2=value2
       
   454  */
       
   455 $.fn.formSerialize = function(semantic) {
       
   456     //hand off to jQuery.param for proper encoding
       
   457     return $.param(this.formToArray(semantic));
       
   458 };
       
   459 
       
   460 /**
       
   461  * Serializes all field elements in the jQuery object into a query string.
       
   462  * This method will return a string in the format: name1=value1&amp;name2=value2
       
   463  */
       
   464 $.fn.fieldSerialize = function(successful) {
       
   465     var a = [];
       
   466     this.each(function() {
       
   467         var n = this.name;
       
   468         if (!n) return;
       
   469         var v = $.fieldValue(this, successful);
       
   470         if (v && v.constructor == Array) {
       
   471             for (var i=0,max=v.length; i < max; i++)
       
   472                 a.push({name: n, value: v[i]});
       
   473         }
       
   474         else if (v !== null && typeof v != 'undefined')
       
   475             a.push({name: this.name, value: v});
       
   476     });
       
   477     //hand off to jQuery.param for proper encoding
       
   478     return $.param(a);
       
   479 };
       
   480 
       
   481 /**
       
   482  * Returns the value(s) of the element in the matched set.  For example, consider the following form:
       
   483  *
       
   484  *  <form><fieldset>
       
   485  *      <input name="A" type="text" />
       
   486  *      <input name="A" type="text" />
       
   487  *      <input name="B" type="checkbox" value="B1" />
       
   488  *      <input name="B" type="checkbox" value="B2"/>
       
   489  *      <input name="C" type="radio" value="C1" />
       
   490  *      <input name="C" type="radio" value="C2" />
       
   491  *  </fieldset></form>
       
   492  *
       
   493  *  var v = $(':text').fieldValue();
       
   494  *  // if no values are entered into the text inputs
       
   495  *  v == ['','']
       
   496  *  // if values entered into the text inputs are 'foo' and 'bar'
       
   497  *  v == ['foo','bar']
       
   498  *
       
   499  *  var v = $(':checkbox').fieldValue();
       
   500  *  // if neither checkbox is checked
       
   501  *  v === undefined
       
   502  *  // if both checkboxes are checked
       
   503  *  v == ['B1', 'B2']
       
   504  *
       
   505  *  var v = $(':radio').fieldValue();
       
   506  *  // if neither radio is checked
       
   507  *  v === undefined
       
   508  *  // if first radio is checked
       
   509  *  v == ['C1']
       
   510  *
       
   511  * The successful argument controls whether or not the field element must be 'successful'
       
   512  * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
       
   513  * The default value of the successful argument is true.  If this value is false the value(s)
       
   514  * for each element is returned.
       
   515  *
       
   516  * Note: This method *always* returns an array.  If no valid value can be determined the
       
   517  *       array will be empty, otherwise it will contain one or more values.
       
   518  */
       
   519 $.fn.fieldValue = function(successful) {
       
   520     for (var val=[], i=0, max=this.length; i < max; i++) {
       
   521         var el = this[i];
       
   522         var v = $.fieldValue(el, successful);
       
   523         if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length))
       
   524             continue;
       
   525         v.constructor == Array ? $.merge(val, v) : val.push(v);
       
   526     }
       
   527     return val;
       
   528 };
       
   529 
       
   530 /**
       
   531  * Returns the value of the field element.
       
   532  */
       
   533 $.fieldValue = function(el, successful) {
       
   534     var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
       
   535     if (typeof successful == 'undefined') successful = true;
       
   536 
       
   537     if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
       
   538         (t == 'checkbox' || t == 'radio') && !el.checked ||
       
   539         (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
       
   540         tag == 'select' && el.selectedIndex == -1))
       
   541             return null;
       
   542 
       
   543     if (tag == 'select') {
       
   544         var index = el.selectedIndex;
       
   545         if (index < 0) return null;
       
   546         var a = [], ops = el.options;
       
   547         var one = (t == 'select-one');
       
   548         var max = (one ? index+1 : ops.length);
       
   549         for(var i=(one ? index : 0); i < max; i++) {
       
   550             var op = ops[i];
       
   551             if (op.selected) {
       
   552 				var v = op.value;
       
   553 				if (!v) // extra pain for IE...
       
   554                 	v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
       
   555                 if (one) return v;
       
   556                 a.push(v);
       
   557             }
       
   558         }
       
   559         return a;
       
   560     }
       
   561     return el.value;
       
   562 };
       
   563 
       
   564 /**
       
   565  * Clears the form data.  Takes the following actions on the form's input fields:
       
   566  *  - input text fields will have their 'value' property set to the empty string
       
   567  *  - select elements will have their 'selectedIndex' property set to -1
       
   568  *  - checkbox and radio inputs will have their 'checked' property set to false
       
   569  *  - inputs of type submit, button, reset, and hidden will *not* be effected
       
   570  *  - button elements will *not* be effected
       
   571  */
       
   572 $.fn.clearForm = function() {
       
   573     return this.each(function() {
       
   574         $('input,select,textarea', this).clearFields();
       
   575     });
       
   576 };
       
   577 
       
   578 /**
       
   579  * Clears the selected form elements.
       
   580  */
       
   581 $.fn.clearFields = $.fn.clearInputs = function() {
       
   582     return this.each(function() {
       
   583         var t = this.type, tag = this.tagName.toLowerCase();
       
   584         if (t == 'text' || t == 'password' || tag == 'textarea')
       
   585             this.value = '';
       
   586         else if (t == 'checkbox' || t == 'radio')
       
   587             this.checked = false;
       
   588         else if (tag == 'select')
       
   589             this.selectedIndex = -1;
       
   590     });
       
   591 };
       
   592 
       
   593 /**
       
   594  * Resets the form data.  Causes all form elements to be reset to their original value.
       
   595  */
       
   596 $.fn.resetForm = function() {
       
   597     return this.each(function() {
       
   598         // guard against an input with the name of 'reset'
       
   599         // note that IE reports the reset function as an 'object'
       
   600         if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType))
       
   601             this.reset();
       
   602     });
       
   603 };
       
   604 
       
   605 /**
       
   606  * Enables or disables any matching elements.
       
   607  */
       
   608 $.fn.enable = function(b) {
       
   609     if (b == undefined) b = true;
       
   610     return this.each(function() {
       
   611         this.disabled = !b;
       
   612     });
       
   613 };
       
   614 
       
   615 /**
       
   616  * Checks/unchecks any matching checkboxes or radio buttons and
       
   617  * selects/deselects and matching option elements.
       
   618  */
       
   619 $.fn.selected = function(select) {
       
   620     if (select == undefined) select = true;
       
   621     return this.each(function() {
       
   622         var t = this.type;
       
   623         if (t == 'checkbox' || t == 'radio')
       
   624             this.checked = select;
       
   625         else if (this.tagName.toLowerCase() == 'option') {
       
   626             var $sel = $(this).parent('select');
       
   627             if (select && $sel[0] && $sel[0].type == 'select-one') {
       
   628                 // deselect all other options
       
   629                 $sel.find('option').selected(false);
       
   630             }
       
   631             this.selected = select;
       
   632         }
       
   633     });
       
   634 };
       
   635 
       
   636 // helper fn for console logging
       
   637 // set $.fn.ajaxSubmit.debug to true to enable debug logging
       
   638 function log() {
       
   639     if ($.fn.ajaxSubmit.debug && window.console && window.console.log)
       
   640         window.console.log('[jquery.form] ' + Array.prototype.join.call(arguments,''));
       
   641 };
       
   642 
       
   643 })(jQuery);