I'm working with JavaScript and HTML and I would like to be able to add user input to a multilevel list in HTML. I have started by making a multilevel list in HTML. As an example I have made a list with Dog information.
<div>
<h3> Dogs </h3>
<ul id="myList">
<li><b>Dog Breeds</b>
<ul>
<li class="facts"> There are a approximately 340 recognized breeds.</li>
</ul>
</li>
<li><b>Dog Fur</b>
<ul>
<li class="facts"> Depending on the dogs, there are a lot of different kinds of fur.</li>
</ul>
</li>
</ul>
</div>
Underneath this list I have made 2 fields which can hold userinput and a button next to it which can add the typed in information to the list. My code for the button and type fields is the following:
<input type='text' id='input' placeholder="Title"/>
<button type="button" id="add">Add new dog fact</button><br>
<textarea id="input2" rows="5" cols="18" placeholder="The dog fact.."></textarea>
In order to add the input to the list, I have written this piece of code:
"myList" is the id I have given the unordered list.
document.getElementById("add").onclick = function() {
var title = document.getElementById("input").value;
var description = document.getElementById("input2").value;
var li = document.createElement("li");
li.textContent = title + description;
document.getElementById("myList").appendChild(li);
document.getElementById("input2").value = ""; // clears the value
document.getElementById("input").value = ""; // clears the value
My problem now, is that it will not be structured as I would like.
By using the code above, the output will be as following if I type in "Dog Size" as title and "Dogs can be both large and small." as the description:
Dog SizeDogs can be both large and small.
instead of:
Dog Size
Dogs can be both large and small.
Does anyone know how to change this, so the user input will be structured the same way the rest of the list is? So that the description will be nested within the title? I'm aware that it is because I have defined "li.textContent" as "title + description", I just don't know how else to add the description data. I have tried to create 2 new list elements in the javaScript code, but this just, as expected, creates 2 new list elements and then I tried to style the description-element with "title.style.listStyleType = "none";", but if I place it in the function, then the entire functions stops working. I'm very confused, and if anyone is able to help me I would be very grateful! Thank you :)
use innerHTML and add <br> between title and description.
document.getElementById("add").onclick = function() {
var title = document.getElementById("input").value;
var description = document.getElementById("input2").value;
var li = document.createElement("li");
li.innerHTML = title + "<br>" + description;
document.getElementById("myList").appendChild(li);
document.getElementById("input2").value = "";
document.getElementById("input").value = "";
}
<div>
<h3> Dogs </h3>
<ul id="myList">
<li><b>Dog Breeds</b>
<ul>
<li class="facts"> There are a approximately 340 recognized breeds.</li>
</ul>
</li>
<li><b>Dog Fur</b>
<ul>
<li class="facts"> Depending on the dogs, there are a lot of different kinds of fur.</li>
</ul>
</li>
</ul>
</div>
<input type='text' id='input' placeholder="Title" />
<button type="button" id="add">Add new dog fact</button><br>
<textarea id="input2" rows="5" cols="18" placeholder="The dog fact.."></textarea>
</div>
Instead of using onclick, use addEventListener and if you want to add the description(as ul) under the title, below is the code.
const list = document.querySelector('#myList');
document.querySelector('button#add')
.addEventListener('click', function() {
const title = document.querySelector('#input').value;
const description = document.querySelector('#input2').value;
const li = document.createElement('li');
li.innerHTML = `<b>${title}</b>`;
const ul = document.createElement('ul');
const childli = document.createElement('li');
childli.textContent = description;
ul.appendChild(childli);
li.appendChild(ul);
list.appendChild(li);
});
<div>
<h3> Dogs </h3>
<ul id="myList">
<li><b>Dog Breeds</b>
<ul>
<li class="facts"> There are a approximately 340 recognized breeds.</li>
</ul>
</li>
<li><b>Dog Fur</b>
<ul>
<li class="facts"> Depending on the dogs, there are a lot of different kinds of fur.</li>
</ul>
</li>
</ul>
</div>
<input type='text' id='input' placeholder="Title" />
<button type="button" id="add">Add new dog fact</button><br>
<textarea id="input2" rows="5" cols="18" placeholder="The dog fact.."></textarea>
Related
I'm trying to create a to-do list app but i cant seems to append the user data to my list
html:
<div id="Html">
<input id="input-task" placeholder="New Task" >
<button id="add-btn" type="button" onclick="newTask()">
Add Tasks
</button>
</div>
<div>
<ul id="task-table">
<li>Task 1</li>
</ul>
</div>
separate javascript file:
const inputTask = document.getElementById('input-task').value;
var li = document.createElement('li');
var t = document.createTextNode('inputTask');
li.appendChild(t);
document.getElementById('task-table').appendChild(li);
}
inputTask is variable containing the text value but you using that as if it is string, remove the quotes around it.
I will also suggest you to avoid inline event handler, you can use addEventListener() instead like the following way:
document.getElementById('add-btn').addEventListener('click', newTask);
function newTask(){
const inputTask = document.getElementById('input-task').value;
var li = document.createElement('li');
var t = document.createTextNode(inputTask); //remove quotes here
li.appendChild(t);
document.getElementById('task-table').appendChild(li);
}
<div id="Html">
<input id="input-task" placeholder="New Task" >
<button id="add-btn" type="button">
Add Tasks
</button>
</div>
<div>
<ul id="task-table">
<li>Task 1</li>
</ul>
</div>
Try like this.
You should call newTask function and append child in it.
const inputTask = document.getElementById('input-task').value;
function newTask(){
var li = document.createElement('li');
var t = document.createTextNode(document.getElementById('input-task').value);
li.appendChild(t);
document.getElementById('task-table').appendChild(li);
document.getElementById('input-task').value="";
}
<div id="Html">
<input id="input-task" placeholder="New Task" >
<button id="add-btn" type="button" onclick="newTask()">
Add Tasks
</button>
</div>
<div>
<ul id="task-table">
<li>Task 1</li>
</ul>
</div>
Nothing wrong in your code!
Simple fixed this line
var t = document.createTextNode('inputTask');
Remove ('' quotes)
var t = document.createTextNode(inputTask);
And Final thing I don't know may be you have already done this but I want to mention this
Wrap this code inside the newTask() function
Example: -
function newTask(){
const inputTask = document.getElementById('input-task').value;
var li = document.createElement('li');
var t = document.createTextNode(inputTask);
li.appendChild(t);
document.getElementById('task-table').appendChild(li);
}
I am struggling with adding new "button" element into my "list". I was trying to append or someting els but doesn't work. It is not usual ul to li. If you ask why button parent it is form bootstrap list-group
UPDATE JS. IT is now adding "button but not corectlly.
<div class="list-group">
<button type="button" class="list-group-item">
<ul class="desc">
<li class="t-desc50">Add Device</li>
<li class="t-desc55"><i class="fa fa-plus fa-2x" aria-hidden="true"></i></li>
</ul>
</button>
<button type="button" class="list-group-item" id="new-item>
<ul class="desc">
<li class="t-desc">Lamp</li>
<li class="t-desc2">5 kwH</li>
<li class="t-desc3"><label class="switch">
<input type="checkbox">
<span class="slider round"></span>
</label></li>
</ul>
</button>
<button type="button" class="list-group-item" id="new-item>
<ul class="desc">
<li class="t-desc">AC</li>
<li class="t-desc2">5 kwH</li>
<li class="t-desc3"><label class="switch">
<input type="checkbox">
<span class="slider round"></span>
</label></li>
</ul>
</button>
</div>
JS
document.querySelector('.fa-plus').addEventListener('click', addItem
);
function addItem() {
var list = document.getElementById("list-group");
var li = document.createElement("button");
li.setAttribute('id', li);
li.appendChild(document.createTextNode(li));
list.appendChild(li);
}
If you want to add an element to the dom, you can use :
var element = document.createElement(tagName);
https://developer.mozilla.org/fr/docs/Web/API/Document/createElement
Then append your element.
You can add event listener to element, and add class before if you need.
Comment answer
The code you need is probably something like that :
function addItem() {
var list = document.getElementById('list-group')
//Button
var button = document.createElement('button');
button.classList.add("list-group-item");
//Ul
var ul = document.createElement('ul');
ul.classList.add("desc");
//li
var liFirst = document.createElement('li');
var liSecond = document.createElement('li');
var liThird = document.createElement('li');
liFirst.innerHTML = "Lamp"
liSecond.innerHTML = "5 kwH"
//Label
var label = document.createElement('label');
label.classList.add("switch");
var input = document.createElement('input');
input.type = 'checkbox';
var span = document.createElement('span');
span.classList.add("slider");
span.classList.add("round");
label.append(input)
label.append(span)
liThird.append(label)
ul.append(liFirst)
ul.append(liSecond)
ul.append(liThird)
button.append(ul)
list.append(button)
}
You need to pass the function as argument instead of calling it:
// wrong:
document.querySelector('.fa-plus').addEventListener('click', addElement());
// right:
document.querySelector('.fa-plus').addEventListener('click', addElement);
addEventListener expects a callback function, if you call the function first, you are sending the result of the function as argument, which is wrong.
You need to pass the addElement function instead, so the addEventListener calls it.
got it!
function addItem() {
var list = document.getElementById('list-group')
var button = document.createElement('button');
var ul = document.createElement('ul');
var liFirst = document.createElement('li');
var liSecond = document.createElement('li');
var liThird = document.createElement('li');
button.classList.add("list-group-item");
ul.classList.add("desc");
liFirst.classList.add("t-desc")
liSecond.classList.add("t-desc2")
liThird.classList.add("t-desc3")
liFirst.innerText = 'TV'
liSecond.innerText = '5kwh'
liThird.innerHTML = `<label class="switch">
<input type="checkbox">
<span class="slider round"></span>
</label>`
ul.append(liFirst)
ul.append(liSecond)
ul.append(liThird)
button.append(ul)
list.append(button)
}
There are several semantic errors in both the markup and the code. Firstly, <button type="button" class="list-group-item" id="new-item> misses the closing double quotes. Secondly, one should not use an id twice as the OP's example does with id="new-item. At third addEventListener misses its 3rd argument.
Besides that it will be hard if not impossible to capture any click event on the fa-plus classified <i/> element; one should use the whole button instead ... that's what a button is for.
Additionally one might rethink how to retrieve/query the structure one wants to add the new element to. I would suggest a more generic approach that retrieves the top most group parent from within the structure where the click event did occur, thus one can make use of more than just on list-group classified element.
Having sanitized the code the OP'S given example then might look similar to this ...
function getClosestParentByClassName(elm, className) {
while (elm && !elm.classList.contains(className)) {
elm = elm.parentNode;
}
return elm;
}
function addItem(evt) {
//console.log(evt.currentTarget);
var
groupParent = getClosestParentByClassName(evt.currentTarget, 'list-group'),
itemBlueprint = groupParent && groupParent.querySelector('.list-group-item.new-item'),
newGroupItem = (itemBlueprint && itemBlueprint.cloneNode(true)) || createDefaultItem();
//console.log(groupParent, itemBlueprint, newGroupItem);
if (newGroupItem) {
// do whatever needs to be done in order to place the right content into this structure.
groupParent.appendChild(newGroupItem);
}
}
getClosestParentByClassName(document.querySelector('.fa-plus'), 'list-group-item').addEventListener('click', addItem, false);
function createDefaultItem() {
var
renderContainer = document.createElement('div');
renderContainer.innerHTML = [
'<button type="button" class="list-group-item new-item">'
, '<ul class="desc">'
, '<li class="t-desc">#missing t-desc</li>'
, '<li class="t-desc2">#missing t-desc2</li>'
, '<li class="t-desc3">'
, '<label class="switch">'
, '<input type="checkbox">'
, '<span class="slider round"></span>'
, '</label>'
, '</li>'
, '</ul>'
, '</button>'
].join('');
return renderContainer.querySelector('button');
}
.as-console-wrapper { max-height: 100%!important; top: 0; }
<div class="list-group">
<button type="button" class="list-group-item">
<ul class="desc">
<li class="t-desc50">Add Device</li>
<li class="t-desc55"><i class="fa fa-plus fa-2x" aria-hidden="true"></i></li>
</ul>
</button>
<button type="button" class="list-group-item new-item">
<ul class="desc">
<li class="t-desc">Lamp</li>
<li class="t-desc2">5 kwH</li>
<li class="t-desc3">
<label class="switch">
<input type="checkbox">
<span class="slider round"></span>
</label>
</li>
</ul>
</button>
<button type="button" class="list-group-item new-item">
<ul class="desc">
<li class="t-desc">AC</li>
<li class="t-desc2">5 kwH</li>
<li class="t-desc3">
<label class="switch">
<input type="checkbox">
<span class="slider round"></span>
</label>
</li>
</ul>
</button>
</div>
Hello I am trying to render a dynamic nested ul list from a json using a for loop in javascript,
After trying for couple of hours I was able to make it work,there are some small details i need to fix, for example my javascript is rendering all the objects as html elements, how do I render only the elements needed on the view, for example:
<ul class="some_class">
<li>
<h3>
level_0_name => Africa
<input type="checkbox" name="level_0_id => VALUE HERE" id="">
</h3>
<ul class="some_class">
<li>
<h3>
level_1_name => Company San Fracisco
<input type="checkbox" name="level_1_id => VALUE HERE" id="">
</h3>
<ul class="some_class">
<li>
<h3>
level_2_name => Some title
<input type="checkbox" name="level_2_id => VALUE HERE" id="">
</h3>
<ul class="some_class">
<li>
<h3>
John Doe
<input type="checkbox" name="" id="" value="id VALUE">
</h3>
</li>
if you look at the http://jsfiddle.net/creativestudio/3avzp6o3/3/ i created you will notice the menu starts at:
"level_0": [
and is rendering markup not needed, is there an easy way to only render the objects with an actual value like "level_1_id" => "12345" into the list?
This is the JS function:
function tree(data) {
if (typeof(data) == 'object') {
var ul = $('<ul>');
for (var i in data) {
ul.append($('<li>').text(i).append(tree(data[i])));
}
return ul;
} else {
var textNode = document.createTextNode(' => ' + data);
return textNode;
}
}
$(document.body).append(tree(data));
I am trying to retrieve data-cost("#packages") and append it to #form next to Ticket-price. I am not getting any errors in console. I can't seen to understand what went wrong.
JS:
<script src="jquery-1.11.2.js"></script>
<script>
$(document).ready(function()
{
var price=$("#packages").data("cost");
var amount=$("<span>"+price+"</span>");
$("#form").next().next().append(amount);
});
</script>
HTML:
<div id="packages">
<h2><u>Tourism Packages:</u></h2>
<ul>
<li data-name="Southern Travels">Travels Name: Southern Travels</li>
<li data-cost="2000">Cost per person: 2000</li>
<li>Duration: 3 days & 4 nights</li>
</ul>
</div>
<div id="form">
<label>Number of persons </label>
<input id="input"type="text"/ autofocus>
<p id="ticket-price">Ticket Price</p>
</div>
For this to work as it is, you must edit your HTML as following:
<div id="packages" data-name="Southern Travels" data-cost="2000">
<h2><u>Tourism Packages:</u></h2>
<ul>
<li>Travels Name: Southern Travels</li>
<li>Cost per person: 2000</li>
<li>Duration: 3 days & 4 nights</li>
</ul>
</div>
Either that, or access the data properties of the <li> elements instead of the div#packages (i.e #packages ul li instead of #packages)
$(document).ready(function() {
// Targeting 2nd li element inside #packages
var price=$("#packages li").eq(2).data("cost");
// create a span element with text 'price'
var amount=$("<span>"+price+"</span>");
// append as last child of the form
$("#form").append(amount);
});
You need to look for your data attribute by name - and look at the LI's.
You also need to build your html string and append it properly to the #ticket-price
WOKING EXAMPLE (FIDDLE): http://jsfiddle.net/ojLo8ojz/
JS:
$(document).ready(function(){
var price = $("#packages li[data-cost]").attr("data-cost");
var amount = "<span> "+price+"</span>";
$("#ticket-price").append(amount);
});
I am teaching myself javascript and don't understand the results I am getting from some example code. I have pruned the code for brevity.
The html:
<body>
<h1>firstChild and lastChild Property Lab</h1>
<hr />
<form>
<label>Enter some text to add or replace in the OL element:</label>
<br />
<input type="text" name="input" size="50" />
<br />
<input type="button" value="Insert at Top"
onclick="prepend(this.form)" />
<input type="button" value="Append to Bottom"
onclick="append(this.form)" />
<br />
<input type="button" value="Replace First Item"
onclick="replaceFirst(this.form)" />
<input type="button" value="Replace Last Item"
onclick="replaceLast(this.form)" />
</form>
<ol id="myList">
<li>Initial Item 1</li>
<li>Initial Item 2</li>
<li>Initial Item 3</li>
<li>Initial Item 4</li>
</ol>
</body>
The javascript:
// helper function for prepend() and append()
function makeNewLI(txt)
{
var newItem = document.createElement("LI");
newItem.innerHTML = txt;
return newItem;
}
function replaceFirst(form)
{
var newItem = makeNewLI(form.input.value)
var firstLI = document.getElementById('myList').firstChild.value;
document.getElementById('myList').replaceChild(newItem, firstLI);
}
I thought if I entered some text in the text box and clicked the Replace First Item button that the first item in the list would be replaced. However, the first time I do that it is prepended to the top of the list and the list now has 5 items. Then if I change the text in the text box and click the Replace First Item button again the first item in the list is changed.
I don't understand why this is happening. I expected the replacement would happen whenever I clicked the button. I am working with Firefox 4 on Ubuntu 10.04. Also, if I try to replace the last item in the list result is the same as I outlined above.
Thanks, Jim
There are 2 things wrong there. Firstly, you are selecting the value instead of the element with var firstLI = document.getElementById('myList').firstChild.value; so use var firstLI = document.getElementById('myList').firstChild; instead.
Secondly, believe it or not your firstChild is a TextNode with empty text with your current markup. Remove the empty space between <ol> and the first <li> so that its <ol><li>...., like here:
http://jsfiddle.net/niklasvh/5anyq/
Two problems:
You need to pass the node, not the value property (which doesn't even exist).
The first child is a text node, not the element (it's white space to be precise). You could either remove the white space or replace the call to firstChild with the more reliable .getElementsByTagName('li')[0].
Working jsFiddle
Some browsers support firstElementChild, which does what it says on the tin. For maximum efficiency, you could do this:
var list = document.getElementById('myList');
var firstLI = list.firstElementChild || list.getElementsByTagName('li')[0];