A lot of divs on one page - javascript

Is there any way to "unrender" elements which aren't visible on screen?
I have a page with a lot divs, some of them have event listeners attached to them. Above 45k divs event handlers are running very slow, so I thought maybe unrendering unnecessary element would help?
FYI - when elements have display: none everything works fine.

Instead of adding 45k of event listeners, you should add one event listener on a parent-div.
With jQuery you can do something like this:
<div id="container">
<div class="clickable">a</div>
<div class="clickable">a</div>
<div class="clickable">a</div>
<div class="clickable">a</div>
<div class="clickable">a</div>
<div class="clickable">a</div>
<div class="clickable">a</div>
<div class="clickable">a</div>
</div>
.
$("#container").on('click', '.clickable', function(e) {
console.log($(e.target));
})
this should improve your javascript code.
If you still need to hide elements who a not visible you will need to calculate their positions, and that might decrease your performence

Use divs when you need to divide (that's what divs are supposed to be used for) sections of your page from one another. Header/footer from content for instance, or individual posts on a blog.
However, you shouldn't use them when semantically where another element would make sense. While this is not a duplicate, I think the info found here will be of use to you. Too Many DIVS?

Related

How do I make display:none to display:block elements not take up its original space in DOM?

I have this sample snippet: https://jsfiddle.net/uyg8tauo/ wherein several divs are initially defined as display: none; and upon clicking the buttons, I would like them to appear by changing the display property of the element to block.
However, I would like the elements to cascade properly based on the buttons I actually clicked. For instance, if I click the the first button 4 times, the elements with ids "school_" + n show up one after another and if I click on the second button the div with id "noSchool_" + n appears after the first ones not on where it is exactly written on my DOM.
Please take note that it has to be supported by legacy browsers (IE8<). Apparently, my divs have to pre-defined and cannot be dynamically added. I really hope I made myself clear with my problem and any feasible solution is greatly appreciated!
Thanks.
If you re-append a DOM element into it's same container, it will be put last in the DOM tree. Consider the following:
<div id="container">
<div id="button-1">1</div>
<div id="button-2">2</div>
<div id="button-3">3</div>
</div>
Now, if you would do this:
document.getElementById('container').appendChild(document.getElementById('button-1'));
This would effectively switch the DOM into the following structure:
<div id="container">
<div id="button-2">2</div>
<div id="button-3">3</div>
<div id="button-1">1</div>
</div>
As explained in the first paragraph here:
https://developer.mozilla.org/en/docs/Web/API/Node/appendChild

Select div after parent with jQuery

<div class="col-1-3">
<div class="click"></div>
</div>
<div class="col-1-3">
</div>
<div class="col-1-2">
</div>
Using jQuery, I need to select the col-1-2 div when a user clicks on the "click" div. I need to replace col-1-2 with col-1-3. So far, I have tried a variety of methods using parent();, next();, find(); etc. etc. Right now, I looking into:
$(".click").parent().next(".col-1-2").removeClass("col-1-2").addClass("col-1-3");
That obviously doesn't work but I am not sure where to go from here.
next will only look at the immediate next element. You need to use nextAll to test all the following siblings.
Using this instead of a selector will make sure that you are dealing with the div that was actually clicked rather than another one with the same class name.
$(this).parent().nextAll(".col-1-2").removeClass("col-1-2").addClass("col-1-3");
You may also wish to filter the results to apply the change to only the first match.
One more slightly shorter version:
$(this).parent().siblings(".col-1-2").toggleClass("col-1-2 col-1-3");
$.fn.toggleClass can be used instead or combination of removeClass + addClass: col-1-2 will be removed and col-1-3 will be added.

Dynamically select specific child div to detach

I have a button that every time you click it I want to be able to detach the div behind the one with a class "selected" inside the div wrapper.
<div class="wrapper" style="height:122px; width:765px;">
<div class="smallImage"></div>
<div class="smallImage"></div>
<div class="smallImage selected"></div>
<div class="smallImage"></div>
<div class="smallImage"></div>
</div>
$('.wrapper').children('.smallImage')[0].detach();
I have tried other variations of children() and :nth-child(1) with no prevail.
Basically as long as I can choose the position of the div I want to detach I will be a happy coder, As i will need to detach divs further than 2+ places behind it if that make sense.
Thanks
Seems like:
$(".wrapper").children('.smallImage.selected').next().detach();
...is what you want. This will call .detach on the div immediately following the .smallImage.selected div.
If you had a specific number you wanted to select, you could use:
.children('.smallImage:not(.selected)').eq(number);

How to animate two jquery objects together

I want to animate two jquery OBJECTS at the same time (using the jquery slideUp method)
I have two divs that have already been 'cached' into a variable like so:
var div1 = $('body').find('#someId');
var div2 = $('body').find('#someOtherId');
I have cached these because they take a considerable amount of processing to find due to the page layout (using framesets and frames...don't ask).
Anyway,
If I do the slide animation like below, they are not in perfect sync (they are lined up so you can easily see it visually)
div1.slideUp(500);
div2.slideUp(500);
So I tried wrapping it like so,
$(div1, div2).slideUp(500);
but only div1 slides.
Is there anyway to get this to work while still maintaining the cached objects?
Edit: Giving the div's a class name does not trigger the animation. I think it may have something to do with the fact that I'm using framesets. The jquery code is in the top frame and so it will not look into other frames for the class. That is why I cached the objects
You can do what you want like this:
div1.add(div2).slideUp(500);
I made a quick jsfiddle you can check out here.
The shortest thing to do is to use a shared class and then select all the items with that class:
$('.willAnimate').slideUp(500);
<div id="element1" class="willAnimate"></div>
...
<div id="other-element" class="willAnimate"></div>
Otherwise, you could use the .add() method http://api.jquery.com/add/
In this case your code will become something like this:
div1.add(div2).slideUp(500);
why you dont add a class to the to div and add do the selector like this
<div id="someId" class="example"> </div>
<div id="simeOtherId" class="example"> </div>
the selector that add the animation it's like this
$(".example").slideUp(500);
and that avoid to find some variables and make more selectors
Give the two divs the same class, i.e. slide and then change your code to $('.slide').slideUp(500).
$('.yourclass').slideUp(500);
<div id="someId" class="yourclass"></div>
<div id="simeOtherId" class="yourclass"></div>

Unresponsive OnMouseOver event in a dynamically-generated nested DIV

I am using JavaScript to generate a map for a game, and each tile is a separate div. In order to be able to position the map on my site, I am throwing them all in another div.
So for example:
<div id="mapBox">
<div id="tile" ... ></div>
<div id="tile" ... ></div>
</div>
The #tile divs are generated from data in an XML file, so they're dynamically generated. On each #tile, I have an onmouseevent that triggers a function (alert(1) for now just to get it to work) but it never seems to be triggered.
If I put an onmouseevent on #mapBox it triggers it, but I can't get it to work for the #tile divs.
Any help with this would be appreciated.
Not sure how you're selecting the #tile divs, but it is not valid to have multiple elements with the same ID.
Selection using duplicate IDs will often give you only the first match (or some other unpredictable behavior).
When a duplicate identifier is needed, you should use a class instead of an ID.
<div id="mapBox">
<div class="tile" ... ></div>
<div class="tile" ... ></div>
</div>
First problem, as mentioned, is that you use the same id for many elements, so the event only fires on the first one.
Secondly you should use the .delegate() method on the #mapBox after giving a class on the tiles like this
$('#mapBox').delegate('.tile', 'mouseover', function(e){
//do whatever here
})
example at http://jsfiddle.net/nXa27/1/
Update
Sorry, didn't see you were not talking about jquery..
Here is an example with pure javascript http://www.jsfiddle.net/AvJf7/
Still you will need to add a tile class to your tiles for easy and valid selecting.

Categories