so i wrote this code that would create a list and then append an input to it on click. really simple. but the problem is it doesn't work and i have no idea why
here is the code:
function pushing() {
var li = document.createElement("li");
var inputValue = document.getElementById("inp").value;
var pushchild = document.createTextNode(inputValue);
li.appendChild(pushchild);
}
sub.addEventListener("click", pushing);
the id inp is an input id. thank you
Add this to the last line of your function. Append your newly created li element to the ul.
document.querySelectorAll(‘ul’).appendChild(newCreatedLi);
Your list item is never appended to a list element.
// Cache the elements,
// add the button listener,
// & focus on the input
const list = document.querySelector('ul');
const input = document.querySelector('#inp');
const sub = document.querySelector('#sub');
sub.addEventListener('click', pushing);
input.focus();
function pushing() {
const li = document.createElement('li');
const text = document.createTextNode(input.value);
li.appendChild(text);
// Adding the list item to the list element
list.appendChild(li);
}
<input id="inp" />
<button id="sub">Click</button>
<ul></ul>
Related
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>
(New to Javascript)
I have created a input box which turns the input value into a list item, and adds a star
I am trying to create a new list whereby when the star is clicked on, it will copy into the 'favourites' section
I have tried this, but it is not working
let newStarSpan = document.querySelector("span")
newStarSpan.addEventListener('click', function(e){
//on click, get the parent node of the item clicked on
//i.e., want to return the individual <li> list item for the starSpan that was cliked on
let favNode = this.parentNode
//create a copy of this list item (the parent node)
let nodeCopy = favNode.cloneNode(true)
//add it to list B - favourites list
listB.appendChild(nodeCopy)
https://codepen.io/jemimacholzer/pen/dyYMKxj
You have few issues in your code, the first issue is related to the selector
const listB = document.querySelector('listB')
update it with
Fix:
const listB = document.getElementById('listB')
the other issue is related to newSpan event declaration & its scope, the newSpan can't be accessed outside of btn.onclick function.
You also assigned click listener to newSpan which seems to declare & bind on page when no newSpan is present in Dom. So instead of defining the listener you need create a function which triggers on newSpan click and bind that function during newSpan creation.
const listA = document.getElementById("listA")
const input = document.querySelector('input')
const btn = document.querySelector('button')
const listB = document.getElementById('listB')
btn.onclick = function() {
let Shopitem = input.value //store current value of input element in variable
input.value = ' ' //empty input element
const listItem = document.createElement('li') //creating a list item for the shopping item
listItem.setAttribute('id', Shopitem)
const span = document.createElement('span') //list text
const newBtn = document.createElement('button') //creating button to delete item
var starSpan = document.createElement("span")
var text = document.createTextNode("\u2B50")
starSpan.appendChild(text)
//making span and button children of the list item (containing within each list item)
listItem.appendChild(starSpan)
listItem.appendChild(span) //add list text to list item
listItem.appendChild(newBtn) //add list remove button to list item
newBtn.textContent = 'Delete'
span.textContent = Shopitem
listA.appendChild(listItem) //add li to the ul list
newBtn.onclick = function(e) {
list.removeChild(listItem)
}
starSpan.onclick = function(e) {
cloneListItem(listItem)
}
input.focus(); //focus the input method ready for entering the next shopping list item
}
//need to create new reference to star span as old reference is inside eother function
function cloneListItem(favNode){
//create a copy of this list item (the parent node)
let nodeCopy = favNode.cloneNode(true)
//add it to list B - favourites list
listB.appendChild(nodeCopy)
}
https://codepen.io/jemimacholzer/pen/dyYMKxj
I am creating a Todolist, when I write something in the input and use the function addNewFunc() it adds a new li, the problem is that it always just overrides that li, it never makes a new li. (example: I write 1 in the input, use the function and 1 will be added as an li, if i write 2 in the input and use the function, that 1 will now become 2, instead of having a 1 and 2)
let input = document.querySelector(".input");
let ul = document.querySelector("ul");
let addNew = document.createElement("li");
let addNewFunc = function () {
let name = ul.appendChild(addNew);
name.textContent = input.value
};
<h1>spooky</h1>
<input type="text" class="input">
<ul>
<li>1</li>
<li>2</li>
</ul>
let input = document.querySelector(".input");
let ul = document.querySelector("ul");
let addNewFunc = function () {
let addNew = document.createElement("li");
addNew.innerHTML = input.value;
let name = ul.appendChild(addNew);
};
<h1>spooky</h1>
<input type="text" class="input"><button onclick='addNewFunc()'> add</button>
<ul>
<li>1</li>
<li>2</li>
</ul>
Create new li element everytime on the function call, add value to it then append to ul element.
A couple of issues.
1) Move let addNew = document.createElement("li"); inside the function. When it's outside the function you're just reusing the same element over and over. If that line is in the function, you create a new element each time the function is called.
2) Might be worth changing that function expression to a function declaration so that it works better as I was picking up the following error in JSFiddle when I was testing the code:
ReferenceError: can't access lexical declaration `addNewFunc' before initialization
let input = document.querySelector(".input");
let ul = document.querySelector("ul");
let button = document.querySelector('button');
button.addEventListener('click', addNewFunc)
function addNewFunc() {
let addNew = document.createElement("li");
addNew.textContent = input.value;
ul.appendChild(addNew);
};
DEMO (I added a button for convenience)
It happens because you have stored ul element in a variable, so you're appending new child at the same position (ul parent is not updated with information about new elements in it).
Try with:
let addNewFunc = function () {
let name = document.querySelector("ul").appendChild(addNew);
};
You can create new li like this:
let addNewFunc = function () {
var ul = document.getElementById("list");
var li = document.createElement("li");
li.appendChild(document.createTextNode("option string"));
ul.appendChild(li);
};
Full code is
let input = document.querySelector(".input");
let ul = document.querySelector("ul");
input.onchange=function(){
let addNew = document.createElement("li");
addNew.innerHTML=this.value;
this.value="";
ul.appendChild(addNew);
}
This should help u.
please note: I have minute changes to your html; here u enter in inputbox and click button to add it to list
here is the fiddle : https://jsfiddle.net/5o2vwdqc/
html
<h1>spooky</h1>
<input type="text" class="input">
<button id="addToList">
Add to List
</button>
<ul id="theList">
<li>1</li>
<li>2</li>
</ul>
js
let input = document.querySelector(".input");
let ul = document.querySelector("ul");
let addNew = document.createElement("li");
document.getElementById("addToList").onclick = function() {
let inputValue = document.getElementsByClassName("input")[0].value;
let addNew = document.createElement("li");
let textNode = document.createTextNode(inputValue);
addNew.appendChild(textNode);
document.getElementById("theList").appendChild(addNew);
}
I have an app with a few buttons, and every button has an element, button one has a "banana" and button 2 has an "apple", when the user clicks on those buttons, a new li element should be added to a list. Here is a JSFiddle with an example of the problem I'm running into:
https://jsfiddle.net/ejha3q94/
Only 1 li is created with every click and the elements are just added on that same li.
var newElement = document.createElement("li");
var newElText = document.createTextNode ("");
document.getElementById("itemOne").addEventListener("click", function() {
newElText = document.createTextNode("Banana");
document.getElementById("list").appendChild(newElement).appendChild(newElText);
});
document.getElementById("itemTwo").addEventListener("click", function() {
newElText = document.createTextNode("Apple");
document.getElementById("list").appendChild(newElement).appendChild(newElText);
});
How can I make it so every click is a new li element using only Javascript?
You can't reuse elements by reassigning them. You have to create a new element each time you wish to insert a new element into the DOM.
This solution creates a generic function addItem for your procedure. You can see all the element creation and DOM manipulation in one place.
// element references
var list = document.getElementById('list');
var appleBtn = document.getElementById('apple');
var bananaBtn = document.getElementById('banana');
// DOM manipulating function
function addItem(listElem, text) {
var li = document.createElement('li');
var textNode = document.createTextNode(text);
listElem.appendChild(li).appendChild(textNode);
}
// event listeners
appleBtn.addEventListener('click', function(event) {
addItem(list, 'apple');
});
bananaBtn.addEventListener('click', function(event) {
addItem(list, 'banana');
});
<ul id="list"></ul>
<button id="apple">Apple</button>
<button id="banana">Banana</button>
But even repeating addItem(list, *) can get repetitious too. Plus, we don't necessarily need one event listener per button. Wouldn't it be nice if we could just use a single event listener to handle all of the cases?
The solution below uses a data-* attribute to store each button's contribution to the list. Then, using event delegation we handle all buttons with a single event listener (function).
// element references
var list = document.getElementById('list');
var buttons = document.getElementById('buttons');
// single #buttons event delegate
buttons.addEventListener('click', function(event) {
// event.target contains the element that was clicked
var item = event.target.dataset.item;
if (item === undefined) return false;
var li = document.createElement('li');
var textNode = document.createTextNode(item);
list.appendChild(li).appendChild(textNode);
});
<ul id="list"></ul>
<div id="buttons">
<button data-item="apple">Apple</button>
<button data-item="banana">Banana</button>
<button data-item="orange">Orange</button>
<button data-item="grape">Grape</button>
<button data-item="plum">Plum</button>
</div>
Make sure that var newElement and newElText is created or cloned on every click instead of referenced: https://jsfiddle.net/ejha3q94/2/
Otherwise it won't create a new list element but modifies the existing list element every time.
document.getElementById("itemOne").addEventListener("click", function() {
var newElement = document.createElement("li");
var newElText = document.createTextNode("Banana");
document.getElementById("list").appendChild(newElement).appendChild(newElText);
});
document.getElementById("itemTwo").addEventListener("click", function() {
var newElement = document.createElement("li");
var newElText = document.createTextNode("Apple");
document.getElementById("list").appendChild(newElement).appendChild(newElText);
});
You can use document.querySelectorAll() with selector "[id^=item]"; iterate elements using for..of loop; create the elements within click event handler; append #text node to li element using HTMLElement.dataset before appending li element to ul element
<div id="itemOne" data-fruit="Banana">
🍌
</div>
<div id="itemTwo" data-fruit="Apple">
🍎
</div>
<ul id="list"> </ul>
<script>
var list = document.getElementById("list");
for (el of document.querySelectorAll("[id^=item]")) {
el.addEventListener("click", function() {
list.appendChild(document.createElement("li"))
.textContent = this.dataset.fruit;
})
}
</script>
jsfiddle https://jsfiddle.net/ejha3q94/4/
There can only be a single newElText node. If you append it multiple times, it will just be moved. You should clone it manually:
var newElement = document.createElement("li");
var list = document.getElementById("list");
document.getElementById("itemOne").addEventListener("click", function() {
var newElText = document.createTextNode("Banana");
list.appendChild(newElement.cloneNode(false)).appendChild(newElText);
});
document.getElementById("itemTwo").addEventListener("click", function() {
var newElText = document.createTextNode("Apple");
list.appendChild(newElement.cloneNode(false)).appendChild(newElText);
});
<div id="itemOne">🍌</div>
<div id="itemTwo">🍎</div>
<ul id ="list"></ul>
Here is my code: http://jsfiddle.net/H5bRH/
Every time I click on the submit button, it should insert what I typed into a new li item.
But instead of that, it inserts what I typed the first time PLUS the new value that I typed. Play with my jsfiddle to see what I mean.
How do I fix this so that it only adds what the user inputs into the form?
I assume there's something wrong here:
function saveTweet() {
var tweet = document.getElementById("tweet");
var tweetName = tweet.value;
var li = document.createElement("li");
li.innerHTML = tweetName;
var ul = document.getElementById("tweets");
ul.appendChild(li);
}
You have attached 2 click event to save button.
button.onclick = saveTweet;
Using jQuery $("#saveTweet").click(function ()
$("#saveTweet").click(function () {
var tweet = document.getElementById("tweet");
var tweetName = tweet.value;
var li = document.createElement("li");
li.innerHTML = tweetName;
var ul = document.getElementById("tweets");
ul.appendChild(li);
$("li").slideDown("fast");
});
JSFiddle
Why not just reduce all that code to :
$("#saveTweet").click(function () {
$('#tweets').append('<li>' + $("#tweet").val() + '</li>')
$("li").slideDown("fast");
});
jsFiddle example
Instead of having two click handlers for the #saveTweet button, move the slideDown call to your saveTweet function.
function saveTweet() {
var tweet = document.getElementById("tweet");
var tweetName = tweet.value;
var li = document.createElement("li");
li.innerHTML = tweetName;
var ul = document.getElementById("tweets");
ul.appendChild(li);
$("li").slideDown("fast");
}
It happens because you bind two click handlers on the #saveTweet element.
One to add the content, and one to animate the li elements..
In your case the animated one is occuring first and the appending second.. so you always animate the previously added element...
Since you use jQuery anyway, why not use that for all your interactions ?
$(function () {
var button = $("#saveTweet");
button.on('click', function () {
var tweet = $("#tweet"),
ul = $("#tweets"),
tweetName = tweet.val(),
li = $('<li>', {html: tweetName});
ul.append(li);
li.slideDown("fast");
});
});
Demo at http://jsfiddle.net/gaby/Y9cY3/1/