kartikmaji kartikmaji - 3 months ago 10
CSS Question

Complexity of $("SELECTOR").css()

I am trying to hide users that aren't in filtered users list.

For this, I am using this code

_.each(users, function (user) {
var display_type = filtered_users.hasOwnProperty(user.email)? "block" : "none";
$("label[for='" + user.email + "']").css({"display":display_type});
});


Where
users
is list of all user objects and
filtered_users
is list of email of filtered users.
I have around 1000 or more users to filter from. And seems like
$("label[for='" + user.email + "']").css({"display":display_type})
operation is taking too much time.

HTML:

<label class="checkbox" for="user1@gmail.com">
<input type="checkbox" name="user" value="user1@gmail.com"> Cordelia Lear (cordelia@zulip.com)
</label>
<label class="checkbox" for="user2@gmail.com">
<input type="checkbox" name="user" value="user2@gmail.com"> Cordelia Lear (cordelia@zulip.com)
</label>


Can someone explain what's the complexity of
$("label[for='" + user.email + "']").css({"display":display_type})
? Any possible way to improvise that?

Answer

This $("label[for='" + user.email + "']") is the part the slows you down. For every user, jquery's sizzle engine have to go over all of the labels in the page, and choose the exact one, so it's at least o(n) * o(n) for iterating the users - o(n2).

To solve that you can create a map of labels by emails once (the same thing you do for filtered_users), and then with o(1), find the element and change the display:

var usersMap = $('.users')
  .find('label')
  .toArray()
  .reduce(function(map, user) {
    var $user = $(user);
    var email = $user.attr('for');
    map[email] = $user;
    return map;
  }, {});

var users = [
         { email: 'user1@gmail.com' }, 
         { email: 'user2@gmail.com'}
        ];

var filtered_users = { 'user1@gmail.com': true };

users.forEach(function(user) {
  var display_type = filtered_users.hasOwnProperty(user.email) ? "block" : "none";
  usersMap[user.email].css({
    "display": display_type
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="users">
  <label class="checkbox" for="user1@gmail.com">
    <input type="checkbox" name="user" value="user1@gmail.com">Cordelia Lear (cordelia@zulip.com)
  </label>
  <label class="checkbox" for="user2@gmail.com">
    <input type="checkbox" name="user" value="user2@gmail.com">Cordelia Lear (cordelia@zulip.com)
  </label>
</div>