Unable to get asynchronous child spawning in JavaScript - javascript

I'm trying to format this code in such a way that when a user clicks a button, new input fields each with a redirect button gets inserted asynchronously into the un-ordered list, it worked up until i added the redirect button to also be inserted upon each click of the spawn button.
Here is my JS code...
function spawnSilly()
{
var div = document.createElement("DIV");
var input = document.createElement("INPUT");
var button = document.createElement("BUTTON");
var att1 = document.createAttribute("type")
var att2 = document.createAttribute("placeholder")
var att3 = document.createAttribute("type")
var att4 = document.createAttribute("onClick")
att1.value = "text"
att2.value = "Title"
att3.value = "button"
att4.value = "redirect()"
input.setAttributeNode(att1)
input.setAttributeNode(att2)
button.setAttribute(att3)
button.setAttribute(att4)
div.appendChild(input)
div.appendChild(button);
var list = document.getElementById("spawnList");
list.insertBefore(div, list.childNodes[0]);
}
This is my HTML
<ul id="spawnList">
</ul>
<button id="spawnbtn" onClick="spawnSilly()">Add</button>
Seems to be the button thats causing the issue, but i can't figure out why?
Any help would be awesome! thanks

Note that setAttribute() takes two arguments, the name of the attribute and the value. Using this in the right way, the code can be simplified like this:
function redirect()
{
console.log("Redirect clicked!");
}
function spawnSilly()
{
var div = document.createElement("DIV");
var input = document.createElement("INPUT");
var button = document.createElement("BUTTON");
input.setAttribute("type", "text");
input.setAttribute("placeholder", "Title");
button.setAttribute("type", "button");
button.setAttribute("onClick", "redirect()");
button.innerHTML = "Redirect";
div.appendChild(input)
div.appendChild(button);
var list = document.getElementById("spawnList");
list.insertBefore(div, list.childNodes[0]);
}
.as-console {background-color:black !important; color:lime;}
<ul id="spawnList"></ul>
<button id="spawnbtn" onClick="spawnSilly()">Add</button>

setAttribute take two parameters, first is the name of attribute and second is value, but you have only one - https://developer.mozilla.org/en-US/docs/Web/API/Element/setAttribute.
Instead you can set the value to attributes using . operator.
Also, you are attaching a function call att4.value = "redirect()". So, whenever the button gets added your redirect will get called. Instead attach a callback to redirect, so it gets called when the button is clicked.
function spawnSilly()
{
const div = document.createElement("DIV");
const input = document.createElement("INPUT");
const button = document.createElement("BUTTON");
input.type = "text";
input.value = "Title";
button.type ="button";
button.onclick = redirect;
button.textContent = "Click Me!";
div.appendChild(input)
div.appendChild(button);
const list = document.getElementById("spawnList");
list.insertBefore(div, list.childNodes[0]);
}
function redirect() {
console.log('In redirect');
}
<ul id="spawnList">
</ul>
<button id="spawnbtn" onClick="spawnSilly()">Add</button>

Related

document.getElementById(idz.toString()) causing Type Error: typ1 is null javascript

I am trying to add a check box when button is pressed and also delete the same checkbox when the delete is pressed. Unfortunatly the delete function cannot run as it seems that the newly created div doesn't exist yet. How can I get around this?
<script>
const list = document.getElementById("list");
const cli_form = document.getElementById("client-form");
let idz = 0;
function add_client(input) {
const div = document.createElement("div");
div.setAttribute("id", idz.toString())
const newCheckbox = document.createElement("input");
newCheckbox.setAttribute("type", 'checkbox');
newCheckbox.setAttribute("id", 'checkbox');
const newLabel = document.createElement("label");
newLabel.setAttribute("for", 'checkbox');
newLabel.innerHTML = input.value;
const br = document.createElement("br");
const del = document.createElement("input");
del.setAttribute("type", 'button');
del.setAttribute("value", idz.toString());
del.onclick = delete_item(document.getElementById(idz.toString()));
div.appendChild(newCheckbox);
div.appendChild(newLabel);
div.appendChild(del);
div.appendChild(br);
list.appendChild(div);
idz++;
}
function delete_item(item1) {
item1.remove();
}
</script>
You are assigning the result of the function delete_item which invoke immediately. Therefore, it is removing the item before it is being added to DOM.
You might use an arrow wrapper to avoid immediate invocation.
Like this :
del.onclick = () => delete_item(document.getElementById(idz.toString()));

Deleting List dynamically when Button is clicked Javascipt

I'm trying to create a list from user text input where each list contains a delete button which deletes the list when the delete button is clicked using javascript. However, I can't get my delete button to work. Here's what I've tried:
In HTML:
<ul id="thisul"></ul>
<input type="text" placeholder="Add New" id="input">
<input type="submit" class="button" value="Submit" onclick ="show()">
In JS:
function show(){
var ul = document.getElementById("thisul");
var input= document.getElementById("input");
var li = document.createElement("li");
li.classList.add("thisLI");
if(input.value!==""){
li.innerHTML=input.value+'<button><i class="fas fa-trash" aria-hidden="true"></i></button>';
ul.appendChild(li);
ul.on("click", "button", function(){
del(this);
});
}
}
function del(x){
var deleting = document.getElementsByClassName("thisLI");
var theList = x.parentElement;
var index = Array.from(deleting).indexOf(x);
theList.removeChild(deleting[index]);
}
Can anyone help me with this?
Thank you!
You seem to be using some jQuery here when adding the event listener. You also want to target some elements in the global scope so you don't have to target them everytime the function is called. Here is how I would do it.
//Global scope
const ul = document.getElementById('thisul');
const input = document.getElementById('input');
function show() {
const li = document.createElement('li')
const div = document.createElement('div')
const button = document.createElement('button')
const i = document.createElement('i')
div.textContent = input.value
i.className = 'fas fa-trash'
i.setAttribute('aria-hidden', 'true')
button.appendChild(i)
button.addEventListener('click', function() {
li.remove()
})
li.append(div, button)
ul.appendChild(li)
}
This should work.
Edit:
Just re-read that you want to click the button to delete. I will tweak the code a little bit.
JSFiddle Link

How to dynamically add remove block using javascript

I am facing a problem while removing a paragraph, which I have added using javascript.
Adding buttons work fine. The problem occurs when I try to remove the paragraph.
function rdn_id(){return Math.random().toString(36).substring(7);}
//create button
function create_btn()
{
//Create a remove button
var btn_remove = document.createElement("BUTTON");
//create a unique button ID
id_btn_remove = rdn_id();
btn_remove.id = id_btn_remove ;
btn_remove.textContent = "Remove file";
return [btn_remove, id_btn_remove];
}
//add elt function
function create_p_btn()
{
//Create paragraph
var paragraph = document.createElement("P");
//create a unique p ID
id_paragraph = rdn_id();
paragraph.id = id_paragraph;
paragraph.style.paddingTop = "5px";
paragraph.style.background = "blue";
document.getElementById("setItHere").appendChild(paragraph);
// add button
var values = create_btn();
var btn_rmv = values[0];
var id_btn = values[1];
paragraph.appendChild(btn_rmv);
document.getElementById(id_btn).addEventListener("onclick", function(){remove_func(id_paragraph);});
}
//Remove function
function remove_func(id_el)
{
var elt = document.getElementById(id_el);
elt.parentNode.removeChild(id_el);
}
<div id="setItHere">
<Button id="start" onclick="create_p_btn();">add</Button>
</div>
Am I missing something ?
Thank you in advance.
You need to make two changes:
Event name should be click instead of onclick
elt.parentNode.removeChild(id_el); should be elt.parentNode.removeChild(elt);
Check out this pen
https://codepen.io/tanmayv/pen/yLNwNNJ

My JavaScript code isn't working properly in Mozilla Firefox

I have a to-do list application on my website that I built using JavaScript. It works perfectly in Google Chrome, but it doesn't work in Mozilla Firefox. I have read that each browser interprets JavaScript differently, but I haven't been able to pinpoint exactly what the problem is in the code.
So, what happens in Firefox is this: When you type something into the text input and click the "Add Task" button, it does show that a task has been added. However, the label appears blank, as do the Edit and Delete buttons. All of the functionality appears to work as normal (the Edit and Delete buttons work properly, they just don't display the text).
In the code, the each list item is created by a function called createTask. Its code is:
var createTask = function(taskString) {
// taskString is the value of the text input (whatever the user wants the task to read)
// Create Elements
var listItem = document.createElement("li");
var checkbox = document.createElement("input");
var label = document.createElement("label");
var editInput = document.createElement("input");
var editButton = document.createElement("button");
var deleteButton = document.createElement("button");
// Modify Elements
checkbox.type = "checkbox";
label.innerText = taskString;
editInput.type = "text";
editButton.innerText = "Edit";
deleteButton.innerText = "Delete";
// Add Event Listeners
checkbox.addEventListener("change", markTask);
editButton.addEventListener("click", editTask);
deleteButton.addEventListener("click", deleteTask);
// Append the Elements to the List Item
listItem.appendChild(checkbox);
listItem.appendChild(label);
listItem.appendChild(editInput);
listItem.appendChild(deleteButton);
listItem.appendChild(editButton);
return listItem;
}
Then, the function addTask appends listItem to the unordered list that is the tasks list.
var addTask = function() {
if (addInput.value === "") {
addError.style.display = "block"; // Display error message if no input
} else {
addError.style.display = "none"; // Stop displaying error message
var listItem = createTask(addInput.value); // Put user input into createTask function
tasksList.appendChild(listItem); // Add the new list item to the unordered list
addInput.value = ""; // Reset the text input field to blank
addInput.focus();
}
}
Looking more closely, within the createTask function, there is:
label.innerText = taskString;
editButton.innerText = "Edit";
deleteButton.innerText = "Delete";
So, I thought that the innerText property may not work properly in Firefox, but I tried changing it to innerHTML and textContent, and that doesn't work either!
Any ideas?
innerText is deprecated.
Try using textContent instead.
This issue has been described here:
'innerText' works in IE, but not in Firefox
use .textContent and log listItem in console you will see they are constructed properly.below is your code with small changes.tested in firefox:
var createTask = function(taskString) {
// taskString is the value of the text input (whatever the user wants the task to read)
// Create Elements
var listItem = document.createElement("li");
var checkbox = document.createElement("input");
var label = document.createElement("label");
var editInput = document.createElement("input");
var editButton = document.createElement("button");
var deleteButton = document.createElement("button");
// Modify Elements
checkbox.type = "checkbox";
label.textContent = taskString;
editInput.type = "text";
editButton.textContent = "Edit";
deleteButton.textContent = "Delete";
//alert(deleteButton.textContent);
// Add Event Listeners
// checkbox.addEventListener("change", markTask); // commented these because i do not had these objects.
// editButton.addEventListener("click", editTask);
// deleteButton.addEventListener("click", deleteTask);
// Append the Elements to the List Item
listItem.appendChild(checkbox);
listItem.appendChild(label);
listItem.appendChild(editInput);
listItem.appendChild(deleteButton);
listItem.appendChild(editButton);
console.log(listItem);
return listItem;
}

Dynamically inserting elements so they can still be deleted

I want to dynamically add textboxes so each textbox added appears as the last in the list but above the button. I also want a button allowing the deletion of each textbox. The code below adds the textboxes just as I want, but when clicking on "Remove Field" only that text is removed. The textbox associated with that text remains. This DOES work if I don't use "insertBefore" so I'm thinking that messes up what "removalLink" knows what to delete?
<script>
var namesCount = 0;
listNames = function (){
var field_area = document.getElementById("fields");
var li = document.createElement("li");
var input = document.createElement("input");
input.id = "txtName"+namesCount;
input.name = "txtName"+namesCount;
input.type = "text";
li.appendChild(input);
field_area.appendChild(li);
//INSERT ELEMENT JUST BEFORE ADD BUTTON
sp2 = document.getElementById("btnNames");
parentDiv = sp2.parentNode;
parentDiv.insertBefore(input, sp2);
//create the removal link
var removalLink = document.createElement("a");
removalLink.onclick = function(){
this.parentNode.parentNode.removeChild(this.parentNode)
}
var removalText = document.createTextNode("Remove Field");
removalLink.appendChild(removalText);
li.appendChild(removalLink);
field_area.appendChild(li);
//INSERT ELEMENT JUST BEFORE ADD BUTTON
var sp2 = document.getElementById("btnNames");
var parentDiv = sp2.parentNode;
parentDiv.insertBefore(div, sp2);
namesCount++
}
</script>
<body>
<ul id="fields">
Add More Names
</ul>
</body>
Since you've tagged jQuery, I'd suggest using it to significantly simplify your code.
First, fix your HTML so all the children of the <ul> are <li> tags like this:
<ul id="fields">
<li>Add More Names</li>
</ul>
And, then you can replace the entire listNames() function with this much simpler version that doesn't have your issue. I use the .closest("li") method to find the parent <li> tag to remove no matter how many parents above it is located which helps to prevent simple errors or dependencies on the exact HTML layout (e.g. it makes the code less fragile or prone to mistakes):
<script>
var nameCount = 0;
function listNames() {
var id = "txtName" + nameCount;
var li = $("<li>");
$("<input/>", {type: "text", name: id, id: id}).appendTo(li);
$("<a>Remove Field</a>").click(function() {
$(this).closest("li").remove();
}).appendTo(li);
li.insertBefore("#fields li:last");
nameCount++;
}
</script>
Working demo: http://jsfiddle.net/jfriend00/tjb24/
As I show in the demo link, you can also get rid of the onclick handler from the HTML and just hook up to it with an event listener, otherwise referred to as unobtrusive javascript where you separate the HTML from the javascript.
If you still want it all in plain javascript, you can do this:
<ul id="fields">
<li id="fieldAdd>Add More Names</li>
</ul>
<script>
var nameCount = 0;
document.getElementById("btnNames").addEventListener("click", function(e) {
var id = "txtName" + nameCount;
var li = document.createElement("li");
var input = document.createElement("input");
input.type = "text";
input.name = input.id = id;
li.appendChild(input);
var removeLink = document.createElement("a");
removeLink.innerHTML = "Remove Field";
removeLink.addEventListener("click", function(e) {
this.parentNode.parentNode.removeChild(this.parentNode);
e.preventDefault();
});
li.appendChild(removeLink);
var fields = document.getElementById("fields");
var fieldAdd = document.getElementById("fieldAdd");
fields.insertBefore(li, fieldAdd);
nameCount++;
e.preventDefault();
});
</script>
Working demo: http://jsfiddle.net/jfriend00/gTWqu/

Categories