TamperMonkey EventListener on button not working - javascript

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>

Related

Call class function with addEventListener

I want to access the doSomething function when the button that the render function creates is clicked? I get the following error instead.
Uncaught ReferenceError: getMethod is not defined
main.js
class Div {
constructor(div){
this.div = div;
}
init(){
this.getMethod();
}
getMethod(){
var div = this.div;
var createButton = {
render: function(){
let button = `
<button
onclick="getMethod.doSomething(this)"
type="button">
Click Me!
</button>
`;
div.innerHTML = button;
},
doSomething: function(){
// do something
}
}
createButton.render();
}
}
const div = new Div(document.querySelector('div'));
div.init();
There are multiple problems with your code.
Event handlers in html attributes (e.g.onclick) get run in global scope, yet getMethod is defined in a local scope, the scope of your class.
getMethod does not have a property doSomething, I think you meant to write createButton.doSomething
To fix the first issue you have to define your button as an object, not just as text. Since text doesn't know anything about scope. Then you can addEventListener to add a handler for the click event. In the handler callback function's you will have access to all variables in your local scope (the scope of the getMethod function)
class Div {
constructor(div){
this.div = div;
}
init(){
this.getMethod();
}
getMethod(){
var div = this.div;
var createButton = {
render: function(){
const button = document.createElement('button');
button.type = "button";
button.textContent = "Click Me!";
button.addEventListener('click', () => {
createButton.doSomething(this)
})
//clear inner html / delete all children
div.innerHTML = '';
div.appendChild(button);
},
doSomething: function(){
console.log("do something");
}
}
createButton.render();
}
}
const divElem = document.getElementById("mydiv");
const div = new Div(divElem);
div.init();
<div id="mydiv"></div>

Javascript - Click event dosen't work on dynamically added elements

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++;
}

How do I add a button to a div class on load from Javascript? [duplicate]

This question already has answers here:
How to add onload event to a div element
(26 answers)
Closed 5 years ago.
For an assignment, I cannot touch the HTML code and am editing an external JS file. I have to refer the code to an existing class and turn that into a button to run a script.
The has to be ran on load to transform an element with a given id into a button that can also run a function on click.
So let's say the we have id="bar",
how do I go about it?
My code doesn't work at all.
document.getElementById("bar").onload = function () { myFunction() };
function myFunction() {
document.getElementById("bar").innerHTML = "<button></button>";
}
Why don't you just execute your script as the DOM is ready? To do so,
document.addEventListener('DOMContentLoaded', function () {
document.getElementById("bar").innerHTML = "<button></button>";
}, false);
You just need a createElement function.
This works:
document.addEventListener("DOMContentLoaded", function(){
var button = document.createElement("button");
button.innerHTML = "This is a button";
// assuming the Div's ID is bar
var div = document.getElementById('bar');
div.appendChild(button);
//the following function will alert a window when the button is clicked
button.addEventListener ("click", function() {
alert("Button was clicked");
});
});
Updated Codepen
I think this is bit tha you needed
var bar = document.getElementById('bar');
window.onload = function() {
var barInner = bar.innerHTML;
bar.innerHTML = '<button>' + barInner + '</button>';
}
bar.onclick = function() {
alert("Hello\nHow are you?");
};
document.getElementById("bar").onload = myFunction();
function myFunction() {
document.getElementById("bar").innerHTML = "<button>Button</button>";
}
There you go!
Not every single HTML element has a load event.
Only some of them are concerned, such as the window, an image... etc
Have a look here on MDN to learn more about this.
Here is a simple snippet resolving all what you mentioned.
window.addEventListener("load", () => {
// you can put your entire script in here.
var elt = document.getElementById("bar"),
button = document.createElement("button");
button.textContent = elt.textContent;
button.onclick = callback;
elt.textContent = '';
elt.appendChild(button);
function callback() {
console.log("The button has been clicked");
}
});
<div id="bar" style="background: beige; height: 2em">Click me</div>
In the previous snippet, I am appending the button in the element. But if the matter is really to transform it into a button, there we go:
window.addEventListener("load", () => {
// you can put your entire script in here.
var elt = document.getElementById("bar"),
container = elt.parentNode,
button = document.createElement("button");
button.id = elt.id; // if you want to keep the id
button.textContent = elt.textContent;
button.onclick = callback;
container.removeChild(elt);
container.appendChild(button);
function callback() {
console.log("The button has been clicked");
}
});
<div style="background: #fee; height: 2em">
<div id="bar" style="background: beige; height: 2em">Click me</div>
</div>

How to hide dynamically created div on ready?

I have a scenario where I need to create a div dynamically, so I created on-ready of document. But it should be displayed on-selection. I am facing the issue, that on page load, the empty div is created. So I need to hide that div and should be shown on-select of text.
JavaScript
$(document).ready(function () {
closePopUp();
var replaceDiv = document.createElement('div');
replaceDiv.id = 'rplceTxtDiv';
document.getElementsByTagName('body')[0].appendChild(replaceDiv);
var innerspan = document.createElement('span');
replaceDiv.appendChild(innerspan);
innerspan.innerHTML += '˟';
var innerDiv = document.createElement('div');
replaceDiv.appendChild(innerDiv);
innerspan.addEventListener("click", closePopUp, false);
replaceDiv.addEventListener("click", getSel, false);
var rplceTxtDiv = $('#rplceTxtDiv');
$('#mytextarea').on('select', function (e) {
var txtarea = document.getElementById("mytextarea");
var start = txtarea.selectionStart;
var finish = txtarea.selectionEnd;
rplceTxtDiv.offset(getCursorXY(txtarea, start, 20)).show();
rplceTxtDiv.find('div').text('replace with stars');
}).on('input', function () {
if (interval) {
interval = false;
edits.push($(this).val());
if (edits.length > maxHistorySize) edits.shift();
setTimeout(() => interval = true, saveInterval);
}
});
document.onkeydown = undo;
});
Here is my plunker
The issue is shown in below image:
Hide the DIV before appending it to the HTML by
replaceDiv.style.display = "none";
and I recommend showing it after you have updated the text by
replaceDiv.style.display = "block";
Set a CSS class as:
.MyClass {
display: none;
}
and with jQuery:
$('#myDivIDorClass').addClass('MyClass');
just hide all div having class name "yourclass" with hide()
like this on ready
$('div.yourclass').css("display","none");

Creating two elements using js and then having access to them later in another function

I am building some js functionality where I will be creating 2 elements on a page
var createBtn = function(
var btn = document.createElement('button')
...
)
var createIframe = function(
var iframe = document.createElement('iframe')
...
)
Pretty basic stuff, but later on I want to add an event listener to the button that will apply a style attribute to the iframe.
Something like:
var displayIframe = function(
Iframe.style['display'] = 'block'
)
button.addEventListener('click', displayIframe)
My question is how can I access the elements after I have created them without going through the annoyance of attaching classes to them and accessing them all over again that way. Is there someway of getting access to them in the create functions from the beginning.
Your codes is almost correct, but some changes is needed
var btn, iframe;
var createBtn = function () {
btn = document.createElement('button');
...
}
var createIframe = function () {
iframe = document.createElement('iframe');
...
}
Callback function
var displayIframe = function(){
iframe.style['display'] = 'block'
}
Attach click listener
btn.addEventListener('click', displayIframe);
Your mistakes:
you should declare btn and iframe as global variables to be accessible to other functions
function starts with { and ends with } not (, )
so far your codes is correct, without any error, but you won't see anything on the page because you have not attached your newly created elements to the body, For accomplish this try this function
function attachToBody(){
document.body.appendChild(btn);
document.body.appendChild(iframe);
}
In your example, I dont know why you use functions to create element, but you must have your point. Try this and let me know does this work for you.
//this is equivalent to: var btn = document.createElement('button');
var btn = (function(){
var btn = document.createElement('button');
return btn;
})();
var iframe = (function{
var iframe = document.createElement('iframe');
return iframe;
})();
document.getElementById("parentId").appendChild(btn);
document.getElementById("parentId").appendChild(iframe);
btn.addEventListener('click', function(){
iframe.style.display = "none";
});
var createBtn = function() {
var btn = document.createElement('button')
btn.setAttribute("id", "myButton");
return btn;
}
var createIframe = function() {
var iframe = document.createElement('iframe')
iframe.setAttribute("id", "myFrame");
return iframe;
}
document.body.appendChild(createBtn()); // Append button to body.
document.body.appendChild(createIframe()); // Append iFrame to body.
// Get Elements by Id.
var myButton = document.getElementById("myButton");
var myFrame = document.getElementById("myFrame");
// Add event listener.
myButton.addEventListener("click", function() {
myFrame.style.display = "none", false);
}

Categories