How to avoid freezing browser upon generating lots of html elements - javascript

I am using Selection.js to create a selectable grid on my web page. In order for this to work, it needs to have x amount of divs that create the selectable area.
In my case, I create all the divs with a for loop, to then return it as an array
renderBoxes() {
let boxArr = [];
this.boxSize = this.state.wrapperWidth / this.props.columns;
let length = this.props.columns * this.props.rows;
for (let i = 0; i < length; i++) {
boxArr.push(<Box key={i}/>)
}
document.styleSheets[1].cssRules[0].style.setProperty('width', this.boxSize + "px", null);
document.styleSheets[1].cssRules[0].style.setProperty('height', this.boxSize + "px", null);
this.boxesCreated = true;
return boxArr;
}
When I set the column count to 100 and row count to 100, it takes quite some time to load.
So my question is: how can i generate lots of divs with the least amount of load time?
Render function:
render() {
return (
<div className="col-9 position-relative" id="box-wrapper">
<div className="background-wrapper">
<img src="img/design.jpg" alt=""/>
</div>
<section className="box-wrap green m-0">
<div className="boxes red">
{this.state.wrapperWidth ? this.renderBoxes() : ""}
</div>
<div className="handle py-2">
Drag to increase/decrease vertical box count
</div>
</section>
</div>
)
}

I've found a solution, thanks to #skyboyer. Creating the elements with document.createElement speeds up the process of rendering 100x100 divs by an insane amount.

Related

Target by ID elements in array assigned by get() jQuery

Apologies if I get the terminology wrong here.
I have a 'grid' of images in html that I want to use jQuery to fade in each element randomly. One item in the grid is a Logo - I want it to fade in last. The grid size could be changed and the position of the 'logo' could also be different. Here is a reduced simplified output of the list.
<ul id="homepage-grid" class="projectsgrid row">
<div id="item1">
</div>
<div id="item2">
</div>
<div id="itemlogo" style="opacity: 0;">
<a href="#" class="block" style="padding-bottom: 100%;">
<div style="background-image:url('logoonly.png')" title="" class="logoblock"></div>
</a>
</div>
<div id="item4">
</div>
<div id="item5">
</div>
</ul>
I have the following script which will collect the elements into an array.
But i can't figure out how to match the element with the 'itemlogo' ID in the collection to split it out and push it to the end of the array so it is last to 'fade in'. I have tried "div#itemlogo", "#itemlogo", "itemlogo" but nothing seems to match, and perhaps not knowing the name of what I am doing I can't find any references.
var elems = $('#homepage-grid > div').get(); // collect elements
console.log(elems);
for (var i = elems.length - 1; i > 1; i--) { // Shuffle the order
var j = Math.floor(Math.random() * (i + 1));
var elem = elems[j];
elems[j] = elems[i];
elems[i] = elem;
}
elms = elems.push(elems.splice(elems.indexOf('div#itemlogo'), 1)[0]); // pull logo to last??
var i = 0;
var timer = setInterval(function() { // animate fade them sequentially
console.log(elems[i]).id();
$(elems[i]).fadeTo( "slow" , 1);
if (i === elems.length) {
clearInterval(timer);
}
i++;
}, 150);
You're on the right path, but the key here is that you need to find a particular item. Those items are DOM elements, not strings or selectors on their own.
elems.push(
elems.splice(
elems.findIndex(node=>node.id === 'itemlogo'),
1
)[0]
);
findIndex allows you to pass a function that should return true for the item you want - in this case, you want the item whose ID is itemlogo. The rest is just the same push-splice thing you have already.
I would also like to praise your correct use of array shuffling. You can simplify it a little bit with destructuring:
[elems[i], elems[j]] = [elems[j], elems[i]];

Sorting Child Elements Based on 'h2' Tag

I have an an example page containing several categories. Each category is wrapped in a .items class which contains an h2 title tag and several links. My goal is to sort each of those categories alphabetically based on the h2 tag.
I found several examples on how to do this, but they were in jquery. I want to do this only in javascript. I found some code that will sort divs but not by the divs's h2 tag.
HTML
<div id="mainContainer" class="column-container row">
<div class="item column">
<h2>Testimonials</h2>
Testimonial slider
</div>
<div class="item column">
<h2>Directories</h2>
Staff Directory
</div>
<div class="item column">
<h2>FAQ</h2>
</div>
<div class="item column">
<h2>Forms</h2>
Simple contact form - WIP
Online payment form using Network Merchants - WIP
Form with attachment
</div>
</div>
JavaScript
sortCategory('#mainContainer');
function sortCategory(s) {
Array.prototype.slice.call(document.body.querySelectorAll(s)).sort(function sort (ea, eb) {
var a = ea.textContent.trim();
var b = eb.textContent.trim();
if (a < b) return -1;
if (a > b) return 1;
return 0;
}).forEach(function(div) {
div.parentElement.appendChild(div);
});
}
How can I modify the javascipt code to sort each .item by the h2 tag?
Solution
With the help of others I figured it out and wanted to share the code. I also formatted the code to be easily read.
//****************************************
// Sort Categories Alphabetically
//****************************************
function sortCategory(elementContainer)
{
var allElements = document.body.querySelectorAll(elementContainer);
Array.prototype.slice.call(allElements).sort(byAlphabet).forEach(function(div)
{
div.parentElement.appendChild(div);
});
}
function byAlphabet(first, second)
{
var order = 0;
var first = first.querySelector('h2').textContent.trim();
var second = second.querySelector('h2').textContent.trim();
first > second ? order = 1 : order = -1;
return order;
}
//Call sortCategory function and pass in the container you want sorted
sortCategory('#mainContainer>.item');
Change ea.textContent.trim() to ea.querySelector('h2').textContent.trim()
and
change eb.textContent.trim() to eb.querySelector('h2').textContent.trim()
This will basically say check each div's first H2 element, rather than the div.
Hope I was helpful!

Apply random class to multiple groups of elements with no repeat

I have multiple groups of divs that I need to apply a random class to with no repeats in each of the groups. Once I've done this, I then need to 'reset' the Array back to the original values, and move onto the next group of divs where I apply a random class to each div again.
The idea is to get to something that looks like this:
<div class="mini-thumbnail-container">
<div class="mini-thumbnail-individual-image left">
<div class="mini-thumbnail-individual-image centre">
<div class="mini-thumbnail-individual-image right">
</div>
<div class="mini-thumbnail-container">
<div class="mini-thumbnail-individual-image centre">
<div class="mini-thumbnail-individual-image right">
<div class="mini-thumbnail-individual-image left">
</div>
<div class="mini-thumbnail-container">
<div class="mini-thumbnail-individual-image right">
<div class="mini-thumbnail-individual-image left">
<div class="mini-thumbnail-individual-image centre">
</div>
etc.
I've shamelessly taken code taken from another stackoverflow question to do with this question, but I can't figure out how to get it to work over all my elements, instead of the first three.
Here's the jQuery:
function shuffle(obj) {
var l = obj.length,
i = 0,
rnd,
tmp;
while (i < l) {
rnd = Math.floor(Math.random() * i);
tmp = obj[i];
obj[i] = obj[rnd];
obj[rnd] = tmp;
i += 1;
}
}
var classes = ["centre", "left", "right"];
shuffle(classes);
jQuery(".mini-thumbnail-individual-image").each(function() {
jQuery(this).addClass(classes.pop());
});
And here's a basic outline of my div structure – I have multiples of these which I want to iterate over and apply the random class to each <div class="mini-thumbnail-individual-image">
HTML:
<div class="col-1-6">
<div class="mini-thumbnail-container">
<div class="mini-thumbnail-individual-image">
<img class="mini-thumbnail-image" src="" />
</div>
<div class="mini-thumbnail-individual-image">
<img class="mini-thumbnail-image" src="" />
</div>
<div class="mini-thumbnail-individual-image">
<img class="mini-thumbnail-image" src="" />
</div>
</div>
</div>
I think I need to create a loop that looks is triggered after each iteration over the array, and once it spots the array is empty, I need to push the class names back in, and then loop over the next group of divs, until each group of divs has a random class applied, but maybe there is a simpler way that I haven't thought of yet.
Thanks in advance!
You're on the right track.
Without speaking of methods to optimize the code, here's (one) way to get quickly to where you need to be:
function shuffle(obj) {
var l = obj.length,
i = 0,
rnd,
tmp;
while (i < l) {
rnd = Math.floor(Math.random() * i);
tmp = obj[i];
obj[i] = obj[rnd];
obj[rnd] = tmp;
i += 1;
}
}
// declare OUTSIDE the function for correct scope
var classes;
// Simple function to set up the classes variable and shuffle.
function setUpClasses() {
classes = ["centre", "left", "right"];
shuffle(classes);
}
jQuery(".mini-thumbnail-individual-image").each(function() {
// Check if classes is set / empty. If so, set up the classes again.
if (!classes || classes.length < 1) {
setUpClasses();
}
jQuery(this).addClass(classes.pop());
});
If you want to look at cleaner / briefer ways to shuffle the array, this article has some other techniques. Here's one of them:
yourArray.sort(function() { return 0.5 - Math.random() });
So you could literally remove your shuffle function, and just do this:
function setUpClasses() {
classes = ["centre", "left", "right"];
classes.sort(function() { return 0.5 - Math.random() });
}
Or, if you wanted maximum brevity:
function setUpClasses() {
classes = ["centre", "left", "right"].sort(function() { return 0.5 - Math.random() });
}
Here is a working Fiddle

Show only 10 items using jquery infinite scroll within the div

Hi I found lots of examples related to this question, but so far the examples that I see they don't match my needs.On my div at the moment I load all the list content retrieved from my function,My goal is I want to be able to only show 6 items and keep on appending the other 6 until the list is exhausted using the infinite scroll in jQuery.
This is how my list look within the div.
<div class="listOfAnything">
<div class="all">apple</div>
<div class="all">Banana</div>
<div class="all">Guava</div>
<div class="all">Pear</div>
<div class="all">mango</div>
<div class="all">Grapes</div>
<div class="all">Avocado</div>
<div class="all">Orange</div>
<div class="all">Lemon</div>
<div class="all">Nartjie</div>
<div class="all">Granadilla</div>
<div class="all">pawpaw</div>
<div class="all">Ginger</div>
<div class="all">Watermelon</div>
<div class="all">potato</div>
<div class="all">Sweet Potato</div>
<div class="all">Peach</div>
</div>
I've tried to follow the tutorials on http://scrollmagic.io/examples/advanced/infinite_scrolling.html but I had no luck because i got stuck here
function addBoxes (amount) {
for (i=1; i<=amount; i++) {
var randomColor = '#'+('00000'+ (Math.random()*0xFFFFFF<<0).toString(16)).slice(-6);
$("<div></div>")
.addClass("box1")
.css("background-color", randomColor)
.appendTo(".dynamicContent #content");
}
// "loading" done -> revert to normal state
scene.update(); // make sure the scene gets the new start position
$("#loader").removeClass("active");
}
// add some boxes to start with.
addBoxes(18);
Because I already have the content on my div.
Added the scroll function
function addBoxes (amount) {
for (i=1; i<=amount; i++) {
var randomColor = '#'+('00000'+ (Math.random()*0xFFFFFF<<0).toString(16)).slice(-6);
$("<div></div>")
.addClass("box1")
.css("background-color", randomColor)
.appendTo(".dynamicContent #content");
}
// "loading" done -> revert to normal state
scene.update(); // make sure the scene gets the new start position
$("#loader").removeClass("active");
}
// add some boxes to start with.
addBoxes(6);
// do things on mousescroll
$(window).bind('mousewheel DOMMouseScroll', function(event)
{
if (event.originalEvent.wheelDelta < 0 || event.originalEvent.detail > 0) {
setTimeout(function(){
addBoxes(6);
}, 1000);
}
});

Forcing two row-fluid to be same size

I have been struggling with a problem and can't figure out how to solve it:
I have made a FIDDLE :
HTML:
<div class="row-fluid">
<div class="span6">
<div class="alert alert-info">
this has text <br>
this has text <br>
</div>
</div>
<div class="span6">
<div class="alert alert-success">
<div class="media">
This needs to be same size as the other box.<br />
This needs to be same size as the other box.<br />
This needs to be same size as the other box.<br />
This needs to be same size as the other box.<br />
This needs to be same size as the other box.<br />
This needs to be same size as the other box.
</div>
</div>
</div>
</div>
</div>
</body>
I want both boxes to be the same size regardless if theres text in the boxes or not. I have tried adding some javascript, but I havent figured out how to do it.
So here is an example using jQuery, it looks for all your rows then targets the columns that must match sizes inside each row. My having the row and col passed in as parameters it should mean if you change your structure you can just update the call with what ever class names you are using.
var updateHeights = function (rowTarget, colTarget) {
$(rowTarget).each(function () {
var maxHeight = 0;
$(colTarget, this).each(function () {
if (maxHeight <$(this).height()) {
maxHeight = $(this).height();
}
});
$(colTarget, this).each(function () {
$(this).height(maxHeight);
});
});
};
updateHeights('.row-fluid','.alert');
fiddle: http://jsfiddle.net/leighking2/rk4t6c45/
The one thing i don;t like about it is the fact it loops twice, once to find the largest height then again to set it.
Simply add min-height you want to have
FIDDLE
.alert{
min-height:150px;
}
Hope i have understood you right
You need to add the "alert" class together with the span-6 class, because the span-6 class is the one giving the visual information after that you can set min-height for alert
Here's a pure JS solution for equalising the heights of matched elements. It also works on resize.
function setHeights(){
//get all the elements that need to be equal height:
var elements = document.getElementsByClassName('alert');
//call the equaliseHeights prototype method
elements.equaliseHeights();
}
/* Extend the HTMLCollection prototype */
HTMLCollection.prototype.equaliseHeights = function() {
var maxHeight=0;
//loop through the collection to find the height of the tallest element:
for (var i = 0; i < this.length; i++) {
this[i].style.minHeight = 0; //reset min-height
var thisHeight = this[i].offsetHeight; //measure height
maxHeight = (thisHeight>maxHeight)?thisHeight:maxHeight; //store the greatest height
}
//now set the min-height for all:
for (var i = 0; i < this.length; i++) {
this[i].style.minHeight = maxHeight+"px"; //set min-height
}
return this;
};
/* on load */
(function waitForReady(){
if (document.readyState === "complete") {
setHeights();//on load, call method
window.onresize = setHeights;//on resize, call method
} else {
setTimeout(waitForReady,10);
}
})();
http://jsfiddle.net/r5ye65vz/5/

Categories