function show() {
var todos = get_todos();
var html = '<ul>';
for(var i=0; i<todos.length; i++) {
html += '<li>' + todos[i] + ' <button class="remove" id="' + i + '">Delete</button></li>';
};
html += '</ul>';
document.getElementById('todos').innerHTML = html;
var buttons = document.getElementsByClassName('remove');
for (var i=0; i < buttons.length; i++) {
buttons[i].addEventListener('click', remove);
};
}
In this code, I want to separate the 'ul and li' structure on the html page. Could you help me?
Here is want something you can do, if you want some code to html
You can refer the js from html using script tag check the plunker below
You need that script too, because you are adding li dynamically using script
Eg: <script src = "script.js"></script>
Steps:
I have taken a html and created a ul element.
Created a script which appends li to the ul element.
Added a reference to that script using the script tag
function show() {
var ul = document.getElementById('list');
var html = '';
var todos = ["Saab", "Volvo", "BMW"];
for(var i=0; i<todos.length; i++) {
var li = document.createElement("li");
li.appendChild(document.createTextNode(todos[i]));
ul.appendChild(li);
};
ul.append(html);
var buttons = document.getElementsByClassName('remove');
for (var i=0; i < buttons.length; i++) {
buttons[i].addEventListener('click', remove);
};
}
<!DOCTYPE html>
<html>
<body>
<ul id="list">
</ul>
<p id="demo" onClick="show()">Click ME</p>
</body>
</html>
Please run the above snippet
Here is a working demo for the same
I think what you want is an HTML template that you can re-use and keep separate from your JS code. A popular templating engine is handlebars.js.
The steps to get this to work are:
Write a template in your HTML. Using a hidden <div> is one way to do it.
Load the template contents in your JS code.
Compile the template to get a function which will accepts data and returns HTML.
Call that function with your data, assign the result to an existing container element.
Use event delegation to attach behavior to active elements like buttons.
Together this will look like this:
var todoListSource = document.getElementById("todoList").innerHTML;
var todoList = Handlebars.compile(todoListSource);
var items = ["Item 1", "Item 2", "Item 3", "Item 4"];
var todoContainer = document.getElementById("todo");
todoContainer.innerHTML = todoList(items);
// event delegation - use the same event handler for all buttons
// modified from https://stackoverflow.com/a/24117490/18771
todoContainer.addEventListener('click', function (e) {
if (!e.target.matches('.deleteTodo')) return;
e.stopPropagation();
var li = e.target.parentElement;
li.parentElement.removeChild(li);
});
.template {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.11/handlebars.min.js"></script>
<div id="todo"></div>
<div class="template" id="todoList">
<ul>
{{#each .}}
<li>
<span>{{.}}</span>
<button class="deleteTodo">delete</button>
</li>
{{/each}}
</ul>
</div>
Using jQuery you can simplify the JS part.
var todoList = Handlebars.compile($("#todoList").html());
var items = ["Item 1", "Item 2", "Item 3", "Item 4"];
$("#todo").html(todoList(items));
// event delegation - use the same event handler for all buttons
$("#todo").on('click', '.deleteTodo', function (e) {
e.stopPropagation();
$(this).closest('li').remove();
});
.template {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.11/handlebars.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="todo"></div>
<div class="template" id="todoList">
<ul>
{{#each .}}
<li>
<span>{{.}}</span>
<button class="deleteTodo">delete</button>
</li>
{{/each}}
</ul>
</div>
Related
I am learing basics of JavaScript and I have coded a simple shopping list with a delete button. This option works with old items, but when I add a new one and try to delete it, it does not work properly.
HTML:
var lista = document.querySelector('#list')
document.getElementById('add').addEventListener('click', function() {
var deletebtn = "<span class='close'>X</span>"
var newValue = document.getElementById('new_item').value + ' ' + deletebtn;
var newItem = document.createElement('li');
newItem.innerHTML = newValue;
lista.appendChild(newItem);
}, false)
var closebtn = document.getElementsByClassName('close');
for (var i = 0; i < closebtn.length; i++) {
closebtn[i].addEventListener('click', function() {
this.parentElement.style.display = 'none';
})
}
<div id=”page”>
<h1 id=”header”>Shopping list</h1>
<h2>What should I buy</h2>
<ul id="list">
<li id="one">Milk<span class="close">X</span></li>
<li id="two">Apples<span class="close">X</span></li>
<li id="three">Oranges<span class="close">X</span></li>
<li id=”four”>Vodka<span class="close">X</span></li>
</ul>
<input type="text" placeholder="Type in a new item" id="new_item"><button id='add'>ADD</button>
</div>
It's because your new item does not have the click event listener attached.
Add event listener for the close button like this:
var deletebtn = document.createElement('span');
// ...add class, inner html...
deletebtn.addEventListener('click', deleteFunc);
Also, make your delete function a reusable function and attach it like this:
function deleteFunc() {
this.parentElement.style.display = 'none';
}
...
closebtn[i].addEventListener('click', deleteFunc)
...
I'm just starting to learn JS and collided with a specific task that i dont understand how to solve.
Suppose we have a page that has a list, and there is a button with which I can supplement this list with new cases.
The problem that I encountered:
I need to implement a function in a certain way that will change the style of the selected line from the list of all existing and added elements.
For example, if our list - "a list of things that we have to do", i need to make so that the user can press the "Done" button, and select the desired line. After the selection the selected line gets a line-through.
function addItemToTheList() {
var newItem = document.createElement("li");
var input = document.getElementById("Input");
newItem.innerHTML = input.value;
input.value = "";
document.getElementById("todo").appendChild(newItem);
}
#todo {
font-family: Arial;
}
#todo .done {
color:gray;
text-decoration:line-through;
}
<!doctype html>
<html>
<head>
<title> How can user change added and predefined elements in the list?</title>
</head>
<pre>
<input type = "text" id = "Input" maxlength = "42" size = "42" placeholder = " Add a task here"> <input
type = "button" value = "Add" onclick = "addItemToTheList()">
</pre>
<hr align = "left" width = "378">
<body>
<div id = "todoList">
<ol id = "todo">
<li class = "done"> Watch all seasons of "Game of Thrones"</li>
<li class = "done"> Write a book</li>
<li class = "undone"> Learn "JS"</li>
</ol>
</div>
</body>
</html>
Would anybody be willing to point me in the right direction?
You have to add, first, a click event on each undone tasks.
Then when you create a task just add another clickevent.
Then you just have to click on an undone tasks to change his state.
Hope this is what you want :
function addItemToTheList() {
var newItem = document.createElement("li");
var input = document.getElementById("Input");
newItem.innerHTML = input.value;
input.value = "";
document.getElementById("todo").appendChild(newItem);
// Add click listener
newItem.addEventListener('click', done);
}
function done() {
this.className = "done";
this.removeEventListener('click',done);
}
// Initialize all listener for current undone tasks
function init() {
var undoneItems = document.getElementsByClassName('undone');
for(var i = 0; i < undoneItems.length; i++){
undoneItems[i].addEventListener('click', done);
}
}
#todo {
font-family: Arial;
}
#todo .done {
color:gray;
text-decoration:line-through;
}
#todo .undone {
cursor: pointer;
}
<!doctype html>
<html>
<head>
<title> How can user change added and predefined elements in the list?</title>
</head>
<body onload="init()">
<pre>
<input type = "text" id = "Input" maxlength = "42" size = "42" placeholder = " Add a task here"> <input
type = "button" value = "Add" onclick = "addItemToTheList()">
</pre>
<hr align = "left" width = "378">
<div id = "todoList">
<ol id = "todo">
<li class = "done"> Watch all seasons of "Game of Thrones"</li>
<li class = "done"> Write a book</li>
<li class = "undone"> Learn "JS"</li>
</ol>
</div>
</body>
</html>
You need to create another function, add a button to each of the li items and add an on click function to each button to change the class to done.
Here is a jsfiddle link where i've begun the work required. It isn't fully functional but what would you learn from me doing everything :)
https://jsfiddle.net/nu6b00o0/
(function(){
var buttons = document.getElementsByTagName('button');
for(i = 0; i <= buttons.length -1; i++){
buttons[i].addEventListener('click', function() {
doOrUndoItem();
}, false);
if(buttons[i].parentNode.className == 'done'){
buttons[i].className = 'btn-success';
} else {
buttons[i].className = 'btn-warning';
}
}
}());
Feel free to ask any more questions
Tom
Hope this helps...
//list your pre existing items
var items = document.querySelectorAll("li");
function createListElement(){
var li = document.createElement("li");
li.appendChild(document.createTextNode(input.value));
ul.appendChild(li);
//add the function in your new items
li.addEventListener("click", alterStatus)
//
input.value = "";
}
// add/remove class
function alterStatus(){
this.classList.toggle("done");
}
//set the function to the pre existing items
for (var i = 0; i < items.length; i++) {
items[i].addEventListener("click", alterStatus);
}
I apologize for posting this question, I'm just learning JavaScript and have tried using the information from other posts but just cannot get my code to work. The object is to create an li tag and insert list items to this newly created tag, then assign an event handler to remove an item if the user clicks on it.
I have the list populating and can remove an item if I hardcode it but cannot for the life of me figure out how to assign the value of the item being clicked on to the removeItem function. I am also trying to clear the list when an item is entered but keep getting the error "Object doesn't support property or method 'reset'".
If someone could point me in the right direction I would appreciate it.
thanks!
<!doctype html>
<html lang="en">
<head>
<title> Add and delete items Objective </title>
<meta charset="utf-8">
<style>
p {
font-style: italic;
}
li:hover {
cursor: pointer;
}
</style>
<script>
// your code here!
var itemList = [];
window.onload = init;
function init() {
var addButton = document.getElementById("submitButton");
addButton.onclick = addItem;
//var itemList = document.getElementById("list");
var itemsList = document.getElementsByTagName("li");
itemsList.onclick = removeItem;
}
function addItem() {
var newItem = document.getElementById("item").value;
var ul = document.getElementById("list");
var li = document.createElement("li");
li.appendChild(document.createTextNode(newItem));
ul.appendChild(li);
itemList.push(newItem);
document.getElementById("item").reset();
}
function removeItem() {
var editList = document.getElementsByTagName("li");
// var editList = document.getElementsById("list");
for (var i = 0; i < editList.length; i++) {
var item = editList[i];
if(editList.options[i].selected) {
editList.removeChild(editList.childNodes[i]);
}
}
}
</script>
</head>
<body>
<form>
<label form="item">Add an item: </label>
<input id="item" type="text" size="20"><br>
<input id="submitButton" type="button" value="Add!">
</form>
<ul id="list">
</ul>
<p>
Click an item to remove it from the list.
</p>
</body>
</html>
Why not set the value of the item input to an empty string rather than using reset?
document.getElementById("item").value = "";
As for removing the list items...
for (var i = 0; i < ul.children.length; i++) {
ul.children[i].addEventListener("click", removeItem);
}
you can only reset forms, so you have to select the form and then reset will work. f.e. with:
document.forms[0].reset()
your code is adding the eventhandler to all existing li-Elements, if you create some new li-Elements later, you have to add the eventhandler to it manually. f.e. in your addItem-Function with:
li.onclick = removeItem;
after pushing the new Item
in your removeItem-Function you have access on the clicked Element via this, so you can remove only this Element with:
this.remove()
You could change your addItem() and removeItem() functions :
function addItem() {
var newItem = document.getElementById("item").value;
$('#list').append("<li id='" + newItem + "' onclick='removeItem(this)'>" + newItem + "</li>");
}
function removeItem(id) {
$(id).remove();
}
Here I am going to make a tag cloud manually.Everything is going well but I face a little problem. Below is my code :
HTML:
<ul id="tagCloud">
<li id="tagcloud_li">Item1</li>
<li id="tagcloud_li">Item2</li>
</ul>
<div id="vis">
<div class="set_texts">
</div>
</div>
JavaScript :
$(function() {
var liArray = document.getElementsByTagName('li');
var list_item = [];
for(var i=0; i < liArray.length ;i++){
list_item.push($(liArray[i]).text());
var get_item_value = ($(liArray[i]).text());
var create_text = $('#vis').find('.set_texts').append($('<a href="" id="tagcloud_list" class="tagcloud_li'+i+'">'));
$('#vis').find(".tagcloud_li"+i).text($(liArray[i]).text());
}
var count_li = $('#vis').find('#tagcloud_list').length+1;
for(var i=0; i < liArray.length ;i++){
for(var j = 0; j < count_li; j++){
if(i == j){
var get_item_value = ($(liArray[i]).text());
var get_class = $('#vis').find('a').text(get_item_value).append(get_class);
}
}
}
});
Output of this code is :
Item2
Item2
In this output both contain value 'Item2'.
But I want to get value 'item1' in first tag 'a' and value 'item2' in second tag 'a' .Like :
Item1
Item2
How I can get this?
HTML:
<ul id="tagCloud">
<li id="tagcloud_li">Item1</li>
<li id="tagcloud_li">Item2</li>
</ul>
<div id="vis">
<div class="set_texts"></div>
</div>
CSS:
.set_text {
height:500px;
width:500px;
background-color:#FFFFFF;
font-family:Arial;
border: 1px solid #FFFFFF;
text-align:left;
}
.tagcloud {
font-size:12px;
text-decoration:none;
color: #FF7600;
}
JS:
$(function () {
var container = $("#vis").find(".set_texts");
$("#tagCloud").find('li').each(function (i) {
$('<a href="" id="tagcloud_list" class="tagcloud tagcloud_li' + i + '"/>').text($(this).text()).appendTo(container);
});
});
Sample: (Fiddle)
Created tag cloud is simple but it's what your code does.
Your code is very complex and thus you won't see the point for sure. I.e.,
var liArray = document.getElementsByTagName('li');
var list_item = [];
for(var i=0; i < liArray.length ;i++){
list_item.push($(liArray[i]).text());
var get_item_value = ($(liArray[i]).text());
var create_text = $('#vis').find('.set_texts').append($('<a href="" id="tagcloud_list" class="tagcloud_li'+i+'" style="font-size:12px;text-decoration:none; color: #FF7600;">'));
$('#vis').find(".tagcloud_li"+i).text($(liArray[i]).text());
}
might be reduced to this:
$("li").each(function() {
var item = $(this);
var text = item.text();
$('<a href="" class="tagcloud_list" id="tagcloud_li'+i+'" style="font-size:12px;text-decoration:none; color: #FF7600;">')
.text( text )
.appendTo( $('#vis').find('.set_texts') );
});
Your example of this loop is fetching same information from DOM several times and drops it in one of those cases. That's expensive by means of performance. Next you might reverse way of adding the <a> so you won't need to add it to the target container first just to get query that one to give it back afterwards.
The resulting <a> are all using same ID which is bad, too. So try swapping class and ID.
According to your issue this code seems to be crucial:
var get_class = $('#vis').find('a').text(get_item_value).append(get_class);
It is finding all <a> in your target assigning single text to all of them.
Change your Javascript to this.. And I used Jquery..
$(document).ready(function(){
var liArray = $("li");
var i;
for(i=0;i < liArray.length;i++){
$("div.set_texts").append('' + liArray[i].innerHTML + '');
}
});
HTML is like this:
<div class="header">
<ul>
<li>
<a class="abc" id="abc" href="www.testing.com">testing</a>
</li>
</ul>
</div>
My javascript is like this:
<script language="javascript" type="text/javascript">
var links = document.getElementById("abc");
var a = links.getElementsByTagName("a");
var thisLocationHref = window.location.href;
for(var i=0;i<a.length;i++)
{
var tempLink = a[i];
if(thisLocationHref === tempLink.href)
{
tempLink.style.backgroundColor="red";
}
else
{
tempLink.style.backgroundColor="blue";
}
}
I cannot remove ID in the a tag because it relates another page.
I know there is something wrong in the code, but cannot figure out where.
Any help is welcome!
Thanks!
Give the id="abc" to the ul and remove it from the a tag, and your code will work.
Demo: http://jsfiddle.net/BgbjD/
From MDN:
element.getElementsByTagName
Returns a list of elements with the given tag name. The subtree
underneath the specified element is searched, excluding the element
itself.
So you have to search the ul node.
<div class="header">
<ul id="abc">
<li> <a class="abc">testing</a>
</li>
</ul>
</div>
Your JavaScript doesn't need any changes.
Not style.background, style.backgroundColor:
var links = document.getElementById("abc");
var a = links.getElementsByTagName("a");
var thisLocationHref = window.location.href;
for (var i = 0; i < a.length; i++) {
var tempLink = a[i];
if (thisLocationHref === tempLink.href) {
tempLink.style.backgroundColor = "red";
} else {
tempLink.style.backgroundColor = "blue";
}
}