jquery loop not working properly - javascript

this is my loop. I want to print 7 li tag and 5 ul tags. This is my code.
for (var i = 0; i <= 4 ; i++) {
$("#calendar").append("<ul></ul>");
for (var j = 0; j <= 6; j++) {
$("#calendar ul").append("<li></li>").addClass("days");
$("#calendar ul li").addClass("day");
count = count + 1;
};
};
but the result is quite different from the expectation. There are 35, 28, 21, 14 and 7 li tags in each consecutive loop. I understand why it is so. The li tags are appended to all the ul's in the #calendar div.
Now, what is the proper way to appended li to the ul tags without the repeatation? Thanks.

It is because $("#calendar ul") will select all the ul elements in calendar including the previously added one's.
for (var i = 0; i <= 4; i++) {
var $ul = $("<ul></ul>").appendTo('#calendar').addClass('days');
for (var j = 0; j <= 6; j++) {
$("<li></li>", {
'class': 'day'
}).appendTo($ul);
};
};
.days {
border: 1px solid grey;
margin-bottom: 2px;
}
.day {
border: 1px solid blue;
margin-bottom: 2px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="calendar"></div>
You can also try
var $ul = $(new Array(6).join('<ul class="days"></ul>')).appendTo('#calendar');
$ul.append(new Array(8).join('<li class="day"></li>'));
.days {
border: 1px solid grey;
margin-bottom: 2px;
}
.day {
border: 1px solid blue;
margin-bottom: 2px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="calendar"></div>

Try to rewrite you code like below,
for(var i = 0; i <= 4 ; i++) {
var ul = $("<ul>").appendTo("#calendar").addClass("days");
for(var j = 0; j <= 6; j++) {
$("<li>").appendTo(ul).addClass("day");
count = count + 1;
};
};
You are using a generic selector $("#something ul"), that will select all the UL elements inside of that div. So you have to collect the newly generated ul in a variable and use it for further manipulations.
Recent edit: inspired from APJhony's code.

The part $("#calendar ul").append("<li></li>").addClass("days"); will append a li to all existing ul's in the calendar element.
Best to do is to save a reference to the ul you want to append the li's to, and do this in the first loop. Then, in the second loop, add the li's.
for (var i = 0; i <= 4 ; i++) {
var $ul = $('<ul/>', { class: 'days'} );
for (var j = 0; j <= 6; j++) {
var $li = $('<li/>', { class: 'day', text: 'li test' });
$ul.append($li);
};
$('#calendar').append($ul);
};
https://jsfiddle.net/s7fkw641/

for (var i = 0; i <= 4 ; i++) {
$("#calendar").append("<ul></ul>");
for (var j = 0; j <= 6; j++) {
$("#calendar ul:last-child").append("<li></li>").addClass("days");
$("#calendar ul:last-child li").addClass("day");
};
};
You can only add ul:last-child

Each time you run $("#calendar ul").append(...), you append data to every single element in the DOM that matches #calendar ul. I recommend building up your elements one by one assigning the results of $(some_html_string) to variables. This way ul will only mean one <ul> element at a time. For example:
var calendar = $("#calendar");
for (var i = 0; i <= 4; i++) {
var ul = $("<ul></ul>");
ul.addClass("days");
for (var j = 0; j <= 6; j++) {
var li = $("<li></li>");
li.addClass("day");
ul.append(li);
count = count + 1;
}
calendar.append(ul);
}

I think you want to create dynamically 5 ul's and inside which 7 li's
Updated Code
jQuery(document).ready(function($){
for (var i = 0; i <= 4 ; i++) {
$("#calendar").append("<ul></ul>");
}
for (var j = 0; j <= 6; j++) {
$("#calendar ul").append("<li></li>").addClass("days");
$("#calendar ul li").addClass("day");
}
});
Hope this helps!

The error is here its appending li to all the class items every and each time he goes in second loop(starting from first ul) to prevent that block it with id (i left the class name assuming it is important to handle css or something).
here is the simple solution
for (var i = 1; i <= 5 ; i++) {
$("#calendar").append("<ul class='days' id='"+i+"'></ul>")
for (var j = 1; j <= 7; j++) {
$("#calendar #"+i+".days ").append("<li class='day'></li>");
};
};

Related

selectionSort Javascript animation

I'm trying to build a visual representation of some famous sorting algorithms in javascript, but I can't understand why my code doesn't print each iteration even if the print function is in the for loop. I only get the final result.
This is the sorting function, in particular the selection sort algorithm:
function selectionSort(array) {
var i, j, min_idx;
let n = array.length;
for (i = 0; i < n-1; i++)
{
min_idx = i;
for (j = i + 1; j < n; j++)
{
if (array[j] < array[min_idx])
{
min_idx = j;
}
}
var temp = array[min_idx];
array[min_idx] = array[i];
array[i] = temp;
printArray(array);
}
}
And this is the printing function:
function printArray(array) {
document.getElementById('container').innerHTML ='';
for(let i = 0; i < array.length; i++)
{
document.getElementById('container').innerHTML += '<div class = "column '+i+'" id = "'+i+'" style = "height: '+array[i]+'px;"></div>';
}
}
Thank you a lot
It's what #Bravo states in the comments. The screen is updates at least 60 times per second, but it takes less time to do the sorting. So you need to add a timeout in a recursive loop so you can actually see the animation.
I replaced the first for loop with this recursive loop. I think the code it self-explanatory.
I did some optimization in your printArray(), where it takes time to constantly doing DOM changes. Instead, loop through to create a text string and then add it once to #container.innerHTML. There were also some faulty thinking in the value that you gave the visualized divs, where you only added the order (i), instead of adding the actual value (array[i]).
const iterationLegend = document.getElementById('iterations');
const containerDiv = document.getElementById('container');
const ANIMATION_SPEED = 1000;
const RESTART = 0;
var firstIteration;
function startSelectionSort(array) {
firstIteration = RESTART;
selectionSort(array);
}
function selectionSort(array) {
let min_idx = firstIteration,
n = array.length;
for (let j = firstIteration + 1; j < n; j++) {
if (array[j] < array[min_idx]) {
min_idx = j;
}
}
var temp = array[min_idx];
array[min_idx] = array[firstIteration];
array[firstIteration] = temp;
visualizeArray(array);
iterationLegend.textContent = 'iteration ' + firstIteration;
if (firstIteration < n - 1) {
firstIteration++;
setTimeout(selectionSort.bind(this, array), ANIMATION_SPEED);
} else {
iterationLegend.textContent = 'Done';
}
}
function visualizeArray(array) {
let elementStr = '';
let value = 0;
for (let i = 0; i < array.length; i++) {
value = array[i];
elementStr += `<div class="column${value}" data-value="${value}"></div>`;
}
containerDiv.innerHTML = elementStr;
}
startSelectionSort([2, 3, 5, 5, 1, 1, 1, 1, 4]);
fieldset {
display: inline;
}
#iterations {
font-size: 13px;
text-transform: uppercase;
}
#container {
display: inline-flex;
}
#container > div {
width: 10px;
height: 100px;
margin: 2px 1px 0px;
}
.column1 {
background-color: brown;
}
.column2 {
background-color: black;
}
.column3 {
background-color: teal;
}
.column4 {
background-color: red;
}
.column5 {
background-color: indigo;
}
<fieldset>
<legend id="iterations">Iterations</legend>
<div id="container"></div>
</fieldset>

How to append divs into another div inside a variable?

So, I am trying to create a HTML code generator just for fun. My actual problem is: How can I append divs from a loop inside another div that does not exist and is saved in a variable?
I hope I have been clear, thank you.
My little JavaScript until now:
colCont = $("<div class=\"stab-cont\"><div class=\"stab-row\"></div></div>");
function repeat(n) {
for (var i = 1; i < n + 1; i++) {
//Here I need to insert the n DIVs generated by this loop
}
}
repeat(3);
console.log(colCont);
JSFiddle: http://jsfiddle.net/qo3vdwhv/
Maybe I am under thinking it here, but this should work.
My code:
colCont = $("<div class=\"stab-cont\"></div>");
function repeat(n) {
for (var i = 1; i < n + 1; i++) {
$("<div class=\"stab-row\"></div>").appendTo(colCont); //build your div like you did with "colCont" and append the new div to colCont
}
}
repeat(3);
colCont.appendTo($("body"))
.stab-cont div {
border: 1px solid #c00;
margin: 10px;
float: left;
width: 200px;
height: 50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Here's something to consider; instead of making your repeat() function dependent on colCont, make it a jQuery function instead.
In this case I've created a function that will repeat the contents of a jQuery object N times (N >= 1).
colCont = $("<div class=\"stab-cont\"></div>");
jQuery.fn.times = function(n) {
var len = this.length;
for (var i = 1; i < n; ++i) {
for (var k = 0; k < len; ++k) {
this.push(this[0].cloneNode(true));
}
}
return this;
};
colCont
.append($('<div class="stab-row"></div>').times(3))
.appendTo('body');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Creating Grid on the fly with jquery

I'm new to frontend and I'm trying to practice doing this simple task: I have to create a grid on the fly that is n * n (n being inputed by the user).
I succesfully created a fix sized grid, but my problem is when trying to do this dynamically.
This is the code I wrote for a 3*3 grid: http://jsfiddle.net/y7c2h8yk/
For trying to create it dynamically I wrote the following function:
var setGridDimensions = function(n) {
// emptying current grid
$(".row").empty();
var $grid = $("#grid");
for (var i = 0; i < n; i++) {
// adding row
$grid.append('<div class="row">');
// adding each to element to row
**var $row = $(".row")[i];**
for (var j = 0; j < n; j++) {
$row.append('<div class="col"></div>');
}
}
};
Now, I understand there is a problem with line var $row = $(".row")[i]. What I need is inside the loop first create the row, then select the row created and then loop again and create each column. How can i do that ?
Any help would be really appreciated. Thanks.
You don't have to force jQuery to search for the .row element in the DOM tree n times. You have easy way to cache the element by setting it as variable.
Another thing, is that you should empty() the whole #grid element instead of .row. empty() method remove contents of the element, but not the element itself.
Alternatively, you could remove rows using $(".row").remove();
.empty() reference
.remove() reference
Code (I would however use the next one)
var setGridDimensions = function(n) {
var $grid = $("#grid").empty();
for (var i = 0; i < n; i++) {
// create .row and cache it setting as '$row' variable:
var $row = $('<div class="row"/>').appendTo($grid);
for (var j = 0; j < n; j++) {
$row.append('<div class="col"></div>');
}
}
};
DEMO
This would be faster than the one above, as it's single DOM modification:
var setGridDimensions = function(n) {
var html ='';
for (var i = 0; i < n; i++) {
html += '<div class="row">';
for (var j = 0; j < n; j++) {
html += '<div class="col"></div>';
}
html += '</div>';
}
// modify the DOM only once:
$("#grid").html(html);
};
DEMO
$(".row")[i] get the HTML element. So late, the $row.append('<div class="col"></div>'); will not work since .append() is a jQuery method.
If you want to select a specific index and keep it as a jQuery object, use .eq() :
var $row = $(".row").eq(i);
for (var j = 0; j < n; j++) {
$row.append('<div class="col"></div>');
}
Here's a way to do it without jQuery.
https://jsfiddle.net/lemoncurry/evxqybaL/1/
<div id="grid-holder"></div>
-
#grid-holder {
width: 100%;
}
.row {
clear: left;
background-color: red;
}
.cell {
width: 50px;
height: 50px;
border: 1px dashed blue;
float: left;
}
-
var gridly = function (n) {
var grid = document.getElementById("grid-holder");
for (var i = 0; i < n; i++) {
var row = document.createElement('div');
row.classList.add("row");
grid.appendChild(row);
for (var j = 0; j < n; j++) {
var cell = document.createElement('div');
cell.classList.add("cell");
row.appendChild(cell);
}
}
}
gridly(5);
use isotope http://isotope.metafizzy.co/ it uses the help of Javascript but it is very popular, so you will find plenty of docs
if you find it very complicated then there are many premium plugins that based their development on isotope already, for example the Media Boxes http://codecanyon.net/item/media-boxes-responsive-jquery-grid/5683020

Adding elements on loop jQuery

I am trying to generate a row of 16 boxes on load of webpage.
Here is my code:
var box = $("<div></div>").addClass("box");
$(document).ready(function(){
for(var i = 0; i < 16; i++) {
$("#container").append(box);
}
});
I also tried this within the for loop's code block:
if($("#container:contains(box)")) {
$(box).append(box);
}
I kind of understand why this does not work. That var box is only referencing an element and is not a copy of an element?
As you can likely tell, I'm new. I would really appreciate some pointers on how I can achieve this. Thanks.
Why not just use like this?
for(var i = 0; i < 16; i++) {
$("#container").append('<div class="box box-'+i+'" />');
}
You're appending the same div over and over. That will just move it (in this case, right back where it was). For a new div each time:
$(document).ready(function(){
var ctr = $('#container');
for(var i = 0; i < 16; i++) {
ctr.append("<div class='box'></div>");
}
});
$(document).ready(function() {
var ctr = $('#container');
for (var i = 0; i < 16; i++) {
ctr.append("<div class='box'></div>");
}
});
.box {
margin: 10px;
height: 25px;
width: 25px;
background-color: red;
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="container"></div>
I recommend against using append in a loop, bad performance. I suggest this:
var buffer = [];
for(var i = 0; i < 16; i++) {
buffer.push("<div class='box'></div>");
}
var html=buffer.join('');
$('#container').append(html);

a dynamic js table not working

this code for javascript not working.can any one help me with this.i've tried a lot but couldn't find out what's wrong here!!checked every line .i dont know if the code is wrong or there is any problem with my browser
<html>
<head>
<title>table dynamic</title>
<style>
tr{width:100%;height:100%;border:1px solid black;}
td{height:33%;width:33%;padding:10px;}
.tableShape{
width:300px;
height:300px;
font-size:30px;
text-align:centre;
color:red;
}
table{border:1px solid black;padding:10px;}
</style>
</head>
<body>
<script>
var i, j;
var arr = new Array(3);
for (i = 0; i < 3; i++) {
arr[i] = new Array(3);
}
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
arr[i][j] = 1;
}
}
function tabs() {
var k, t;
var m = document.createElement("table");
m.setAttribute('class', "tableShape");
for (k = 0; k < 3; k++) {
var p = m.insertRow(k);
for (t = 0; t < 3; t++) {
var s = p.insertCell(t);
s.innerHTML += arr[i][j];
}
}
}
window.onLoad = tabs();
</script>
</body>
</html>
You have to append your created element to the DOM:
function tabs() {
var k, t;
var m = document.createElement("table");
m.setAttribute('class', "tableShape");
for (k = 0; k < 3; k++) {
var p = m.insertRow(k);
for (t = 0; t < 3; t++) {
var s = p.insertCell(t);
s.innerHTML += arr[i][j];
}
}
document.body.appendChild(m);
}
When you create DOM elements in javascript, they are created in memory detached from DOM, to see them you have to append it to some node in DOM.
document.body.appendChild(m);
You are doing a nested operation using variables k and t so use it inside the loop
s.innerHTML+=arr[k][t];
Here is a fiddle http://jsfiddle.net/AmH22/1/

Categories

Resources