Jack M.
Jack M.

Reputation: 32080

Better performance for selecting options by value with jQuery?

I am trying to work out some performance problems with some JavaScript I've been working on for a few days. One of the pieces of the functions is below:

var removeAddress = function(pk) {
    var startTime = new Date();
    jQuery('.add_driver select.primary_address:has(option[value=' + pk + ']:selected)').each(function(c, o) {
        console.log("Shouldn't get here yet...");
        showInputs(o);
    });
    console.log('removeAddress1:  ', (new Date() - startTime) / 1000);
    jQuery('.add_driver select.primary_address option[value=' + pk + ']').remove();
    console.log('removeAddress2:  ', (new Date() - startTime) / 1000);
};

This code is quite peppy in Firefox:

removeAddress1:  0.004
removeAddress2: 0.023

But in IE8 it is another story:

LOG: removeAddress1: 0.203
LOG: removeAddress2: 0.547

The form in question is a 20-person in put form with first name, last name, and 5 address fields. I've also put in a drop down for selecting other addresses already existing in the form (.primary_address). This code is removing an address from the primary address select boxes.

I'm trying to nail down why this is taking so long, and the only thing which stands out is the option[value=????] section. This was the most practical way to find the elements in question, so I ran with it. Is there something about these two selectors which is causing IE to lose its lunch?

Upvotes: 0

Views: 319

Answers (3)

Frank Schwieterman
Frank Schwieterman

Reputation: 24480

Maybe precompute $('formId .add_driver select') outside of the removeAddress function, then reuse that so the removeAddress() doesn't have to enumerate so many elements.

Upvotes: 0

jasongetsdown
jasongetsdown

Reputation: 1305

You can likely speed this up a lot by breaking down your uber-selector string.

To start, begin with an id, or even better a cached element. Then get your select elements using .children(). Instead of using the :has selector use .has(). Methods are generally faster than complex selector syntax because jQ doesn't have to parts a string to figure out what you mean. Then, as Rafael said, you can skip the :selected and just look at the value of the matched select's.

formElem = document.getElementById('formId');
jQuery('.add_driver', formElem)
    .children('select.primary_address')
        .has('[value=' + pk + ']')
        .each(...);

Passing formElem as the second arg uses it as the context for the search so jQ doesn't have to start at the root.

To .remove() the elements either cache the jQuery object from above or chain it on after the .each() so you don't have to reselect everything again.

Upvotes: 0

Rafael
Rafael

Reputation: 569

The option element is always temperamental. Perhaps it's simpler to just get all the SELECT elements and then simply query their values. The selected OPTION always will give its value property to the SELECT as well. So:

jQuery('.add_driver select.primary_address').filter(function() {
  return $(this).value === pk;
});

jQuery('.add_driver select.primary_address[value='+pk+']');

Maybe one of those will be faster - not sure if the second will work.

Upvotes: 1

Related Questions