Apart from below information, one additional information.
We have used the jQuery form plugin js in our project. This handles the form
and request submit. The code is as attached here.
________________________________________
From: Rahul Singh <rksing...@hotmail.com>
Sent: Tuesday, January 19, 2016 11:30 AM
To: Tomcat Users List
Subject: Re: File size >= 2GB not uploaded in application [Tomcat 7.0.54
Struts: 2.3.24 JAVA: openJDK 1.7.79]
Hi Christopher ,
>>So... what makes you sure that the browser actually made the request?
>>I'd like to see some kind of confirmation using a tool you didn't
>>write. Perhaps something like Firebug, LiveHttpHeaders, Fiddler, or
>>even Wireshark showing that the request was made, what headers it had,
>>etc.
OK,
We have used HTTP Analayzer for file upload via Internet Explorer-8. Following
are the scenario observed.
For lesser than 2gb file uploads : The request header shows the correct
content-length value of the file.The uploads works fine further also.
For more than 2gb file uploads: The file length is 2151533567 bytes(which is
roughly 2.15 Gb). The request is aborted in this case and the request header
shows the content length
as -214343325 bytes (which is rougly 214 Mb).The upload process does not
proceed further in this case.
both cases request headers are attached in screenshot.
________________________________________
From: Christopher Schultz <ch...@christopherschultz.net>
Sent: Monday, January 18, 2016 11:17 AM
To: Tomcat Users List
Subject: Re: File size >= 2GB not uploaded in application [Tomcat 7.0.54
Struts: 2.3.24 JAVA: openJDK 1.7.79]
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Rahul,
On 1/17/16 11:28 PM, Rahul Singh wrote:
> Code flow is attached, forgot to attach in trailing mail.
>
> ----------------------------------------------------------------------
- --
>
>
*From:* Rahul Singh <rksing...@hotmail.com>
> *Sent:* Monday, January 18, 2016 8:39 AM *To:* Tomcat Users List
> *Subject:* Re: File size >= 2GB not uploaded in application
> [Tomcat 7.0.54 Struts: 2.3.24 JAVA: openJDK 1.7.79]
>
> Hello Christopher, thanks for your prompt response !!
>
>> Why didn't you come to the Tomcat community first?
> Sorry for the delay, we wanted to make sure about the component
> causing the problem.
>
>
>>> I don't have a test-case in front of me, but I'm fairly
>>> confident that Tomcat allows file uploads of greater than 2GiB.
>>> I suspect the problem
> is another component.
>>> Are you using Servlet 3.0-based file upload, or are you
>>> allowing Struts to handle the file-upload for you? If you use
>>> Servlet-3.0 file-upload, then you'll have code that deals with
>>> Multipart classes and configuration in web.xml. If you are
>>> using Struts's file-upload, then you'll mostly just be calling
>>> getFile or getInputStream or however Struts 2 does things (I
>>> can't remember how it all works off the top of my head).
>
>
> In our case the filter class implements the javax.servlet.flter
> and imports javax.servlet.* The Filter class mentioned in the
> previous threads is the first one as declared in the web.xml
> (followed by other struts filters). All (url) requests are mapped
> to this filter. So this is where our file upload request goes. It
> is only in greater than 2 gb file upload request that the
> dofilter() fails to get any request. So we feel servlet 3.0 being
> used in our case the Filter is not being able to handle greater
> than 2 gb requests.
>
>
>>> The point is, if you are using Struts, then Tomcat will not
>>> touch the request and Struts is handling the whole thing. If
>>> Struts is the problem, you'll need to talk to the Struts
>>> team[1].
>
>>> If you are using Servlet-3.0 file-upload, then Struts is just a
>>> red herring and this is the right place to get your issue
>>> solved.
>
> As mentioned above Servlet 3.0 is being used. So request the
> tomcat community to please look into our issue.
>
>>> So far, you have posted some configuration for Struts and some
>>> JSP tablib-filled code, plus some Java code for a Filter. You
>>> didn't say where the Filter was in the filter chain (before or
>>> after Struts filter). You also mentioned that the form is
>>> actually posted using XMLHttpRequest and not through a standard
>>> form, but you didn't explain what component is doing that or
>>> how it actually works.
>
>>> There isn't enough information here to make any sense of the
>>> situation. Can you please address all of the questions I've
>>> posed above and maybe we can then help you?
>
>
> <<<Code model >>>> We need to model the following code to be told:
> jsp submit of the form How the .js submit it further in
> XmlHttpRequest How the Filter is declared How the web.xml is
> declared
>
>
>> Are you sure the request is even made to the server in these
>> cases?What if the Javascript upload component is failing before
>> it even starts?
>
> Yes the request is made in these cases. We have compared the
> scenario for greater than 2gb and lesser size file uploads and
> drawn the following inference from it.We have checked the request
> and content length for dofilter() method in our logs. The
> JavaScript is not the culprit in this case. The JavaScript sets the
> AJAX field to success after sending request and thereafter waits
> for response(which is not received in our case). Our application
> works fine for lesser than 2 gb fie uploads but fails for greater
> size files as the request fails to reach the dofilter() method
> after which the request can be forwarded to the requested method.
>
>
>
> Regards, Rahul
>
> ________________________________________ From: Christopher Schultz
> <ch...@christopherschultz.net> Sent: Saturday, January 16, 2016
> 9:33 AM To: Tomcat Users List Subject: Re: File size >= 2GB not
> uploaded in application [Tomcat 7.0.54 Struts: 2.3.24 JAVA: openJDK
> 1.7.79]
>
> Rahul,
>
> On 1/15/16 1:02 AM, Rahul Singh wrote:
>> Thanks for your guidelines, we have big hope from Apache Tomcat
>> Team to solve this problem as this is show stopper for our
>> application, we have also raise this question on various forum
>> like stack overflow and other, but no relevant reply till now.
>
> Why didn't you come to the Tomcat community first?
>
>> Hope you understand my situation,
>
>> please refer the below stackoverflow reference for more detail
>> about this issue.
>
>> http://stackoverflow.com/questions/34783438/dofilter-fails-to-get-any
- -
>
>>
<http://stackoverflow.com/questions/34783438/dofilter-fails-to-get-any->
> doFilter() fails to get any request for the file upload > 2gb
> <http://stackoverflow.com/questions/34783438/dofilter-fails-to-get-any
- ->
>
>
stackoverflow.com
> For my struts project the doFilter() fails to get any request from
> the file upload form in cases the size of the file is greater than
> 2gb. Below is the code fragment: Filter (class is FilterUp) is...
>
>
>
> request-for-the-file-upload-2gb?noredirect=1#comment57315528_34783438
>
>
>
>
> for more information:
>
>> -No error are printed in tomcat logs. - how to configure "call
>> HttpServletRequest.getHeader("Content-Length") as a String and
>> parse it yourself."
>
> I don't have a test-case in front of my, but I'm fairly confident
> that Tomcat allows file uploads of greater than 2GiB. I suspect the
> problem is another component.
>
> Are you using Servlet 3.0-based file upload, or are you allowing
> Struts to handle the file-upload for you? If you use Servlet-3.0
> file-upload, then you'll have code that deals with Multipart
> classes and configuration in web.xml. If you are using Struts's
> file-upload, then you'll mostly just be calling getFile or
> getInputStream or however Struts 2 does things (I can't remember
> how it all works off the top of my head).
>
> The point is, if you are using Struts, then Tomcat will not touch
> the request and Struts is handling the whole thing. If Struts is
> the problem, you'll need to talk to the Struts team[1].
>
> If you are using Servlet-3.0 file-upload, then Struts is just a
> red herring and this is the right place to get your issue solved.
>
> So far, you have posted some configuration for Struts and some JSP
> tablib-filled code, plus some Java code for a Filter. You didn't
> say where the Filter was in the filter chain (before or after
> Struts filter). You also mentioned that the form is actually
> posted using XMLHttpRequest and not through a standard form, but
> you didn't explain what component is doing that or how it actually
> works.
>
> There isn't enough information here to make any sense of the
> situation. Can you please address all of the questions I've posed
> above and maybe we can then help you?
>
> Are you sure the request is even made to the server in these
> cases? What if the Javascript upload component is failing before it
> even starts ?
>
> -chris
>
> [1] http://struts.apache.org/mail.html
>
>> ________________________________________ From: Christopher
>> Schultz <ch...@christopherschultz.net> Sent: Thursday, January
>> 14, 2016 8:43 PM To: Tomcat Users List Subject: Re: File size >=
>> 2GB not uploaded in application [Tomcat 7.0.54 Struts: 2.3.24
>> JAVA: openJDK 1.7.79]
>
>> André,
>
>> On 1/14/16 5:02 AM, André Warnier (tomcat) wrote:
>>> I have not followed this thread in details, but did you check
>>> this :
>>>
>>> http://tomcat.apache.org/tomcat-7.0-doc/config/http.html#Common_Attr
i
>
>>>
butes
>>>
>>>
>>>
> --> maxPostSize
>
>> +1
>
>>> The maximum size in bytes of the POST which will be handled by
>>> the container FORM URL parameter parsing. The limit can be
>>> disabled by setting this attribute to a value less than zero.
>>> If not specified, this attribute is set to 2097152 (2
>>> megabytes). Note that the FailedRequestFilter can be used to
>>> reject requests that exceed this limit.
>>>
>>> Note: the size above might relate to the *encoded* size of the
>>> file, as it is transmitted over the WWW (possibly encoded as
>>> Base64 e.g.), which may mean that an original 1 MB file
>>> translates to more than 1 MB bytes while being uploaded.
>>>
>>> Note also : maybe "Struts" is setting this to some other
>>> default value..
>>>
>>> Another question : did you check the Tomcat logs ?
>
>> IIRC, Tomcat doesn't log anything in these cases. You have to
>> use the FailedRequestFilter to detect and report the condition.
>> I wouldn't use that Filter in productio, but it would be good as
>> a simple test to see if this is the error that is occurring.
>
>> When Tomcat refuses to allow a file upload that it too large, it
>> simply does not parse the parameters, but the request continues
>> to process as usual (but the servlet doesn't end up getting any
>> of the parameters). I'm surprised that Struts isn't getting the
>> request in these cases.
>
>> -chris
So... what makes you sure that the browser actually made the request?
I'd like to see some kind of confirmation using a tool you didn't
write. Perhaps something like Firebug, LiveHttpHeaders, Fiddler, or
even Wireshark showing that the request was made, what headers it had,
etc.
- -chris
-----BEGIN PGP SIGNATURE-----
Comment: GPGTools - http://gpgtools.org
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/
iEYEARECAAYFAlacfGwACgkQ9CaO5/Lv0PDZ9wCgk9toUxcJpCosg5Nx5sKDF6lB
MQ4AnimyBJlk2kFmNj/Kiolfd8WQUYLR
=TuoH
-----END PGP SIGNATURE-----
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org
/*!
* jQuery Form Plugin
* version: 2.52 (07-DEC-2010)
* @requires jQuery v1.3.2 or later
*
* Examples and documentation at: http://malsup.com/jquery/form/
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*/
;(function($) {
/*
Usage Note:
-----------
Do not use both ajaxSubmit and ajaxForm on the same form. These
functions are intended to be exclusive. Use ajaxSubmit if you want
to bind your own submit handler to the form. For example,
$(document).ready(function() {
$('#myForm').bind('submit', function() {
$(this).ajaxSubmit({
target: '#output'
});
return false; // <-- important!
});
});
Use ajaxForm when you want the plugin to manage all the event binding
for you. For example,
$(document).ready(function() {
$('#myForm').ajaxForm({
target: '#output'
});
});
When using ajaxForm, the ajaxSubmit function will be invoked for you
at the appropriate time.
*/
/**
* ajaxSubmit() provides a mechanism for immediately submitting
* an HTML form using AJAX.
*/
$.fn.ajaxSubmit = function(options) {
// fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
if (!this.length) {
log('ajaxSubmit: skipping submit process - no element
selected');
return this;
}
if (typeof options == 'function')
options = { success: options };
var url = $.trim(this.attr('action'));
if (url) {
// clean url (don't include hash vaue)
url = (url.match(/^([^#]+)/)||[])[1];
}
url = url || window.location.href || '';
options = $.extend({
url: url,
type: this.attr('method') || 'GET',
iframeSrc: /^https/i.test(window.location.href || '') ?
'javascript:false' : 'about:blank'
}, options || {});
// hook for manipulating the form data before it is extracted;
// convenient for use with rich editors like tinyMCE or FCKEditor
var veto = {};
this.trigger('form-pre-serialize', [this, options, veto]);
if (veto.veto) {
log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
return this;
}
// provide opportunity to alter form data before it is serialized
if (options.beforeSerialize && options.beforeSerialize(this, options)
=== false) {
log('ajaxSubmit: submit aborted via beforeSerialize callback');
return this;
}
var a = this.formToArray(options.semantic);
if (options.data) {
options.extraData = options.data;
for (var n in options.data) {
if(options.data[n] instanceof Array) {
for (var k in options.data[n])
a.push( { name: n, value: options.data[n][k] } );
}
else
a.push( { name: n, value: options.data[n] } );
}
}
// give pre-submit callback an opportunity to abort the submit
if (options.beforeSubmit && options.beforeSubmit(a, this, options) ===
false) {
log('ajaxSubmit: submit aborted via beforeSubmit callback');
return this;
}
// fire vetoable 'validate' event
this.trigger('form-submit-validate', [a, this, options, veto]);
if (veto.veto) {
log('ajaxSubmit: submit vetoed via form-submit-validate
trigger');
return this;
}
var q = $.param(a);
if (options.type.toUpperCase() == 'GET') {
options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
options.data = null; // data is null for 'get'
}
else
options.data = q; // data is the query string for 'post'
var $form = this, callbacks = [];
if (options.resetForm) callbacks.push(function() { $form.resetForm();
});
if (options.clearForm) callbacks.push(function() { $form.clearForm();
});
// perform a load on the target only if dataType is not provided
if (!options.dataType && options.target) {
var oldSuccess = options.success || function(){};
callbacks.push(function(data) {
$(options.target).html(data).each(oldSuccess,
arguments);
});
}
else if (options.success)
callbacks.push(options.success);
options.success = function(data, status) {
for (var i=0, max=callbacks.length; i < max; i++)
callbacks[i].apply(options, [data, status, $form]);
};
// are there files to upload?
var files = $('input:file', this).fieldValue();
var found = false;
for (var j=0; j < files.length; j++)
if (files[j])
found = true;
var multipart = false;
// var mp = 'multipart/form-data';
// multipart = ($form.attr('enctype') == mp || $form.attr('encoding') ==
mp);
// options.iframe allows user to force iframe mode
// 06-NOV-09: now defaulting to iframe mode if file input is detected
if ((files.length && options.iframe !== false) || options.iframe || found ||
multipart) {
// hack to fix Safari hang (thanks to Tim Molendijk for this)
// see:
http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
if (options.closeKeepAlive)
$.get(options.closeKeepAlive, fileUpload);
else
fileUpload();
}
else
$.ajax(options);
// fire 'notify' event
this.trigger('form-submit-notify', [this, options]);
return this;
// private function for handling file uploads (hat tip to YAHOO!)
function fileUpload() {
var form = $form[0];
if ($(':input[name=submit]', form).length) {
alert('Error: Form elements must not be named
"submit".');
return;
}
var opts = $.extend({}, $.ajaxSettings, options);
var s = $.extend(true, {}, $.extend(true, {}, $.ajaxSettings),
opts);
var id = 'jqFormIO' + (new Date().getTime());
var $io = $('<iframe id="' + id + '" name="' + id + '" src="'+
opts.iframeSrc +'" />');
var io = $io[0];
$io.css({ position: 'absolute', top: '-1000px', left: '-1000px'
});
var xhr = { // mock object
aborted: 0,
responseText: null,
responseXML: null,
status: 0,
statusText: 'n/a',
getAllResponseHeaders: function() {},
getResponseHeader: function() {},
setRequestHeader: function() {},
abort: function() {
this.aborted = 1;
$io.attr('src', opts.iframeSrc); // abort op in
progress
}
};
var g = opts.global;
// trigger ajax global events so that activity/block indicators
work like normal
if (g && ! $.active++) $.event.trigger("ajaxStart");
if (g) $.event.trigger("ajaxSend", [xhr, opts]);
if (s.beforeSend && s.beforeSend(xhr, s) === false) {
s.global && $.active--;
return;
}
if (xhr.aborted)
return;
var cbInvoked = 0;
var timedOut = 0;
// add submitting element to data if we know it
var sub = form.clk;
if (sub) {
var n = sub.name;
if (n && !sub.disabled) {
options.extraData = options.extraData || {};
options.extraData[n] = sub.value;
if (sub.type == "image") {
options.extraData[name+'.x'] =
form.clk_x;
options.extraData[name+'.y'] =
form.clk_y;
}
}
}
// take a breath so that pending repaints get some cpu time
before the upload starts
setTimeout(function() {
// make sure form attrs are set
var t = $form.attr('target'), a = $form.attr('action');
// update form attrs in IE friendly way
form.setAttribute('target',id);
if (form.getAttribute('method') != 'POST')
form.setAttribute('method', 'POST');
if (form.getAttribute('action') != opts.url)
form.setAttribute('action', opts.url);
// ie borks in some cases when setting encoding
if (! options.skipEncodingOverride) {
$form.attr({
encoding: 'multipart/form-data',
enctype: 'multipart/form-data'
});
}
// support timout
if (opts.timeout)
setTimeout(function() { timedOut = true; cb();
}, opts.timeout);
// add "extra" data to form if provided in options
var extraInputs = [];
try {
if (options.extraData)
for (var n in options.extraData)
extraInputs.push(
$('<input type="hidden"
name="'+n+'" value="'+options.extraData[n]+'" />')
.appendTo(form)[0]);
// add iframe to doc and submit the form
$io.appendTo('body');
io.attachEvent ? io.attachEvent('onload', cb) :
io.addEventListener('load', cb, false);
form.submit();
}
finally {
// reset attrs and remove "extra" input elements
form.setAttribute('action',a);
t ? form.setAttribute('target', t) :
$form.removeAttr('target');
$(extraInputs).remove();
}
}, 10);
var domCheckCount = 50;
function cb() {
if (cbInvoked++) return;
io.detachEvent ? io.detachEvent('onload', cb) :
io.removeEventListener('load', cb, false);
var ok = true;
try {
if (timedOut) throw 'timeout';
// extract the server response from the iframe
var data, doc;
doc = io.contentWindow ?
io.contentWindow.document : io.contentDocument ? io.contentDocument :
io.document;
var isXml = opts.dataType == 'xml' ||
doc.XMLDocument || $.isXMLDoc(doc);
log('isXml='+isXml);
if (!isXml && (doc.body == null ||
doc.body.innerHTML == '')) {
if (--domCheckCount) {
// in some browsers (Opera) the
iframe DOM is not always traversable when
// the onload callback fires,
so we loop a bit to accommodate
cbInvoked = 0;
setTimeout(cb, 100);
return;
}
log('Could not access iframe DOM after
50 tries.');
return;
}
xhr.responseText = doc.body ?
doc.body.innerHTML : null;
xhr.responseXML = doc.XMLDocument ?
doc.XMLDocument : doc;
xhr.getResponseHeader = function(header){
var headers = {'content-type':
opts.dataType};
return headers[header];
};
if (opts.dataType == 'json' || opts.dataType ==
'script') {
// see if user embedded response in
textarea
var ta =
doc.getElementsByTagName('textarea')[0];
if (ta)
xhr.responseText = ta.value;
else {
// account for browsers
injecting pre around json response
var pre =
doc.getElementsByTagName('pre')[0];
if (pre)
xhr.responseText =
pre.innerHTML;
}
}
else if (opts.dataType == 'xml' &&
!xhr.responseXML && xhr.responseText != null) {
xhr.responseXML =
toXml(xhr.responseText);
}
data = $.httpData(xhr, opts.dataType);
}
catch(e){
ok = false;
$.handleError(opts, xhr, 'error', e);
}
// ordering of these callbacks/triggers is odd, but
that's how $.ajax does it
if (ok) {
opts.success(data, 'success');
if (g) $.event.trigger("ajaxSuccess", [xhr,
opts]);
}
if (g) $.event.trigger("ajaxComplete", [xhr, opts]);
if (g && ! --$.active) $.event.trigger("ajaxStop");
if (opts.complete) opts.complete(xhr, ok ? 'success' :
'error');
// clean up
setTimeout(function() {
$io.remove();
xhr.responseXML = null;
}, 100);
};
function toXml(s, doc) {
if (window.ActiveXObject) {
doc = new ActiveXObject('Microsoft.XMLDOM');
doc.async = 'false';
doc.loadXML(s);
}
else
doc = (new DOMParser()).parseFromString(s,
'text/xml');
return (doc && doc.documentElement &&
doc.documentElement.tagName != 'parsererror') ? doc : null;
};
};
};
/**
* ajaxForm() provides a mechanism for fully automating form submission.
*
* The advantages of using this method instead of ajaxSubmit() are:
*
* 1: This method will include coordinates for <input type="image" /> elements
(if the element
* is used to submit the form).
* 2. This method will include the submit element's name/value data (for the
element that was
* used to submit the form).
* 3. This method binds the submit() method to the form for you.
*
* The options argument for ajaxForm works exactly as it does for ajaxSubmit.
ajaxForm merely
* passes the options argument along after properly binding events for submit
elements and
* the form itself.
*/
$.fn.ajaxForm = function(options) {
return this.ajaxFormUnbind().bind('submit.form-plugin', function() {
$(this).ajaxSubmit(options);
return false;
}).bind('click.form-plugin', function(e) {
var target = e.target;
var $el = $(target);
if (!($el.is(":submit,input:image"))) {
// is this a child element of the submit el? (ex: a
span within a button)
var t = $el.closest(':submit');
if (t.length == 0)
return;
target = t[0];
}
var form = this;
form.clk = target;
if (target.type == 'image') {
if (e.offsetX != undefined) {
form.clk_x = e.offsetX;
form.clk_y = e.offsetY;
} else if (typeof $.fn.offset == 'function') { // try
to use dimensions plugin
var offset = $el.offset();
form.clk_x = e.pageX - offset.left;
form.clk_y = e.pageY - offset.top;
} else {
form.clk_x = e.pageX - target.offsetLeft;
form.clk_y = e.pageY - target.offsetTop;
}
}
// clear form vars
setTimeout(function() { form.clk = form.clk_x = form.clk_y =
null; }, 100);
});
};
// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
$.fn.ajaxFormUnbind = function() {
return this.unbind('submit.form-plugin click.form-plugin');
};
/**
* formToArray() gathers form element data into an array of objects that can
* be passed to any of the following ajax functions: $.get, $.post, or load.
* Each object in the array has both a 'name' and 'value' property. An example
of
* an array for a simple login form might be:
*
* [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret'
} ]
*
* It is this array that is passed to pre-submit callback functions provided to
the
* ajaxSubmit() and ajaxForm() methods.
*/
$.fn.formToArray = function(semantic) {
var a = [];
if (this.length == 0) return a;
var form = this[0];
var els = semantic ? form.getElementsByTagName('*') : form.elements;
if (!els) return a;
for(var i=0, max=els.length; i < max; i++) {
var el = els[i];
var n = el.name;
if (!n) continue;
if (semantic && form.clk && el.type == "image") {
// handle image inputs on the fly when semantic == true
if(!el.disabled && form.clk == el) {
a.push({name: n, value: $(el).val()});
a.push({name: n+'.x', value: form.clk_x},
{name: n+'.y', value: form.clk_y});
}
continue;
}
var v = $.fieldValue(el, true);
if (v && v.constructor == Array) {
for(var j=0, jmax=v.length; j < jmax; j++)
a.push({name: n, value: v[j]});
}
else if (v !== null && typeof v != 'undefined')
a.push({name: n, value: v});
}
if (!semantic && form.clk) {
// input type=='image' are not found in elements array! handle
it here
var $input = $(form.clk), input = $input[0], n = input.name;
if (n && !input.disabled && input.type == 'image') {
a.push({name: n, value: $input.val()});
a.push({name: n+'.x', value: form.clk_x}, {name:
n+'.y', value: form.clk_y});
}
}
return a;
};
/**
* Serializes form data into a 'submittable' string. This method will return a
string
* in the format: name1=value1&name2=value2
*/
$.fn.formSerialize = function(semantic) {
//hand off to jQuery.param for proper encoding
return $.param(this.formToArray(semantic));
};
/**
* Serializes all field elements in the jQuery object into a query string.
* This method will return a string in the format: name1=value1&name2=value2
*/
$.fn.fieldSerialize = function(successful) {
var a = [];
this.each(function() {
var n = this.name;
if (!n) return;
var v = $.fieldValue(this, successful);
if (v && v.constructor == Array) {
for (var i=0,max=v.length; i < max; i++)
a.push({name: n, value: v[i]});
}
else if (v !== null && typeof v != 'undefined')
a.push({name: this.name, value: v});
});
//hand off to jQuery.param for proper encoding
return $.param(a);
};
/**
* Returns the value(s) of the element in the matched set. For example,
consider the following form:
*
* <form><fieldset>
* <input name="A" type="text" />
* <input name="A" type="text" />
* <input name="B" type="checkbox" value="B1" />
* <input name="B" type="checkbox" value="B2"/>
* <input name="C" type="radio" value="C1" />
* <input name="C" type="radio" value="C2" />
* </fieldset></form>
*
* var v = $(':text').fieldValue();
* // if no values are entered into the text inputs
* v == ['','']
* // if values entered into the text inputs are 'foo' and 'bar'
* v == ['foo','bar']
*
* var v = $(':checkbox').fieldValue();
* // if neither checkbox is checked
* v === undefined
* // if both checkboxes are checked
* v == ['B1', 'B2']
*
* var v = $(':radio').fieldValue();
* // if neither radio is checked
* v === undefined
* // if first radio is checked
* v == ['C1']
*
* The successful argument controls whether or not the field element must be
'successful'
* (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
* The default value of the successful argument is true. If this value is
false the value(s)
* for each element is returned.
*
* Note: This method *always* returns an array. If no valid value can be
determined the
* array will be empty, otherwise it will contain one or more values.
*/
$.fn.fieldValue = function(successful) {
for (var val=[], i=0, max=this.length; i < max; i++) {
var el = this[i];
var v = $.fieldValue(el, successful);
if (v === null || typeof v == 'undefined' || (v.constructor ==
Array && !v.length))
continue;
v.constructor == Array ? $.merge(val, v) : val.push(v);
}
return val;
};
/**
* Returns the value of the field element.
*/
$.fieldValue = function(el, successful) {
var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
if (typeof successful == 'undefined') successful = true;
if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
(t == 'checkbox' || t == 'radio') && !el.checked ||
(t == 'submit' || t == 'image') && el.form && el.form.clk != el
||
tag == 'select' && el.selectedIndex == -1))
return null;
if (tag == 'select') {
var index = el.selectedIndex;
if (index < 0) return null;
var a = [], ops = el.options;
var one = (t == 'select-one');
var max = (one ? index+1 : ops.length);
for(var i=(one ? index : 0); i < max; i++) {
var op = ops[i];
if (op.selected) {
var v = op.value;
if (!v) // extra pain for IE...
v = (op.attributes &&
op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text :
op.value;
if (one) return v;
a.push(v);
}
}
return a;
}
return el.value;
};
/**
* Clears the form data. Takes the following actions on the form's input
fields:
* - input text fields will have their 'value' property set to the empty string
* - select elements will have their 'selectedIndex' property set to -1
* - checkbox and radio inputs will have their 'checked' property set to false
* - inputs of type submit, button, reset, and hidden will *not* be effected
* - button elements will *not* be effected
*/
$.fn.clearForm = function() {
return this.each(function() {
$('input,select,textarea', this).clearFields();
});
};
/**
* Clears the selected form elements.
*/
$.fn.clearFields = $.fn.clearInputs = function() {
return this.each(function() {
var t = this.type, tag = this.tagName.toLowerCase();
if (t == 'text' || t == 'password' || tag == 'textarea')
this.value = '';
else if (t == 'checkbox' || t == 'radio')
this.checked = false;
else if (tag == 'select')
this.selectedIndex = -1;
});
};
/**
* Resets the form data. Causes all form elements to be reset to their
original value.
*/
$.fn.resetForm = function() {
return this.each(function() {
// guard against an input with the name of 'reset'
// note that IE reports the reset function as an 'object'
if (typeof this.reset == 'function' || (typeof this.reset ==
'object' && !this.reset.nodeType))
this.reset();
});
};
/**
* Enables or disables any matching elements.
*/
$.fn.enable = function(b) {
if (b == undefined) b = true;
return this.each(function() {
this.disabled = !b;
});
};
/**
* Checks/unchecks any matching checkboxes or radio buttons and
* selects/deselects and matching option elements.
*/
$.fn.selected = function(select) {
if (select == undefined) select = true;
return this.each(function() {
var t = this.type;
if (t == 'checkbox' || t == 'radio')
this.checked = select;
else if (this.tagName.toLowerCase() == 'option') {
var $sel = $(this).parent('select');
if (select && $sel[0] && $sel[0].type == 'select-one') {
// deselect all other options
$sel.find('option').selected(false);
}
this.selected = select;
}
});
};
// helper fn for console logging
// set $.fn.ajaxSubmit.debug to true to enable debug logging
function log() {
if ($.fn.ajaxSubmit.debug && window.console && window.console.log)
window.console.log('[jquery.form] ' +
Array.prototype.join.call(arguments,''));
};
})(jQuery);
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org