Loop through items and target first 3 and last items seperately - javascript

Is there a better way to write this for loop?
I am basically looping through a collection of divs. (The number of divs can increase and decrease dynamically, so it's never a set number).
If the length of the collection is greater than 4, I want to set flex styling the first 3 items. And I want to set a width on the remaining items, from the 4th item on wards.
If the length of the collection is less than 4, I want to set flex styling on all items.
This works at the most basic level but wondered if there was a smarter way to write this?
let divCount = document.getElementsByClassName("luggage-tile-wrapper active");
for (let i = 0; i < divCount.length; i++) {
if (divCount.length > 3) {
for (let i = 0; i < 3; i++) {
divCount[i].style.flex = "1 0 22.2%";
};
for (let i = 3; i < divCount.length; i++) {
divCount[i].style.width = "145px";
};
} else {
for (let i = 0; i < divCount.length; i++) {
divCount[i].style.flex = "1 0 22.2%";
};
};
}
Thanks,

Do two loops, one for the first 3, the other for the rest. If there are less than 3 divs, the second loop won't do anything.
let first3 = Math.min(3, divCount.length); // don't go past the end if less than 3
for (let i = 0; i < first3; i++) {
divCount[i].style.flex = "1 0 22.2%";
}
for (let i = 3; i < divCount.length; i++) {
divCount[i].style.width = "145px";
}

So you always want to do
divCount[i].style.flex = "1 0 22.2%";
for the first 3 items
And for every other item you want
divCount[i].style.width = "145px";
So this is it
for (let i = 0; i < divCount.length; i++) {
if (i < 3) {
divCount[i].style.flex = "1 0 22.2%";
} else {
divCount[i].style.width = "145px";
}
}

I know you've already accepted an answer--and I realize I don't have all the information--but it seems like you could achieve this entirely in css, without any javascript at all.
.container {
display: flex;
flex-wrap: wrap;
}
.container > * {
flex: 1 0 22.2%;
background: skyblue;
}
.container > :nth-child(1n + 4) {
background: pink;
width: 145px;
}
<div class="container">
<div class="luggage-tile-wrapper active">item</div>
<div class="luggage-tile-wrapper active">item</div>
<div class="luggage-tile-wrapper active">item</div>
<div class="luggage-tile-wrapper active">item</div>
<div class="luggage-tile-wrapper active">item</div>
<div class="luggage-tile-wrapper active">item</div>
<div class="luggage-tile-wrapper active">item</div>
</div>

Related

Bubble Sort algorithm visualizer app made in Svelte is giving me some weird output

I'm trying to do a Bubble Sort algorithm visualizer. However the output is strange,
This is the image of the output. You can try the app here: https://svelte.dev/repl/hello-world?version=3.38.3 by pasting the following code: (I know that a lot of code isn't mine but I made this for practicing Svelte)
<script>
import { flip } from 'svelte/animate'
const ARRAY_LENGTH = 54
var arr = Array.from(Array(ARRAY_LENGTH)).map(x=>Math.random() * 200 + 1)
function BubbleSort() {
for(var i = 0; i < arr.length; i++){
for(var j = 0; j < ( arr.length - i -1 ); j++){
if(arr[j] > arr[j+1]){
var temp = arr[j]
arr[j] = arr[j + 1]
arr[j+1] = temp
}
}
}
}
</script>
<div>
{#each arr as item (item)}
<div style="
background-color: green;
width: 10px;
height: {item}px;
margin: 0 1px;
display: inline-block;
"
animate:flip={{duration:500}}
/>
{/each}
</div>
<button on:click={BubbleSort}>
Next
</button>

Connect Four Diagonal Check

I am trying to make a function to check diagonal win in connect four. Already done with vertical and horizontal checks. I am adding a class to my class .slot with "player1" or "player2" depending on the var currentPlayer. I have an array of all possible combinations to victory and I am iterating over the combinations and setting a counter. But the counter doesn´t goes up. I run out of ideas whats happening there. Not sure if it has to do with jQuery and the way I am iterating, but otherwise I got an error.
Someone sees the error in the function?
var combinations = [
[$(".hole").eq(2), $(".hole").eq(9), $(".hole").eq(16), $(".hole").eq(23)],
[$(".hole").eq(1), $(".hole").eq(8), $(".hole").eq(15), $(".hole").eq(22)],
[$(".hole").eq(8), $(".hole").eq(15), $(".hole").eq(22), $(".hole").eq(29)],
[$(".hole").eq(0), $(".hole").eq(7), $(".hole").eq(14), $(".hole").eq(21)],
[$(".hole").eq(7), $(".hole").eq(14), $(".hole").eq(21), $(".hole").eq(28)],
[$(".hole").eq(14), $(".hole").eq(21), $(".hole").eq(28), $(".hole").eq(35)],
[$(".hole").eq(6), $(".hole").eq(13), $(".hole").eq(20), $(".hole").eq(27)],
[$(".hole").eq(13), $(".hole").eq(20), $(".hole").eq(27), $(".hole").eq(34)],
[$(".hole").eq(20), $(".hole").eq(27), $(".hole").eq(34), $(".hole").eq(41)],
[$(".hole").eq(12), $(".hole").eq(19), $(".hole").eq(26), $(".hole").eq(33)],
[$(".hole").eq(19), $(".hole").eq(26), $(".hole").eq(33), $(".hole").eq(40)],
[$(".hole").eq(18), $(".hole").eq(25), $(".hole").eq(32), $(".hole").eq(39)]
];
function checkDiagonal() {
for (var i = 0; i < combinations.length; i ++) {
for (var j = 0; j < combinations[i].length; j++) {
var count = 0;
if (combinations[i][j].hasClass(currentPlayer)) {
// console.log(combinations[i][j]);
// console.log(count);
count++;
if (count == 4) {
return true;
} else {
count = 0;
}
}
}
}
}
Try this, it's not elegant to remove the j loop but I think it will work for you:
function checkDiagonal() {
for (var i = 0; i < combinations.length; i ++) {
const test1 = combinations[i][0].hasClass(currentPlayer);
const test2 = combinations[i][1].hasClass(currentPlayer);
const test3 = combinations[i][2].hasClass(currentPlayer);
const test4 = combinations[i][3].hasClass(currentPlayer);
if (test1 && test2 && test3 && test4) {
console.log('diagonal win at i = ', i);
}
}
}
You can use .some and .every:
function checkDiagonal() {
return (combinations.some((combi, i) =>
combi.every(cell => cell.hasClass(currentPlayer)));
}

Put a line break in a for loop that is generating html content

I have a for loop that is generating some HTML content:
var boxes = "";
for (i = 0; i < 11; i ++) {
boxes += "<div class=\"box\"><img src=\"unlkd.png\"/></div>";
}
document.getElementById("id").innerHTML = boxes;
I want to display 3 boxes in one row, then below them 2 boxes in one row, then 1, then 3 again, 2, and 1.
First i thought of using the if statement to check whether i > 2 to add a line break, but it will also add a line break after every box past the third one. Nothing comes to mind, and my basic knowledge of javascript tells me I'll have to make a loop for each row I want to make. Any advice?
I would use a different approch :
Use a array to store the number of item per row :
var array = [3, 2, 1, 3, 2];
Then, using two loops to iterate this
for(var i = 0; i < array.length; i++){
//Start the row
for(var j = 0; j < array[i]; ++j){
//create the item inline
}
//End the row
}
And you have a pretty system that will be dynamic if you load/update the array.
PS : not write javascript in a while, might be some syntax error
Edit :
To generate an id, this would be simple.
create a variable that will be used as a counter.
var counter = 0;
On each creating of an item, set the id like
var id = 'boxes_inline_' + counter++;
And add this value to the item you are generating.
Note : This is a small part of the algorithm I used to build a form generator. Of course the array contained much more values (properties). But this gave a really nice solution to build form depending on JSON
You can try something like this:
Idea
Keep an array of batch size
Loop over array and check if iterator is at par with position
If yes, update position and index to fetch next position
var boxes = "";
var intervals = [3, 2, 1];
var position = intervals[0];
var index = 0;
for (i = 0; i < 11; i++) {
boxes += "<div class=\"box\"><img src=\"unlkd.png\"/></div>";
if ((position-1) === i) {
boxes += "<br/>";
index = (index + 1) % intervals.length;
position += intervals[index]
}
}
document.getElementById("content").innerHTML = boxes;
.box{
display: inline-block;
}
<div id="content"></div>
var boxes = "",
boxesInRow = 3,
count = 0;
for (i = 0; i < 11; i ++) {
boxes += "<div class=\"box\"><img src=\"unlkd.png\"/></div>";
count++;
if(count === boxesInRow) {
boxes += "<br/>";
boxesInRow -= 1;
count = 0;
if (boxesInRow === 0) {
boxesInRow = 3;
}
}
}
document.getElementById("id").innerHTML = boxes;
var i;
var boxes = "";
for (i = 0; i < boxes.length; i++) {
boxes += "<div class=""><img src=""/></div>";
function displayboxes() {
"use strict";
for (i = 0; i < boxes.length; i++) {
out.appendChild(document.createTextNode(boxes[i] + "<br>"));
}
}
displayboxes(boxes);

Javascript variable working without var?

I am trying to write an image slider in Javascript, I was looking at examples online and found this particular one:
function slider(){
var current = 0;
slides = document.getElementsByClassName("images");
setInterval(function() {
for (var i = 0; i < slides.length; i++) {
slides[i].style.opacity = 0;
}
current = (current != slides.length - 1) ? current + 1 : 0;
slides[current].style.opacity = 1;
}, 3000);
}
window.onload=slider;
I have tested this and it works with no errors.
I am wondering why the variable 'slides' is not declared as 'var slides', when I add 'var' the script stops working.
Don't all variables in Javascript start with 'var'? why does this work without the 'var'?
Correctly declaring slides as var slides does not break this function.
Run the example below.
function slider() {
var current = 0;
var slides = document.getElementsByClassName("images");
setInterval(function() {
for (var i = 0; i < slides.length; i++) {
slides[i].style.opacity = 0;
}
current = (current != slides.length - 1) ? current + 1 : 0;
slides[current].style.opacity = 1;
}, 3000);
}
window.onload=slider;
<div class="images">image1</div>
<div class="images">image2</div>
<div class="images">image3</div>

Loop should not break on encountering a invalid statement

Check out this code...
HTML
<span>TEST </span>
<div style="color:red">COlured div</div>
<div style="color:blue">COlured div</div>
<p style="color:red">Colourful TExt</p>
<p style="color:blue">Colourful TExt</p>
<p style="color:green">Colourful TExt</p>
<p style="color:brown">Colourful TExt</p>
<button onclick="changetobw()">CHANGE COLOR</button>
JavaScript
function changetobw() {
a = document.getElementsByTagName('p');
b = document.getElementsByTagName('div');
var i = 0;
do {
a[i].classList.add('nocolor');
b[i].classList.add('nocolor');
i++;
} while (i < a.length && i < b.length);
}
CSS
.nocolor {
color:#000 !important;
}
DEMO
What i am attempting to do here is on click of the button make all the div and span font color "black".
My code breaks(obviously) when the counter crosses i=2 because there are just 2 div and hence "i[2]" would be undefined and hence the loop breaks.
Is there anyway for the loop not to break after hitting this point? Maybe I am not getting my point perfectly across. Hope you all understand?
To use the loop like you use it, you have to make sure both arrays have the same length.
Obviously, their length isn't equal, so either you seperate this one loop into two loops (1) or you go for two if-statements checking i against the length of both arrays (2). Even better would be using for in combination with the querySelectorAll (3).
(1):
function changetobw() {
a = document.getElementsByTagName('p');
b = document.getElementsByTagName('div');
var i = 0;
do {
a[i].classList.add('nocolor');
i++;
} while (i < a.length);
i = 0;
do {
b[i].classList.add('nocolor');
i++;
} while (i < b.length);
}
(2) (fiddle):
function changetobw() {
a = document.getElementsByTagName('p');
b = document.getElementsByTagName('div');
var i = 0;
do {
if(i < a.length)
a[i].classList.add('nocolor');
if(i < b.length)
b[i].classList.add('nocolor');
i++;
} while (i < a.length || i < b.length);
}
(3) (fiddle):
function changetobw() {
var els = document.querySelectorAll('p, div');
for(var i = 0; i < els.length; i++) {
els.item(i).classList.add("nocolor");
}
}
If you're not worried about browsers beneath IE9, you should use querySelectorAll instead as this will allow you to pick up both types of element in the same query.
var a = document.querySelectorAll('p, div');
for (var i = 0, l = a.length; i < l; i++){
a[i].classList.add('nocolor');
}
Fiddle
I think u should make a specific generic method to change the color and then call it for each tag type u need rather then changing all in one
try this :
function changetobw()
{
changeColor(document.getElementsByTagName('p'));
changeColor(document.getElementsByTagName('div')) ;
}
function changeColor(obj)
{
var i = 0;
do {
obj[i].classList.add('nocolor');
i++;
} while (i < obj.length);
}
demo : http://jsfiddle.net/A52Lj/5/
This do the trick (maybe there is a more elegant solution)
function changetobw() {
a = document.getElementsByTagName('p');
b = document.getElementsByTagName('div');
var i = 0;
do {
a[i].classList.add('nocolor');
i++;
} while (i < a.length);
i = 0;
do {
b[i].classList.add('nocolor');
i++;
} while (i < b.length);
}
Another approach found :
function changetobw() {
a = document.getElementsByTagName('p');
b = document.getElementsByTagName('div');
var j=(a.length>b.length)?a.length:b.length;
var i = 0;
do {
if(i<a.length){
a[i].classList.add('nocolor');
}
if(i<b.length){
b[i].classList.add('nocolor');
}
i++;
} while (i <j);
}

Categories

Resources