JQuery Boostrap append row every 2 iterations but columns are ignored - javascript

I'm using JQuery 3 and Bootstrap 3. I'm trying to add dynamically row and col but I don't understand my error.
Every 2 iterations I want to add <div class="row"></div> in my dom and in this row I want to add 2 columns.
I'd like to get this HTML :
<div class="row">
<div class="col-xs-6">test</div>
<div class="col-xs-6">test</div>
</div>
<div class="row">
<div class="col-xs-6">test</div>
<div class="col-xs-6">test</div>
</div>
<div class="row">
<div class="col-xs-6">test</div>
</div>
But the current result what I get is :
<div class="row">
<div class="col-xs-6">test</div>
</div>
<div class="row">
<div class="col-xs-6">test</div>
</div>
I don't understand why some col are ignored. Here is my javascript code :
for (var i = 1; i < 5; i++) {
let row = $("<div>", {"class": "row"});
if (i % 2) {
$('.container').append(row);
}
let col = '<div class="col-xs-6">test</div>';
row.append(col);
}
And my jsfiddle : https://jsfiddle.net/gkn4vmx8/

Please try this
let row=null;
for (var i = 1; i < 5; i++) {
if (i % 2) {
row= $("<div>", {"class": "row"});
$('.container').append(row);
}
let col = '<div class="col-xs-6">test</div>';
row.append(col);
}

You can try this:
for (var i = 1; i < 5; i++) {
let row = $("<div>", {"class": "row"});
let col = '<div class="col-xs-6">test</div>';
if (i % 2) {
$('.container').append(row);
row.append(col);
}
row.append(col);
}

You have to reinitialize the row every 2 loops not every time so you can append on the same row to childs
let row;
for (var i = 1; i < 5; i++) {
if (i % 2) {
row= $("<div>", {"class": "row"});
$('.container').append(row);
}
let col = '<div class="col-xs-6">test</div>';
row.append(col);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container"></div>

Related

Building HTML using loops in JS

Afternoon all, I am trying to build some HTML elements in JS through a loop within which I have another loop. I have written the HTML so I know what I want, so I have now tried to translate it into the JS.
The HTML I want to build (this will be a 3x3 grid):
<div class="grid">
<div class="square-row d-flex flex-row">
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
</div>
<div class="square-row d-flex flex-row">
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
</div>
<div class="square-row d-flex flex-row">
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
</div>
</div>
the JS code I have written (sorry for the poor formating (my first Stackoverflow post and I cannot get it to behave):
function generateGrid(requirement) {
let grid = `
<div class="grid">
`;
if (requirement) {
for (let i = 0; i < gridSize; i++) {
let gridRow = `
<div class="square-row d-flex flex-row">
`;
for (let s = 0; s < gridSize; s++) {
let square = `
<div class="square squares" id="${i}"></div>
`;
gridRow += square;
}
gridRow +=`
</div>
`;
}
} else {
for (let i = 0; i < gridSize; i++) {
let gridRow = `
<div class="square-row d-flex flex-row">
`;
for (let x = 0; x < gridSize; x++) {
let square =`
<div class="square squares" id="square${i}" onclick="addColour(${i})"></div>
`;
gridRow += square;
}
gridRow +=`
</div>
`;
}
}
grid += `
</div>
`;
return grid;
}
I end up with this when I run it:
<div class="grid">
</div>
I have used the keyword 'debugger' in the middle of the loop and it is moving through it. gridSize is the value of 3, so the outer loop should run three times with the inner loop also running three times for each run of the outer.
Any help or advice would be appreciated.
Im not 100% sure exactly what you meant but it seems your issue is a simple mistake of forgetting to add the gridRow to the grid.
let gridSize = 3
function generateGrid(requirement) {
let grid = `<div class="grid">\n`;
if (requirement) {
for (let i = 0; i < gridSize; i++) {
let gridRow = `\t<div class="square-row d-flex flex-row">\n`;
for (let s = 0; s < gridSize; s++) {
let square = `\t\t<div class="square squares" id="square${i}" onclick="addColour(${i})"></div>\n`
if (requirement) {
square = `\t\t<div class="square squares" id="${i}"></div>\n`;
}
gridRow += square;
}
gridRow += `\t</div>\n`;
grid += gridRow; // this line
}
}
grid += `</div>\n`;
return grid;
}
console.log(generateGrid(true))

'querySelector' on 'Document' is not a valid selector error raised even though id's of divs seem fine [duplicate]

This question already has answers here:
Using querySelector with IDs that are numbers
(9 answers)
Closed 2 years ago.
I am trying to add styles via Javascript. For some reason unknown to me, I am getting an error that says my query selector is not a valid selector, even though my ids look correct. Can someone please help me to understand what is going wrong with my code?
var currentRow;
var rowCol;
for(let i = 0; i < 3; i++)
{
var x = i.toString();
currentRow = document.querySelector("#0");
for(let j = 0; j < 3; j++)
{
y = j.toString();
rowCol = currentRow.querySelector("#" + x + y);
if(i == 1)
{
rowCol.style.border = "5px 'solid black'";
rowCol.style.border = "5px 'solid black'";
}
if(j == 0 || j == 1)
{
rowCol.style.border = "5px 'solid black'";
}
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="./tictactoe.css">
</head>
<body>
<script src="tictactoe.js"></script>
<div class= "header">
</div>
<div class= "main">
<div id = '0'>
<div id = "00">x</div>
<div id = "01">x</div>
<div id = "02">x</div>
</div>
<div id = "1">
<div id = "10">x</div>
<div id = "11">x</div>
<div id = "12">x</div>
</div>
<div class = "2">
<div id = "20">x</div>
<div id = "21">x</div>
<div id = "22">x</div>
</div>
</div>
</body>
</html>
Your script is included in the head and executed before the body of the HTML document is parsed, so the elements don't exist yet. Move the script to just before the closing body tag.
Then, use .getElementById() to access your elements that have numbers as the first character in their id. .querySelector() won't work on those ids.
Also, your CSS is incorrect. Instead of:
"5px 'solid black'"
It should be:
"5px solid black"
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="./tictactoe.css">
</head>
<body>
<div class= "header"></div>
<div class= "main">
<div id = '0'>
<div id = "00">r1c1</div>
<div id = "01">r1c2</div>
<div id = "02">r1c3</div>
</div>
<div id = "1">
<div id = "10">r2c1</div>
<div id = "11">r2c2</div>
<div id = "12">r3c3</div>
</div>
<div class = "2">
<div id = "20">r3c1</div>
<div id = "21">r3c2</div>
<div id = "22">r3c3</div>
</div>
</div>
<!-- With the script here, all the HTML above will be parsed
and in memory so you can access the elements. -->
<script src="tictactoe.js"></script>
<script>
var currentRow;
var rowCol;
for(let i = 0; i < 3; i++){
var x = i.toString();
currentRow = document.getElementById("0");
for(let j = 0; j < 3; j++){
y = j.toString();
rowCol = document.getElementById(x + y);
if(i == 1){
rowCol.style.border = "5px solid black";
rowCol.style.border = "5px solid black";
}
if(j == 0 || j == 1){rowCol.style.border = "5px solid black";}
}
}
</script>
</body>
</html>

How to append html tag <br> after div?

I want to append a <br> after a <div>.
My code
function generatescene() {
for (i = 1; i < 101; i++) {
$('#fightarea').append('<div class=\'block block' + i + '\'><img src=block.png></div>');
if (i % 5) { } else {
if (i % 5 == 0) {
console.log('.block' + i + ' img');
$('.block' + i).after('<br>');
}
}
}
$('.block').wrapAll('<div class=\'scene\'></div>');
}
I have this result
<div>
<div class="scene">
<div class="block block1"><img src="block.png"></div>
<div class="block block2"><img src="block.png"></div>
<div class="block block3"><img src="block.png"></div>
<div class="block block4"><img src="block.png"></div>
<div class="block block5"><img src="block.png"></div>
<div class="block block6"><img src="block.png"></div>
<div class="block block7"><img src="block.png"></div>
<div class="block block8"><img src="block.png"></div>
<div class="block block9"><img src="block.png"></div>
<div class="block block10"><img src="block.png"></div>
<!-- ... -->
</div><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br>
</div>
The <br> append after the div.scene but I want the <br> append after the "div.block" + i.
The issue is this line:
$('.block').wrapAll('<div class=\'scene\'></div>');
which, as stated in the jquery wrapAll doc does:
The structure will be wrapped around all of the elements in the set of matched elements, as a single group.
so it takes all the .block elements that are siblings and creates a single group, thus moving your <br/>s to outside the .scene div.
function generatescene() {
for (i = 1; i < 100; i++) {
$('#fightarea').append('<div class=\'block block' + i + '\'><img src=block.png></div>');
if (i % 5) { } else {
if (i % 5 == 0) {
console.log('.block' + i + ' img');
$('.block' + i).after('<br>');
}
}
}
//$('.block').wrapAll('<div class=\'scene\'></div>');
}
generatescene();
$("#btn").click(function() {
$('.block').wrapAll('<div class=\'scene\'></div>');
});
.block { float:left; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="btn">wrap all </button>
<hr/>
<div id='fightarea'>
</div>
It's not clear exactly what you're trying to achieve, perhaps adding the .scene div first and then inserting the blocks inside that?
function generatescene() {
var scene = $('<div class=\'scene\'></div>').appendTo("#fightarea");
for (i = 1; i < 100; i++) {
scene.append('<div class=\'block block' + i + '\'><img src=block.png></div>');
if (i % 5) { } else {
if (i % 5 == 0) {
console.log('.block' + i + ' img');
$('.block' + i).after('<br>');
}
}
}
}
generatescene();
.block { float:left; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='fightarea'>
</div>
You could use
$('.block' + i).append('<br>');
instead of
$('.block' + i).after('<br>');
Explanation:
When you are using .after() you put the element after the element
Ex.
$('.a').after($('.c'));
will result in
<div class='a'>
<div class='b'>b</div>
</div>
<div class='c'>c</div>
but on the other hand when using .append()
$('.a').append($('.c'));
to
<div class='a'>
<div class='b'>b</div>
<div class='c'>c</div>
</div>
Hope that helped!
Try the following code:
function generatescene() {
for (i = 1; i < 101; i++) {
var sthtm ='<div class=\'block block' + i + '\'><img src=block.png></div>';
if(i==0) shtm ='<div class=\'scene\'>'+shtm;
if ((i % 5) == 0) {
sthtm +='<br>';
console.log('.block' + i + ' img');
}
if(i==100) shtm +='</div>';
$('#fightarea').append(sthtm);
}
}

Find duplicates by one of multiple classes

I have divs with multiple classes (brand and color) like:
<div id="pad">
<div class="bmw white"> </div>
<div class="porsche yellow"> </div>
<div class="porsche red"> </div>
<div class="bmw white"> </div>
<div class="bmw blue"> </div>
<div class="bmw white"> </div>
</div>
<div id="same"></div>
And when I need to know how many duplicate brands I have in #pad I use this code:
function sameCars() {
var elems = $("#pad div").length;
var brands = ['bmw', 'porsche'];
for (var i=0; i<brands.length; i++) {
var k = 0;
for (var j=0; j<elems; j++) {
var mainDiv = document.getElementById('pad'),
childDiv = mainDiv.getElementsByTagName('div')[j];
if(childDiv.className.split(' ')[0] == brands[i]) {
k = k+1;
}
}
addiv = document.getElementById("same");
addiv.innerHTML += brands[i] + ": " + k;
}
}
Now I want to make changes in my code:
1) to find duplicates for all classes (there could be more classes, first one is brand, the second one is color, etc) like bmw: 4, porsche: 2, white: 3, black: 3, sedan: 2, coupe: 3
2) not to use list of brands, colors, etc. I don't want to make a long list of all possible colors or car brands. Just get colors from classname
3) Make my code shorter and more elegant
You just have to dynamically gather all classes fists:
$(document).ready(function () {
var duplicates = {};
var $pad = $('#pad');
$('#pad > div').each(function () {
var classes = $(this)[0].classList;
for (var i = 0; i < classes.length; i++) {
if (typeof duplicates[classes[i]] === 'undefined') {
duplicates[classes[i]] = 1;
} else {
duplicates[classes[i]]++;
}
}
});
for (var j in duplicates) {
$pad.append('<div>'+j+':'+duplicates[j]+'</div>');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="pad">
<div class="bmw white"> </div>
<div class="porsche yellow"> </div>
<div class="porsche red"> </div>
<div class="bmw white"> </div>
<div class="bmw blue"> </div>
<div class="bmw white"> </div>
</div>
<div id="same"></div>
You can use jquery to get classes dynamically and apply logic to get unique counts like this.
sameCars();
function sameCars() {
var brands = [];
var colors = [];
$("#pad div").each(function(){
brands.push($(this).attr("class").split(' ')[0])
colors.push($(this).attr("class").split(' ')[1])
});
//console.log(brands)
//console.log(colors)
var cars_count = {};
$.each(brands, function( index, value ) {
cars_count[value] = cars_count[value] + 1 || 1;
});
console.log("Unique cars count :")
console.log(cars_count);
var count_color = {};
$.each(colors, function( index, value ) {
count_color[value] = count_color[value] + 1 || 1;
});
console.log("Unique Colors count :")
console.log(count_color);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="pad">
<div class="bmw white"> </div>
<div class="porsche yellow"> </div>
<div class="porsche red"> </div>
<div class="bmw white"> </div>
<div class="bmw blue"> </div>
<div class="bmw white"> </div>
</div>
<div id="same"></div>
Here is a nice way of getting what you want. Note I do not manipulate the DOM, I'll leave that up to you.
function classIsDup(className, setOfClasses)
{
return (setOfClasses.indexOf(className) > -1);
}
function getDuplicates()
{
var setOfClasses = [];
var listOfDuplicates = [];
$('#pad').children('div').each(function( index ) {
if(classIsDup($(this).attr('class'), setOfClasses))
{
listOfDuplicates.push($(this).attr('class'));
}
else
{
setOfClasses.push($(this).attr('class'));
}
});
// just in case dups exist within the list of dups
$.uniqueSort(listOfDuplicates);
}
getDuplicates();
Javascript example (no jquery required)
var parentWrapper = document.getElementById('pad');
var displayWrapper = document.getElementById('same');
var classesList = getUniqueClassList(parentWrapper);
displayCounts(classesList);
function displayCounts(list) {
for (var className in list) {
var number = list[className];
displayWrapper.innerHTML += className + ' ' + number + '<br>';
}
}
function getUniqueClassList(wrapper) {
var list = {};
for (var elem of wrapper.getElementsByTagName('div')) {
for (var cssClass of elem.classList) {
if (!list[cssClass]) {
list[cssClass] = 1;
} else {
list[cssClass]++;
}
}
}
return list;
}
Fiddle https://fiddle.jshell.net/r1rk1xL3/5/

infinite loop over divs showing 4 at a time

I would like to create something akin to a slide show, whenever the button #more-projectsis clicked 4 divs would show, when it's clicked again those divs get hidden and the next 4 divs show, this needs to loop infinitely and be applied to any number of divs.
In this context I have 6 divs with the class .thumbnail-cnt within the div '#container', when I click #more-projects I would like the first 4 of these divs to show, divs 1,2,3,4. When #more-projects is clicked again the next 4 divs in the cycle would be shown so 5,6,1,2. Clicked again, divs 1,2,3,4 are shown. How can I select the next index and make the function iterate over the elements infinitely?
<div id="container">
<div class="thumbnail-cnt" data-num="1">1
</div>
<div class="thumbnail-cnt" data-num="2">2
</div>
<div class="thumbnail-cnt" data-num="3">3
</div>
<div class="thumbnail-cnt" data-num="4">4
</div>
<div class="thumbnail-cnt" data-num="5">5
</div>
<div class="thumbnail-cnt" data-num="6">6
</div>
</div>
<button id="more-projects" > Next
</button>
My JS so far is
var startIndex = 0;
$('#more-projects').on("click", function() {
var endIndex = startIndex + 4;
var nextIndex = endIndex +1;
$('#container .thumbnail-cnt').slice(startIndex, endIndex).addClass('visible');
var startIndex = nextIndex;
}
CSS
.thumbnail-cnt {
display: none;
}
.visible {
display: block;
}
A solution can be based on:
save the initial value of max number of visible items as data value of your div
save the start index as another data value
So, the initial value is:
<div id="container" data-start-index="0" data-max-visible-length="4">
In the click handler compute the end index position. If it exceeds the max you need to start from the beginning. Save this new value as the new start index.
$('#more-projects').on("click", function() {
var startIndex = $('#container').data('startIndex');
var maxVisibleLength = $('#container').data('maxVisibleLength');
var endIndex = startIndex + maxVisibleLength;
var itemCounts = $('#container .thumbnail-cnt').length;
$('#container .thumbnail-cnt.visible').removeClass('visible');
if (endIndex > itemCounts) {
endIndex = endIndex - itemCounts;
$('#container .thumbnail-cnt').slice(startIndex).addClass('visible');
$('#container .thumbnail-cnt').slice(0, endIndex).addClass('visible');
} else {
$('#container .thumbnail-cnt').slice(startIndex, endIndex).addClass('visible');
}
$('#container').data('startIndex', endIndex);
});
.thumbnail-cnt {
display: none;
}
.visible {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container" data-start-index="0" data-max-visible-length="4">
<div class="thumbnail-cnt" data-num="1">1
</div>
<div class="thumbnail-cnt" data-num="2">2
</div>
<div class="thumbnail-cnt" data-num="3">3
</div>
<div class="thumbnail-cnt" data-num="4">4
</div>
<div class="thumbnail-cnt" data-num="5">5
</div>
<div class="thumbnail-cnt" data-num="6">6
</div>
</div>
<button id="more-projects" > Next
</button>
You can try this for your JS. This will ensure an infinite loop-
var startIndex = 0;
$('#more-projects').on("click", function() {
var count = 0;
var divs = $('#container .thumbnail-cnt');
var len = divs.length
var index;
while( count < 4 ){
index = (startIndex+count) % len;
divs[index].addClass('visible');
count++;
}
startIndex += count;
index++; //to ensure removal start from the next
while( count < len ){
index = index % len;
divs[index++].removeClass('visible');
count++;
}
}
% ensures the boundary and wrapping. Removing class visible for the other divs that need not be shown. Your current implementation must have been failing on this.

Categories

Resources