HTML Button created in object constructors onclick event not working - javascript

So whatever is causing the error must actually be in this loop:
Creating a box by calling the gridBox constructor on its own works. But those created by the buildField function do not return an on click event.
var grid = [];
function buildField(size){
//loops through each row
for(var y=0; y<size;y++){
//loops through each column
grid[y]=[];
for(var x=0; x<size; x++){
//create new object for grid
grid[y][x] = new gridBox(x,y);
}
document.getElementById("board").innerHTML += "<br>";
}
}
function gridBox(x,y){
this.x=x;
this.y=y;
var me = this;
//function to create and add button.
function makeBtn(){
var btn = document.createElement("BUTTON");
btn.type = "BUTTON";
btn.className = "gridButton";
btn.value = "BUTTON";
btn.name = me;
btn.onclick = function(){
console.log("click");
};
document.getElementById("board").appendChild(btn);
console.log("madeButton");
}
makeBtn();
}

document.getElementById("board").innerHTML += "<br>";
This will:
Convert the DOM to HTML
Add <br> to that HTML
Convert that HTML to DOM
Overwrite the existing DOM with that
… the onclick event handlers will not be part of the serialised HTML, so they will be lost when step 4 happens.
Use createElement and appendChild again. Don't use innerHTML.

This is working for me:
function gridBox(x,y){
this.x=x;
this.y=y;
var me = this;
//function to create and add button.
function makeBtn(){
var btn = document.createElement("BUTTON");
btn.className = "gridButton";
btn.textContent = "Click Me";
btn.name = me;
btn.onclick = function(){
console.log("click");
};
document.getElementById("board").appendChild(btn);
console.log("madeButton");
}
makeBtn();
}
gridBox(10,10);
.gridButton {
height:30px;
width:100px;
}
<div id=board></div>

try adding btn.onClick after document...appendChild(..) :
this works for me
function gridBox(x,y){
this.x=x;
this.y=y;
var me = this;
//function to create and add button.
function makeBtn(){
var btn = document.createElement("BUTTON");
btn.type = "BUTTON";
btn.className = "gridButton";
btn.value = "BUTTON";
btn.name = me;
document.getElementById("board").appendChild(btn);
btn.onclick = function(){
console.log("click");
};
console.log("madeButton");
}
makeBtn();
}
// make simple button
gridBox(10,10);
<div id="board">
</div>

Try with:
btn.addEventListener('click', function(){ });
instead of your btn.onclick

Related

How do i disable a button after i have clicked it 2 times?

I have a project for school, which consists of making a text editor. I added a menu button, which is supposed to be clicked and disabled after clicking it 2 times, so it wont append more and more childs of the menu button.
Here is the code:
let btn = document.createElement('input');
btn.type = 'button';
btn.value = 'Open Menu';
btn.onclick = () => {
let btn2 = document.createElement('input');
btn2.type = 'button';
btn2.value = 'New Text';
document.body.appendChild(btn2);
}
document.body.appendChild(btn);
As you can see, i have a button that after it gets clicked, appends a new button to the body of the document. And if you click it 2 or 3 times, 3 new buttons gets appended, which is buggy.
I tried adding a counter like this:
let counter = 0;
if (counter === 2) {
document.querySelector("button")[0].disabled = "disabled"; || document.querySelector("button")[0].disabled = true;
}
Well, that didn't seem to work out as expected.
Any ideas on how to get this working?
Thank you
You should initialize the counter outside of the onclick event handler. Then you can add this code in the end of onclick event handler:
counter++;
if (counter === 2) btn.disabled = true;
const btn = document.createElement('input');
let counter = 0;
btn.type = 'button';
btn.value = 'Open Menu';
btn.onclick = () => {
let btn2 = document.createElement('input');
btn2.type = 'button';
btn2.value = 'New Text';
document.body.appendChild(btn2);
counter++;
if (counter === 2) btn.disabled = true;
}
document.body.appendChild(btn);

How to create buttons in a for loop without losing their references?

I am trying to create buttons for each letter in alphabet. When the button is pressed, it will alert the letter written on the button. But i think since i create them i a for loop, js can't keep their reference because when i open the browser, on the each button 'undefined' is written. I also tried to add the buttons to an array then append them to the container, but the result was same. Is there any way to fix this problem? Thanks.
function CreateButtons()
{
var letters = "ABCDEFGHJKLMNOPRSTUVYZQWXI";
var frame = document.getElementById('buttons'); //container.
for (var i = 0; i < letters.length;i++)
{
document.addEventListener('DOMContentLoaded', function() {
var button = document.createElement('button');
button.type = 'button';
button.innerHTML = letters[i];
button.className = 'btn-styled';
button.style.padding = "20px";
button.style.marginTop = "10px";
button.style.lineHeight = "30px";
button.style.fontWeight = "bold";
button.style.padding = "0 30px";
button.style.background = "salmon";
button.style.border = "none";
button.style.color ="blue";
button.onclick = function() {
alert(letters[i]); //when the button is pressed, it will alert the letter at i. position.
};
frame.appendChild(button);
}, false);
}
}
You need to create a closure. Because loop will finish its execution and the button created will never know the value of letter[i]
function CreateButtons() {
var letters = "ABCDEFGHJKLMNOPRSTUVYZQWXI";
var frame = document.getElementById('buttons'); //container.
for (var i = 0; i < letters.length; i++) {
(function(z) {
document.addEventListener('DOMContentLoaded', function() {
var button = document.createElement('button');
button.type = 'button';
button.innerHTML = z;
button.className = 'btn-styled';
button.style.padding = "20px";
button.style.marginTop = "10px";
button.style.lineHeight = "30px";
button.style.fontWeight = "bold";
button.style.padding = "0 30px";
button.style.background = "salmon";
button.style.border = "none";
button.style.color = "blue";
button.onclick = function() {
alert(z); //when the button is pressed, it will alert the letter at i. position.
};
frame.appendChild(button);
}, false);
}(letters[i]))
}
}
CreateButtons()
<div id='buttons'></div>
Alternatively instead of var use let
function CreateButtons() {
var letters = "ABCDEFGHJKLMNOPRSTUVYZQWXI";
var frame = document.getElementById('buttons'); //container.
for (let i = 0; i < letters.length; i++) {
document.addEventListener('DOMContentLoaded', function() {
var button = document.createElement('button');
button.type = 'button';
button.innerHTML = letters[i];
button.className = 'btn-styled';
button.style.padding = "20px";
button.style.marginTop = "10px";
button.style.lineHeight = "30px";
button.style.fontWeight = "bold";
button.style.padding = "0 30px";
button.style.background = "salmon";
button.style.border = "none";
button.style.color = "blue";
button.onclick = function() {
alert(letters[i]); //when the button is pressed, it will alert the letter at i. position.
};
frame.appendChild(button);
}, false);
}
}
CreateButtons()
<div id='buttons'></div>

why my input element which is a div child is unclickable while when i replace this input by a button, the button is clickable

I want to create a div element which contains a button and an input element.
but when the input is in the div the input becomes unclickable
var video_button = document.createElement("BUTTON");
var user_area = document.createElement("DIV");
var inp = document.createElement("INPUT");
function upload_video(e){
console.log("upload_video function");
var v = document.createElement("VIDEO");
inp.onchange = function(e){
v.src = window.URL.createObjectURL(inp.files[0]);
v.style.heigth = "1000px";
v.style.width = "1000px";
user_area.appendChild(v);
}
}
function input(e){
console.log("input function");
inp.setAttribute("type","file");
user_area.appendChild(inp);
inp.addEventListener("click",upload_video)
}
window.onload = function(){
video_button.innerHTML = "upload a video";
video_button.addEventListener("click",input);
user_area.setAttribute("contentEditable","true");
user_area.style.width = "100px";
user_area.style.height = "500px";
document.body.appendChild(user_area);
user_area.appendChild(video_button);
}
This is not working on firefox because of the content editable attribute set to true. And there is a reason behind it.
If you don't need it that much, you can remove it.
var video_button = document.createElement("BUTTON");
var user_area = document.createElement("DIV");
var input_wrapper = document.createElement("DIV");
var inp = document.createElement("INPUT");
function upload_video(e){
console.log("upload_video function");
var v = document.createElement("VIDEO");
inp.onchange = function(e){
v.src = window.URL.createObjectURL(inp.files[0]);
v.style.heigth = "1000px";
v.style.width = "1000px";
user_area.appendChild(v);
}
}
function input(e){
console.log("input function");
inp.setAttribute("type","file");
input_wrapper.setAttribute("contentEditable","false");
user_area.appendChild(input_wrapper);
input_wrapper.appendChild(inp);
inp.addEventListener("click",upload_video)
}
window.onload = function(){
video_button.innerHTML = "upload a video";
video_button.addEventListener("click",input);
user_area.setAttribute("contentEditable","true");
user_area.style.width = "100px";
user_area.style.height = "500px";
document.body.appendChild(user_area);
user_area.appendChild(video_button);
}

how do i add functionality to each of the buttons?

The first part of the code is working correctly, but now that each button appears, how do i add functionality to each of them? currently the only button which does something when pressed is always the last one, the rest do nothing.
Change it to
{
var output = "";
var data = JSON.parse(e.target.responseText);
for(var i=0; i<data.length; i++)
{
output = data[i].title + ' ';
var p = document.createElement("p");
var div = document.getElementById("response");
var textNode = document.createTextNode(output);
p.appendChild(textNode);
var button = document.createElement("button");
button.innerHTML = "Download";
p.appendChild(button);
div.appendChild(p);
button.addEventListener ("click", () =>
{
alert("Test");
});
}
}
You are adding the below code out side the for loop
button.addEventListener ("click", () =>
{
alert("Test");
} );
Keep the above code inside the for loop. So that for each button the event listener will be added.
Another way to approach this would be to add the callback function to the onclick variable of the elements prototype:
function doStuff() {
var output = "";
var data = JSON.parse(e.target.responseText);
for (var i = 0; i < data.length; i++) {
output = data[i].title + ' ';
var p = document.createElement("p");
var div = document.getElementById("response");
var textNode = document.createTextNode(output);
p.appendChild(textNode);
var button = document.createElement("button");
button.innerHTML = "Download";
// Adds the callback function here
button.onclick = () => {
// fill in your arrow function here...
alert("Test");
};
p.appendChild(button);
div.appendChild(p);
};
}
doStuff();
Here is a jsFiddle
You should use event delegation for dynamically added elements
// sample data
var data = [{
title: 'one'
}, {
title: 'two'
},{
title: 'three'
}];
var output = "";
for (var i = 0; i < data.length; i++) {
var output = data[i].title + " ";
var p = document.createElement("p");
var div = document.getElementById("response");
var textNode = document.createTextNode(output);
p.appendChild(textNode);
var button = document.createElement("button");
// added output to button text for identification
button.innerHTML = output + " Download";
p.appendChild(button);
div.appendChild(p);
}
// Get the parent element, add a click listener
document.getElementById("response").addEventListener("click", function(e) {
// e.target is the clicked element!
// If it was a button
if (e.target && e.target.nodeName == "BUTTON") {
// Button found! Output the identifying data!
// do other work on click
document.getElementById("display").innerHTML = e.target.innerHTML + " Clicked";
}
});
<div id="response"></div>
<div id="display">Display</div>

buttons added to table won't fire handler

In my table, I'm trying to include an Edit button at the end of each row. The idea is for the user to click one of these to alter the row's content. I can build and populate the table just fine, but I cannot get the buttons to fire off their handler.
Here's a code snippet:
window.onload = function (){
// a bunch of stuff happens correctly...
while (!Rs.EOF)
{
var oRow = oTicketsTable.insertRow();
for (j=0; j < field.length; j++)
{
var oCell = oRow.insertCell();
oCell.style.fontSize = "10";
oCell.style.fontWeight = "normal";
oCell.style.border = "thin black solid";
oCell.innerText = Rs(field[j]);
}
var oCell = oRow.insertCell();
oCell.style.border = "thin black solid";
var oBtn = document.createElement("button");
oCell.appendChild(oBtn);
oBtn.innerHTML = Rs('idnum');
oBtn.onClick = function () { alert("oBtn.onClick"); }
Rs.MoveNext();
}
Rs.Close ();
delete Rs;
var btn = document.createElement("button");
btn.style.height = "50px";
btn.style.width = "150px";
document.body.appendChild(btn);
btn.innerHTML="button1";
btn.onclick = function() { alert("button1 calling");
}
The code at the end creates a test button which fires off just fine. But none of the buttons in the table work.
The onclick function in the table is camel case: try changing it to lower case? Change obtn.onClick to obtn.onclick.
oBtn.onclick = function () { alert("oBtn.onClick"); }
Try:
oBtn.onclick = function () { alert("oBtn.onClick"); }
Rs.MoveNext();
}
Instead of:
oBtn.onClick = function () { alert("oBtn.onClick"); }
Rs.MoveNext();
}
capitalized 'C', should be just 'c'
If I not mistaken, you should place your event outside, as global.
var oBtn,btn;
window.onload = function (){
// other code
// other code
oBtn = document.createElement("button");
oBtn.innerHTML = Rs('idnum');
btn = document.createElement("button");
btn.style.height = "50px";
btn.style.width = "150px";
document.body.appendChild(btn);
btn.innerHTML="button1";
}
// make your event global
oBtn.onClick = function () { alert("oBtn.onClick"); }
btn.onclick = function() { alert("button1 calling"); }
.onClick is an old practice. But I think it would just prompt you a warning, not an error.

Categories