Reputation: 6529
I have a page that selects all the elements in a form and serializes them like this:
var filter = 'form :not([name^=ww],[id$=IDF] *,.tools *)';
var serialized = $(filter).serialize();
This works, unless the form gets around 600+ elements. Then the user gets s javascript error saying that the script is running slow and may make their browsers unresponsive. It then gives them the option to stop running the script.
I have tried running the filters separately, I have tried using .not on the selectors, then serializing them, but I run into one of two problems. Either it runs faster without the error, but also does not filter the elements, or it does filter the elements and gives me the slow script error.
Any ideas?
Upvotes: 2
Views: 400
Reputation: 112000
With 600+ elements this is going to be dead slow. You need to offer Sizzle (jQuery's selector engine) some opportunities for optimisation.
First, consider the fact that jQuery can use the natively-supported querySelectorAll
method (in modern browsers) if your selector complies with the CSS3 spec (or at least to the extent of what's currently supported in browsers).
With your case, that would mean passing only one simple selector to :not
instead of 3 (1 simple, 2 complex).
form :not([name^=ww])
That would be quite fast... although you're not being kind to browsers that don't support querySelectorAll
.
Look at your selector and think about how much Sizzle has to do with each element. First it needs to get ALL elements within the page (you're not pre-qualifying the :not
selector with a tag/class/id). Then, on each element it does the following:
(assume that it exits if a result of a check is false)
nodeName.toLowerCase()
of form
.name
attribute starting with ww
(basic indexOf
operation).id
attribute ending in IDF
. (expensive operation)class
attribute containing tools
.The last two operations are slow.
It may be best to manually construct a filter
function, like so:
var jq = $([1]);
$('form :input').filter(function(){
// Re-order conditions so that
// most likely to fail is at the top!
jq[0] = this; // faster than constructing a new jQ obj
return (
!jq.closest('[id$=IDF]')[0]
// this can be improved. Maybe pre-qualify
// attribute selector with a tag name
&& !jq.closest('.tools')[0]
&& this.name.indexOf('ww') !== 0
);
});
Note: that function is untested. Hopefully you get the idea...
Upvotes: 5
Reputation: 196306
use the :input
selector to only select applicable elements..
Upvotes: 0
Reputation: 30452
Could you maybe just serialize the whole form and do your filtering on the backend? Also, why-oh-why is the form growing to 600+ fields?
Upvotes: 1