Sorry for silly question , but I can't add class to button on click. I have list of buttons and on click I need to change background of active button . I dont know how to get index of element on click inside list and add class. I need to make it on pure javascript. Only need to leave $(document).ready(function() . Here is my fiddle https://jsfiddle.net/armakarma/ns5tfcL0/15/
HTML
<div class="content-itinerary__buttons-wrapper">
<button class="content-itinerary__buttons description-text ">Day 2</button>
<button class="content-itinerary__buttons description-text">Day 3</button>
<button class="content-itinerary__buttons description-text">Day 4</button>
</div>
JS
$(document).ready(function() {
let myBtns=document.querySelector('.content-itinerary__buttons-wrapper')
myBtns.addEventListener('click', ()=>{
console.log('test')
})
});
Only need to leave $(document).ready(function()
I am not sure why do you need to leave that when you have the equivalent JavaScript (DOMContentLoaded).
Loop through all the buttons, inside the event handler function first remove the class from all the buttons then add the class only to the clicked button:
document.addEventListener('DOMContentLoaded', () => {
let myBtns=document.querySelectorAll('.content-itinerary__buttons');
myBtns.forEach(function(btn) {
btn.addEventListener('click', () => {
myBtns.forEach(b => b.classList.remove('active'));
btn.classList.add('active');
});
});
});
.active {
color: #fff;
background-color: #4CAF50;
}
<div class="content-itinerary__buttons-wrapper">
<button class="content-itinerary__buttons description-text ">Day 2</button>
<button class="content-itinerary__buttons description-text">Day 3</button>
<button class="content-itinerary__buttons description-text">Day 4</button>
</div>
You just need to use event object in click event
$(document).ready(function() {
let myBtns=document.querySelectorAll('.content-itinerary__buttons-wrapper')[0];
myBtns.addEventListener('click', (e)=> {
if (e.target.className.indexOf('clicked') === -1) {
e.target.className += ' clicked';
} else {
e.target.className = e.target.className.replace(' clicked', '');
}
})
});
This is your solution
var header = document.getElementById("myDIV");
var btns = header.getElementsByClassName("content-itinerary__buttons");
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function() {
var current = document.getElementsByClassName("active");
current[0].className = current[0].className.replace(" active", "");
this.className += " active";
});
}
.content-itinerary__buttons-wrapper {
display: flex;
margin-top: 20px;
}
.content-itinerary__buttons {
flex-grow: 1;
padding: 21px 15px 15px 15px;
box-sizing: border-box;
border: 1px solid #D7D7D7;
outline: none;
&:not(:last-child) {
border-right: 0;
}
}
.active, .btn:hover {
background-color: red;
color: white;
}
<div class="content-itinerary__buttons-wrapper" id="myDIV">
<button class="content-itinerary__buttons description-text active ">Day 2</button>
<button class="content-itinerary__buttons description-text">Day 3</button>
<button class="content-itinerary__buttons description-text ">Day 4</button>
<button class="content-itinerary__buttons description-text">Day 5</button>
<button class="content-itinerary__buttons description-text">Day 6</button>
<button class="content-itinerary__buttons description-text">Day 7</button>
<button class="content-itinerary__buttons description-text">Day 8</button>
<button class="content-itinerary__buttons description-text">Day 9</button>
<button class="content-itinerary__buttons description-text">Day 10</button>
</div>
See Code link
I would definitely use Element.classList API for adding/removing classes to/from elements.
Why?
Adding/removing classes won't affect other classes already set to the element
Updating the className of the element will replace all existing classes
It comes with handy functions like "toggle" and "replace
Your code will look something like this:
$(document).ready(function() {
let myBtns=document.querySelectorAll('.content-itinerary__buttons-wrapper')
myBtns
.forEach(btn => btn
.addEventListener('click', (e)=>{
// Check if the classList already exists on the element clicked
// If so, remove it
// Else, add it
e.classList.contains('clicked')
? e.classList.add('clicked')
: e.classList.remove('clicked');
})
);
});
Onclick of the button you can set class name to the button
function a(e)
{
e.setAttribute("class","active");
}
.active
{
color:red
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="content-itinerary__buttons-wrapper">
<button class="content-itinerary__buttons description-text" onclick="a(this)">Day </button>
<button class="content-itinerary__buttons description-text" onclick="a(this)">Day </button>
<button class="content-itinerary__buttons description-text" onclick="a(this)">Day </button>
</div>
If you going to get rid of jQuery replace wrapper function to use listen for DOMContentLoaded event. It's the same as jQuery documentReady.
In your click handler use event object, ev.target in my example is a button which fired the event. Then use classList property to add your class.
document.addEventListener('DOMContentLoaded', function(){
let myBtns=document.querySelector('.content-itinerary__buttons-wrapper')
myBtns.addEventListener('click', (ev)=>{
let btn = ev.target;
btn.classList.add('red');
});
});
Just use forEach loop :)
$(document).ready(function() {
let myBtns=document.querySelectorAll('.content-itinerary__buttons-wrapper')
let myAllButtons = myBtns.querySelectorAll('.content-itinerary__buttons')
myAllButtons.forEach(function(element) {
element.onclick = () => element.classList.add('some-class')
})
});
Related
I have a set of buttons where a js code selected the current button to display it differently.
What I would like to do is to have two sets of buttons, in which I can interact with the buttons in the different sets independently.
Like select the button "1" on the first set and "2" on the second set. In a perfect world, I would like to have only one function in js to do it for different sets. I don't know how to do it.
My one set of button is like this :
// Add active class to the current button (highlight it)
var header = document.getElementById("myDIV");
var btns = header.getElementsByClassName("btn");
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function() {
var current = document.getElementsByClassName("active");
current[0].className = current[0].className.replace(" active", "");
this.className += " active";
});
}
.btn {
border: none;
outline: none;
padding: 10px 16px;
background-color: #f1f1f1;
cursor: pointer;
font-size: 18px;
}
/* Style the active class, and buttons on mouse-over */
.active, .btn:hover {
background-color: #666;
color: white;
}
<div id="myDIV">
<button class="btn">1</button>
<button class="btn active">2</button>
<button class="btn">3</button>
<button class="btn">4</button>
<button class="btn">5</button>
</div>
your question is unclear, is this answer a good one ?
this is about JS event delegation,
you should also use classList.toggle(), which allows to directly include the test
const DivAllButtons = document.getElementById('All-buttons')
DivAllButtons.onclick = ({target : clicked_Element }) =>
{
if (!clicked_Element.matches('button.btn')) return
clicked_Element.parentNode
.querySelectorAll('button.btn')
.forEach( bt =>
{
bt.classList.toggle( 'active', bt===clicked_Element )
});
}
#All-buttons > div {
margin: 1em;
}
.btn {
border : none;
outline : none;
padding : 10px 16px;
background-color : #f1f1f1;
cursor : pointer;
font-size : 18px;
}
.active,
.btn:hover {
background-color : #666;
color : white;
}
<div id="All-buttons">
<div>
<button class="btn">1</button> <button class="btn active">2</button>
<button class="btn">3</button> <button class="btn">4</button> <button class="btn">5</button>
</div>
<div>
<button class="btn">1</button> <button class="btn active">2</button>
<button class="btn">3</button> <button class="btn">4</button> <button class="btn">5</button>
</div>
<div>
<button class="btn">1</button> <button class="btn active">2</button>
<button class="btn">3</button> <button class="btn">4</button> <button class="btn">5</button>
</div>
<div>
<button class="btn">1</button> <button class="btn active">2</button>
<button class="btn">3</button> <button class="btn">4</button> <button class="btn">5</button>
</div>
<div>
<button class="btn">1</button> <button class="btn active">2</button>
<button class="btn">3</button> <button class="btn">4</button> <button class="btn">5</button>
</div>
</div>
Your question is not clear about what you want, but I guess this is what you want, I added another button in the following snippet, I change few things:
Remove the selector based on the ID and replace it with selector for class name document.querySelectorAll(".button-set") via querySelectorAll()
Loop though the button set (2 element in my snippet), and change the selector of the button for active class to the current div id since it is unique and allow us to target a specific set.
Add unique ID value for div group or set.
var sets = document.querySelectorAll(".button-set");
sets.forEach((el, i) => {
btns = el.getElementsByClassName("btn");
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function() {
var button = document.querySelector(`#${el.id} .active`);
button.className = button.className.replace(" active", "");
this.className += " active";
});
}
});
.btn {
border: none;
outline: none;
padding: 10px 16px;
background-color: #f1f1f1;
cursor: pointer;
font-size: 18px;
}
/* Style the active class, and buttons on mouse-over */
.active, .btn:hover {
background-color: #666;
color: white;
}
<div id="myDIV" class="button-set">
<button class="btn">1</button>
<button class="btn active">2</button>
<button class="btn">3</button>
<button class="btn">4</button>
<button class="btn">5</button>
</div>
<br />
<div id="myDIV2" class="button-set">
<button class="btn">1</button>
<button class="btn active">2</button>
<button class="btn">3</button>
<button class="btn">4</button>
<button class="btn">5</button>
</div>
I have problem with removing div containing button. First I clone and add button, then change its class from 'add' to 'remove'. Then I try to remove div containing button with 'remove' but I can't access remove functions.
<div class="margin"></div>
<div class='new'>
<button type="button" class="btn btn-success add"><i class="fas fa-plus"></i></button>
</div>
<script>
$(document).ready(function() {
var div = document.getElementById('new');
$(".add").click(function(){
clone = div.cloneNode(true);
$(clone).insertAfter(".margin");
$("button.add:not(:last)).removeClass('add').addClass('remove');
$(".remove").click(function(){
console.log('inside')
//$(this).parent('div').remove();
});
});
</script>
document.getElementById('new') ... ur element does not have an ID. Its class-name is 'new' but not its ID. Some corrections should make it work:
$(document).ready(function() {
var div = document.getElementById('new');
$(".add").click(function(){
clone = div.cloneNode(true);
$(clone).insertAfter(".margin");
$("button.add:not(:last)").removeClass('add').addClass('remove');
$(".remove").click(function(){
console.log('inside')
//$(this).parent('div').remove();
});
})
});
.add {
background: green;
}
.remove {
background: red;
}
button {
color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="new">
<button type="button" class="btn btn-success add">
<i class="fas fa-plus"></i> new
</button>
</div>
<div class="margin"></div>
Edit:
Is there a more elegant way to do this?
Maybe like so:
$('.add').on('click', function() {
$(this).clone()
.toggleClass('add remove')
.on('click', function() {
$(this).remove()
})
.prependTo('#new');
})
.add {
background: green;
}
.remove {
background: red;
}
button {
color: white;
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="new">
<button type="button" class="btn btn-success add">
<i class="fas fa-plus"></i> new
</button>
</div>
I have css and js on a button group so that when you click a button from the group it shows as active, and when you click a different button, that button becomes active and the rest are cleared. I have to have 22 of these button groups (I only put 2 here for the sake of space) on my page, when I have just one the code works, but when I add the others everything comes crumbling down, can anyone help! How do use the script multiple times, where the script is applied to every group and doesn't intervene with the others.
function codeAddress() {
var header = document.getElementById("myDIV");
var btns = header.getElementsByClassName("btn");
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function() {
var current = document.getElementsByClassName("active");
current[0].className = current[0].className.replace(" active", "");
this.className += " active";
});
}
}
window.onload = codeAddress;
.btn {
background-color: white;
border: 3px solid #0099ff;
color: #0099ff;
cursor: pointer;
float: left;
padding: 10px 16px;
font-size: 18px;
}
.active,
.btn:hover {
background-color: #0099ff;
color: white;
border: 3px solid #0099ff;
cursor: pointer;
}
<div id="myDIV">
<button class="btn active">GQL</button>
<button class="btn">PSV</button>
<button class="btn">WT2</button>
<button class="btn">NBV</button>
<button class="btn">MBD</button>
</div>
<div id="myDIV">
<button class="btn active">GQL</button>
<button class="btn">PSV</button>
<button class="btn">WT2</button>
<button class="btn">NBV</button>
<button class="btn">MBD</button>
</div>
Here give this ago. I believe this is the intended response you expect when clicking button from different groups. Something like radio buttons. As already mentioned an ID can only represent one element not several. Use class instead. So i have changed your id to a class btn-group.
function codeAddress() {
const btnClick = function () {
this.parentNode.getElementsByClassName("active")[0].classList.remove("active");
this.classList.add("active");
};
document.querySelectorAll(".btn-group .btn").forEach(btn => btn.addEventListener('click', btnClick));
// This is the same as above just another way of doing it. use which ever you like
// var btns = document.querySelectorAll(".btn-group .btn");
// for (var i = 0; i < btns.length; i++) {
// btns[i].addEventListener("click", function () {
// this.parentNode.getElementsByClassName("active")[0].classList.remove("active");
// this.classList.add("active");
// });
// }
}
window.onload = codeAddress;
.btn {
background-color: white;
border: 3px solid #0099ff;
color: #0099ff;
cursor: pointer;
float: left;
padding: 10px 16px;
font-size: 18px;
}
.active,
.btn:hover {
background-color: #0099ff;
color: white;
border: 3px solid #0099ff;
cursor: pointer;
}
<div class="btn-group">
<button class="btn active">GQL</button>
<button class="btn">PSV</button>
<button class="btn">WT2</button>
<button class="btn">NBV</button>
<button class="btn">MBD</button>
</div>
<br style="clear:both">
<div class="btn-group">
<button class="btn active">GQL</button>
<button class="btn">PSV</button>
<button class="btn">WT2</button>
<button class="btn">NBV</button>
<button class="btn">MBD</button>
</div>
Here the example what you need https://jsbin.com/bomegabiqo/1/edit?html,js,output
First of all, I want to say that you don't need to have two div with the same id
The second point is that you need to attach eventListener to the parent element, due to best-practice and performance optimization (you can read about it somewhere)
So here is updated version of HTML:
<div id="myGroupButtonsWrapper">
<div id="myDIV">
<button class="btn active">GQL</button>
<button class="btn">PSV</button>
<button class="btn">WT2</button>
<button class="btn">NBV</button>
<button class="btn">MBD</button>
</div>
<div id="myDIVV">
<button class="btn">GQL</button>
<button class="btn">PSV</button>
<button class="btn">WT2</button>
<button class="btn">NBV</button>
<button class="btn">MBD</button>
</div>
</div>
And JavaScript:
function codeAddress() {
function myClickCallback(e) {
if (e.target.className === 'btn') {
var allButtons = document.querySelectorAll("#myGroupButtonsWrapper .btn");
allButtons.forEach((elem) => {
elem.className = elem.className.replace(" active", "");
});
e.target.className += ' active';
} else {
return;
}
}
var header = document.getElementById("myGroupButtonsWrapper");
header.addEventListener("click", myClickCallback);
}
window.onload = codeAddress;
It's not working because you have multiple IDs:
<div id="myDIV">...</div>
<div id="myDIV">...</div>
You can't do this - first, it's invalid HTML, and second, it'll do one of two things with the JS: cause an error, which you can see in the console, or it'll treat header as a NodeList, which is a collection of nodes that match the query selection, which means that it won't work. If you make them all have different IDs (e.g. div1, div2, div3, etc), it'll work if you modify your code to take multiple divs.
The other option is to make a class (e.g. myDIV) and modify your existing JavaScript code to use a class.
Instead of individual buttons, I would recommend using radio buttons for something like this. It already has functionality built in to group together for a selection similar to what you're going for. Then you just have to use built in commands to set the active button or check the values.
https://www.w3schools.com/jsref/prop_radio_checked.asp
https://www.w3schools.com/html/html_forms.asp
it is fairly simple to accomplish this using just 3 steps.
// First step is to create a onBtnClick handler function:
// The btn which was clicked can be accessed from event.target
// And then we can use the build in function classList.toggle to toggle the active class on that btn
const onBtnClickHandler = function (ev){ev.target.classList.toggle("active")};
// Next step is to find all btns, this can be done using the build in querySelectorAll function
const btns = document.querySelectorAll('.btn'); //returns NodeList array
// Last step is to add the eventListener callback function to each btn
btns.forEach(btn => btn.addEventListener('click', onBtnClickHandler));
Hope this helps.
Is there a method I can use in jquery to click all of these div elements at once instead of using the javascript method below.
document.getElementById('Div_Remove_1').click();
document.getElementById('Div_Remove_2').click();
document.getElementById('Div_Remove_3').click();
document.getElementById('Div_Remove_4').click();
Yes, it is called start-with selector:
$('[id^="Div_Remove_"]').click(function() {
// you code here
});
You can trigger a click event for more than one selector in a row with jQuery:
$('div').on('click', function(){
$(this).addClass('clicked');
});
$('#Div_Remove_1, #Div_Remove_2, #Div_Remove_3, #Div_Remove_4').trigger('click');
div { width: 100px; height: 80px; background: black; margin-bottom: 10px; }
div.clicked { background: red; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="Div_Remove_1"></div>
<div id="Div_Remove_2"></div>
<div id="Div_Remove_3"></div>
<div id="Div_Remove_4"></div>
Anyway if you are able to add a class to those divs, you will easily do whatever with all of them, eg. $('.mydivs').trigger('click');
1. With jQuery
(function($) {
// Assign handlers
$('button').click(function() {
console.log(this.id);
});
// Click all
$('button').trigger('click');
})(jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="button-1">button 1</button>
<button id="button-2">button 1</button>
<button id="button-3">button 1</button>
<button id="button-4">button 1</button>
2. Without jQuery
You can use a loop to do it. like this snippet:
// Select all buttons
var buttons = document.querySelectorAll('[id^="button"]');
// Assign handlers
for (var i = 0; i < buttons.length; i++) {
buttons[i].onclick = clickHandler;
}
// Handler function
function clickHandler(e) {
console.log(e.target.id);
}
// Trigger handlers
for (var i = 0; i < buttons.length; i++) {
buttons[i].click();
}
<button id="button-1">button 1</button>
<button id="button-2">button 2</button>
<button id="button-3">button 3</button>
<button id="button-4">button 4</button>
I have this code where I link few flies in an IFrame, i want the color of the selected button to change and remain different until another button is pressed.
<style>
.myButton:active
{
position:relative;
top:1px;
}
</style>
<a class="myButton " href="" target="someFrame">Button1</a>
<a class="myButton " href="" target="someFrame" >Button 02</a>
<a class="myButton " href="" target="someFrame">Button 03</a>
<a class="myButton " href="" target="someFrame">Button 04</a>
<a class="myButton " " target="someFrame" >Button 05</a>
What you could do is have a JS/jQuery function that is called when the button is pressed. That function would be something like the pseudo code below:
function(){
removeClassFromOtherButtons('activeClass');
this.addClass('activeClass');
}
Then in your CSS, have .activeClass have a different colored background.
If you'd prefer a solution without JavaScript, you can achieve that with some hidden radiobutton trickery:
input[type="radio"][name="toggleRadio"] {
display: none;
}
input[type="radio"][name="toggleRadio"] + a label {
cursor: pointer;
}
input[type="radio"][name="toggleRadio"]:checked + a {
color: #000;
text-decoration: none;
}
<input type="radio" name="toggleRadio" id="toggleRadio1"><label class="myButton" for="toggleRadio1">Button1</label>
<input type="radio" name="toggleRadio" id="toggleRadio2"><label class="myButton" for="toggleRadio2">Button2</label>
<input type="radio" name="toggleRadio" id="toggleRadio3"><label class="myButton" for="toggleRadio3">Button3</label>
<input type="radio" name="toggleRadio" id="toggleRadio4"><label class="myButton" for="toggleRadio4">Button4</label>
<input type="radio" name="toggleRadio" id="toggleRadio5" checked><label class="myButton" for="toggleRadio5">Button5</label>
On your css file create an .active class that will be added to a button when pressed and removed from the others.
var buttons = document.querySelectorAll('.myButton');
buttons.forEach(function(button) {
button.addEventListener('click', function() {
toggleClass(buttons, this);
});
});
function toggleClass(buttons, buttonToActivate) {
buttons.forEach(function(btn) {
btn.classList.remove('active');
});
buttonToActivate.classList.add('active');
}
So, the :active is a :pseudo-class that is used when the button or anchor is being pressed.
If you want to your button to have a active state you need mark it with another class.
var buttons = document.querySelectorAll('.myButton');
var activeClassName = 'active';
function activeState(items, activeName) {
for(var i = 0; i < items.length; i++) {
if(items[i].classList.contains(activeName)) {
items[i].classList.remove(activeName);
}
}
}
for(var i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', function(e){
activeState(buttons, activeClassName);
e.target.classList.add(activeClassName);
});
}
.myButton {
position:relative;
top:1px;
}
.myButton.active {
background: #f00;
color: #fff;
border-color: #f00;
}
<button class="myButton">Test 1</button>
<button class="myButton">Test 2</button>
<button class="myButton">Test 3</button>
<button class="myButton">Test 4</button>
<button class="myButton">Test 5</button>
<button class="myButton">Test 6</button>
I used here vanilla javascript but this code can be re-written using ES6 or Jquery and it will be much more simple.
Here some reference links for you:
https://www.w3schools.com/css/css_pseudo_classes.asp
https://developer.mozilla.org/docs/Web/API/Element/classList
https://developer.mozilla.org/docs/Web/API/Element/addEventListener
Once you click the button call onclick function
Use common class name to remove active class from all buttons then add active class to specific button
In css give color which you want selected button to be
.active{
background:red;}
Onclick function
$(".mybutton").on("click",function(event){ addclassactive(event.target);
}
function addclassactive (caller){
$(".mybutton").removeClass("active");
$(caller).addClass("active"):
}