select nested data-click within data-template - javascript

My template involving parent div with attribute of data-template and child button with attribute of data-click:
<script type="text/html" id="containerTemplate">
<div data-template="myTemplate">
<ul>
<li>
<button type="button" data-click="done">
<span>some text</span>
</button>
</li>
</ul>
</div>
</script>
How can i select the button with the data-click="done"?
I've tried this
const doneBtn = document.querySelector('[data-template = myTemplate] [data-click = done]');
if (doneBtn) {
//register some event listeners
}
But the doneBtn is returning null.

You put your html code in javascript tags that's why javascript was unable to access your html DOM. Try below code it will work.
<div data-template="myTemplate">
<ul>
<li>
<button type="button" data-click="done">
<span>some text</span>
</button>
</li>
</ul>
</div>
<script type="text/javascript">
const doneBtn = document.querySelector('[data-template = myTemplate] [data-click = done]');
if (doneBtn) {
//register some event listeners
console.log($(doneBtn).html());
}
</script>

Related

finding closest sibling in jQuery

I have the following code in HTML:
$(".remove-post").click((event) => {
$(event.target).fadeOut();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="side-bar">
<button class="remove-post"> delete </button>
<a class="list">
<p>post title</p>
</a>
<button class="remove-post"> delete <button>
<a class="list"><p>another post title</p></a>
</div>
every time that I click on a delete button I want to delete the closest "a" tag with the paragraph inside it as well as the delete button by itself. I was able to delete the button but can't target the closest a tag to that clicked button
I wrote it in jQuery
If the button will always stay before paragraph you can do:
$(".remove-post").on("click", function () {
$(this).next(".list").fadeOut()
$(this).fadeOut()
})
I would recommend you to wrap the paragraph and the button together like:
<div class="side-bar">
<div class="wrapper">
<button class="remove-post">Delete<button>
<a class="list">Another post title</a>
</div>
<div class="wrapper">
<button class="remove-post">Delete <button>
<a class="list">Another post title</a>
</div>
</div>
If you do so, then you can use this:
$(".remove-post").on("click", function () {
$(this).parent().fadeOut()
})
Assuming you want to remove the next a.list sibling, use .next()
$(".remove-post").on("click", function() {
const btn = $(this)
btn.add(btn.next("a.list")).fadeOut()
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="side-bar">
<button class="remove-post">delete</button>
<a class="list"><p>post title</p></a>
<button class="remove-post">delete</button>
<a class="list"><p>another post title</p></a>
</div>
jQuery's .add() is used here to collect both the <button> and <a> so you can fade them out together.

Need to click twice to add/remove a Class with Javascript

I read some of the answers here similar to my question, but I still don't understand what's going on.
I have this JS snippet:
function renderButtons() {
let buttonCollection = document.getElementsByClassName("btn");
let arrayOfBtn = [...buttonCollection];
arrayOfBtn.forEach(function(element) {
function modifyClass() {
element.classList.toggle("active");
}
element.addEventListener("click", modifyClass);
})
}
That is meant to add/remove the class "active" of a button when I click on it.
This is the HTML:
<div class="panel controls">
<ul>
<li>
<button class="btn btn-pepperonni active">Pepperonni</button>
</li>
<li>
<button class="btn btn-mushrooms active">Mushrooms</button>
</li>
<li>
<button class="btn btn-green-peppers active">Green peppers</button>
</li>
<li>
<button class="btn btn-sauce active">White sauce</button>
</li>
<li>
<button class="btn btn-crust active">Gluten-free crust</button>
</li>
</ul>
</div>
And it works, the problem is that I have to click twice each time on the button to add or remove the class of that button in particular.
Any help will be very appreciated.
Thank you very much!
EDIT:
Remove your RenderButtons function and instead toggle the "active" class once you click the button like this on every ingredient:
document.querySelector('.btn.btn-pepperonni').onclick = function() {
state.pepperonni = !state.pepperonni;
renderEverything()
this.classList.toggle("active");
}
Basically what you do is you call two onclick events on the button and they do not work together.
Also you are over complicating the whole thing with your RenderButtons Functions :)
Hope that helps!
Your JS must be loaded at the end of your HTML. Your HTML will load the content from TOP to BOTTOM. So your Scirpt want to access "btn" elements, which are at the moment not genereted.
First HTML, then JS.
For such a short function, you could use a inline function as below.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body>
<div class="panel controls">
<ul>
<li>
<button class="btn btn-pepperonni active">Pepperonni</button>
</li>
<li>
<button class="btn btn-mushrooms active">Mushrooms</button>
</li>
<li>
<button class="btn btn-green-peppers active">Green peppers</button>
</li>
<li>
<button class="btn btn-sauce active">White sauce</button>
</li>
<li>
<button class="btn btn-crust active">Gluten-free crust</button>
</li>
</ul>
</div>
</body>
<script>
var buttonCollection = document.getElementsByClassName("btn");
for (var i = 0; i < buttonCollection.length; i++)
{
buttonCollection[i].addEventListener("click", function(){
this.classList.toggle("active");
});
}
</script>
</html>
As previous answers have shown how to fix your original code I have tried to find a simplified version of what you want to do.
In my solution I am using a "delegated event binding": the click event is bound to the parent <div> element and fires only when the actual click target is of class btn. This approach will work on elements that have not even been created at the time of the binding. And it is more "lightweight", as there is only one binding.
document.querySelector("div.panel.controls")
.addEventListener("click",function(ev){
var cl=ev.target.classList;
if (cl.contains("btn")) cl.toggle("active");
});
.active {background-color: #fcc}
<div class="panel controls">
<ul>
<li>
<button class="btn btn-pepperonni active">Pepperonni</button>
</li>
<li>
<button class="btn btn-mushrooms active">Mushrooms</button>
</li>
<li>
<button class="btn btn-green-peppers active">Green peppers</button>
</li>
<li>
<button class="btn btn-sauce active">White sauce</button>
</li>
<li>
<button class="btn btn-crust active">Gluten-free crust</button>
</li>
</ul>
</div>

JS button only firing on first element

I created a button that changes text upon clicking. However, the action only works for the first button on the page. Any button further down in the code, that has the same action, doesn't work. How do I change the JS so that it allows for multiple firings of the event?
Thanks!
HTML:
<div class="addtocart">
<a href="#" class="add-to-cart">
<div class="pretext">
ADD TO CART
</div>
</a>
<div class="pretext done">
<div class="posttext"><i class="fas fa-check"></i> ADDED</div>
</div>
</div>
JS:
<script>
const button = document.querySelector(".addtocart");
const done = document.querySelector(".done");
console.log(button);
let added = false;
button.addEventListener("click", () => {
if (added) {
done.style.transform = "translate(-110%) skew(-40deg)";
added = false;
} else {
done.style.transform = "translate(0px)";
added = true;
}
});
</script>
I think what you want is to select all button elements. Using querySelectorAll.
This will return an array of DOM elements matching the query. Then you loop through and add the event listener to each.
What the above code does is, select the first instance of a DOM element with .addtocart, not every instance, then adds the event listener.
Here is example of working code. You need to use this keyword to get what you want.
<div class="addtocart">
<a href="#" class="add-to-cart" id="addToCardItem1" onclick="addToCart(this)">
<div class="pretext">
ADD TO CART
</div>
</a>
</div>
<div class="addtocart" id="addToCardItem1" onclick="addToCart(this)">
<a href="#" class="add-to-cart">
<div class="pretext">
ADD TO CART
</div>
</a>
</div>
<script>
function addToCart(elem) {
alert(elem.id);
}
</script>

First To-do-list with querySelectorAll [duplicate]

This question already has answers here:
Adding click event listener to elements with the same class
(5 answers)
Closed 4 years ago.
I have some problems with querySelectorAll. Script is working only with querySelector, but it deletes only first li. When I try to replace querySelector with querySelectorAll to make all delete buttons work there is error - "deleteButton.addEventListener is not a function".
html:
body>
<div id="buttons">
<input type="text" placeholder="twoje zadanie...">
<button type="submit" class="add">dodaj</button>
</div>
<div id="tasks">
<ul>
<li><button class="done">done</button>
asd
<button class="delete">x</button></li>
<li>
<button class="done">done</button>
asdd
<button class="delete">x</button></li>
<li>
<button class="done">done</button>
dsad
<button class="delete">x</button></li>
</ul>
</div>
<script src="script.js"></script>
</body>
js:
var deleteButton = document.querySelectorAll('.delete');
deleteButton.addEventListener('click', function() {
var li = document.querySelector('li');
li.classList.add('li-delete');
});
Reason: Coz querySelectorAll get you the list of matching nodes. And there is no .addEve.. property that you can use on list.
Moreover, document.querySelector('.delete'); will get you the first button and will only add listener to the this button but you don't want.
If you want to add listeners to all of the elements you should loop through the list and add a listener on all of the matched elements. Like
var el = document.querySelectorAll('.delete');
for(var i=0; i<el.length; i++){
el[i].addEventListener('click', function(){
console.log("clicked");
var li = this.parentNode;
li.classList.add('li-delete');
})
}
.li-delete{
color : red;
}
<div id="tasks">
<ul>
<li><button class="done">done</button>
asd
<button class="delete">x</button></li>
<li>
<button class="done">done</button>
asdd
<button class="delete">x</button></li>
<li>
<button class="done">done</button>
dsad
<button class="delete">x</button></li>
</ul>
</div>
addEventListener on NodeList
You have to iterate through each node and attach the event listener if you want to use .querySelectorAll to select your elements.
It looks like you might be new to working with the DOM in JavaScript. If that's the case, I'd recommend taking a look at jQuery. It's not a lightweight library, but it makes many of these things much easier.
2 Problens in your code.
First querySelectorAll will return an array of all the elements that match the query. I added a console.log(deleteButtons), so you can see what thequerySelectorAll`` is generating. You will need a loop to add the event listener to each of the elements in the array.
Second, you can use this to get the button that trigger the event and then go get their parent <li> using the js .parentNode
Hope this helps :)
var deleteButton = document.querySelectorAll('.delete');
console.log(deleteButton);
for(let i=0; i<deleteButton.length;i++){
deleteButton[i].addEventListener('click', function() {
var li = this.parentNode;
li.classList.add('li-delete');
})
};
.li-delete {display:none;}
<div id="buttons">
<input type="text" placeholder="twoje zadanie...">
<button type="submit" class="add">dodaj</button>
</div>
<div id="tasks">
<ul>
<li><button class="done">done</button>
asd
<button class="delete">x</button></li>
<li>
<button class="done">done</button>
asdd
<button class="delete">x</button></li>
<li>
<button class="done">done</button>
dsad
<button class="delete">x</button></li>
</ul>
</div>
<script src="script.js"></script>

Show multiple <div> on click JavaScript

I am trying to add some code to a page that keeps adding <div> sections to a page when a link is clicked. Here's my code:
<script type="text/javascript">
function ShowDiv() {
document.getElementById("show").style.display = "";
}
</script>
<p><a href="#" class="control" onclick="ShowDiv()"; >Add New</a></p>
<div id="show" style="display: none;">
<p>This is the div!</p>
</div>
This works great for one <div> but I need it to keep adding down the page when the link is clicked. I t is going to be used to hold a form with an array of ids for posting to PHP.
You can clone original div (which will be as template) and append cloned one to the page:
Fiddle.
HTML:
<p>
<a id="add" href="#" class="control">Add New</a>
</p>
<div id="show" style="display: none;">
<p>This is the div!</p>
</div>
JS:
$(document).ready(function()
{
var i = 0;
$('#add').click(function()
{
var newEl = $('#show').clone();
newEl.attr('id', "show" + i);
i++;
newEl.show().appendTo("body");
});
});
<script type="text/javascript">
function ShowDiv() {
var a = $("#show").clone(true); // clones element
$(".test").append(a); // appends to parent
}
</script>
<p><a href="#" class="control" onclick="ShowDiv()"; >Add New</a></p>
<div class="test"> <!-- defines parent for simple selection -->
<div id="show"> <!-- element to clone -->
<p>This is the div!</p>
</div>
</div>

Categories

Resources