jQuery click append elements to series of divs - javascript

I have the following code:
$('button').click(function(e) {
e.preventDefault();
var count = 0;
if (count < 5) {
$(".container .column:nth-child(1)").append('<div class="element"></div>');
count++;
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button type="button">Add</button>
<div class="container">
<div class="column"></div>
<div class="column"></div>
<div class="column"></div>
<div class="column"></div>
</div>
When I click the button I want to add 4 elements maximum in each column, one by one. For example if I click the button 6 times, the HTML will look like this:
<div class="container">
<div class="column">
<div class="element"></div>
<div class="element"></div>
<div class="element"></div>
<div class="element"></div>
</div>
<div class="column">
<div class="element"></div>
<div class="element"></div>
</div>
<div class="column"></div>
<div class="column"></div>
</div>
This adds 1 element div to the first column, each time I click a button, with a 4 element div limit.
How can I do the same for the next columns?
Bonus Question
Is it possible to also do the opposite when clicking a button to remove elements?

You can target the column div by checking the no of elements in it using the length property.
Additionally, You don't need :nth-child(1) property.
$('.add').click(function(e) {
e.preventDefault();
var count = 0;
if (count < 5) {
$(".container .column").filter(function() {
return $(this).children('.element').length < 4;
}).first()
.append('<div class="element">e</div>');
count++;
}
});
$('.remove').click(function(e) {
e.preventDefault();
$(".container .column .element:last").remove();
});
.column {
border: 1px solid red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button type="button" class="add">Add</button>
<button type="button" class="remove">Remove</button>
<div class="container">
<div class="column"></div>
<div class="column"></div>
<div class="column"></div>
<div class="column"></div>
</div>
References:
.filter()
.first()

You can try this code:
$('button').click(function(e) {
e.preventDefault();
var columns = $(".container .column");
var added = false;
for (var i = 0; i < columns.length; i++) {
if (columns[i].childNodes.length < 4) {
$(columns[i]).append('<div class="element"></div>');
added = true;
break;
}
}
if (!added) {
console.log('All columns were filled!');
}
});
.container {
display: flex;
flex-direction: row;
justify-content: space-between;
}
.column {
flex: 1;
}
.element {
width: 10px;
height: 10px;
background: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button type="button">Add</button>
<div class="container">
<div class="column"></div>
<div class="column"></div>
<div class="column"></div>
<div class="column"></div>
</div>

Related

classList does not work as expected inside a for loop

I have a slider that shows rotate slides on desktop with swipper slider,
I destroy the slider on mobile and would like to show 3 static slides that do not rotate with a show more button.
I added a class called hidden to all the elements except the first 3 and added a button to show more slides on click.
Now when you click on the button I would like to remove the hidden class from all the slides elements but it does not work.
Here is the HTML:
<div class="icon-slider">
<div class="swiper-container js-icon-slider">
<div class="swiper-wrapper">
<div class="swiper-slide">
<div class="img-wrap">image here</div>
</div>
<div class="swiper-slide">
<div class="img-wrap">image here</div>
</div>
<div class="swiper-slide">
<div class="img-wrap">image here</div>
</div>
<div class="swiper-slide">
<div class="img-wrap">image here</div>
</div>
<div class="swiper-slide">
<div class="img-wrap">image here</div>
</div>
<div class="swiper-slide">
<div class="img-wrap">image here</div>
</div>
</div>
</div>
And my JS code:
var slider = document.querySelector('.icon-slider'),
slides = slider.querySelectorAll('.swiper-slide'),
btnMore = '<div class="more-btn-wrap"><button class="wp-block-button__link">View all</button></div>';
for (let i = 2; i < slides.length; i++) {
slides[i].classList.add('hidden');
}
if (!slider.querySelector(".more-btn-wrap")) {
slider.innerHTML = slider.innerHTML + btnMore;
}
let btn = document.querySelector('.more-btn-wrap');
btn.addEventListener('click', function () {
this.remove();
slides.forEach(slide => slide.classList.remove('hidden'));
});
When I just try to put this line in the console it works as expected so I think it's something with the addEventListener
slides.forEach(slide => slide.classList.remove('hidden'));
You don't need 2 for loops, add eventlistener inside for loop and remove second for loop inside addeventlistener also remove 3 and type 0 to start loop from 0
<style type="text/css">
.slide {
width: 80px;
height: 80px;
background-color: red;
border: 2px solid blue;
}
.hidden {
opacity: 0.1;
}
</style>
<button class="btn">Button</button>
<div class="slider">
<div class="slide">Slide1</div>
<div class="slide">Slide2</div>
<div class="slide">Slide3</div>
</div>
<script>
let btn = document.querySelector('.btn');
let slider = document.querySelector('.slider');
let slides = slider.querySelectorAll('.slide');
for (let i = 0; i < slides.length; i++) {
slides[i].classList.add('hidden');
btn.addEventListener('click', function() {
slides[i].classList.remove('hidden');
});
}
</script>

Check if div-container has more than one div-inner no jQuery

I need a if else function that checks if div_container has more than one div_inner inside of it with Javascript only.
Here's my example code:
var inner = document.querySelector('.inner')
var container = document.querySelector('.container').innerHTML;
if(container > '1') {
container.classList.add('test');
}
else {
// do nothing
}
.test {
color: red;
}
<div class="container">
<div class="inner">Test</div>
</div>
<div class="container">
<div class="inner">Test</div>
<div class="inner">Test</div>
</div>
I only want to use Javascript. No jQuery at all.
You have to use querySelectorAll() to get all the container and loop through them to check the inner div's length:
var container = document.querySelectorAll('.container');
container.forEach(function(el){
var inner = el.querySelectorAll('.inner').length;
if(inner > 1) {
el.classList.add('test');
}
else {
// do nothing
}
});
.test {
color: red;
background-color: lightgray;
}
<div class="container">
<div class="inner">Test</div>
</div>
<div class="container">
<div class="inner">Test</div>
<div class="inner">Test</div>
</div>
You can use querySelectorAll()
for (const container of document.querySelectorAll('.container')) {
if (container.querySelectorAll('.inner').length > 1) {
container.classList.add('test');
}
}
.test {
color: red;
}
<div class="container">
<div class="inner">Test</div>
</div>
<div class="container">
<div class="inner">Test</div>
<div class="inner">Test</div>
</div>

Only allow the user to select a maximum of three blocks

I have a piece of code that adds an event listener to a number of buttons, when the user clicks a button a class is applied to the button container. How can I restrict this so the user can only select a maximum of three buttons. The code below is working to a point, when you get to three you cannot deselect. Can anyone help me achieve
var blocks = document.querySelectorAll(".block");
var btn = document.querySelectorAll("button");
var total = 0;
for (let i = 0; i < btn.length; i++) {
btn[i].addEventListener("click", function() {
if (total < 3 && blocks[i].classList.contains("active")) {
blocks[i].classList.remove("active");
total--;
} else if (total < 3 && !blocks[i].classList.contains("active")) {
blocks[i].classList.add("active");
total++;
}
});
}
.container{
display:flex;
}
.block{
padding: 50px;
border:1px solid;
max-width:
}
.block.active{
background:grey;
}
<div class="container">
<div class="block">
<button>click</button>
</div>
<div class="block">
<button>click</button>
</div>
<div class="block">
<button>click</button>
</div>
<div class="block">
<button>click</button>
</div>
</div>
this.
You simply need to remove this condition total < 3 && from your first if. The number of selected items is irrelevant if the element is already selected. You just want to de-select it.
var blocks = document.querySelectorAll(".block");
var btn = document.querySelectorAll("button");
var total = 0;
for (let i = 0; i < btn.length; i++) {
btn[i].addEventListener("click", function() {
if (blocks[i].classList.contains("active")) {
blocks[i].classList.remove("active");
total--;
} else if (total < 3 && !blocks[i].classList.contains("active")) {
blocks[i].classList.add("active");
total++;
}
});
}
.container{
display:flex;
}
.block{
padding: 50px;
border:1px solid;
max-width:
}
.block.active{
background:grey;
}
<div class="container">
<div class="block">
<button>click</button>
</div>
<div class="block">
<button>click</button>
</div>
<div class="block">
<button>click</button>
</div>
<div class="block">
<button>click</button>
</div>
</div>

Refactoring jQuery repeating pattern

I have painted my self into a corner in order to quickly prototype.
What's the best way to refactor the following jQuery code? Its functionality is to toggle between some sidebar navigation items. I need it to be more dynamic in order to be scalable.
Would you add the IDs inside the if statements, in an array and iterate through them? Use variables? Create a function and call it on the html side onClick? No matter what I think of, it stills leads to a bunch of repeating code.
Thank you!
// TOGGLING LEFT NAVIGATION
$('#settingsClick').click(function() {
if( $('#addContainer, #noteContainer, #logoContainer, #themeContainer').is(':visible') ) {
$('#addContainer').slideUp(350);
$('#noteContainer').slideUp(350);
$('#logoContainer').slideUp(350);
$('#settingsContainer').slideDown(350);
$('#themeContainer').slideUp(350);
} else {
$('#settingsContainer').slideToggle(350);
}
});
$('#addClick').click(function() {
if( $('#settingsContainer, #noteContainer, #logoContainer, #themeContainer').is(':visible') ) {
$('#settingsContainer').slideUp(350);
$('#noteContainer').slideUp(350);
$('#logoContainer').slideUp(350);
$('#addContainer').slideDown(350);
$('#themeContainer').slideUp(350);
} else {
$('#addContainer').slideToggle(350);
}
});
$('#noteClick').click(function() {
if( $('#settingsContainer, #addContainer, #logoContainer, #themeContainer').is(':visible') ) {
$('#settingsContainer').slideUp(350);
$('#addContainer').slideUp(350);
$('#logoContainer').slideUp(350);
$('#noteContainer').slideDown(350);
$('#themeContainer').slideUp(350);
} else {
$('#noteContainer').slideToggle(350);
}
});
$('#logoClick').click(function() {
if( $('#settingsContainer, #addContainer, #noteContainer, #themeContainer').is(':visible') ) {
$('#settingsContainer').slideUp(350);
$('#addContainer').slideUp(350);
$('#noteContainer').slideUp(350);
$('#logoContainer').slideDown(350);
$('#themeContainer').slideUp(350);
} else {
$('#logoContainer').slideToggle(350);
}
});
$('#themeClick').click(function() {
if( $('#settingsContainer, #addContainer, #noteContainer, #logoContainer').is(':visible') ) {
$('#settingsContainer').slideUp(350);
$('#addContainer').slideUp(350);
$('#noteContainer').slideUp(350);
$('#logoContainer').slideUp(350);
$('#themeContainer').slideDown(350);
} else {
$('#themeContainer').slideToggle(350);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a id="settingsClick">Click Me</a><br>
<div id="settingsContainer">Content...</div>
<br><br>
<a id="addClick">Click Me</a><br>
<div id="addContainer">Content...</div>
<br><br>
<p> Etc... Etc....</p>
You should group using the common CSS class, i.e. header and content. Using the established relationship you can target the others content holder and content associated with the current clicked header element.
$('.container .header').on('click', function() {
//Get the current element
var $this = $(this);
//find the content
var $content = $this.closest('.container').find('.content'); //$this.next()
//get all contents
var content = $('.container .content');
//Slide up others
content.not($content).slideUp(350);
//Slide down
$content.slideToggle(350);
});
.content {
display: none
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="header" id="settingsClick">Click Me</div>
<div class="content" id="settingsContainer">Content...</div>
</div>
<div class="container">
<div class="header" id="addClick">Click Me</div>
<div class="content" id="addContainer">Content...</div>
</div>
<div class="container">
<div class="header" id="noteClick">Click Me</div>
<div class="content" id="noteContainer">Content...</div>
</div>
the best bet would be to do it like so
$(document).on('click', ".trigger", function() {
var sibling_content = $(this).siblings(".content");
if (!sibling_content.hasClass('active')) {
$(".content").slideUp('slow').removeClass('active');
sibling_content.slideDown('slow').addClass('active');
} else {
sibling_content.slideUp('slow').removeClass('active');
}
})
.trigger {
background-color: red;
color: white;
font-size: 16px;
}
.content {
background-color: blue;
color: white;
font-size: 16px;
padding: 20px 0;
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="trigger">trigger</div>
<div class="content">content</div>
</div>
<div class="container">
<div class="trigger">trigger</div>
<div class="content">content</div>
</div>
<div class="container">
<div class="trigger">trigger</div>
<div class="content">content</div>
</div>
<div class="container">
<div class="trigger">trigger</div>
<div class="content">content</div>
</div>

how to check if it was the last element

how can I check if it was the last div? If it was I need to remove all classes "ready"
html:
<div class="green"></div>
<div class="orange"></div>
<div class="red"></div>
<div class="green"></div>
<div class="orange"></div>
js:
$(function() {
setInterval(showBlock, 1000);
function showBlock() {
var x = $("div:first").addClass("ready");
var c = $("div");
$(".ready").css("display", "block");
if (c.hasClass("ready")) {
$(".ready:last").next().addClass("ready");
}
}
})
;
Looking at your code what I understand is you want display one div after each second. For that I'll suggest following approach.
First add hidden class to all divs and then remove it from first hidden div at each second.
$(function() {
$('div').addClass('hidden');
var i = setInterval(showBlock, 1000);
function showBlock() {
var x = $("div.hidden:first").removeClass("hidden");
if($("div.hidden").length == 0) {
clearInterval(i);
}
}
});
.hidden {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="green">Green</div>
<div class="orange">Orange</div>
<div class="red">Red</div>
<div class="green">Green</div>
<div class="orange">Orange</div>
As far as I understand your problem, following solution must work in your case:
$(function() {
setInterval(showBlock, 1000);
function showBlock() {
var ready_divs = $("div.ready").length;
var total_divs = $("div").length;
if(ready_divs!=total_divs){
if(ready_divs==0){
$("div:first").addClass('ready');
}else{
$("div.ready:last").next('div').addClass('ready');
}
}else{
$("div").removeClass('ready')
}
}
});
div{
width: 20px;
height: 20px;
border:1px solid red;
}
div.ready{
border:3px solid blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="green"></div>
<div class="orange"></div>
<div class="red"></div>
<div class="green"></div>
<div class="orange"></div>

Categories

Resources