Reputation: 3440
I want to improve my sites performance. The site is build with multiple height: 100%; width: 100%
sections, for example the following build (multiplied ten times):
<div id="fullpage">
<div class="section active" id="f01">
<span class="trigger">Button</span>
<div class="example">Content</div>
</div>
<div class="section" id="f02">
<span class="trigger">Button</span>
<div class="example">Content</div>
</div>
</div>
The div.example
is hidden by default, and will be shown using fadeToggle
on span.trigger
. What happens now is that on every of the ten divs the div.example
will be faded in.
var start_action = function(){
//a lot of random actions, for example this one:
$('.example').stop().fadeToggle();
}
$('span.trigger').click(start_action);
This needs a lot of performance on mobile devices.
I want to animate only the current div using .section.active
and afterwards toggle every other div without using animations (to save performance).
What is the fastest and cleanest way to do this? Do I have to create two functions start_action
and start_action_no_animation
and fire one at .section.active
and the other one at all the other .section
?
If I cache my selectors var example = $('.example', #fullpage)
can I combine this cached selector with $('.section.active).find(example)
?
Upvotes: 4
Views: 95
Reputation: 206669
jQuery does lot of work behind the scenes in animation for a vast majority of browsers, but
is not that good at animations. Libraries like Velocity.js and Greensock are, thanks to good browsers and fast machines. So roughly, browsers are good enough if you exploit the CSS(3) animations capabilities.
So instead of using jQuery animation methods, you could simply use CSS classes, CSS3 transition
, and jQuery but just to toggle an element's class:
.section {height: 80px;}
.trigger {cursor: pointer;}
.content { opacity: 0; transition: opacity 1s; }
.CSS3fadeIn{opacity: 1;}
// Cache:
var $fullpage = $("#fullpage");
var $sections = $fullpage.find(".section");
var $content = $sections.find(".content");
// Store (temporary):
// inside $visible we will store our visible el,
// so we don't need to run over all our elements
// and sniff for classes:
var $visible = null;
// (no need to cache .trigger if only used here)
$sections.on("click", ".trigger", function(){
// Remove from $visible (if not null):
if($visible) $visible.removeClass("CSS3fadeIn");
// Set a new visible element:
$visible = $(this).next(".content");
// Use that $visible one now:
$visible.addClass("CSS3fadeIn");
});
Note that above I've used CSS3 transition on opacity. You might want to do whatever you need. (Test also using different animation libraries, jQuery too ofc, CSS3, and on different devices).
Caching selectors means in performance only if you have plans to reuse the same selectors again (...and again) somewhere in your code:
$(".partyBrakers").remove(); // No need to cache those guys. We don't need them.
// Some fun going on here...
Caching selectors improves speed specially when you have functions running frequently (like in a loop) recalling the same elements.
// Mean You: // Computer:
setInterval( letsDance, 800 ); // "OK, let's do that dance"
function letsDance() {
$(".dancer").fadeToggle(); // "Wait, let me find dancers first. ugh.. OK guys, dance."
}
// Good You: // Computer:
var $dancers = $(".dancer"); // "Hi guys! Wanna dance?"
setInterval( letsDance, 800 ); // "Let's dance!"
function letsDance() {
$dancers.fadeToggle(); // "You know the move! YEY"
}
You got the point.
By adding dynamic to your elements by adding mutable selectors classes, there's two ways, the slower way and the faster way.
The slow way is when you assign a class to i.e. a clicked element, and than at some point you want to recall those elements:
var $danceFloor = $("#danceFloor");
var $dancers = $danceFloor.find(".dancer");
// some party with $dancers here...
// At some point in time some $dancer can become a .tiredDancer
$dancers.on("click", function(){
$(this).addClass("tiredDancer");
});
// and you meanly want to
$("#button_kickTiredDancers").on("click", function() {
$danceFloor.find(".tiredDancer").remove(); // Ohhh... OK, wait let me ask everyone..
});
above, even if we cached those guys, we still need to go find on the #danceFloor
any dancer that is eventually a .tiredDancer
.
The faster way would be to have a listOfTiredDancers
Array, and put selected elements in it:
var listOfTiredDancers = [];
// ...
$dancers.on("click", function(){
listOfTiredDancers.push( this );
});
you push
a tired Element Object (this
) into that Array list, and when needed you act only on that list instead:
$("#button_kickTiredDancers").on("click", function() {
$( listOfTiredDancers ).remove(); // YEY! I know already who those are!
});
preventing to "go find those ones in the Document Object Model" (specially if you have a huge number of elements).
Upvotes: 3
Reputation: 179
@MarianRick: What I understood after reading your question is that, you want to close all other '.example' blocks without animation, when a new '.trigger' block is clicked.
I modified the javascript a bit to create this snippet. It hides all other '.example' blocks when a '.trigger' is clicked.
About optimisation, this is a bit optimised as it is not toggling every '.example' block, and that reduces the number of DOM manipulations. It also doesn't use easing/fading animation while closing the other opened 'example' block.
I couldn't figure out the need of that '.section.active' selector though. If this is not what you were looking for then please supply more details, so that it's more clear.
Below is my snippet:
$('span.trigger').on('click', function() {
var trigger_el = $(this);
trigger_el.parent().siblings('.section').children('.example').hide();
trigger_el.siblings('.example').fadeToggle();
});
.trigger {
cursor: pointer;
}
.example {
display: none;
}
#fullpage {
height: 100%;
width: 100%;
position: relative;
}
.section {
height: 80px;
width: 100%;
}
#f01 {
background-color: red;
}
#f02 {
background-color: blue;
}
#f03 {
background-color: green;
}
#f04 {
background-color: yellow;
}
#f05 {
background-color: orange;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="fullpage">
<div class="section" id="f01">
<span class="trigger">Button</span>
<div class="example">Content</div>
</div>
<div class="section" id="f02">
<span class="trigger">Button</span>
<div class="example">Content</div>
</div>
<div class="section active" id="f03">
<span class="trigger">Button</span>
<div class="example">Content</div>
</div>
<div class="section" id="f04">
<span class="trigger">Button</span>
<div class="example">Content</div>
</div>
<div class="section" id="f05">
<span class="trigger">Button</span>
<div class="example">Content</div>
</div>
</div>
Upvotes: 1