How can I run an event on dynamically added elements, because my click event doesn't work on new elements.
I found some answer in here but all about jQuery so I'm coding with vanilla javascript. So do you have any advice ?
document.querySelectorAll('.galeri-cart').forEach(function (cart) {
cart.addEventListener('click', function () {
// something awesome happening in here
})
});
creating element codes;
success: function () {
let imageData = JSON.parse(this.files[i].xhr.response);
let img = document.createElement('img');
img.setAttribute('src', imageData.url);
img.setAttribute('data-id',imageData.id);
img.setAttribute('alt', imageData.alt);
let subDiv = document.createElement('div');
subDiv.className = "galeri-cart";
subDiv.appendChild(img);
let midDiv = document.createElement('div');
midDiv.className = "col-md-4";
midDiv.appendChild(subDiv);
let div = document.querySelector('.row');
div.insertBefore(midDiv, div.childNodes[0]);
i++
}
Since you are adding the elements to the DOM manually, you can simply attach the event listener after you create the element and before you append it to the DOM, like so:
function galeriClickHandler () {
// something awesome happening in here
}
success: function () {
let imageData = JSON.parse(this.files[i].xhr.response);
let img = document.createElement('img');
img.setAttribute('src', imageData.url);
img.setAttribute('data-id',imageData.id);
img.setAttribute('alt', imageData.alt);
let subDiv = document.createElement('div');
subDiv.className = "galeri-cart";
// add event listener here
subDiv.addEventListener('click', galeriClickHandler);
subDiv.appendChild(img);
let midDiv = document.createElement('div');
midDiv.className = "col-md-4";
midDiv.appendChild(subDiv);
let div = document.querySelector('.row');
div.insertBefore(midDiv, div.childNodes[0]);
i++
}
Alternatively, you can use event delegation on the static parent element and listen for clicks on specific children, like so:
function galeriClickHandler () {
// something awesome happening in here
}
// Get the parent DIV, add click listener...
document.querySelector(".row").addEventListener("click",function(e) {
// e.target was the clicked element
if (e.target && e.target.matches(".galeri-cart")) {
galeriClickHandler();
}
});
Since you didn't give any info on how you're adding the elements, the only direct code solution to give would be one that delegates the event handling to some container element.
var par = document.querySelector("#parent");
var button = document.querySelector("button");
button.addEventListener("click", function() {
par.insertAdjacentHTML("beforeend", `<p class=galeri-cart>cart ${getCarts().length+1}</p>`)
});
par.addEventListener('click', function(event) {
var cart = event.target.closest(".galeri-cart")
if (cart)
cart.textContent += " clicked!"
});
function getCarts() {
return par.querySelectorAll(".galeri-cart");
}
<button>Add Cart</button>
<div id=parent>
<p class=galeri-cart>cart 1</p>
<p class=galeri-cart>cart 2</p>
<p class=galeri-cart>cart 3</p>
</div>
You added your code. You're already adding attributes and properties to the element, so you just do what you're already doing... bind the handler.
Here's a rewrite that makes your code much more concise and readable.
First, create the event handler.
function clickHandler() {
// your handler code
}
Then create the element and bind the handler to it.
success: function() {
let imageData = JSON.parse(this.files[i].xhr.response);
let div = document.querySelector('.row');
div.insertAdjacentHTML("afterbegin", `
<div class="col-md-4">
<div class="galeri=cart">
<img src="${imageData.url}" data-id="${imageData.id}" alt="${imageData.alt}">
</div>
</div>`);
div.firstElementChild
.firstElementChild
.addEventListener("click", clickHandler);
i++;
}
Related
I have button that creates a div on click. I want to return this created div when I click a button. But the following code actually returns this button.
var create = $('#create').on('click', function(e){
var content = $('<div class="foo"/>')
return content
})
var test = create.trigger('click')
console.log(test)
Result is:
init [div#create, context: document, selector: '#create']
Is this not possible to do this this way or am I missing something?
No, it is not possible. You can add a function which will be executed in your event handler to do something with the object you create in the listener:
var create = $('#create').on('click', function(e){
var content = $('<div class="foo"/>')
doSomething(content)
})
create.trigger('click')
function doSomething(test) {
console.log(test)
}
There is no other way and it is because the handler function assigned with .on() method is called when the browser triggers an event (or you use .trigger() method) and the return statement is used only to force calling event.stopPropagation() and event.preventDefault() methods (you have to return false in the handler or just assign false instead of a function as an event handler - check the documentation, section The event handler and its environment) and not to return any value when you trigger an event manually.
You can also use an external variable to store the data "generated" in your event handler:
const divs = []
var create = $('#create').on('click', function(e){
var content = $('<div class="foo"/>')
divs.push(content)
doSomething()
})
create.trigger('click')
function doSomething() {
console.dir(divs)
}
You're calling a variable ("create") which stores the event listener on the button. This is what it looks like:
var test = $('#create').on('click', function(e){
var content = $('<div class="foo"/>')
return content
}).trigger('click')
console.log(test)
This is the solution:
jQuery
var create = function() {
return $('<div class="foo"/>');
};
var createEl = $('#create');
createEl.on('click', function() {
console.log(create());
// <div class="foo"></div>
});
createEl.trigger("click");
JavaScript
var create = function() {
var el = document.createElement('div');
el.className = "foo";
// Add other attributes if you'd like
return el;
};
var createEl = document.querySelector('#create');
createEl.addEventListener("click", function() {
console.log(create());
// <div class="foo"></div>
});
createEl.click();
(jQuery) Live example
var create = function() {
return $('<div class="foo"/>');
};
var createEl = $('#create');
createEl.on('click', function() {
console.log(create());
// <div class="foo"></div>
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<button id="create">Create</button>
(JavaScript) Live example
var create = function() {
var el = document.createElement('div');
el.className = "foo";
// Add other attributes if you'd like
return el;
};
var createEl = document.querySelector('#create');
createEl.addEventListener("click", function() {
console.log(create());
// <div class="foo"></div>
});
createEl.trigger("click");
var create = function() {
var el = document.createElement('div');
el.className = "foo";
// Add other attributes if you'd like
return el;
};
var createEl = document.querySelector('#create');
createEl.addEventListener("click", function() {
console.log(create());
// <div class="foo"></div>
});
<button id="create">Create</button>
I cant remove eventlistener in an array tag when I try a lot of thing but cant accomplished anything, so at last I prefer to write down here.. Please does anyone have any idea?
I create "a" tags and than I click on one of them than bacground colors start to change but than I want to stop when I push "end" button but the problem is it never stops always continue...
Here is What I tried yet.... (Please check it in big screen)
function myFunction() {
var btn = document.createElement("A");
btn.innerHTML = "CLICK ME TO START<br> EVENTLISTENER";
btn.style.marginLeft = "20px";
btn.className = "formulbitti boya ";
document.getElementById("kanban").appendChild(btn);
$(".formulbitti").click(function() {
index_valbas = $(".formulbitti").index(this)
$(".formulbitti").mouseover(function() {
index_val = $(".formulbitti").index(this)
elements = document.querySelectorAll('.formulbitti');
elements.forEach(element => {
element.addEventListener('mouseover', denemefunc(index_val, index_valbas, elements));
});
});
$(".sonlandir").click(function() {
elements = document.querySelectorAll('.formulbitti');
elements.forEach(element => {
element.removeEventListener('mouseover', denemefunc);
});
});
});
alert(deneme);
}
function denemefunc(index_val, index_valbas, elements) {
var classesName = $('.formulbitti')[index_val].className;
classlists = document.getElementsByClassName("formulbitti").length;
var i = 0;
while (i < classlists) {
document.getElementsByClassName("formulbitti")[i].style.backgroundColor = "rgba(255,255,255, 1)";
i = i + 1;
};
document.getElementsByClassName("formulbitti")[index_valbas].style.backgroundColor = "rgba(220, 220, 220, 1)";
var i = index_valbas;
while (i < index_val + 1) {
document.getElementsByClassName("formulbitti")[i].style.backgroundColor = "rgba(220, 220, 220, 1)";
i = i + 1;
};
alert(deneme);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>I can start eventlistener but cant finish it with </p>
<div id="kanban">
<button onclick="myFunction()">Try it</button>
</div>
<button class="sonlandir">end</button>
The main issue in your code is that you never actually add any event listeners. addEventListener() expects a function as second argument. Yet you pass denemefunc(index_val, index_valbas, elements). Although denemefunc is a function, by adding (index_val, index_valbas, elements) you directly invoke the function thus passing the return value (which is undefined).
To have each .formulbitti element call denemefunc with different parameters you should create callbacks for each element and store them (so you can remove the event listeners later). Then add an event listener for each element passing the callback you created.
The snippet below should give you an idea of how handle the addition and remove of a list of event listeners. This snippet is a bit verbose and might be further simplified.
const $formulbittis = $(".formulbitti");
let callbacks = null;
$("#set-events").on("click", function () {
// prevent adding multiple event listeners to a single element
if (callbacks) return;
// create and store callbacks
callbacks = $formulbittis.map(function (index, element) {
return (event) => denemefunc(index, element);
});
// add event listeners
$formulbittis.each(function (index, element) {
element.addEventListener("mouseover", callbacks[index]);
});
});
$("#del-events").on("click", function () {
// no callbacks means there is nothing to remove
if (!callbacks) return;
// remove event listeners
$formulbittis.each(function (index, element) {
element.removeEventListener("mouseover", callbacks[index]);
});
// clear callbacks array
callbacks = null;
});
function denemefunc(index, element) {
console.log(index, element);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="set-events" type="button">set event listeners</button>
<button id="del-events" type="button">delete event listeners</button>
<ul>
<li class="formulbitti">one</li>
<li class="formulbitti">two</li>
<li class="formulbitti">three</li>
</ul>
I created this snippet:
function addClick(button, container) {
console.log("In add click");
const data = container.nextElementSibling.childNodes[0].innerHTML;
button.addEventListener('click', ()=>{
alert('clicked')
console.log("Clicked");
})
}
function createCopyButtons(array){
array.forEach(element => {
const container = document.createElement('div');
const button = document.createElement('button');
button.innerHTML = "Copy"
styleContainer(container);
styleButton(button, element);
stylePrevious(element);
container.innerHTML = element.outerHTML + button.outerHTML;
element.parentNode.replaceChild(container, element);
addClick(button, container);
});
}
Now in here the array is the array of DOM elements I want this property to apply and I call the createCopyButtons() function down with some more stuff. Now the thing is that this event listener does not apply or does not work. I tried to wait till the document is loaded by these answers and only then apply my javascript snippet but the event listener doesn't seems to work.
document.addEventListener("DOMContentLoaded", function(event) {
//do work
});
if (document.readyState == "complete") {
// document is ready. Do your stuff here
}
Please help.
update:
function addClick(button) {
button.addEventListener('click', ()=>{
console.log("Clicked");
})
}
let p = document.querySelectorAll('p');
// innerHTML not work
let btn1 = document.createElement('button');
btn1.innerHTML = "Not work";
p[0].innerHTML = btn1.outerHTML;
addClick(btn1)
// work
let btn2 = document.createElement('button');
btn2.innerHTML = "work";
p[1].appendChild(btn2);
addClick(btn2)
<p></p>
<p></p>
because you append the button to the container using string (.innerHTML) not DOM or using appendChild()
container.innerHTML = element.outerHTML + button.outerHTML
the following function will not apply the event
addClick(button, container);
I don't know why you need to wrap target element and the button inside div, why not just append the button after target element using or insertBefore() or insertAdjacentHTML() but below is working code that follow yours.
it find the button inside the container for using as addClick() parameters
function addClick(button, container) {
console.log("In add click");
const data = container.nextElementSibling.childNodes[0].innerHTML;
button.addEventListener('click', () => {
alert('clicked')
console.log("Clicked");
})
}
function createCopyButtons(array) {
array.forEach(element => {
const container = document.createElement('div');
let button = document.createElement('button');
button.innerHTML = "Copy"
container.innerHTML = element.outerHTML + button.outerHTML;
element.parentNode.replaceChild(container, element);
let btn = container.querySelector('button'); // <== find the button
addClick(btn, btn.parentNode);
});
}
createCopyButtons(document.querySelectorAll('input'))
<div>
<input type="text">
<p><span>test</span></p>
</div>
Imagine having a class that generates content on the page. Part of the content should have event listener attached in html such as onclick=function().
How can I make sure to call the function from within the class that constructed the html?
class Container {
constructor(hook) {
this.hook = "#" + hook;
this.addDiv = this.addDiv.bind(this);
this.fireMe = this.fireMe.bind(this);
this.init = this.init.bind(this);
this.init();
}
addDiv() {
const div = `<div onclick="fireMe()">FIRE ME</div>`;
document.querySelector(this.hook).innerHTML = div;
}
fireMe() {
console.log("hello!");
}
init() {
this.addDiv();
}
}
let div = new Container("app");
now getting error that fireMe is undefined (which is right because it is not available in global scope).
I know I can add event listener by rendering the div first and than adding the event listener, but is there a way of adding event listener from within <div> tag to actually reach Container.fireMe() method?
You have to create the element -> something like this
class Container {
constructor (hook) {
this.hook = '#' + hook;
this.addDiv = this.addDiv.bind(this);
this.fireMe = this.fireMe.bind(this);
this.init = this.init.bind(this);
this.init();
}
addDiv () {
const div = document.createElement('div');
div.textContent = 'FIRE ME';
div.addEventListener('click', this.fireMe );
document.querySelector(this.hook).innerHTML = div;
}
fireMe () {
console.log('hello!');
}
init () {
this.addDiv();
}
}
const div = new Container('app');
Never use inline event handlers as there are many reasons to avoid this 20+ year old technique that just will not die.
Instead, use modern, standards-based code with .addEventListener(). If you do this along with making the new HTML using the DOM API, you'll be able to more easily accomplish your goal:
addDiv() {
const div = document.createElement("div");
div.textConent = "FIRE ME";
div.addEventListener("click", this.fireMe);
document.querySelector(this.hook).innerHTML = div;
}
You should create elements use document.createElement() rather than using string
class Container {
constructor(hook) {
this.hook = "#" + hook;
this.addDiv = this.addDiv.bind(this);
this.fireMe = this.fireMe.bind(this);
this.init = this.init.bind(this);
this.init();
}
addDiv(){
const div = document.createElement('div');
div.innerHTML = "Fire Me";
div.addEventListener("click",this.fireMe);
document.querySelector(this.hook).appendChild(div);
}
fireMe() {
console.log("hello!");
}
init() {
this.addDiv();
}
}
let div = new Container("app");
I am creating a new div on a click of button and inside that onclick function I am adding a click event to newly created div but its not working.
document.getElementById('blah').onclick = function(){
var innerDiv = document.createElement("div");
document.getElementById('container').appendChild(innerDiv);
innerDiv.onclick =createWorkFunction;
}
function createWorkFunction(e){
alert();
}
can anybody quickly help me
Your code is corrct, But you did not set the text of the your div (an empty div can not be clicked by an user), Try this:
document.getElementById('blah').onclick = function(){
var innerDiv = document.createElement("div");
innerDiv.innerHTML = 'This is a div'; // set it's text
document.getElementById('container').appendChild(innerDiv);
innerDiv.onclick = createWorkFunction;
}
function createWorkFunction(e){
alert('this is some text');
}
Also it's better to use addEventListener
(function() {
var oBlah = document.getElementById('blah');
oBlah.addEventListener('click', function() {
var innerDiv = document.createElement("div");
document.getElementById('container').appendChild(innerDiv);
}, false);
innerDiv.addEventListener('click', function() {
alert();
}, false);
})();
This should help.
try this:
innerDiv.setAttribute("onclick","createWorkFunction()")
function createWorkFunction(){
alert("working");
}