Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you replace CSS/toggle a large amount of elements?

Tags:

jquery

EDIT: The question morphed into how to optimize a massive CSS change to 700 or more divs. I'm leaving the old question below to describe my original approach.

I have the following jQuery but it is not behaving as I expect. There are around 700 divs with class gr so hiding them takes a noticeable time. I am trying to do:

  1. When "Show/hide Pronunciation" is clicked, immediately change that text to "Working"
  2. Wait until all 'div.gr' are hidden/shown
  3. "Working" goes back to "Show/hide Pronunciation"

    $(document).ready(function () {
     $('#togglePron').click(function() {
       $('#togglePron').html("Working...");
       $('div.gr').toggle();
       $('#togglePron').html("Show/hide Pronunciation");
      });
    });
    ...
    ... 
    <div class="pronlink" id="togglePron">Show/hide P</div>
    
    <div class="gr">hai</div><div class="zi">A</div>
    <div class="gr">nao</div><div class="zi">B</div>  
    etc.
    

Thanks to Mike Lentini there's a jsfiddle for this question.

This is the full page I'm working on

The behavior I observe is that "Show/hide P" takes a noticeable time to change, then it changes briefly to "Working", and it goes back to "Show/hide". So is jQuery bunching together both the html() and .toggle(), instead of running html() first?

This seems to be browser specific because in Opera it does what I want. In IE 7 and Chrome 18, the behavior is as I described. Is there a way to make the behavior I want in Chrome happen? Or a better way to do what I am describing?

like image 763
Heitor Chang Avatar asked Dec 16 '22 02:12

Heitor Chang


2 Answers

EDIT :

Rather than using the toggle function to bind an event, why not just swap in a class on all the elements? This should be much faster:

$(document).ready(function(){
  $('#toggleP').click(function(){
    $('.gr').toggleClass('hidden');
  });
});

Then in your CSS, add this style:

.hidden { display: none !important; }

See this fiddle for an example.

ADDITIONAL EDIT :

As noted by kingjeffrey, class-swapping the parent element instead of the child elements is even more efficient:

JS:
$('#togglePron').click(function(){
  $('table').toggleClass('hide-pron');
});

CSS:
table.hide-pron .gr { display: none !important; }

For a (relatively) small number of children, the difference between these approaches is negligible – but as the child count increases, swapping the parent class can be noticeably faster.


ORIGINAL ANSWER :

Your element isn't going to update until the click() function returns. Here's one way (probably not the best way) to do it:

$(document).ready(function () {
  $('#toggleP').click(function() {
    $('#toggleP').html("Working...");
    setTimeout(
      "$('div.g').toggle(10,function(){$('#toggleP').html('Show/Hide P');});",
      10)
  });
});

The toggle() is now asynchronous due to being "scheduled" for 10ms in the future via setTimeout(). This means the click() function can return almost immediately, without waiting on the toggle() to complete.

As others have noted, the best option is probably to wrap all of your divs in a parent (if this is feasible for your actual code) and then toggle that parent div.

JSFiddle link: http://jsfiddle.net/5E45Q/

like image 60
Justin ᚅᚔᚈᚄᚒᚔ Avatar answered Jan 17 '23 22:01

Justin ᚅᚔᚈᚄᚒᚔ


If you can group all your div.g's in a parent element, you will be able to hide that single parent element without modifying the DOM 700 times. See http://jsfiddle.net/SVf5k/6/

But if that is unavoidable, you can add a short delay before you toggle the div.g's. This will give the js engine an opportunity to change the html on #toggleP. See http://jsfiddle.net/SVf5k/5/

like image 31
kingjeffrey Avatar answered Jan 17 '23 22:01

kingjeffrey