Dynamically inserting elements so they can still be deleted - javascript

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/

Related

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

Unable to get asynchronous child spawning in 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>

Create List Item From Rich Text Field Content

I want to take the user input text from this div and input tag I've got:
<input id="title" placeholder="Title (Optional)">
<div class="editor" contenteditable></div>
The div is a rich text field that I've put in place of a regular textarea tag
and create a list item inside a <ul> tag.
Here is the javascript I've got, but is not working...
(works just fine with regular text area, but I get nothing with the rich text form)
/*------POST SUBMIT JS------*/
//target all necessary HTML elements
var ul = document.getElementById('list'),
removeAll = document.getElementById('removeAll'),
add = document.getElementById('add');
//make something happen when clicking on 'submit'
add.onclick = function(){
addLi(ul)
};
//function for adding items
function addLi(targetUl){
var inputText = document.getElementsByClassName('editor').value, //grab input text (the new entry)
header = document.getElementById('title').value, //grab title text
li = document.createElement('li'), //create new entry/li inside ul
content = document.createElement('div'),
title = document.createElement('div'),
removeButton = document.createElement('button'); //create button to remove entries
content.setAttribute('class','content')
title.setAttribute('class','title')
content.innerHTML = inputText;
title.innerHTML = header;
if (inputText.split(' ').join(' ').length === 0) {
//check for empty inputs
alert ('No input');
return false;
}
removeButton.className = 'removeMe'; //add class to button for CSS
removeButton.innerHTML = 'Delete'; //add text to the remove button
removeButton.setAttribute('onclick', 'removeMe(this);'); //creates onclick event that triggers when entry is clicked
li.appendChild(title); //add title textnode to created li
li.appendChild(content); //add content textnode to created li
li.appendChild(removeButton); //add Remove button to created li
targetUl.appendChild(li); //add constructed li to the ul
}
//function to remove entries
function removeMe(item){
var deleteConfirm = confirm('Are you sure you want to delete this entry?');
if (deleteConfirm){var parent = item.parentElement;
parent.parentElement.removeChild(parent)}
};
function checkRemoval(){
var entryConfirm = confirm('Are you sure you want to delete all entries?');
if (entryConfirm){
ul.innerHTML = '';
}
};
Here is the demo I'm working on
Here is the demo using a textarea tag
getElementsByClassName('editor') is going to return an array of elements with the class editor, so you can't just do .value, you need to get the first element in the array.
Also, since it's a div, I think you want to use textContent, so it'll look like this
var inputText = document.getElementsByClassName('editor')[0].textContent
for the input type you have to write following into your javascript:
var input_val = getElementsByClassName('title').value;
for the div you have to write following into your javascript:
var div_val = getElementsByClass('editor').value;
I hope this will work

Dynamic creation of radio button in Html for IE

Can anybody give me a working code for creating dynamic radio buttons in html (and javascript) which works in IE, Firefox and Chrome?
I saw a lot of codes in the internet, but none of them worked for me.
I also need them to have a label. And I don't want to use Jquery.
Tried this code:
function test() {
var element = document.createElement("input");
//Assign different attributes to the element.
element.setAttribute('type', 'radio');
element.setAttribute('value', 'source');
element.setAttribute('name', 'source');
element.setAttribute('id', 'source_id');
var foo = document.getElementById("divTxt");
foo.appendChild(element);
var newlabel2 = document.createElement("Label");
newlabel2.for = "source_id";
newlabel2.innerHTML = "first name ";
foo.appendChild(newlabel2);
}
var radio1 = document.createElement('input');
radio1.id = 'myRadioId1';
radio1.type = 'radio';
radio1.name = 'radioGroup';
radio1.value = 'someValue1';
var radio2 = document.createElement('input');
radio2.id = 'myRadioId2';
radio2.type = 'radio';
radio2.name = 'radioGroup';
radio2.value = 'someValue2';
var label1 = document.createElement('label');
label1.htmlFor = radio1.id;
label1.innerHTML = 'label for radio1';
var label2 = document.createElement('label');
label2.htmlFor = radio2.id;
label2.innerHTML = 'label for radio2';
Appending to container:
var container = document.getElementById('mydivid');
container.appendChild(radio1);
container.appendChild(label1);
container.appendChild(radio2);
container.appendChild(label2);
If you need radio group, you should give them same names. Here is fiddle
The main problem with the code (which you posted in a comment and I copied into the question) is that it contains only a function definition. The function is not called at all, so need to have a statement like test(). Moreover, the function postulates that there is an element with id=divTxt on the page, and that element must appear before the calling the function. The following code successfully creates a radio button element and its label and inserts them into an existing element on the page:
<!DOCTYPE html>
<title>Demo</title>
<div id=divTxt></div>
<script>
function test() {
var element = document.createElement("input");
//Assign different attributes to the element.
element.setAttribute('type', 'radio');
element.setAttribute('value', 'source');
element.setAttribute('name', 'source');
element.setAttribute('id', 'source_id');
var foo = document.getElementById("divTxt");
foo.appendChild(element);
var newlabel2 = document.createElement("Label");
newlabel2.setAttribute('for', "source_id");
newlabel2.innerHTML = "first name ";
foo.appendChild(newlabel2);
}
test();
</script>
(You cannot use the for property in JavaScript; the property name is htmlFor, but it is probably simpler to set the for attribute as above.)
However, radio buttons should always appear in groups, due to their nature, so you should use a function with some arguments to generate a set of radio buttons according to a common pattern. Like this:
<!DOCTYPE html>
<title>Demo</title>
<div id=divTxt></div>
<script>
function radio(name, value, text) {
var element = document.createElement("input");
var id = name + value;
element.setAttribute('type', 'radio');
element.setAttribute('value', value);
element.setAttribute('name', name);
element.setAttribute('id', id);
var foo = document.getElementById("divTxt");
foo.appendChild(element);
var newlabel2 = document.createElement("label");
newlabel2.setAttribute('for', id);
newlabel2.innerHTML = text;
foo.appendChild(newlabel2);
}
radio('sex', '0', 'male');
radio('sex', '1', 'female');
</script>
You should minimally enhance this by adding code that adds line breaks between the items, or preferably put each pair of a button and its label inside a div elemebt.

Change the onClick function to target the edit buttons

I have the following script
var counter = 0;
function appendText(){
var text = document.getElementById('usertext').value;
if ( document.getElementById('usertext').value ){
var div = document.createElement('div');
div.className = 'divex';
var li = document.createElement('li');
li.setAttribute('id', 'list');
div.appendChild(li);
var texty = document.createTextNode(text);
var bigdiv = document.getElementById('addedText');
var editbutton = document.createElement('BUTTON');
editbutton.setAttribute('id', 'button_click');
var buttontext = document.createTextNode('Edit');
editbutton.appendChild(buttontext);
bigdiv.appendChild(li).appendChild(texty);
bigdiv.appendChild(li).appendChild(editbutton);
document.getElementById('button_click').setAttribute('onClick', makeAreaEditable());
document.getElementById('usertext').value = "";
counter++;
}
};
var makeAreaEditable = function(){
alert('Hello world!');
};
I want the makeAreaeditable function to work when the Edit button is pressed(for each of the edit buttons that are appended under the textarea).. In this state, the script, alerts me when i hit the Addtext button.
the following is the html. P.S. i need this in pure javascript, if you can help. thanks
<textarea id="usertext"></textarea>
<button onClick="appendText()">Add text </button>
<div id="addedText" style="float:left">
</div>
instead of:
document.getElementById('button_click').setAttribute('onClick', makeAreaEditable());
you need to do this:
editbutton.onclick = makeAreaEditable;
the function's name goes without brackets unless you want to execute it
instead of obtaining the element from the DOM using document.getElementById('button_click')
you can use the editbutton variable already created. this object is the DOM element you are looking for
SIDE NOTE:
the standard way to do it is to add the onclick property before appending the element

Categories