I created the sort button HTML element in javascript, and the button shows in the console, however, when I apply the sortList.style.display = "block"; to make it display when the add button is clicked the sort button shows as well, not sure why it is not showing.
I do have the sort button hidden in the CSS file, only so that I can have it show when submit event is clicked
const elements = {
form: document.querySelector("#new-task-form"),
input: document.querySelector("#new-task-input"),
list: document.querySelector("#tasks"),
cal: document.querySelector("#calendar"),
sort: document.querySelector(".sort")
elements.list.addEventListener('click',event => {
const {target} = event;
const {id} = target.dataset;
const task = id ? document.querySelector('[data-id="${id}"]'): null;
const sortList = event.target.querySelector(".sort")
for (var i=0; i < sortList.length; i++){
sortList[i].style.display = 'block';
}
}
There is more to the code, however, it's just the sortList.style.display = "block"; I need help with.
Let me know if you need more of the code if the above does not help?
I believe you want sortList to be done as follows:
const sortList = event.target.getElementsByClassName('sort')
for (var i=0; i < sortList .length; i++) {
sortList[i].style.display = 'block';
}
I solved the issue. The issue was that it was not needed to add a display:none in the CSS file because the sort button would appear anyway along with the task list.
as its only created in the tasks.innerHTML.
const tasks = document.createElement("div");
tasks.innerHTML = `
<button class = "sort" >Sort</button>
<div class="task" date-id = "${id}">
<div class="content">
<input type ="checkbox" class="tick">
<input type ="text" class = text id = "text" readonly>${task}
<label class = "due-date" for ="text">${date}</label>
<input type ="date" class = date id = "date">
</div>
<div class = "actions">
<button class="edit" data-id="${id}">Edit</button>
<button class="delete" data-id="${id}">Delete</button>
</div>
</div>
`
Related
first of all, super beginner here. I'm trying to do a to do list. The add part works fine, it looks like this:
let salvar = document.getElementById("salvar")
let remove = document.getElementById("remover")
salvar.onclick = saveitem
function saveitem() {
let item = document.getElementById("input").value
let novoitem = document.createElement("tr")
let lista = document.getElementById("todoitems")
novoitem.innerText = item
lista.appendChild(novoitem)
}
<input type="text" id="input">
<div class="container">
<button id="salvar">Save</button>
<button id="remover">Remove</button>
</div>
<table id="todoitems">
<tr>
<th>Tarefa</th>
</tr>
</table>
How can i create a function that removes the last added item?
First of all we need to use correct markup for your table. tr must be a child of either thead or tbody. Secondly, you cannot have text nodes as children of tr; these must be placed in td or th elements. Also it's bad practice to use non-English variable names, I've changed that to English.
That being said, here's your solution:
let add = document.getElementById("add")
let remove = document.getElementById("remove")
remove.onclick = removeLastItem;
add.onclick = saveitem;
function saveitem() {
let item = document.getElementById("input").value;
let newRow = document.createElement("tr");
let list = document.getElementById("todoitems");
newRow.innerHTML = `<td>${item}</d>`;
list.appendChild(newRow);
}
function removeLastItem() {
document.querySelector('#todoitems tr:last-child')?.remove();
}
<input type="text" id="input">
<div class="container">
<button id="add">Save</button>
<button id="remove">Remove</button>
</div>
<table>
<thead>
<tr>
<th>Tarefa</th>
</tr>
</thead>
<tbody id="todoitems"></tbody>
</table>
Explanation of the removeLastItem() function:
document.querySelector('#todoitems tr:last-child')?.remove()
querySelector allows you to pass in a CSS selector that works just like it does in CSS. To select the last tr in the tbody#todoitems you use #todoitems tr:last-child as your CSS selector. The ? is the safe navigator/optional chaining that makes sure your code doesn't throw an error if someone clicks the remove button when there are no items in your table.
document.getElementById('todoitems').lastChild.remove()
use last child property
instead of using remove button you can add button inside tr and when pressed it can delete the that tr for you
function saveitem(){
let item = document.getElementById("input").value
let novoitem = document.createElement("tr")
let delBtn = document.createElement("button")
delBtn.innerText = "del"
delBtn.addEventListener("click",function(){
novoitem.remove();
})
let lista = document.getElementById("todoitems")
novoitem.innerText = item
lista.appendChild(novoitem)
novoitem.append(delBtn);
}
let salvar = document.getElementById("salvar");
let remove = document.getElementById("remover");
salvar.onclick = saveitem;
remove.onclick = removeitem;
function saveitem(){
let item = document.getElementById("input").value;
let novoitem = document.createElement("tr");
let lista = document.getElementById("todoitems");
novoitem.innerText = item;
novoitem.onclick = function() {this.remove();};
lista.appendChild(novoitem);
}
function removeitem() {
document.getElementById("todoitems").lastChild.remove();
}
<input type="text" id="input">
<div class="container">
<button id="salvar">Save</button>
<button id="remover">Remove last</button>
</div>
<table id="todoitems">
<tr onclick="this.remove();">
<th>Tarefa</th>
</tr>
</table>
Are you want this
kui klõpsate tr-ile, siis see kustub!
var allElm = document.getElementById("todoitems").getElementsByTagName("tr");
allElm[allElm.length-1].remove();
What you can do is to pass id using this in the js code and then call function on click. This way you can delete any item from the list and not the last item added. Here's the sample code i wrote for you with jsfiddle:
<input type="text" id="input">
<div class="container">
<button id="salvar">Save</button>
<button id="remover">Remove</button>
</div>
<table id="todoitems">
<tr>
<th>Tarefa</th>
</tr>
</table>
JS Code:
let salvar = document.getElementById("salvar")
let remove = document.getElementById("remover")
salvar.onclick = saveitem
function removeItem(item){
item.remove();
}
function saveitem() {
let item = document.getElementById("input").value
let novoitem = document.createElement("tr")
let lista = document.getElementById("todoitems")
novoitem.setAttribute('id',item);
novoitem.setAttribute('onClick','removeItem(this)');
novoitem.innerText = item
lista.appendChild(novoitem)
}
This will remove the item you click on the list.
I have some To Do-s that are dinamically created by the user:
<div>
<h3 class = 'taskTitle'>do homework </h3>
<p class = 'taskDate'>Expires: 2021.12.31</p>
<input type = button class = 'delBtn' value = 'x'></input>
<input type = button class = 'expandBtn' value = '...'></input>
</div>
<div>
<h3 class = 'taskTitle'>workout </h3>
<p class = 'taskDate'>Expires: 2021.10.11</p>
<input type = button class = 'delBtn' value = 'x'></input>
<input type = button class = 'expandBtn' value = '...'></input>
</div>
**etc.**
On click of the expandBtn a pop up window appears that would contain the title (h3) and the date (p) of the specific To Do.
script:
function showDescription(){
const expandBtns= document.querySelectorAll('.expandBtn')
expandBtns.forEach(btn => {
btn.addEventListener('click', function(event){
let popUp = document.createElement('div')
popUp.classList.add('descriptionBox')
let title = event.target.parentNode.firstChild.textContent **<--says its undefined**
let date = event.target.parentNode.firstChild.textContent **<--says its undefined**
popUp.innerHTML = `
<h3>${title}</h3>
<p class = 'description'> lorem ipsum </p>
<p class = 'dateDescription'>${date}</p>
<input class = 'delDescription' type = button value = 'x'></input>`
const todos = document.querySelector('#todos')
todos.appendChild(popUp)
//close button for popUp
const delDescription = document.querySelectorAll('.delDescription')
delDescription.forEach(btn => {
btn.addEventListener('click', function (event){
event.target.parentNode.remove()
})
})
// alert(document.querySelector('.activeProject').textContent)
})
})
}
So how could I target them? querySelector isn't good either, as I have more than 1 To Do-s. Any help appreciated!
You could add a unique id or class to all the div elements. For example:
<div id="to-do-1"><p>Test</p></div>
<button onclick="myFunction()">Click Me!</button>
<script>
function myFunction() {
document.getElementById("to-do-1").style.display = "inline";
}
</script>
<style>
#to-do-1 {
display: none;
}
</style>
Select all expandBtn
var btn = document.getElementsByClassName("expandBtn")
Create a loop and addEventListener for all of them
for(let i =0; i < btn.length; i++) {
btn[i].addEventListener("click", function () {
let h3 = this.parentNode.getElementsByTagName("h3")[0];
let p = this.parentNode.getElementsByTagName("p")[0];
alert("h3 = "+ h3.innerText + " & p = " + p.innerText);
}
}
now when the user clicking on anyone of them it's will search for h3, p who is belong to the parent of this button
Using .children will get you what you want:
document.addEventListener("click",ev=>{
if (ev.target.className!=="expandBtn") return;
const [name,date]=[...ev.target.parentNode.children].slice(0,2).map(e=>e.textContent)
console.log(name,date);
// further code for popup ...
})
<div>
<h3 class = 'taskTitle'>do homework </h3>
<p class = 'taskDate'>Expires: 2021.12.31</p>
<input type = button class = 'delBtn' value = 'x'></input>
<input type = button class = 'expandBtn' value = '...'></input>
</div>
<div>
<h3 class = 'taskTitle'>workout </h3>
<p class = 'taskDate'>Expires: 2021.10.11</p>
<input type = button class = 'delBtn' value = 'x'></input>
<input type = button class = 'expandBtn' value = '...'></input>
</div>
.firstChild will return the first childNode, which in your case would have been a blank and a line-break and not the <h3> element you expected.
.children on the other hand will return a collection of all child elements (like: <div>, <p>, <span>, ... etc.), the chained .slice(0,2) will slice off the first two elements only.
edited with all the code, sorry for my messy coding, I am begginer
hope you can help with this,
I have just created a button in the dom with a function, I gave the button a class to apply an event listener, for some reason i am not able to activate the listener, does anyone have a clue about what I am doing wrong?
//this is th initial array of items, after I am changing it to an arrayof objects
let shoppingList = ['banana','apples','cherries','oranges', 'peaches'];
const list = document.querySelector('.list');
//this is the last thing I need, create new items and allow the del button
const foo=()=>{
console.log('hi');
}
const adder =(item, index, price,name)=>{
list.innerHTML += `<div class='item${[index+1]}'>${name}, price ${price} </div>`;
item[index]= {name,price};
const delElm = document.createElement('button');//the element to remove items
delElm.className = 'remove';
delElm.innerHTML = 'X';
list.appendChild(delElm);
const btndel = document.querySelector('.remove')
console.log(btndel)
btndel.addEventListener('click', foo)
}
//assign a random price to the original array
for (let i = 0; i < shoppingList.length; i++) {
let prices = i+Math.round((((Math.random()*5)+10))*100)/100;
let name = shoppingList[i];
adder(shoppingList,i,prices,name);
}
const btnElm= document.querySelector('.press');
//function to add new elements
const addItm=()=>{
const nameElm = document.querySelector('#text');
const priceElm = document.querySelector('#price');
let name = nameElm.value;
let prices = Number(priceElm.value);
let i = shoppingList.length-1;
adder(shoppingList, i, prices,name)
console.log(shoppingList)
}
console.log(shoppingList)
btnElm.addEventListener('click', addItm)
edit with the HTML, basically, the user can add new items filling the form, each item should be posible to be removed,
<input type="text" id="text" placeholder="name item">
<input type="text" id="price" placeholder="price">
<button class="press">add</button> -->
thanks you in advance
I am trying to do a web app similar to google calendar. I have done the object and methods within it but now it's time to be able to add what I want as a task. My idea is for the user to add something to the input and that input being console.logged for now.
Any idea?
HTML
<div class="new-task" id="task-input">
<div id="add-new-task">Task: <input type="text"></div>
<div id="add-time">Time: <input type="text"></div>
<button class ="save-task" onclick="">Save task</button>
</div>
Javascript
var idCounter = 0
var tasksManager = {
array: [],
add: function(task){
taskObject = {
title: task,
idVerification: idCounter ++
}
tasksManager.array.push(taskObject)
},
show:function(id){
var i;
for (i = 0; i < tasksManager.array.length; i++) {
if(id === tasksManager.array[i].idVerification){
return tasksManager.array[i]
}
}
},
delete:function(task){
if(this.show){
tasksManager.array.splice(task)
}
}
}
var newTask = document.getElementById("add-new-task")
newTask.addEventListener('click',tasksManager.add())
console.log(tasksManager.array)
As you can see with console.log above the array index [0] is logged as undefined but I wanted the user to write in the input " Go to the gym" and this to be logged within the array.
Thanks
Some issues:
You are not assigning the click handler. Instead you execute it immediately (not on click).
When you call .add() you don't provide an argument: the name of the task
The click handler should be on the button element, not on the div that has the input element. And so it will be useful to give that button an id attribute.
You should retrieve the value from the input element, and so it would be more appropriate to give that element an id and not so much the div that wraps it.
The console.log at the end of your script is executed immediately. It should be done only when the user has clicked the button.
Snippet with some corrections (also in the HTML!):
var idCounter = 0
var tasksManager = {
array: [],
add: function(task){
let taskObject = {
title: task,
idVerification: idCounter ++
}
tasksManager.array.push(taskObject)
},
show:function(id){
var i;
for (i = 0; i < tasksManager.array.length; i++) {
if(id === tasksManager.array[i].idVerification){
return tasksManager.array[i]
}
}
},
delete:function(task){
if(this.show){
tasksManager.array.splice(task)
}
}
}
var button = document.getElementById("save-task"); // <-- the button
var input = document.getElementById("add-new-task"); // <-- the input (move the ID attribute to the input!)
button.addEventListener('click', () => {
tasksManager.add(input.value);
console.log(tasksManager.array)
})
<div class="new-task" id="task-input">
<div >Task: <input id="add-new-task" type="text"></div>
<div id="add-time">Time: <input type="text"></div>
<button class ="save-task" id ="save-task" onclick="">Save task</button>
</div>
I am making a To-do list, where I want to be able to add new tasks, and delete tasks that are checked off. However, it seems my function just deletes all tasks, not just the ones that are checked off. Neither does it seem to allow new tasks to be added.
html:
<h1 id="title"> To-do list</h1>
<div id="task_area">
</div>
<input type="text" id="putin"></input>
<button id="add">add</button>
javascript:
<button id="clear">Clear completed tasks</button>
var tasks = document.getElementById("task_area")
var new_task = document.getElementById("add")
var clear = document.getElementById("clear")
new_task.addEventListener("click", function() {
var putin = document.getElementById("putin")
var input = document.createElement('input')
input.type = "checkbox"
var label = document.createElement('label')
label.appendChild(document.createTextNode(putin.value))
task_area.appendChild(input)
task_area.appendChild(label)
})
clear.addEventListener("click", function() {
for (i = 0; i < task_area.children.length; i++) {
if (task_area.children[i].checked === true) {
task_area.remove(tasks.children[i])
}
}
})
jsfiddle: https://jsfiddle.net/4coxL3um/
.remove removes the element you are calling it from, and doesn't take an argument for what to remove. The following:
task_area.remove(tasks.children[i])
should be
tasks.children[i].remove()
EDIT: As Mononess commented below, this will only remove the checkboxes and not the labels. While you could delete both using Jayesh Goyani's answer below, it's probably better that each input/label pair be wrapped in a single div or span for easier management.
You could try adding an event listener to each child of task_area that calls the below function. Haven't gotten a chance to test it out, and may not fulfill all of your requirements, but should get the job done.
function removeClicked() {
this.parentNode.removeChild(this);
}
Please try with the below code snippet. Below code will help you to remove selected checkbox with label.
<body>
<h1 id="title">To-do list</h1>
<div id="task_area">
</div>
<input type="text" id="putin" />
<button id="add">add</button>
<button id="clear">Clear completed tasks</button>
<script>
var tasks = document.getElementById("task_area")
var new_task = document.getElementById("add")
var clear = document.getElementById("clear")
new_task.addEventListener("click", function () {
var putin = document.getElementById("putin")
var input = document.createElement('input')
input.type = "checkbox"
var label = document.createElement('label')
label.appendChild(document.createTextNode(putin.value))
task_area.appendChild(input)
task_area.appendChild(label)
//document.getElementById("task_area").innerHTML = putin.value
})
clear.addEventListener("click", function () {
for (i = 0; i < task_area.children.length; i++) {
if (task_area.children[i].checked === true) {
tasks.children[i].nextSibling.remove();
tasks.children[i].remove();
}
}
})
</script>
</body>
Please let me know if any concern.