I have some data fetched and they all have the same buttons for opening modal, but each modal should have content about that specific item that has been clicked.
Button is shown on all items in the row, but when I click it it opens modal only on the first item in the row.
I have simple button in HTML
// this is part of fetched items in a row, each item has this button
<div>
<button id="openUniqueModal">
BUTTON
</button>
</div>
And open function in JS
let openUniqueModalBtn = document.getElementById('openUniqueModal');
if (openUniqueModalBtn != null) {
document.getElementById(
'openUniqueModal'
).onclick = function () {
modal.style.display = 'block';
};
.....
.....
How can I achieve that each button item in row will get triggered onclick? Do I have to loop through it in JS code?
EDIT:
another approach
<button class="openUniqueModal">BUTTON</button>
document
.querySelectorAll('.openUniqueModal')
.addEventListener('click', (event) => {
myModal.style.display = 'block';
});
You don't need to attach event listener to every button instead you can use add a common class to add buttons and then add listener just once
document.querySelector('.btn').addEventListener('click', (event) => {
// you can check button id and take different actions if needed
// event.target.id
});
you can use Zohaib Ijaz's answer and you can even add a wild card if you want to the '.btn' phrase.
[id^='openUniqueModal'] will match all ids starting with openUniqueModal.
[id$='openUniqueModal'] will match all ids ending with openUniqueModal.
[id*='openUniqueModal'] will match all ids containing openUniqueModal.
Please don't use duplicate ids on elements. as button 'openUniqueModal' will be duplicated in your dom for each row as there will be no increment on the id.
Having elements with the same id will cause lots of problems when it comes to industrial.
if you're using jquery you use the below function,
$( "#openUniqueModal" ).on( "click", function() {
// your desired functionality here
// use $( this ) to access current element
});
*I would've added this as a comment in Zohaib Ijaz's answer but I don't have enough permission.
Related
I'm working on a web-app in HTML and JS and I need to catch the clicks on each listItem of a list.
The list is dynamically created in a for-loop as follows:
var i = document.createElement("li");
i.innerHTML = "something"
uList.appendChild(i);
How can I make listItems clickable or catch clicks on each of them separately (get the specific item clicked)?
I've tried adding an eventListener on the list, and then isolate the target of the event (click). The problem is that this would count as many clicks as the size of the list.
Bind the onclick listener to the new element.
i.onclick = () => {
console.log('hi');
};
I am making a chrome extension, in which I am adding an item in the list and it has a button to delete the item.
It performs its function as intended but is giving an error in the extension panel.
Uncaught TypeError: Cannot read property 'style' of null
For line : li.style.display = "none";
Upon adding alert in the function, I see that when any of the delete button is clicked first the intended index is alerted and in some cases, -1 is also alerted.
Code which is adding the item and has the delete functionality as well :
function addItem(value){
var li = document.createElement("LI");
var para = document.createElement("P");
var deleteButton = document.createElement("BUTTON"); // Create a <p> node
var t = document.createTextNode(value); // Create a text node
deleteButton.className = "delete";
para.appendChild(t);
li.appendChild(para);
li.appendChild(deleteButton);
textList.appendChild(li);
$(".delete").click(function () {
var index = $(this).index(".delete");
alert(index); //This alert sometimes gives -1
var li = this.parentElement;
li.style.display = "none";
removeItem(index); //This function just removes it from chrome local storage
$(".delete").eq(index).remove();
})
}
Code not posted just initializes list and add item upon button click.
What could be the reason for this -1 index being triggered and how can it be fixed?
When you do this: $(".delete").click(...
...you're adding a click callback to every delete button that exists at the time you execute that code, including the delete buttons that already exist, not just the individual delete button you just created.
After you've added three items, for example, the first item's delete button will have three click callbacks, the second will have two click callbacks, and the third will have one.
When you delete the first item, it will smoothly delete once, then twice give you the -1 error, because it has already deleted itself and won't be found.
I think if you change the code like this:
$(deleteButton).click(...
...that should fix the problem.
The issue is because you're attaching multiple event handlers to the existing .delete buttons every time you add a new row.
A better approach is to use a single delegate event handler for them all. Also note that you can make the code more succinct by using jQuery, as you already have a reference to it in the page. Try this:
function addItem(value) {
$(textList).append(`<li><p>${value}</p><button class="delete"></button></li>`);
}
jQuery($ => {
$(textList).on('click', '.delete', function() {
let $button = $(this);
removeItem($button.index('.delete'));
$button.closest('li').remove();
});
});
I have a table. Each column has a button at the top. If the td elements below within the column have content in them, then hide the button. If not then display the button and onClick add class active too the td element.
$(document).ready(function (){
$('.button-fill').on("click", function() {
var i=$(this).parent().index();
if($(this).closest("tr").siblings().find("td:eq("+i+")").text()=="")
$(this).hide();
else
$(this).show();
});
<!-- Fill in the td -->
$('.button-fill').on("click", function() {
var i=$(this).parent().index();
$(this).closest("tr").siblings().find("td:eq("+i+")").addClass("active");
//});
});
});
http://jsfiddle.net/ujw0u6au/
I've created a jsfiddle. I don't know what i'm doing wrong? Thank you
Since you have bind the button toggle logic inside button click - you will always have the button in the starting. When you will click on the button only then it will first hide the button and then make the content active.
In case you want this behavior in the starting as soon as the page loads, you should change below line (the 2nd line in your code) from your code -
$('.button-fill').on("click", function() {
to
$('.button-fill').each( function(i,e) {
also, you should not use <!-- Fill in the td --> style of commenting in JavaScript.
I can see you are having two "click" event handler on same class. Instead of it, you can merge it as well.
Here is the optimized version of your code :
JavaScript :
$(document).ready(function (){
$('.button-fill').on("click", function() { //Only one click event handler
var $this = $(this);
var i=$this.parent().index();
var $trSibling = $this.closest("tr").siblings();
$this.toggle($trSibling.find("td:eq("+i+")").addClass("active").text() != ""); //adds the class as well and check the text as well.
})
$(".button-fill").trigger("click");
// explicitly clicking on button to make sure that initially button should not be shown if column text is not empty
});
JSFiddle link : http://jsfiddle.net/ujw0u6au/1/
Is this the same what you want?
#Vijay has the right answer, but as a side note, you need to change this:
if($(this).closest("tr").siblings().find("td:eq("+i+")").text()=="")
to this
if($(this).closest("tr").siblings().find("td:eq("+i+")").text()!="")
if you want to hide the button when there is content, instead of the other way around (notice the != near the end).
I am using jQuery to dynamically add elements every time a user clicks a link (".add-event"). Also included in this element is a icon to remove the entire element if the user chooses. I want to hide or disable this remove icon if the element is the last left on the page. This is what I have tried so far:
$(document).on('click','.close_box2:only-child',function(){
event.preventDefault();
});
AND
if( $('.event').length===1) {
$('.close_box2').hide()
}
HTML:
<div class="event">
<span class="close_box2"><i class="icon-remove"></i></span>
<span class="add-event">Add Event</span>
</div>
What am I doing wrong!? Thanks
JSFiddle: http://jsfiddle.net/TrueBlueAussie/KPY9r/6/
You just want to check for the "last one" inside the delete handler:
// initial hide of sole close button
$('.close_box2').hide();
// On add, clone the template and show all close buttons
$(document).on('click', '.add-event', function () {
// Create a new event based on the template
$('#events').append($('#template').html());
// Show all close buttons (as we must now have > 1 event)
$('.close_box2').show();
});
$(document).on('click', '.close_box2', function (e) {
$(this).closest('.event').remove();
// Is there only one left?
if ($('.event').length === 1) {
// Hide the close box on the last event
$('.close_box2').hide()
}
});
Notes:
I use a dummy <script> element to hold you HTML template. This is better than cloning an element on the page and much better than inline HTML strings in your code.
The following looks better regarding performance:
$('.close_box2:only-child').on('click', function(event){
event.preventDefault();
});
I am adding the form my current list in a div box at the bottom of the table.
I am appending the div box when someone clicks on add button.
But when i click add button multiple times , then many div boxes are appended.
Is there any way that no matter how many times I click the button, only one instance gets append to div box.
This is my code
$var = $(this).parent().parent();
$var.append($('.jq_div')[0].outerHTML);
attach your listener using .one().
$("button").one('click', function(){
// Your code
});
Read more: http://api.jquery.com/one
This is under the assumption that you're using jQuery 1.7+
One simple solution would be having a boolean flag that you can toggle once your button is clicked. Additionally, there is actually a jQuery function that provides this exact functionality.
It's called one() -
Attach a handler to an event for the elements. The handler is executed
at most once per element.
So your code would look something like this -
$("#someTrigger").one('click', function(){
$var = $(this).parent().parent();
$var.append($('.jq_div')[0].outerHTML);
});
The boolean method is also very simple -
var wasClicked = false;
$("#someTrigger").on('click', function(){
if (wasClicked == false){
// append your form
wasClicked = true;
}
});
Reference -
one()