Problem
Adding an event handler for click events with dynamically added buttons does not result in anything when clicked. I'm trying to build a build a chrome extension that dynamically adds a button.
Code
In content script (js)
// 1. Create the button
var button = document.createElement("button");
button.innerHTML = "Do Something";
// 2. Append somewhere in the document body
var body = document.getElementsByTagName("body")[0];
body.appendChild(button);
// 3. Add event handler
button.addEventListener ("click", function() {
alert("did something");
});
While the button does get rendered, clicking the button does nothing.
Notes
Event handlers for checkboxes work, though! Uses href = "javascript: function()"
var check = document.createElement("input");
check.id = "checkbox1";
check.type = "checkbox";
//if check is checked, then call removeSticky()
check.href="javascript:removeSticky()"
check.addEventListener('change', () => {
if (check.checked) {
removeSticky();
} else {
// nothing
}
});
document.getElementById("sticky").append(check);
//hidesthe sticky note
function removeSticky() {
window.alert("removeSticky() is working.");
// Removes an element from the document.
var element = document.getElementById("sticky");
element.style.display = "none";
}
However, doing the same with the BUTTON causes removeSticky() to be called whenever the webpage is fully loaded, when the user hasn't clicked anything yet.
Related
i have a form, inside this form i have "local" "airport" "oneway" "roundtrip" buttons.
i have written an javascript code, which will set action attribute according to which button is clicked but the problem is when i mistakenly clicked on wrong button and then click on correct button the action attribute is not switching to the correct button route but to switch the correct route in the action attribute i have to refresh the page.
i want to change the action attribute value without refreshing the page.
here is the image of the form
here is my javascript code:-
var addInputBtn = document.getElementById("addInputBtn");
var myform = document.getElementById("cabform");
var clicked = false;
addInputBtn.addEventListener("click", function(){
if (!clicked) {
myform.setAttribute("action", "/airport");
clicked = true;
}
});
var localBtn = document.getElementById("localBtn");
localBtn.addEventListener("click", function(){
if (!clicked) {
myform.setAttribute("action", "/local");
clicked = true;
}
});
var oneWay = document.getElementById("oneWay");
oneWay.addEventListener("click", function(){
if (!clicked) {
myform.setAttribute("action", "/oneway");
clicked = true;
}
});
var roundTrip = document.getElementById("roundTrip");
roundTrip.addEventListener("click", function(){
if (!clicked) {
myform.setAttribute("action", "/roundtrip");
clicked = true;
}
});
var searchcab = document.getElementById("searchcab");
var paragraphId = document.getElementById("pid");
searchcab.addEventListener("click", function(){
if (!clicked) {
paragraphId.innerHTML = "Please select one of the Button: Airport, local"
searchcab.setAttribute("type", "button");
} else if (clicked) {
searchcab.setAttribute("type", "submit");
}
});
</script>````
Any suggestion, any help would be great thanks🙏🙏🙏
i am trying to setting the action attribute when a user click on a button, problem is i have to do refresh the page to select the another button otherwise it redirect to the wrong route
if you want this behavior then simply remove your if-condition. once u click on the element, you set clicked to true meaning your action attribute can never update until you refresh, because clicked is false by default.
I am trying to make a simple Shopping List App in which user can Add, Delete and mark the task done when completed. So far, I am able to add the task but facing problem in executing the done and delete functions. I am getting an error because when I execute it, the done and delete buttons are not there but what should I do to fix it?
var inp = document.getElementById("form");
var button = document.getElementById("click");
//Create List Function with Done and Delete Buttons
function addVal() {
var ul = document.getElementById("list");
var li = document.createElement("li");
var span = document.createElement("span");
var done = document.createElement("button");
var del = document.createElement("button");
li.appendChild(document.createTextNode(""));
span.appendChild(document.createTextNode(inp.value));
done.appendChild(document.createTextNode("Done"));
del.appendChild(document.createTextNode("Delete"));
li.appendChild(span);
li.appendChild(done);
li.appendChild(del);
done.setAttribute("class", "doneBut");
del.setAttribute("class", "delBut");
ul.appendChild(li);
inp.value = "";
}
//Get Input Length
function checkLength() {
return inp.value.length;
}
//Run function on Button Click
function onButtonClick() {
if (checkLength() > 0) {
addVal();
}
}
//Run function on Enter Keypress
function onEnter(event) {
if (checkLength() > 0 && event.which === 13) {
addVal();
}
}
//Trigger Events
button.addEventListener("click", onButtonClick);
inp.addEventListener("keypress", onEnter);
//Done and Delete Button Functions
var doneButton = document.getElementsByClassName("doneBut");
var deleteButton = document.getElementsByClassName("delBut");
function doneTask() {
doneButton.parentNode.classList.add("done");
}
function delTask() {
deleteButton.parentNode.classList.add("delete");
}
doneButton.addEventListener("click", doneTask);
deleteButton.addEventListener("click", delTask);
<input type="text" placeholder="Enter Your Task..." id="form" />
<button id="click">Add Task</button>
<h2>List:</h2>
<ul id="list"></ul>
Please Help.
Your problem is that the code tries to add events before the buttons exist. The buttons don’t exist until the addVal function gets called. Since addVal is not being called before the you try to add your event handlers, the getElementById returns null, and you attempt to add an event listener to null.
Additionally it looks like you’re planning to add multiple done and delete buttons. That wouldn’t normally be a problem, except you’re referencing them by ID, and IDs MUST be unique. You’ll need to switch this to a class or an attribute, since you’ll need one per item in the shopping cart.
You’ll probably want to look into event delegation, so that you can add your events once to the page before any buttons exist. https://javascript.info/event-delegation
It's most likely because your script is running before your code is running. Add the <script> tags just before the closing </body> tag to fix it:
<script>/* Your code here */</script>
</body>
You need to place this in a window.onload function, or run it in a function inside of the body tag's onload. Those elements don't exist yet when the script is run:
window.onload = function() {
var inp = document.getElementById("form");
var button = document.getElementById("click");
button.addEventListener("click", onButtonClick);
inp.addEventListener("keypress", onEnter);
}
So I have the following function called addPanels() which adds an event listener to every element with class "accordion"
function addPanels(){
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function() {
var panel = this.nextElementSibling;
if (panel.style.display === "block") {
panel.style.display = "none";
} else {
panel.style.display = "block";
}
var arrow = this.children[0].children[0];
if (panel.style.display === "block") {
arrow.src = "Iconos/arrow_up.png";
} else {
arrow.src = "Iconos/arrow_down.png";
}
});
}
}
Then I have this:
$(document).ready(function() {
api.routines.getRoutines().done(function(data) {
$.each(data, function(i, item){
var list = document.getElementById("routines_list");
var acc = document.createElement("div");
acc.setAttribute("class", "accordion");
var panel = document.createElement("div");
panel.setAttribute("class", "panel");
//more stuff
});
acc.appendChild(panel);
list.appendChild(acc);
// ...
});
addPanels(); //WORKS ONLY WITH PREVIOUS ACCORDIONS NOT WITH THE NEW ONE! WHY??
}).fail(function(jqXHR, textStatus, errorThrown) {
//do sth
});
});
addPanels seems to add the listener ONLY to the elements with class ACCORDION that weren't loaded from API (they were already in the HTML). Why is this happening?
Because at the time the listeners were added, your new elements didn't exist.
api.routines.getRoutines().done specifies a callback function that should run at some future point in time - we don't know when that will be. So, while that API goes out to begin its process, addPanels(); is immediately called next, which sets up the event handlers, but getRoutines() hasn't completed yet, so you wind up only setting up the handlers on the panels that exist before getRoutines() is finished. This is how asynchronous processing works.
To solve a problem like this, you need to use event delegation, which is when you set up the event handler on an object that exists right from the start and then you capture events that were initiated by descendant elements via event bubbling. When the event is handled, you check the source of the event and see if it matches the criteria you want. This way, it doesn't matter when the element gets created.
Here's a simplified example:
// Set up a click event handler on the document (which all descendant element events will bubble up to)
document.addEventListener("click", function(evt){
console.log("Click event handled!");
// Is the clicked element NOT the document?
if(evt.target.classList){
// Check for dynamically created elements that were given
// the "dynamic" class upon creation (you can use any criteria you want here)
if(evt.target.classList.contains("dynamic")){
console.log("Click event for dynamically created element, " + evt.target.nodeName + " handled by document");
}
}
});
// Now, we'll create some elements and inject them into the DOM AFTER the event handler
// has been set up. Also, these elements were not specifically set up with event handlers.
var div = document.createElement("div");
div.classList.add("dynamic");
div.textContent = "Click Me";
document.body.appendChild(div);
var btn = document.createElement("input");
btn.classList.add("dynamic");
btn.type = "button";
btn.value = "Click Me!";
document.body.appendChild(btn);
.dynamic { font-weight:bold; color:#800080; }
I have been trying to find a way to inject a button when a textarea in the window document got clicked(onfocus) ...for weeks, but I failed to do so.
The function is similar as how Grammarly's extension does.
Grammarly's extension
The thing is, I want to add a button nearby or in the textarea when it is onfocus or keypressed. Then I could return the text value to the extension. What is the right way to detect the div in the content script?
the button code is like this:
function appendBtn (){
var btn = document.createElement("INPUT");
btn.setAttribute("type", "button");
btn.setAttribute("value", "button");
document.body.appendChild(btn);
}
document.onclick = function() {
appendBtn();
}
what I want is to find the right div instead of appending the element after body...which it always show at the bottom of the page, especially on facebook page, which I can't even target the input boxes of the comment area..
Please help me with this! I am so desperate right now...
Use the focusin event (it bubbles unlike the focus event) in a content script of your extension:
var btn = createButton();
document.addEventListener('focusin', onFocusIn);
function onFocusIn(event) {
var el = event.target;
if (el.contentEditable ||
el.matches('input, textarea') && el.type.match(/email|number|search|text|url/))
{
appendButton(el);
}
}
function createButton() {
var btn = document.createElement('button');
btn.textContent = 'Yay!';
btn.onclick = function(event) {
btn.textContent += '!';
};
return btn;
}
function appendButton(textElement) {
textElement.parentElement.insertBefore(btn, textElement.nextElementSibling);
}
I am trying to create a library code that can be used across all my html pages.
I am very new to JS and this is the first code that I am trying to write like a library function.
I have a text field and a button next to it, on click of the button this adds a another text field below and a button next to it, this also removes the button in previous line.
I managed to do a button in the same row and adding text field in next lines, but the button click for newly added methods are not working with pure JS so I tried to use jquery "on" click event. For some reason its not getting triggered in my case.
Not sure what I am missing.
Code in external file
var addAnother = {
addAnotherField: function (eventTrigger, fieldContainer, arrayField) {
console.log("called");
var eventTrigger = eventTrigger;
console.log("ready called", eventTrigger);
$(document).on('click', eventTrigger, function (e) {
console.log("click called");
var buttonText = this.value;
var div = document.getElementById(fieldContainer);
var element = document.getElementById(eventTrigger);
element.parentNode.removeChild(element);
var input = document.createElement("input");
input.type = "text";
input.name = arrayField;
div.appendChild(document.createElement("br"));
div.appendChild(input);
var button = document.createElement("input");
button.type = "button";
button.id = eventTrigger;
button.value = buttonText;
div.appendChild(button);
});
}
}
code in HTML
$(document).ready(function () {
addAnother.addAnotherField("addAnother", "addAnotherContainer", "fieldArray[]");
});
Working JS code:
http://jsfiddle.net/balasivagnanam/ekoob8f0/
next button non working code JS
http://jsfiddle.net/balasivagnanam/ukseeuak/
with Jquery:
http://jsfiddle.net/balasivagnanam/6ea2dk6m/
Is this what you want:
/** this part will be located in another file added as a js library */
function addAnother(elem) {
var text = $("#addAnotherField").clone();
$("<br/>").insertBefore($("#addAnother"));
text.insertBefore($("#addAnother"));
}
/* this part will be coded below the above code file in the html file*/
$(document).ready(function () {
$('#addAnother').click(function () {
addAnother(this);
});
});
Here is the JSFiddle demo