Change div HTML content with attribute from button on click - javascript

I have some data attributes on buttons that I need to send as content to a div when those buttons are clicked. A part of my code until now is this:
function getDiscount() {
var buttons = document.querySelectorAll(".form-button");
buttons.forEach(function(item, index) {
item.addEventListener('click', function() {
var discount = getDiscount(this);
});
});
function getDiscount(clicked_element) {
var val = clicked_element.getAttribute("data-discount");
return val;
}
};
<div class="discount__Topics">
<div><strong class="discount-amount">50</strong>%</div>
<div class="offers">
<button class="form-button" data-discount="38">Offer 1</button>
<button class="form-button" data-discount="50">Offer 2</button>
<button class="form-button" data-discount="22">Offer 3</button>
<button class="form-button" data-discount="88">Offer 4</button>
</div>
</div>
<div class="discount__Topics">
<div><strong class="discount-amount">60</strong>%</div>
<div class="offers">
<button class="form-button" data-discount="12">Offer 1</button>
<button class="form-button" data-discount="32">Offer 2</button>
<button class="form-button" data-discount="44">Offer 3</button>
<button class="form-button" data-discount="55">Offer 4</button>
</div>
</div>
I'm just not seeing how to change the html with attribute when it's clicked and how to have two sets of buttons or more on the same page.
Hope someone can help.
Many thanks
UPDATE: Now the code is running properly but im having troubles with getting multiples div's with multiple buttons working. I've created a for.Each wic logs my div correctly but im not beeing able to have the working properly.
var discounters = document.querySelectorAll(".discount__Topics");
discounters.forEach((index) => {
console.log(index)
var buttons = document.querySelectorAll(".form-button");
buttons.forEach(function (item) {
item.addEventListener('click', function(){
var discount = getDiscount(this);
let span = document.querySelector('.discount-amount')
span.innerHTML = '<strong>' + discount+ '</strong>'
});
});
function getDiscount(clicked_element) {
var val = clicked_element.getAttribute("data-discount");
return val;
}
});
<div class="discount__Topics">
<div><strong class="discount-amount">38</strong>%</div>
<div class="offers">
<button class="form-button" data-discount="38">Offer 1</button>
<button class="form-button" data-discount="50">Offer 2</button>
<button class="form-button" data-discount="22">Offer 3</button>
<button class="form-button" data-discount="88">Offer 4</button>
</div>
</div>
<div class="discount__Topics">
<div><strong class="discount-amount">12</strong>%</div>
<div class="offers">
<button class="form-button" data-discount="12">Offer 1</button>
<button class="form-button" data-discount="32">Offer 2</button>
<button class="form-button" data-discount="44">Offer 3</button>
<button class="form-button" data-discount="55">Offer 4</button>
</div>
</div>

You have defined two functions called getDiscount, it would be better to let them have different name
function init(){
var buttons = document.querySelectorAll(".form-button");
buttons.forEach(function (item, index) {
item.addEventListener('click', function(){
var discount = getDiscount(this);
let span = document.querySelector('.discount-amount')
span.innerHTML = '<strong>' + discount+ '</strong>%'
//span.innerHTML =discount.bold()+ '%' // we can use bold() instead
});
});
function getDiscount(clicked_element) {
var val = clicked_element.getAttribute("data-discount");
return val;
}
};
init()
<div><span class="discount-amount"><strong>55</strong>%</div>
<div class="offers">
<button class="form-button" data-discount="38">Offer 1</button>
<button class="form-button" data-discount="50">Offer 2</button>
<button class="form-button" data-discount="22">Offer 3</button>
<button class="form-button" data-discount="88">Offer 4</button>
</div>
Update:
for your updated question,since it has multiple button groups and divs,so we need to sepereate them correctly.
One solution is to using index,change
let span = document.querySelector('.discount-amount')
to
let span = document.querySelectorAll('.discount-amount')[Math.floor(index/4)]
In my opinios,the best way is to let them have different id or class,so that we can query them easily.
function init(){
var buttons = document.querySelectorAll(".form-button");
buttons.forEach(function (item, index) {
item.addEventListener('click', function(){
var discount = getDiscount(this);
let span = document.querySelectorAll('.discount-amount')[Math.floor(index/4)]
span.innerHTML = '<strong>' + discount+ '</strong>%'
//span.innerHTML =discount.bold()+ '%' // we can use bold() instead
});
});
function getDiscount(clicked_element) {
var val = clicked_element.getAttribute("data-discount");
return val;
}
};
init()
<div class="discount__Topics">
<div><strong class="discount-amount">50</strong>%</div>
<div class="offers">
<button class="form-button" data-discount="38">Offer 1</button>
<button class="form-button" data-discount="50">Offer 2</button>
<button class="form-button" data-discount="22">Offer 3</button>
<button class="form-button" data-discount="88">Offer 4</button>
</div>
</div>
<div class="discount__Topics">
<div><strong class="discount-amount">60</strong>%</div>
<div class="offers">
<button class="form-button" data-discount="12">Offer 1</button>
<button class="form-button" data-discount="32">Offer 2</button>
<button class="form-button" data-discount="44">Offer 3</button>
<button class="form-button" data-discount="55">Offer 4</button>
</div>
</div>

If I understand your question correctly, you are looking for something like this.
var buttons = document.querySelectorAll(".form-button");
var discountRef = document.querySelector(".discount-amount");
function setDiscount(pointerEvent) {
// get the clicked button from the pointerEvent
var discount = pointerEvent.target.dataset.discount
// add the discount to <span class="discount-amount"></span>
discountRef.innerText = discount
}
buttons.forEach(function (item) {
item.addEventListener('click', setDiscount);
});
Let me know if this helped you out!

Related

Vanilla JS not(this)

I am looking for an easy and clean Vanilla JS solution for this jQuery code:
$(this).addClass('highlighted');
$('button').not(this).removeClass('highlighted');
When I click a specific button element, it should add the class 'highlighted', all the other button elements not(this) should have the highlighted class removed.
If your buttons have IDs, using them would be a good solution. Otherwise, you can simply filter the results from querySelectorAll:
Using ids:
function highlight(event) {
const target = event.target;
target.classList.add('highlighted');
document.querySelectorAll(`button:not(#${target.id})`).forEach(item => item.classList.remove('highlighted'));
}
.highlighted {
background: pink
}
<button id="btn1" onclick="highlight(event)">Button 1</button>
<button id="btn2" onclick="highlight(event)">Button 2</button>
<button id="btn3" onclick="highlight(event)">Button 3</button>
<button id="btn4" onclick="highlight(event)">Button 4</button>
Filtering the results:
function highlight(event) {
const target = event.target;
target.classList.add('highlighted');
Array.from(document.querySelectorAll(`button`)).filter(item => item != target).forEach(item => item.classList.remove('highlighted'));
}
.highlighted {
background: pink
}
<button onclick="highlight(event)">Button 1</button>
<button onclick="highlight(event)">Button 2</button>
<button onclick="highlight(event)">Button 3</button>
<button onclick="highlight(event)">Button 4</button>
If you remove the highlighted class from all buttons first, you can add it afterward to the only highlighted button.
const stripHighlighted = (button) => {
button.classList.remove("highlighted");
}
document.querySelectorAll("button").forEach(stripHighlighted);
this.classList.add("highlighted");

How to optimize code that shows one block and hides others?

I have 3 blocks, when opening one, all should hide. I wrote the simplest code (I'm a beginner), I understand that it can and should be optimized. How can I do that?
I'm thinking of using "if else" construction, but not sure how to do it correctly.
function openLink(){
document.getElementsByClassName('open_link')[0].style.display = 'block';
document.getElementsByClassName('open_images')[0].style.display = 'none';
document.getElementsByClassName('open_video')[0].style.display = 'none';
}
function openImages(){
document.getElementsByClassName('open_images')[0].style.display = 'block';
document.getElementsByClassName('open_link')[0].style.display = 'none';
document.getElementsByClassName('open_video')[0].style.display = 'none';
}
function openVideo(){
document.getElementsByClassName('open_video')[0].style.display = 'block';
document.getElementsByClassName('open_images')[0].style.display = 'none';
document.getElementsByClassName('open_link')[0].style.display = 'none';
}
function closeForm(){
document.getElementsByClassName('open_link')[0].style.display = 'none';
document.getElementsByClassName('open_images')[0].style.display = 'none';
document.getElementsByClassName('open_video')[0].style.display = 'none';
}
<a onclick="openLink()" href='#'>One</a>
<a onclick="openVideo()" href='#'>Two</a>
<a onclick="openImages()" href='#'>Three</a>
<div class="open_link" style="display: none;">
<button onclick="closeForm()">Save 1</button>
<button onclick="closeForm()">Close 1</button>
</div>
<div class="open_video" style="display: none;">
<button onclick="closeForm()">Save 2</button>
<button onclick="closeForm()" >Close 2</button>
</div>
<form class="open_images" style="display: none;">
<input onclick="closeForm()" value="Upload 3"/>
<button onclick="closeForm()" >Close 3</button>
</form>
Delegate
Here is a start
const content = document.getElementById("content");
document.getElementById("nav").addEventListener("click", function(e) {
const tgt = e.target;
const id = tgt.dataset.id;
[...content.querySelectorAll("div")].forEach(div => {
if (div.id !== id) div.classList.add("hide");
})
document.getElementById(id).classList.remove("hide");
})
content.addEventListener("click", function(e) {
const tgt = e.target;
if (tgt.classList.contains("close")) {
tgt.closest("div").classList.add("hide")
}
})
.hide {
display: none;
}
<div id="nav">
<a data-id="link" href='#'>One</a>
<a data-id="video" href='#'>Two</a>
<a data-id="images" href='#'>Three</a>
</div>
<div id="content">
<div id="link" class="hide">
<button type="button" id="save1">Save 1</button>
<button type="button" class="close">Close 1</button>
</div>
<div id="video" class="hide">
<button type="button" id="save2">Save 2</button>
<button type="button" class="close">Close 2</button>
</div>
<div id="images" class="hide">
<form>
<input id="upload" value="Upload 3" />
<button type="button" class="close">Close 3</button>
</form>
</div>
</div>
You can sum up some of your redundant code into one function and pass parameters to it.
function openAndClose(classBlock, classNone, classNone1) {
document.getElementsByClassName(classBlock)[0].style.display = 'block';
document.getElementsByClassName(classNone)[0].style.display = 'none';
document.getElementsByClassName(classNone1)[0].style.display = 'none'
}
function closeForm(){
document.getElementsByClassName('open_link')[0].style.display = 'none';
document.getElementsByClassName('open_images')[0].style.display = 'none';
document.getElementsByClassName('open_video')[0].style.display = 'none';
}
<a onclick="openAndClose('open_link', 'open_images', 'open_video')" href='#'>One</a>
<a onclick="openAndClose('open_video', 'open_images', 'open_link')" href='#'>Two</a>
<a onclick="openAndClose('open_images', 'open_link', 'open_video')" href='#'>Three</a>
<div class="open_link" style="display: none;">
<button onclick="closeForm()">Save 1</button>
<button onclick="closeForm()">Close 1</button>
</div>
<div class="open_video" style="display: none;">
<button onclick="closeForm()">Save 2</button>
<button onclick="closeForm()" >Close 2</button>
</div>
<form class="open_images" style="display: none;">
<input onclick="closeForm()" value="Upload 3"/>
<button onclick="closeForm()" >Close 3</button>
</form>
Try this but with your own ids and classes
.open are the div to open
id of the target is id of your div, you did this with classes
document.querySelectorAll(".open").forEach(div => {
div.onclick = (e) => {
switch (e.target.id) {
case "open_link":
openLink()
break;
case "open_video":
openVideo()
break;
case "open_images":
openImages()
break;
}
}
})

Upwards Transverse in Javascript DOM

I want to transverse upwards in javascript. like if i give input an element it will show all its parent elements till html tag but its not working like that. It only shows DIV,BODY,HTML.
function Transverse(p) {
var path = "";
var A = [];
var element = document.querySelector(document.getElementById(p).nodeName);
path = element.parentElement;
while (path) {
A.push(path);
path = path.parentElement;
}
console.log(A);
}
<div>
<button id="btn1" onclick="Transverse('btn1')">button 1</button>
<ul>
<button id="btn2" onclick="Transverse('btn2')">button 2</button>
<li>
<button id="btn3" onclick="Transverse('btn3')">button 3</button>
</li><br>
<section>
<a href="#">
<button id="btn4" onclick="Transverse('btn4')">button 4</button>
</a>
</section>
</ul>
<ol>
<li>
<h1>End of Page</h1>
<button id="btn5" onclick="Transverse('btn5')">Button 5</button>
</li>
</ol>
</div>
Thanks all it is working now ! I did the following Changes
function Transverse(p){
var A=[];
var element = document.getElementById(p);
var path=element.parentElement;
while(path){
A.push(path.nodeName);
path=path.parentElement;
}
console.log(A);
}

Display none if child and parent element have the same class

I have these menus around my horizontal scrolling site.
<section class="fun-stuff portfolio-cards" id="slide-1">
<div class="nav-list">
<button class="about">ABOUT</button>
<button class="fun-stuff">FUN STUFF</button>
<button class="home">HOME</button>
<button class="professional">PROFESSIONAL</button>
<button class="contact">CONTACT</button>
</div>
</section
The goal is to filter them based if the button classes have the same class as the ones in the section. If they have the same class (in this example 'fun-stuff') then that button will display:none.
My jQuery. I feel I'm close or totally over-complicating it.
jQuery(document).ready(function($) {
var theList = $('.nav-list button');
var i;
for (i=0; i < theList.length; i++){
var theButtons = '"' + theList[i].className + '"';
var parentClassName = theList[i].closest('section').className;
// tried this one. Was close i believe but no dice
if(theButtons = theList[i].closest('section').hasClass('"' + theButtons + '"') ){
// display that button as none
}
// tried this as well and for each button got 'no' in the console
if( $(theList[i].closest('section') ).hasClass(theButtons) ){
console.log('yes');
} else {
console.log ('no');
}
}
});
Yes you overdid it somewhat
$(function() {
$("button").each(function() {
var $parent = $(this).closest("section"), // the section wrapping the button
same = $parent.hasClass($(this).attr("class")); // parent has this button's class too
$(this).toggle(!same); // hide if the same (show if not)
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section class="fun-stuff portfolio-cards" id="slide-1">
<div class="nav-list">
<button class="about">ABOUT</button>
<button class="fun-stuff">FUN STUFF</button>
<button class="home">HOME</button>
<button class="professional">PROFESSIONAL</button>
<button class="contact">CONTACT</button>
</div>
</section>
If you have more than one class on the button and you want to hide if one of them matches
$(function() {
$("button").each(function() {
var bList = this.classList,
parentList = $(this).closest("section")[0].classList, // the DOM element's classList
same = [...parentList] // convert to iterable
.filter(ele => bList.contains(ele)) // look up parent class in button classList
.length>0; // found?
$(this).toggle(!same);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section class="fun-stuff portfolio-cards" id="slide-1">
<div class="nav-list">
<button class="about">ABOUT</button>
<button class="fun-stuff bla">FUN STUFF</button>
<button class="home">HOME</button>
<button class="professional">PROFESSIONAL</button>
<button class="contact">CONTACT</button>
</div>
</section>
You can turn the section classes into a regular array, then filter and hide the buttons.
jQuery(document).ready(function($) {
var classes = $('#slide-1').attr("class").split(/\s+/);
classes.forEach(function (cls) {
$('.nav-list button').filter('.' + cls).hide()
})
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section class="fun-stuff portfolio-cards" id="slide-1">
<div class="nav-list">
<button class="about">ABOUT</button>
<button class="fun-stuff">FUN STUFF</button>
<button class="home">HOME</button>
<button class="professional">PROFESSIONAL</button>
<button class="contact">CONTACT</button>
</div>
</section>
You can do this pretty easily with vanilla Javascript:
const classNames = document.getElementById("slide-1").classList;
document.querySelectorAll(".nav-list > button").forEach((el) => {
if(classNames.contains(el.classList)){
el.style.display = "none";
}
});
<section class="fun-stuff portfolio-cards" id="slide-1">
<div class="nav-list">
<button class="about">ABOUT</button>
<button class="fun-stuff">FUN STUFF</button>
<button class="home">HOME</button>
<button class="professional">PROFESSIONAL</button>
<button class="contact">CONTACT</button>
</div>
</section>
Edit: Done with two lines of code:
const classList = document.getElementById("slide-1").classList;
document.querySelectorAll(".nav-list > button").forEach(el => el.style.display = classList.contains(el.classList) ? "none": "initial");
<section class="fun-stuff portfolio-cards" id="slide-1">
<div class="nav-list">
<button class="about">ABOUT</button>
<button class="fun-stuff">FUN STUFF</button>
<button class="home">HOME</button>
<button class="professional">PROFESSIONAL</button>
<button class="contact">CONTACT</button>
</div>
</section>

How to know the button pressed among buttons in the div in Javascript

I have a div of 4 buttons, when I click on any button it redirects to the same page for all the buttons, I want to know which button the user has pressed before going to the next page, I've been trying, but couldn't find that.
Here is my code :
$( "#buttons" ).click(function() {
alert('button');
window.location.href = "score.html";
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id="countdown"></p>
<div id="buttons">
<button type="button" id="button1">button 1</button>
<button type="button" id="button2">button 2</button>
<button type="button" id="button3">button 3</button>
<button type="button" id="button4">button 4</button>
</div>
Do you have any idea
The element that the click started in is available as target on the event object passed into your handler, so (but see more below):
// Accept the event arg -------v
$( "#buttons" ).click(function(e) {
alert('button: ' + e.target.id); // <=== Use e.target.id to get its ID
// window.location.href = "score.html"; (commented out for live demo)
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id="countdown"></p>
<div id="buttons">
<button type="button" id="button1">button 1</button>
<button type="button" id="button2">button 2</button>
<button type="button" id="button3">button 3</button>
<button type="button" id="button4">button 4</button>
</div>
Note that that will do the alert whenever there's a click inside the #buttons div, even if it's not on a button. If you only want clicks on the buttons, you can use a selector with .on to only call you when the click went through a button. It will call your handler as though you had hooked the handler directly to the buttons, even though in fact you've hooked it to the #button div, and so we use this.id for the ID:
$( "#buttons" ).on("click", "button", function() {
alert('button: ' + this.id);
// window.location.href = "score.html"; (commented out for live demo)
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id="countdown"></p>
<div id="buttons">
<button type="button" id="button1">button 1</button>
<button type="button" id="button2">button 2</button>
<button type="button" id="button3">button 3</button>
<button type="button" id="button4">button 4</button>
</div>

Categories

Resources