Dynamic table with button click not working - javascript

Hi I was trying to demonstrate a problem with an example in fiddle, however I am stuck in the first step. In the fiddle that follows I am trying to dynamically create a table with td containing buttons and on click of that button I want to print the event.I dont see any error in the console. But the click event is never fired. Can someone please help me. I have another problem which I need to try out after this has been fixed.
HTML
<body>
<div class="myElement" id="test">
</div>
</body>
JS
var table = document.createElement('table');
for (var i = 1; i < 4; i++){
var tr = document.createElement('tr');
var td1 = document.createElement('td');
var text1 = document.createTextNode('Text1');
var btn = document.createElement("BUTTON");
btn.className ="clickable";
var t = document.createTextNode("CLICK ME");
btn.appendChild(t);
td1.appendChild(btn);
td1.appendChild(text1);
tr.appendChild(td1);
table.appendChild(tr);
}
$('.clickable').click(function(){
alert('You clicked me');
console.log("You clicked meg");
});
var tooltipSpan = document.createElement('span');
tooltipSpan.appendChild(table);
var innerHtml = document.createElement("div");
innerHtml.appendChild(tooltipSpan);
$("#test").append(innerHtml);
https://jsfiddle.net/dzrn7rus/

Related

Why does deleting this element with a non-unique ID delete the one I want?

Pardon the bad title, it's hard to explain. If you know how to phrase it better, please comment and I will update as soon as I can.
So, I was messing around with a random generator site (perchance.org) and writing my own HTML/Javascript to make my generator work. It has a behavior that is what I want, but that shouldn't be happening according to my knowledge of HTML.
Let me explain with a minimal example.
The example code here is to produce a simple page that has a button.
This button should generate <input>s with <button>s next to them, attached with similar ID's.
The button, when clicked, deletes the <input> and <button>.
Here is a snippet to show you the code/let you reproduce the results:
<html>
<head>
<script>
var current_id = 0;
function add_input () {
var list = document.getElementById("list");
var input = document.createElement("input");
var delete_button = document.createElement("button");
var br = document.createElement("br");
input.id = "input_" + current_id;
delete_button.id = "button_" + current_id;
br.id = "br_" + current_id;
input.value = input.id;
delete_button.textContent = "Delete";
delete_button.onclick = function () {
delete_input(this.id.slice(7)) //To get the numerical ID
}
list.appendChild(input);
list.appendChild(delete_button);
list.appendChild(br);
current_id++;
}
function delete_input (id) {
var input = document.getElementById("input_"+id);
var button = document.getElementById("button_"+id);
var br = document.getElementById("br_"+id);
input.remove();
button.remove();
br.remove();
current_id--;
}
</script>
</head>
<body>
<div id="list">
</div>
<button onclick="add_input()">Add</button>
</body>
</html>
When you add two inputs, then delete the first, and add one more, it leaves you with two inputs using the same ID. It also leaves you with two buttons with the same ID. And yet, both buttons delete their intended target.
Why?
You really should delegate - here I wrap in a div that can be removed in one go
You can rename each input to have incremented IDs but just letting the cnt run, gives you unique IDs
let cnt = 0;
function add_input() {
var list = document.getElementById("list");
var div = document.createElement("div");
var input = document.createElement("input");
var delete_button = document.createElement("button");
var br = document.createElement("br");
input.id = "input_" + (cnt++)// list.querySelectorAll("div").length
input.value = input.id;
delete_button.textContent = "Delete";
delete_button.classList.add("delete")
div.appendChild(input);
div.appendChild(delete_button);
div.appendChild(br);
list.appendChild(div);
}
window.addEventListener("load", function() {
document.getElementById("list").addEventListener("click", function(e) {
const tgt = e.target;
if (tgt.classList.contains("delete")) tgt.closest("div").remove();
})
})
<div id="list">
</div>
<button onclick="add_input()">Add</button>
I changed your code to be more effective.
I'm not using IDs as they aren't adding any benefit instead making it more complex.
Instead I target the element via the event handler and an argument.
I also wrap each set of inputs/buttons in a div so I can just remove that div and it will remove all of the children.
function add_input() {
var list = document.getElementById("list");
var input = document.createElement("input");
var delete_button = document.createElement("button");
var br = document.createElement("br");
delete_button.textContent = "Delete";
delete_button.onclick = function(e) {
e.target.parentNode.remove();
}
var div = document.createElement("div");
div.appendChild(input);
div.appendChild(delete_button);
div.appendChild(br);
list.appendChild(div)
}
<div id="list">
</div>
<button onclick="add_input()">Add</button>

How to add event listener to buttons in a loop

I'm new to javascript and I'm trying to create a menu of buttons. In the menu, I want to add event listeners when I click a button.
My problem is I'm not sure how to implement it, to make it possible to target each button with the specific code that button need to run.
I have a button that needs to turn red when clicked and another that needs to load another site. How is it possible to achieve these things.
At the moment I generate the Buttons from a JSON document and create them in the code you can see below.
EDIT: added id attribute to javascript
function createMenu(jsonObj) {
let menu = jsonObj["menuitems"];
console.log(menu[0]);
let table = document.createElement("table");
for (let i = 0; i < menu.length; i++) {
let tableSection = document.createElement("tr");
let tableItem = document.createElement("td");
tableSection.appendChild(tableItem);
let button = document.createElement("BUTTON");
tableItem.appendChild(button);
let text = document.createTextNode(menu[i].item);
button.appendChild(text);
button.classList.add("menuButtons");
table.appendChild(tableSection);
button.setAttribute("id", menu[i].id);
button.addEventListener("click",/*What do i write here*/);
}
document.getElementById("menuDiv").appendChild(table);
}
Standards advice to not declare variable in loop. You can make an attribute (data-horsSujet) and compare the value to know what to do. Like this :
function createMenu(jsonObj) {
const menu = jsonObj["menuitems"];
console.log(menu[0]);
const table = document.createElement("table");
const myfct = function (event) {
const button = event.target;
if (button.getAttribute("data-horsSujet") == 1)
button.style.color = "red";
else
document.location = "google.fr";
}
for (let i = 0, tableSection, tableItem, button, text; i < menu.length; i++) {
tableSection = document.createElement("tr");
tableItem = document.createElement("td");
tableSection.appendChild(tableItem);
button = document.createElement("BUTTON");
tableItem.appendChild(button);
text = document.createTextNode(menu[i].item);
button.appendChild(text);
button.classList.add("menuButtons");
table.appendChild(tableSection);
button.setAttribute("id", menu[i].id);
button.addEventListener("click", myfct);
button.setAttribute("data-horsSujet", i);
}
document.getElementById("menuDiv").appendChild(table);
}

Create Element with onclick

I have a table, and each row is added through JavaScript. I create these rows so that when they're clicked another cell will be created beneath them where I can display additional information. Now I want to be able to destroy the row I just created when the user clicks a button etc. So essentially, I need to be able to have the row I created have an onclick attribute, but it doesn't seem to work... I've tried everything I can think of so any help would be awesome!
var table = document.getElementById("main_table");
var row = table.insertRow(1);
row.id = count;
row.onclick = function ()
{
var id = this.id;
var target = document.getElementById(id);
var newElement = document.createElement('tr');
newElement.style.height = "500px";
newElement.id = id + "" + id;
//newElement.innerHTML = text;
target.parentNode.insertBefore(newElement, target.nextSibling );
//var newRow = document.createElement("tr");
//var list = document.getElementById(id);
//list.insertAfter(newRow,list);
var newRow = table.insertRow(newID);
}
I have tried to mimic your problem with below fiddle.
http://jsfiddle.net/kr7ttdhq/12/
newElement.onclick = createClickableCells;
del.onclick = delCell;
The above code shows the snippet from the fiddle
During the onclick event of the cell. New cells are created which in turn have the same onclick events as the first cell.
Moreover, a 'close' text cell is inserted by which you can delete the entire row.
Hope this helps

Button click doesnt fire when used with smallipop jquery plugin

I have an application in which I display a table(basically used to display errors) inside a popup, one of the tds have a button which is used to suppress this error. My problem is when used in conjuction with the smallipop plugin the click event is not getting fired , however it is running when run without the smallipop plugin. I have no clue whats going on here. I have fiddles for both the scenarios below:
HTML
<body>
<label>testing with smalipop</label>
<div class="myElement" id="test" style="width:100px;height:200px;background:blue">
</div>
</body>
JS
var table = document.createElement('table');
for (var i = 1; i < 4; i++){
var tr = document.createElement('tr');
var td1 = document.createElement('td');
var text1 = document.createTextNode('Text1');
var btn = document.createElement("BUTTON");
btn.className ="clickable";
var t = document.createTextNode("CLICK ME");
btn.appendChild(t);
btn.addEventListener( 'click', function ( e ) {
console.log('you clicked me');
}, false );
td1.appendChild(btn);
td1.appendChild(text1);
tr.appendChild(td1);
table.appendChild(tr);
}
var tooltipSpan = document.createElement('span');
tooltipSpan.className = "smallipop-hint";
tooltipSpan.appendChild(table);
$("#test").append(tooltipSpan);
$('.myElement').smallipop();
Fiddle with smallipop
http://jsfiddle.net/fdu9vtv0/8/
Fiddle without smallipop
https://jsfiddle.net/dzrn7rus/12/
There might be a problem with interfering JavaScript. Sometimes plugins override click events and especially because smallipop has special options for the behaviour of clicks inside the tooltip (see for example hideOnTriggerClick), this might be the problem.
I found out that when binding with jQuery, the listener still works:
var table = document.createElement('table');
for (var i = 1; i < 4; i++){
var tr = document.createElement('tr');
var td1 = document.createElement('td');
var text1 = document.createTextNode('Text1');
var btn = document.createElement("BUTTON");
btn.className ="clickable";
var t = document.createTextNode("CLICK ME");
btn.appendChild(t);
$(btn).on( "click", function() {
alert('You clicked me');
console.log('you clicked me');
});
td1.appendChild(btn);
td1.appendChild(text1);
tr.appendChild(td1);
table.appendChild(tr);
}
var tooltipSpan = document.createElement('span');
tooltipSpan.className = "smallipop-hint";
tooltipSpan.appendChild(table);
$("#test").append(tooltipSpan);
$('.myElement').smallipop();
This works as expected. See corresponding jsFiddle.
As to why it doesn't work with JavaScript: I have no clue. You might look into the source code of smallipop (although this seems to be offline at the moment). Probably there are some methods that smallipop uses that override the click events of its content.

Add div Dynamically

I have a table that adds rows dynamically as new users become active. The function will add a new row that displays the user's name and a button that activates a lightbox to show more information. The name and button are put in a single cell, but I'd like to right align the button and left align the name within the cell. I found this post Right align and left align text in same HTML table cell that shows how to do it with divs in HTML, but I need to do this dynamically. Anyone have a guess? I tried the following code, it works, but doesn't justify the name and button how I'd like. It just centers them within the cell. I'd appreciate any help.
function addRow(tableID, user, phone, age, city, zipCode) {
var table = document.getElementById(tableID);
var rowCount = table.rows.length;
var row = table.insertRow(rowCount);
var colCount = table.rows[0].cells.length;
for(var i=0; i<colCount; i++) {
tabbody=document.getElementsByTagName("tbody").item(2);
cell1 = document.createElement("TD"); //Create New Row
leftDiv = document.createElement("div"); //Create left div
leftDiv.id = "left"; //Assign div id
leftDiv.setAttribute("style", "float:left;width:50%;"); //Set div attributes
rightDiv = document.createElement("div"); //Create right div
rightDiv.id = "right"; //Assign div id
rightDiv.setAttribute("style", "float:right;width:50%;"); //Set div attributes
user_name = document.createTextNode(user + ' '); //Set user name
details_btn = document.createElement("button"); //Create details button
btn_txt = document.createTextNode("Details"); //Create button text
details_btn.appendChild(btn_txt); //Add "Details" to button text
details_btn.onclick = function(){moreInfo(user, phone, age, city, zipCode);}; //Assign button function
cell1.appendChild(leftDiv);
cell1.appendChild(user_name); //Add name to row
cell1.appendChild(rightDiv);
cell1.appendChild(details_btn); //Add button to row
row.appendChild(cell1); //Add row to table
tabbody.appendChild(row);
var newcell = row.insertCell(i);
newcell.innerHTML = table.rows[0].cells[i].innerHTML;
}
}
Try this:
function creatediv() {
var newdiv = document.createElement('div');
newdiv.setAttribute('id', id);
newdiv.style.width = 300;
newdiv.style.height = 300;
newdiv.style.position = "absolute";
newdiv.style.background = "#C0C0C0";
newdiv.innerHTML = "Dynamic Div";
document.body.appendChild(newdiv);
}
The problem is that you need to place the username and button inside the floating divs you have created, whereas you have placed them in the same cell as the div, but at the same level as the divs.
So try changing this section:
cell1.appendChild(leftDiv);
cell1.appendChild(user_name); //Add name to row
cell1.appendChild(rightDiv);
cell1.appendChild(details_btn); //Add button to row
row.appendChild(cell1); //Add row to table
tabbody.appendChild(row);
to this:
leftDiv.appendChild(user_name); // Add name to left div
rightDiv.appendChild(details_btn); // Add button to right div
cell1.appendChild(leftDiv);
cell1.appendChild(rightDiv);
row.appendChild(cell1); //Add row to table
tabbody.appendChild(row);
Also, if more than 1 row is going to be added, the divs will get duplicate IDs of "left" and "right". Use a class instead.
Finally, you shouldn't need to set the width of the rightDiv to 50%. It should automatically right-align itself, if that is what you are after.
Instead of giving css rules individually, use css rule set directly like this :
div.className = "div_class_right/left"; //for creating right/left div respectively.
And create rule set div_class like this in your css :
.div_class_right/left{
float : right/left;
width : 50%;
}

Categories

Resources