Add edit option for text inside <li> element using JavaScript - javascript

I want to change li.innerHtml when I click <li> it creates new input where I can change <li>'s text but after that I want to save it, it does not work well.
I need to change each <li> text when I click that <li>
function setText(elem, text){
elem.innerHTML += text;
}
var arr = ["one", "two", "three"];
for( var i = 0; i < arr.length; i++ ){
var li = document.createElement("li");
li.addEventListener("click", changeText);
setText(li, arr[i]);
var ul = document.createElement("ul");
document.body.appendChild(ul);
ul.appendChild(li);
}
var input = 0;
function changeText(){
input = document.createElement("input");
input.addEventListener("blur", saveText);
document.body.appendChild(input);
input.value = this.innerHTML;
}
function saveText(){
li.innerHTML = this.value;
}

You can assign an ID when creating the li and then add this id as a data attribute on input so you would know which input was changed and which li to update.
Here
function setText(elem, text){
elem.innerHTML += text;
}
var arr = ["one", "two", "three"];
for( var i = 0; i < arr.length; i++ ){
var li = document.createElement("li");
li.id = i;
li.addEventListener("click", changeText);
setText(li, arr[i]);
var ul = document.createElement("ul");
document.body.appendChild(ul);
ul.appendChild(li);
}
var input = 0;
function changeText(event){
input = document.createElement("input");
input.addEventListener("blur", saveText);
document.body.appendChild(input);
input.setAttribute("data-liID", event.target.id);
input.value = this.innerHTML;
}
function saveText(event){
document.getElementById(event.srcElement.getAttribute("data-liID")).innerHTML = this.value
}

Modify your function as below
function setText(elem, text){
elem.innerHTML += text;
}
var arr = ["one", "two", "three"];
var ul = document.createElement("ul");
document.body.appendChild(ul);
for( var i = 0; i < arr.length; i++ ){
var li = document.createElement("li");
li.addEventListener("click", changeText);
setText(li, arr[i]);
ul.appendChild(li);
}
var input = 0;
function changeText(){
input = document.createElement("input");
input.addEventListener("change", saveText);
document.body.appendChild(input);
input.value = this.innerHTML;
}
function saveText(){
var li=ul.children;
for (var liElement in li) {
li[liElement].innerHTML = this.value;
}
}

The main issue is, that li in saveText() is undefined. You have to reference it to the input somehow.
Also be aware that you are creating an ul container for each seperate li element. I do not know if that is on purpose. Yet it might be handy, if you see example two.
Example using data-attribute
Here is an example on how to do it with a data-attribute using your code with some slight changes (see comments):
//An array holding potential li-elements
var arr = ['one', 'two', 'three'];
//Creates an input element to change the text for the li element with
function changeText(){
var tIndex = this.getAttribute('data-index'); //The index we gave to the li-element on creating
var input = document.querySelector("input[data-index='" + tIndex + "']"); //Check if the input exists already
if(!input){
input = document.createElement('input'); //Make it local
input.setAttribute('data-index', this.getAttribute('data-index')); //We use this to find the correct li-element in saveText
input.addEventListener('blur', saveText);
document.body.appendChild(input);
input.value = this.innerHTML;
}
};
function setText(elem, text){
elem.innerHTML += text;
};
function saveText(){
var li = document.querySelector("li[data-index='" + this.getAttribute('data-index') + "']"); //Now with the index we can find our element
li.innerHTML = this.value;
};
window.onload = function(){
for(var i = 0; i < arr.length; i++){
var li = document.createElement('li');
li.setAttribute('data-index', i); //We use this to find the correct li-element in saveText
li.addEventListener('click', changeText);
setText(li, arr[i]);
var ul = document.createElement('ul');
document.body.appendChild(ul);
ul.appendChild(li);
}
}
Example using ul as parentNode for both
Another way is to add the input to the ul, so you can just access its parent:
//An array holding potential li-elements
var arr = ['one', 'two', 'three'];
//Creates an input element to change the text for the li element with
function changeText(){
var input = this.parentNode.querySelector('input'); //Check if exists yet
if(!input){
input = document.createElement('input');
input.addEventListener('blur', saveText);
this.parentNode.appendChild(input); //We add the input to the ul instead of the body
input.value = this.innerHTML;
}
};
function setText(elem, text){
elem.innerHTML += text;
};
function saveText(){
var li = this.parentNode.firstChild; //firstchild is the li in this case
li.innerHTML = this.value;
};
window.onload = function(){
for(var i = 0; i < arr.length; i++){
var li = document.createElement('li');
li.addEventListener('click', changeText);
setText(li, arr[i]);
var ul = document.createElement('ul');
document.body.appendChild(ul);
ul.appendChild(li);
}
}
Example using contentEditable
It can also be done by making the li elements editable:
https://developer.mozilla.org/de/docs/Web/API/HTMLElement/contentEditable
var arr = ['one', 'two', 'three'];
window.onload = function(){
var ul = document.createElement('ul');
for(var i = 0; i < arr.length; i++){
var li = document.createElement('li');
li.textContent = arr[i];
li.contentEditable = true;
ul.appendChild(li);
};
document.body.appendChild(ul);
}

Related

Card from Javascript into HTML, there must be a better way (working)

There must be a better, shorter way to generate many cards from javascript into HTML.
This is the format to follow, it's working but can it be better?????
span{color: red;}
<div id="mycard"></div>
var dateSpan = document.createElement('span')
var ul = document.createElement('ul')
var ol = document.createElement('ol')
var li = document.createElement('li');
var li2 = document.createElement('li')
dateSpan.innerHTML = '#3500';
li.textContent = 'Title of card '
li2.textContent = '"Small description"'
li.appendChild(dateSpan);
li.appendChild(ul);
ul.appendChild(li2);
ol.appendChild(li);
var app = document.querySelector('#mycard');
app.appendChild(ol)
Note: Yeah, you can add a '<b/r>' but the "Small description" should be stylish later on... :)
Create a function to generate html content and then call that function as many time as you want.
For example
function generateList(title, description){
var htmlVal = `<li>${title}<br>${description}</li>`;
return htmlVal;
}
Then call the function however you like and append it to the element.
document.getElementById("myCard") += generateList("Title of Card #3500","Small description");
Where in your html there's an element with id "myCard"
You can create a class cardMaker and create instances with a for loop:
class cardMaker {
constructor(n) {
var dateSpan = document.createElement('span')
var ul = document.createElement('ul')
var ol = document.createElement('ol')
var li = document.createElement('li');
var li2 = document.createElement('li')
dateSpan.innerHTML = '#3500' + n;
li.textContent = 'Title of card '
li2.textContent = '"Small description"'
li.appendChild(dateSpan);
li.appendChild(ul);
ul.appendChild(li2);
ol.appendChild(li);
var app = document.querySelector('#mycard');
app.appendChild(ol)
}
}
let cards = [];
for (let i = 0; i < 10; i++) {
cards[i] = new cardMaker(i);
}

Create span element in li with Javascript

I'm working on a to-do list project and when creating a new li I would like it to start with a span containing a "X". I wrote the code below, but instead of a span I get "[object HTMLSpanElement]". Anybody knows how to fix this? Thank you!
var enterItem = document.querySelectorAll("input");
var todoList = document.getElementById("todo-list");
for (var i = 0; i < enterItem.length; i++) {
enterItem[i].addEventListener("keypress", function(key) {
if(key.which === 13){
var newLi = document.createElement("li");
var span = document.createElement("span");
var newItem = this.value;
span.textContent = "X";
newLi.appendChild(document.createTextNode(span + " " + newItem));
todoList.appendChild(newLi);
this.value = "";
}
});
}
You are trying to add an html element in a textNode so it triggers the toString of the element
You need
const todoList = document.getElementById("todo-list");
document.getElementById("inputContainer").addEventListener("keypress", function(e) {
const tgt = e.target;
if (tgt.type === "text" && e.which === 13) {
let newLi = document.createElement("li");
let span = document.createElement("span");
span.classList.add("remove");
let newItem = tgt.value;
span.textContent = "X";
newLi.appendChild(span)
newLi.appendChild(document.createTextNode(" " + newItem));
todoList.appendChild(newLi);
tgt.value = "";
}
});
document.getElementById("todo-list").addEventListener("click", function(e) {
const tgt = e.target;
if (tgt.classList.contains("remove")) {
tgt.closest("li").remove();
}
})
<div id="inputContainer">
<input type="text" />
</div>
<ul id="todo-list"></ul>

Adding item to dynamic list

I'm trying to add text items from the user to a dynamic list. I tried but not getting it. How to go about it...thanks.
<div id="displayList"></div>
Add Text
<script>
var displayList = document.getElementById('displayList')
var inputTxt = document.getElementById('inpText')
var listArray = ['Orange', 'White', 'Green'];
var li;
var ul = document.createElement('ul')
var len = listArray.length;
for(var i=0; i<len; i++){
li = document.createElement('li')
li.appendChild(document.createTextNode(listArray[i]))
ul.appendChild(li)
}
displayList.appendChild(ul)
</script>
The code seems to work just fine as you can see.
var displayList = document.getElementById('displayList')
var inputTxt = document.getElementById('inpText')
var listArray = ['Orange', 'White', 'Green'];
var li;
var ul = document.createElement('ul')
var len = listArray.length;
for(var i=0; i<len; i++){
li = document.createElement('li')
li.appendChild(document.createTextNode(listArray[i]))
ul.appendChild(li)
}
displayList.appendChild(ul)
<div id="displayList"></div>
So the only problem that might exist is if the script is run before the DOM is ready and thus the document.getElementById('displayList') does not return anything because the displayList does not yet exist.
Try running your script at the end of the file. Or run it after the DOM ready event (in the DOMContentLoaded event)
document.addEventListener('DOMContentLoaded', function() {
var displayList = document.getElementById('displayList')
var inputTxt = document.getElementById('inpText')
var listArray = ['Orange', 'White', 'Green'];
var li;
var ul = document.createElement('ul')
var len = listArray.length;
for(var i=0; i<len; i++){
li = document.createElement('li')
li.appendChild(document.createTextNode(listArray[i]))
ul.appendChild(li)
}
displayList.appendChild(ul)
}, false);
Try this:
$('#displayList').append(ul);

How can i create a submenu using the DOM in javascript

I'm trying to create a submenu, so that when the item on the menu line is clicked then a submenu will appear along with all its values.
I've created a label along with a div to illustate it.
Once the label is clicked, another div needs to produce another list of items, i haven't got a clue how to do this. Please help !!
<script>
var div = document.createElement("div");
var lbl = document.createElement("label");
lbl.innerHTML = "Menu";
div.appendChild(lbl)
btn.onlclick = function() {
var alert = prompt("This button works");
};
The list works but i need to show up when i click on the label
(function() {
var outerUL, li, innerUL, thirdLI, index;
outerUL = document.createElement('ul');
for (index = 0; index < 5; ++index) {
li = document.createElement('li');
li.innerHTML = "SubMenu" + index;
if (index === 2) {
thirdLI = li;
}
outerUL.appendChild(li);
}
innerUL = document.createElement('ul');
for (index = 0; index < 3; ++index) {
li = document.createElement('li');
li.innerHTML = "Subsubmenu #" + index;
innerUL.appendChild(li);
}
thirdLI.appendChild(innerUL);
document.body.appendChild(outerUL);
})();
document.body.appendChild(div);
Any Suggestions ??
Thank you

Remove clicked <li> onclick

I have this JavaScript code:
window.onload = init;
function init () {
var button = document.getElementById("submitButton");
button.onclick = addItem;
var listItems = document.querySelectorAll("li"); //assigning the remove click event to all list items
for (var i = 0; i < listItems.length; i++) {
listItems[i].onclick = li.parentNode.removeChild(li);
}
}
function addItem() {
var textInput = document.getElementById("item"); //getting text input
var text = textInput.value; //getting value of text input element
var ul = document.getElementById("ul"); //getting element <ul> to add element to
var li = document.createElement("li"); //creating li element to add
li.innerHTML = text; //inserting text into newly created <li> element
if (ul.childElementCount == 0) { //using if/else statement to add items to top of list
ul.appendChild(li); // will add if count of ul children is 0 otherwise add before first item
}
else {
ul.insertBefore(li, ul.firstChild);
}
}
function remove(e) {
var li = e.target;
var listItems = document.querySelectorAll("li");
var ul = document.getElementById("ul");
li.parentNode.removeChild(li);
}
and this HTML:
<body>
<form>
<label for="item">Add an item: </label>
<input id="item" type="text" size="20"><br>
<input id="submitButton" type="button" value="Add!">
</form>
<ul id="ul">
</ul>
<p>
Click an item to remove it from the list.
</p>
</body>
What I want to do is remove the whichever <li> element the user clicks, but this doesn't seem to be working and I am unable to find an answer anywhere else online for this specific scenario. Hoping someone can help me out here and show me what i am missing.
UPDATE
Plain JS delegation
Add the eventListener to the UL to delegate the click even on dynamically inserted LIs:
document.getElementById("ul").addEventListener("click",function(e) {
var tgt = e.target;
if (tgt.tagName.toUpperCase() == "LI") {
tgt.parentNode.removeChild(tgt); // or tgt.remove();
}
});
jQuery delegation
$(function() {
$("#submitButton").on("click",function() {
var text = $("#item").val(); //getting value of text input element
var li = $('<li/>').text(text)
$("#ul").prepend(li);
});
$("#ul").on("click","li",function() {
$(this).remove();
});
});
Original answer
Since you did not mention jQuery
var listItems = document.getElementsByTagName("li"); // or document.querySelectorAll("li");
for (var i = 0; i < listItems.length; i++) {
listItems[i].onclick = function() {this.parentNode.removeChild(this);}
}
you may want to wrap that in
window.onload=function() { // or addEventListener
// do stuff to the DOM here
}
Re-reading the question I think you also want to add that to the dynamic LIs
li.innerHTML = text; //inserting text into newly created <li> element
li.onclick = function() {
this.parentNode.removeChild(this);
// or this.remove(); if supported
}
Here is the complete code as I expect you meant to code it
Live Demo
window.onload=function() {
var button = document.getElementById("submitButton");
button.onclick = addItem;
}
function addItem() {
var textInput = document.getElementById("item"); //getting text input
var text = textInput.value; //getting value of text input element
var ul = document.getElementById("ul"); //getting element <ul> to add element to
var li = document.createElement("li"); //creating li element to add
li.innerHTML = text; //inserting text into newly created <li> element
li.onclick = function() {
this.parentNode.removeChild(this);
// or this.remove(); if supported
}
if (ul.childElementCount == 0) { //using if/else statement to add items to top of list
ul.appendChild(li); // will add if count of ul children is 0 otherwise add before first item
}
else {
ul.insertBefore(li, ul.firstChild);
}
}
In case you want to use jQuery, the whole thing gets somewhat simpler
Live Demo
$(function() {
$("#submitButton").on("click",function() {
var text = $("#item").val(); //getting value of text input element
var li = $('<li/>')
.text(text)
.on("click",function() { $(this).remove()});
$("#ul").prepend(li);
});
});
I know you already received an answer, but back to your original remove function. You have the following:
function remove(e) {
var li = e.target;
var listItems = document.querySelectorAll("li");
var ul = document.getElementById("ul");
li.parentNode.removeChild(li);
}
Change it to this and you should get what you were trying to achieve:
function remove(e)
{
var li = e.target;
var ol = li.parentElement;
ol.removeChild( li);
return false;
}
I'd suggest simplifying things a little:
Object.prototype.remove = function(){
this.parentNode.removeChild(this);
};
var lis = document.querySelectorAll('li');
for (var i = 0, len = lis.length; i < len; i++) {
lis[i].addEventListener('click', remove, false);
}
JS Fiddle demo.
Of course, having done the above, I'd then have to go further (possibly because I like jQuery too much) and also:
Object.prototype.on = function (evt, fn) {
var self = this.length ? this : [this];
for (var i = 0, len = self.length; i < len; i++){
self[i].addEventListener(evt, fn, false);
}
};
Object.prototype.remove = function(){
var self = this.length ? this : [this];
for (var i = 0, len = self.length; i < len; i++){
self[i].parentNode.removeChild(self[i]);
}
};
document.querySelectorAll('li').on('click', remove);
JS Fiddle demo.
If you don't want to write function in javascript, you can use immediately invoked anonymous function like below...
<elem onclick="(function(_this){_this.parentNode.removeChild(_this);})(this);"
If I understood you correctly:
$("li").on("click", function() {
$(this).remove()
});
The answer is more obvious than it could seem, you forgot to add init() in your script, is normal that the click event aren't triggered, they're not set on the element!
EDIT:
Your code has some logical errors. If you don't add an onclick function for all those created elements you will not be able to remove the clicked element. This is because the function init() is called one time at the load of the page!
function init() {
var button = document.getElementById("submitButton");
button.onclick = function() {addItem()};
}
function addItem() {
var textInput = document.getElementById("item"); //getting text input
var text = textInput.value; //getting value of text input element
var ul = document.getElementById("ul"); //getting element <ul> to add element to
var li = document.createElement("li"); //creating li element to add
li.innerHTML = text; //inserting text into newly created <li> element
li.onclick = function() {this.parentNode.removeChild(this);}
if (ul.childElementCount == 0) { //using if/else statement to add items to top of list
ul.appendChild(li); // will add if count of ul children is 0 otherwise add before first item
} else {
ul.insertBefore(li, ul.firstChild);
}
}
init();

Categories

Resources