Beginner here.
I'm in the process of building a simple to do website with Javascript. The website allows you to set a title for the task and add steps too.
I'm having some troubles displaying task steps once you add the task to the task list.
The following code:
let data = document.getElementById('task-steps-new');
let dataList = data.childNodes;
let list = document.querySelector('.task-ul');
dataList.forEach((item)=> {
li = document.createElement('li');
li.innerText = item;
list.appendChild(li);
});
displays the task steps as [object HTMLLIElement] instead of the actual text. Cannot wrap my head around why it's not working, so any help would be greatly appreciated! I've also added below the whole function which grabs the task title input and steps and moves it to the task list. Everything works except the issue stated above.
function addTask() {
const inputValue = document.getElementById("add-task").value;
const newTask = document.createElement('h2');
const t = document.createTextNode(inputValue);
const stepList = document.getElementById('task-steps-new');
const newUl = document.createElement('ul');
const newLi = document.createElement('li');
newTask.appendChild(t);
if (inputValue === '') {
alert("You must type something!")
} else {
newLi.className = "task";
newTask.className = "task-title";
newUl.className = "task-ul";
document.querySelector(".task-list").appendChild(newLi);
newLi.appendChild(newTask);
newLi.appendChild(newUl);
let data = document.getElementById('task-steps-new');
let dataList = data.childNodes;
let list = document.querySelector('.task-ul');
dataList.forEach((item)=> {
li = document.createElement('li');
li.innerText = item;
list.appendChild(li);
});
}
document.getElementById("add-task").value = "";
stepList.innerHTML = '';
var span = document.createElement("SPAN");
var txt = document.createTextNode("\u00D7");
span.className = "close";
span.appendChild(txt);
newLi.appendChild(span);
for (i = 0; i < close.length; i++) {
close[i].onclick = function() {
var div = this.parentElement;
div.remove();
}
}
}
Related
In my XML there are some items that have a description tag, while others do not. I would like to display all the items as blog posts, but the description on them should be shown only if it is included.
When I loop through the items, as soon as it detects an item with no description tag, the code breaks. Thus only the first 3 items are displayed on my website, as they have a description but the 4th item does not.
I have tried the if statement in many ways but can't get it to work. Here's what I am working with:
loadXMLFeed = () => {
const url =
'https://myurl.rss';
fetch(url)
.then((response) => response.text())
.then((data) => {
let parser = new DOMParser();
let xml = parser.parseFromString(data, 'application/xml');
loadContent(xml);
});
};
document.addEventListener('DOMContentLoaded', loadXMLFeed);
function loadContent(x) {
let list = document.getElementById('item');
let item = x.getElementsByTagName('item');
let itemNum = x.getElementsByTagName('item').length;
for (let i = 0; i < itemNum; i++) {
let li = document.createElement('li');
li.className = 'listItem';
li.innerHTML = `
<h3>${item[i].getElementsByTagName('title')[0].innerHTML}</h3>
<p>${item[i].getElementsByTagName('description')[0].innerHTML}</p>
`;
list.appendChild(li);
}
}
Finally managed to fix this, using this code:
function loadContent(x) {
let list = document.getElementById('item');
let item = x.getElementsByTagName('item');
let itemNum = x.getElementsByTagName('item').length;
for (let i = 0; i < itemNum; i++) {
let li = document.createElement('li');
li.className = 'listItem';
let title = (li.innerHTML = `
<h3>${item[i].getElementsByTagName('title')[0].innerHTML}</h3>
`);
if (item[i].getElementsByTagName('description')[0]) {
li.innerHTML =
title +
`<p>${item[i].getElementsByTagName('description')[0].innerHTML}</p>`;
}
list.appendChild(li);
}
}
I want to be able to press on my trashcan and be able to delete any todo i want. Right now i can only remove the first index off my todo with with the help off splice. Also when i inspect my array in console i want to be able to use true or false. So when i click on my button my object gets removed from my screen and inside off the array in console it should show that my object indeed have been removed and turns into true instead of false( todoIsRemoved: false). here is a link so you can see all off my code: https://jsfiddle.net/marvstarv/tqdzn8bg/.
this is my class:
let p=0;
let allTheToDos = [];
class Todo{
constructor(toDoItem, removedToDo){
this.Id= p ++;
this.toDoItem = toDoItem;
this.removedToDo = removedToDo;
}
}
this is the function i need help with,
function removeTask (){
let liContainer = document.getElementById ("mySection"); // contains my label(checkmark), Li, and trashcan button.
allTheToDos.splice(Todo,1);
liContainer.innerHTML="";
generateHtml();
console.log(allTheToDos);
}
this function is conected to line 64 off my "main.js": deleteButton.addEventListener('click', () =>{removeTask(allTheToDos[i])});
i appriciate all the help, get back to me if anything was unclear.enter code here
I updated your Js file to:
window.onload = function(){
// without this my site keeps realoding when adding a new item
let firstTask = new Todo ('Bädda sängen',false);
let secondTask = new Todo ('Hänga upp tavlorna',false);
let thirdTask = new Todo ('Kick back & realx',false);
// Adding my premade todo's into my Array that has the variable 'allTheToDos'
allTheToDos.push(firstTask);
allTheToDos.push(secondTask);
allTheToDos.push(thirdTask);
// creating a function so that the user can add a new todo
let addButton = document.getElementById('addBtn');
addButton.addEventListener('click',addNewTask);
generateHtml ();
// let checkedLi = document.getElementById('listItem')
// checkedLi.addEventListener('click',)
console.log(allTheToDos);
}
// my puublic
let p=0;
let allTheToDos = [];
class Todo{
constructor(toDoItem, removedToDo){
this.Id= p ++;
this.toDoItem = toDoItem;
this.removedToDo = removedToDo;
}
}
function generateHtml (){
// Creating an Ul for my items
let section = document.getElementById('mySection');
let myUl = document.createElement('ul');
myUl.className = 'listContainer';
section.appendChild(myUl);
// Creating the loop for my premade todo objects
for(i=0; i<allTheToDos.length; i++){
// Create a div wrapper for my li
let myListWrapperItemContainer = document.createElement('div');
myListWrapperItemContainer.className = "listItemsWrapper";
let id = `to_do_${i}`;
myListWrapperItemContainer.id = id;
// Creating Checked button
let checkedIcon = document.createElement('label');
checkedIcon.className = 'checkedIcon listItemsIcon';
checkedIcon.innerHTML = '<i class="fas fa-check"></i>';
//Creating li
let myLi = document.createElement("li");
myLi.classList = "listItem lineTrough";
myLi.id= "listItem";
// Creating delete button
let deleteButton = document.createElement('button');
deleteButton.id ="deleteButton";
deleteButton.className = 'trashCan listItemsIcon';
deleteButton.innerHTML = '<i class="fas fa-trash-alt"></i>';
// OnClick
deleteButton.addEventListener('click', () => {removeTask(id)});
// Adding everything to my html
myListWrapperItemContainer.appendChild(checkedIcon);
myListWrapperItemContainer.appendChild(myLi);
myListWrapperItemContainer.appendChild(deleteButton);
myLi.innerHTML = allTheToDos[i].toDoItem;
myUl.appendChild(myListWrapperItemContainer);
}
}
function addNewTask (stopRefresh){
stopRefresh.preventDefault();
let liContainer = document.getElementById ("mySection");
let inputValue = document.getElementById('textBox').value;
liContainer.innerHTML="";
if (inputValue == ""){
alert("Type in something");
generateHtml();
}
else{
let newInputValue = new Todo (inputValue);
allTheToDos.push(newInputValue);
generateHtml();
}
}
function removeTask (id){
let element = document.getElementById(id);
let index = allTheToDos.findIndex(e => e.toDoItem === element.textContent);
allTheToDos.splice(index,1);
element.parentNode.removeChild(element);
}
I'm trying to use local storage so that my invites stay on the page when refreshed. How would I go about implementing this into my code. I really don't know where to start and I'm really struggling with it. Please cans someone just show me how to implement this into my code. Ive been creating child elements and appending them to the UL in the HTML.
const form = document.getElementById("registrar");
const input = form.querySelector("input");
const mainDiv = document.querySelector(".main");
const ul = document.getElementById("invitedList");
const div = document.createElement('div');
const filterLabel = document.createElement('label');
const filterCheckBox = document.createElement('input');
filterLabel.textContent = "Hide those who havent responded";
filterCheckBox.type = 'checkbox';
div.appendChild(filterLabel);
div.appendChild(filterCheckBox);
mainDiv.insertBefore(div, ul);
/*
This creates a checkbox to see you has confirmed if they are coming
to the event or not.
*/
filterCheckBox.addEventListener("change", (e) => {
const isChecked = e.target.checked;
const lis = ul.children;
if (isChecked) {
for (let i = 0; i < lis.length; i += 1) {
let li = lis[i]
if (li.className === 'responded') {
li.style.display = '';
} else {
li.style.display = 'none';
}
}
} else {
for (let i = 0; i < lis.length; i += 1) {
let li = lis[i]
li.style.display = '';
}
}
});
/*
This function creates new list items (the invites).
*/
createLi = (text) => {
createElement = (elementName, property, value) => {
const element = document.createElement(elementName);
element[property] = value;
return element;
}
appendElement = (elementName, property, value) => {
const element = createElement(elementName, property, value);
li.appendChild(element);
return element;
}
const li = document.createElement("li");
appendElement("span", "textContent", text);
appendElement("label", "textContent", "Confirmed")
.appendChild(createElement("input", "type", "checkbox"));
appendElement("button", "textContent", "edit");
appendElement("button", "textContent", "remove");
return li;
}
}
form.addEventListener("submit", (event) => {
event.preventDefault();
const text = input.value;
input.value = "";
const li = createLi(text);
ul.appendChild(li);
});
ul.addEventListener("change", () => {
const checkbox = event.target;
const checked = checkbox.checked;
const listItem = checkbox.parentNode.parentNode;
if (checked) {
listItem.className = "responded";
} else {
listItem.className = "";
}
});
ul.addEventListener("click", (e) => {
if (e.target.tagName === 'BUTTON') {
const button = e.target;
const li = button.parentNode;
const ul = li.parentNode;
const action = button.textContent;
const nameActions = {
remove: () => {
ul.removeChild(li);
},
edit: () => {
const span = li.firstElementChild;
const input = document.createElement('input');
input.type = 'text';
input.value = span.textContent;
li.insertBefore(input, span);
li.removeChild(span);
button.textContent = 'Save';
},
Save: () => {
const input = li.firstElementChild;
const span = document.createElement('span');
span.textContent = input.value;
li.insertBefore(span, input);
li.removeChild(input);
button.textContent = 'edit';
}
};
nameActions[action]();
}
});
I only can give you an idea for this, if you are planning to save any big data to localStorage, you can save your data to string and remake it to JSON object!
Here's an exmaple for saving data set
var toSave = [ ];
var whatToSave = (Your invites data List, maybe a "text" var for your code?, organize
to array or loop for your "UL" tag)
for(var i=0;i<whatToSave.length;i++){
var obj = [];
obj[i] = {
text:whatToSave[i].text,
data1:whatToSave[i].data1,
data2:whatToSave[i].data2,
...
}
toSave.push(obj[i]);
}
var saveToString = JSON.stringify(toSave);
localStorage.setItem('invites', saveToString); //your invite data saved in local
storage
....
//after refreshing or when you need to use your saved data
var cameBack = JSON.parse(localStorage.getItem('invites'));
//this will return same data again
//and make function to make UL using retured data array
you don't really need to for loop and push if you already organized needed data to array, just wrote it to make you understand an idea to save data in localStorage. I don't know if this will help you but get an idea and implement it to your project :)
So, I am building a basic to-do list app using a to-do list api and I am having trouble figuring out how to delete one to-do at a time when the user clicks a delete button. I am using the id# that gets created for a new todo that is made.
I thought the code I currently have would work, but nothing happens when I click the delete button.
Any insights into what I am doing wrong?
Here's all my JavaScript, but what I am having trouble with is the last addEventListener at the bottom of the code:
function Todo(title, description, price){
this.title = title;
this.description = description;
this.price = price;
}
document.todo.addEventListener("submit", function(e){
e.preventDefault();
var titleForm = document.todo.title.value;
var descriptionForm = document.todo.description.value;
var priceForm = document.todo.price.value;
var newTodo = new Todo(titleForm, descriptionForm, priceForm);
axios.post("https://api.todo.io/name/todo", newTodo).then(function(response){
console.log(response.data);
})
})
axios.get("https://api.todo.io/name/todo").then(function(response){
for(var i = 0; i < response.data.length; i++){
var h1 = document.createElement("h1");
var h3 = document.createElement("h3");
var h3Price = document.createElement("h3");
var div = document.createElement("div");
var delButton = document.createElement("button");
var displaytitle = document.createTextNode(`Title: ${response.data[i].title}`);
var displayDescription = document.createTextNode(`Description: ${response.data[i].description}`);
var displayPrice = document.createTextNode(`Price: ${response.data[i].price}`);
var displayButton = document.createTextNode("Delete");
h1.appendChild(displaytitle);
h3.appendChild(displayDescription);
h3Price.appendChild(displayPrice);
delButton.appendChild(displayButton);
div.appendChild(h1);
div.appendChild(h3);
div.appendChild(h3Price);
div.appendChild(delButton);
document.body.appendChild(div);
delButton.addEventListener("submit", function(e){
e.preventDefault();
axios.delete(`https://api.todo.io/name/todo/${response.data[i]._id}`).then(function(response){
console.log("Todo Deleted!");
})
})
}
console.log(response.data);
});
From the docs for the 'submit' event:
Note that submit is fired only on the form element, not the button or submit input. (Forms are submitted, not buttons.)
As for your scoping problem, if you extract the body of your for loop as a function:
function addTodo({ _id, description, price, title }) {
const h1 = document.createElement("h1");
const displaytitle = document.createTextNode(`Title: ${title}`);
h1.appendChild(displaytitle);
const h3 = document.createElement("h3");
const displayDescription = document.createTextNode(`Description: ${description}`);
h3.appendChild(displayDescription);
const h3Price = document.createElement("h3");
const displayPrice = document.createTextNode(`Price: ${price}`);
h3Price.appendChild(displayPrice);
const delButton = document.createElement("button");
const displayButton = document.createTextNode("Delete");
delButton.appendChild(displayButton);
delButton.addEventListener("click", function(e) {
e.preventDefault();
axios
.delete(`https://api.todo.io/name/todo/${_id}`)
.then(function(response) {
console.log("Todo Deleted!");
});
});
const div = document.createElement("div");
div.appendChild(h1);
div.appendChild(h3);
div.appendChild(h3Price);
div.appendChild(delButton);
document.body.appendChild(div);
}
axios.get("https://api.todo.io/name/todo").then(function(response) {
for (var i = 0; i < response.data.length; i++) {
addTodo(response.data[i]);
}
console.log(response.data);
});
When adding a new item to the list i would like it to change color based on the input value.
How do i add the input.value to my new appended li item?
I have created a codepen if anyone would be able to help
http://codepen.io/o-sewell/pen/mOBjvQ
// DIV TOGGLE
const toggleButton = document.querySelector('#toggleList');
const listDiv = document.querySelector('.list');
// User INPUT
const userInput = document.querySelector('.userInput');
const button = document.querySelector('button.description');
const p = document.querySelector('p.description');
let listItem = document.querySelectorAll('li');
// ADD ITEM
const addItemInput = document.querySelector('.addItemInput');
const addItemButton = document.querySelector('button.addItemButton');
button.addEventListener('click', () => {
for (let i = 0; i < listItem.length; i++) {
listItem[i].style.color = userInput.value;
}
p.innerHTML = userInput.value + ':';
});
toggleButton.addEventListener('click', () => {
if (listDiv.style.display == 'none') {
listDiv.style.display = 'block';
toggleButton.textContent = 'Hide list';
} else {
listDiv.style.display = 'none';
toggleButton.textContent = 'Show list';
}
});
addItemButton.addEventListener('click', () => {
let list = document.querySelector('ul');
let li = document.createElement('li');
li.textContent = addItemInput.value;
let appendedItem = list.appendChild(li);
console.log(appendedItem);
for (let i = 0; i < appendedItem.length; i++) {
appendedItem[i].style.color = userInput.value;
}
console.log(appended item);
addItemInput.value = '';
});
Here is the new one :
//DIV TOGGLE
const toggleButton = document.querySelector('#toggleList');
const listDiv = document.querySelector('.list');
var lastPickedColor = "black"; // it will store the last picked color
//User INPUT
const userInput = document.querySelector('.userInput');
const button = document.querySelector('button.description');
const p = document.querySelector('p.description');
let listItem = document.querySelectorAll('li');
//ADD ITEM
const addItemInput = document.querySelector('.addItemInput');
const addItemButton = document.querySelector('button.addItemButton');
button.addEventListener('click', () => {
lastPickedColor = userInput.value;
for(let i = 0; i < listItem.length; i++) {
listItem[i].style.color = lastPickedColor;
}
p.innerHTML = userInput.value + ':';
});
toggleButton.addEventListener('click', () => {
if (listDiv.style.display == 'none') {
listDiv.style.display = 'block';
toggleButton.textContent = 'Hide list';
} else {
listDiv.style.display = 'none';
toggleButton.textContent = 'Show list';
}
});
addItemButton.addEventListener('click', () => {
let list = document.querySelector('ul');
let li = document.createElement('li');
li.style.color = lastPickedColor; // so it will add li with last picked color
li.textContent = addItemInput.value;
let appendedItem = list.appendChild(li);
console.log(appendedItem);
for(let i = 0; i < appendedItem.length; i++) {
appendedItem[i].style.color = userInput.value;
}
console.log(appendeditem);
addItemInput.value = '';
});
I added lastPickedColor variable to top of the page whenever you change the color, it will store the lastPickedColor and all list add with this color.
The answer is quite simple.
You're defining the initial list when the js is executed, but the new element is created dynamically. Therefore, you'll have to create a new nodelist based on all elements, including the new one. You can simply redefine it inside the current click event:
button.addEventListener('click', () => {
listItem = document.querySelectorAll('li');
for(let i = 0; i < listItem.length; i++) {
listItem[i].style.color = userInput.value;
}
p.innerHTML = userInput.value + ':';
});
To give it the same color as the existing ones, change this function to apply the styling directly on the latest added element:
addItemButton.addEventListener('click', () => {
let list = document.querySelector('ul');
let li = document.createElement('li');
li.textContent = addItemInput.value;
let appendedItem = list.appendChild(li);
appendedItem.style.color = userInput.value;
addItemInput.value = '';
});
Working codepen example
so I have made 2 changes for your code to work. Please see
http://codepen.io/amoolya/pen/GNMXqa?editors=1111
First change
addItemButton.addEventListener('click', () => {
let list = document.querySelector('ul');
let li = document.createElement('li');
li.textContent = addItemInput.value;
let appendedItem = list.appendChild(li);
appendedItem.style.color = list.firstElementChild.style.color; //The newly appended item is given the color of the first list element. In your case, this would be whatever color the user chose last.
});
Second Change:
I added
document.querySelectorAll('li');
inside your event handler for the color change button so that each time, the length of the new list is calculated.