Nested loop in JavaScript/jQuery not working - javascript

Im calling a for loop inside a for loop and its not working, here's the code :
function PopulateMonths() {
for (var m = 0; m < 12; m++) {
var $month = $('.d-month').clone();
$month.find('.d-header').text(m);
$month = PopulateDays($month);
$month.appendTo('#diary').show();
$month = null;
}
}
function PopulateDays($month) {
for (var d = 0; d < 30; d++) {
var $row = $('.d-row').clone();
$row.find('.d-day').text(d);
$row.appendTo($month).show();
$row = null;
}
return $month;
}
If I call PopulateDays manually 12 times it works fine, as soon as I try to loop 12 times using PopulateMonths() the page crashes, CPU usage goes through the roof so im assuming a lot of work is going on.
What am I missing?

I've had to tackle a very similar issue before. It's because when you are cloning the element, you are also cloning their classes etc. And then you insert the cloned item into the document.
The next time you try to look for an element with that class, it will find two instances - the original one, and the one you cloned in the previous step. Both will be cloned again, and now you have 4 elements on the page. So you're basically doubling the number of elements on each iteration, and doing it 12 times for days, and 30 times for months.
2^12 = 4096
2^30 = 1,073,741,824
These are just rough estimates of how large it can grow. I haven't done any further analysis to find the exact numbers, but basically the exponential growth is eating up the CPU and crashing your browser.

I believe because you are cloning the set of month elements in this line:
var $month = $('.d-month').clone();
and then in the populate days function appending 30 rows to the month in this line:
$row.appendTo($month).show();
Then appending the month to the diary in this line:
$month.appendTo('#diary').show();
Then next time this line executes there is another month that get cloned in this line:
var $month = $('.d-month').clone();
As well as cloning the rows you just appended over again in this line:
var $row = $('.d-row').clone();
Executing this in a loop increases the load substantially.

Related

Append 4 rows to an Excel document using XLSX and NodeJS

So far I've had the best luck with members from here for my questions. Right now I'm trying to correct a whole column with javascript. I have an array at the top full of values, if the array in the document doesn't agree, it gets corrected. However, my array is 4 longer than the document's rows. I need to append 4 more rows to get the document corrected.
I've tried messing with Range.e.r, no luck. I've tried countless experimenting and looking at other posted solutions, but none seem to work for my situation. If you have time, I appreciate your help. Thanks so much for your kindness and generosity.
I can work with 4 rows appended to the end. It'll be sloppy, but I can have variables carry the data to their proper locations. A better solution would be appending rows where it's wrong and inserting the names there. I also don't know how to do that.
Here's my code:
var worksheet5 = wb.Sheets[272];
var range = XLSX.utils.decode_range(worksheet5['!ref']);
range.s.r = 2; // <-- zero-indexed, so setting to 1 will skip row 0
worksheet5['!ref'] =XLSX.utils.encode_range(range);
header = getHeaderRow(worksheet5,range);
var data5 = XLSX.utils.sheet_to_json(worksheet5);
var n = 0;
var newData5 = data5.map(function(record){
if(record.Count === GAC[n]){
n++;
}
else{
if(record.Count != GAC[n]){
var Holdon = record.County;
record.Count = GAC[n];
if(Holdon === GAC[n]){
record.Count = Holdon;
n++;
}
n++;
}
}
return record;
}); ```

How to get previous Six months into an array

I am trying to use moment to get the previous six months, using the below code.
ngOnInit(){
let mom: moment.Moment;
var d = new Date();
let numberOfMonths=6;
let previousSIxMonths:string[]=[];
while (this.numberOfMonths > 0) {
this.previousSixMonths.push(mom.subtract(this.numberOfMonths, 'months').format('MMMM'));
this.numberOfMonths--;
console.log(this.numberOfMonths);
}
console.log(this.previousSixMonths);
}
However these cards should be displayed whenever I am on the page, and hence I have written the above code inside OnInit. Once I have all the past six months in the array, the idea is to loop over the array and display in cards. But the doesn't really work for me.
I want all my previous six months to be in an array so that I could loop across the array.
Considering this is October month, the expected output should be:
["Oct","Sept","Aug","July","June","May"]
Here is a quick way to do what you're needing:
var previousSixMonths = function(){
let n = 0;
let arRet = [];
for(; n < 6; n++)
arRet.push(moment().subtract(n, 'months').format('MMMM'));
return(arRet)
}();
console.log(previousSixMonths);

Include duplicates in for and if loop of array as count number is too small

I'm new to javascript so any help would be greatly appreciated.
What I'm trying to do is cycle through every element in the array and count the number of times the value of an element matches a given condition (even if the value is duplicated).
function loaddata(xml) {
var count = 0;
var i;
var xmlDoc = xml.responseXML;
var z = xmlDoc.getElementsByTagName("group");
if (value1 <= value2) {
for (i = 0; i < (0 + z.length); i++) {
if (z[i].getElementsByTagName("name")[0].childNodes[0].nodeValue == "John") {
count++;
}
}
}
$('#count1').html(count);
};
The count value outputted is too small. I believe the reason for this that the for loop isn't iterating through all elements in the array. When I remove the second if loop and output the count for just the for loop this value is also too small. I believe that the for loop isn't searching through the duplicate elements of the array (i.e. it is ignoring them so that they aren't then fed into the second if loop). Is it possible to specify that the for loop include duplicates?
Do a console.log(z[i].getElementsByTagName("name")) and open your browser's console, and see if that array has data in it.
Then console.log(z[i].getElementsByTagName("name")[0].childNodes) and make sure you have nodes in it.
Also, do you have many <group></group> tags? Because that's what you are selecting with var z = xmlDoc.getElementsByTagName("group");
I hope that helps,

Fetching the two values from second inner array

hey guys am a javascript developer..I have a multidimensional array..
My array structure looks like
var m = [[1,23,4],[4544,34,54],[6,7,68]]
What i want to display is 4544 and 34 from a single code(not by slicing or replacing)
My code is
var m = [[1,23,4],[4544,34,54],[6,7,68]]
for(i=0;i<2;i++) {
for(j=0;j<2;j++) {
console.log(m[i][j]);
}
}
This code outputs me 1,23,4544 and 34.
The output i needed is 4544 and 34..
Thanks..
There is no need for the first for loop you have, but the second can work, even though it is not necessary. With the loop you can do
var m = [[1,23,4],[4544,34,54],[6,7,68]];
for(i=0;i<2;i++) {
console.log(m[1][i]);
}
This will just print the first two elements from the second array inside the m array. You can also do this easily without a loop like this
var m = [[1,23,4],[4544,34,54],[6,7,68]];
console.log(m[1][0]);
console.log(m[1][1]);
They are both relatively short and they both produce the result
4544
34
What is wrong with the current code you have
var m = [[1,23,4],[4544,34,54],[6,7,68]]
for(i=0;i<2;i++) {
for(j=0;j<2;j++) {
console.log(m[i][j]);
}
}
With your first loop, you are actually iterating through the first two nested arrays that you have. Then, you are looping through the first two items in each of those. This is why you get the result of
1
23
4544
34
Since you only need items in the second nested array, there is no reason to have a second loop. Of course, you could do
var m = [[1,23,4],[4544,34,54],[6,7,68]]
for(i=1;i<2;i++) {
for(j=0;j<2;j++) {
console.log(m[i][j]);
}
}
but that would be pointless.
You could keep the first index fixed and only loop on the second index
var j, i=1
for (j=0;j<2;++j) {
console.log(m[i][j])
}
var m = [[1,23,4],[4544,34,54],[6,7,68]]
for(j=0;j<2;j++) {
console.log(m[1][j]);
}

How to wrap elements based on loop, plus amount of modulus?

I need to wrap every third instance of a <div> in some HTML dynamically, and, if there is a remainder, to wrap that less-than-three amount in a similar manner, so it would serve as the last instance of the "wrap".
Getting every third instance wrapped is pretty basic:
var divs = $(".someclass");
var limit = 10;
for(var i = 0; i < limit; i+=3) {
divs.slice(i, i+3).wrapAll("<div class='classwrap'></div>");
}
However, because there is a remainder of 1 in this example, and I am otherwise dynamically generating HTML elsewhere (too complex to demo here, but that aspect works fine), the result in this example creates four .classwrap divs wrapping sets of three .someclass divs, giving me twelve .someclass divs, but not ten, however.
What I'm trying to achieve in this example is indeed four sets of .classwrap divs, but with the first three of those wrapper sets each containing three .someclass divs, and then getting a fourth .classwrap div that contains only one .someclass div, for the grand total of ten .someclass divs, as indicated by the limit variable.
I have tried to sneak in a modulus operator somewhere in my loop but it always throws off the math and wrapping accordingly.
Here is the answer I think you are looking for.
You need to determine when the last grouping is being made.
then use the modo value to only wrap that many sections.
Updated fiddle
var divs = $(".someclass");
var limit = 10;//divs.length;
var grouper = 3
var modo = limit % grouper;
for(var i = 0; i < limit; i+=grouper) {
var offset = grouper;
if(modo + i === limit) {
offset = modo;
}
divs.slice(i, i+offset).wrapAll("<div class='classwrap' style='background-color:#def;'></div>");
}
OR
replace your initial selection with:
Fiddle for slice
var limit = 10;
var divs = $(".someclass").slice(0,limit);

Categories

Resources