Here we have a tab with incompled tasks and the list is supposed to be attached to the first tab(all-taks). After the task is finished it is supposed to get deleted from first list and move to second one with completed tasks. And after you switch to second tab, all the completed ones should be there. I can't figure out the way to do it. I hope I could get some help or some detailed explanation, 'cause I have been stuck on this for some time.
Here is an image for more clarification: [1]: https://i.stack.imgur.com/Dy0KL.png
HTML code:
<body>
<div >
<header>
<h1>To-Do List</h1>
<h4>Describe your list...</h4>
</header>
<form action="" >
<div >
<!-- action is where files will be sent after submitting -->
<input type="text" placeholder="Add a task...">
</div>
<div >
<button type="submit">Add</button>
</div>
</form>
<div >
<ul>
<li >
<span></span>All tasks (<span >0</span>)</span>
</li>
<li >
<span>Completed (<span >0</span>)</span>
</li>
</ul>
</div>
<div >
<div data-tab="1">
<ol ></ol>
</div>
<div data-tab="2">
<ol ></ol>
</div>
</div>
</body>
JS code:
//Selectors
const todoForm = document.querySelector('.todo-form');
const todoInput = document.querySelector('.todo-input');
const todoButton = document.querySelector('.todo-button');
const tabs = document.querySelectorAll('.todo-tabs ul li');
const tabWrap = document.querySelector('.todo-tabs ul');
const undone = document.querySelector('.undone-tasks');
const done = document.querySelectorAll('.done-tasks');
//Event Listeners
tabWrap.addEventListener('click', tabs)
todoButton.addEventListener('click', addToDo);
//Functions
tabs.forEach(function (tab, tab_index) {
tab.addEventListener("click", function () {
tabs.forEach(function (tab) {
tab.classList.remove("active");
})
tabWrap.forEach(function (todoList, todoList_index) {
if (todoList_index == tab_index) {
todoList.style.display = "block";
}
else[
todoList.style.display = "none"
]
})
})
})
function addToDo(event) {
//Prevent form from submitting
event.preventDefault();
if (todoInput.value != "") {
const todoDiv = document.createElement('div');
todoDiv.classList.add('todo-div');
const inputCheckbox = document.createElement('input');
inputCheckbox.classList.add("checkbox-incompleted");
inputCheckbox.setAttribute('type', 'checkbox');
todoDiv.appendChild(inputCheckbox);
//Create li
const newToDo = document.createElement('li');
newToDo.classList.add('todo-item');
newToDo.insertAdjacentText("beforeend", todoInput.value);
todoDiv.appendChild(newToDo);
console.log(newToDo)
//Append to list
undone.appendChild(todoDiv);
//Clear todo input value
todoInput.value = "";
//Focusing after 1st input
todoInput.focus();
}
}
The commented area is what i tried to do for tabs and lists to switch, but it gives the following error:
Uncaught TypeError: tabWrap.forEach is not a function
at HTMLLIElement.<anonymous> (script.js:32:17)
(anonymous) @ script.js:32
The error starts at the beggining of the tabWrap.forEach function. But I guess there could be other way to solve this
CodePudding user response:
tabWrap
is not useful for what you want: it is a single element. Instead, you'll want to iterate over the tab contents, which are identified by class tabs-content
. It is those that you need to iterate and show or hide.
Then, to decide which contents to use, you may need to use that data-tab
attribute you have in your HTML (not sure, since it is nowhere referenced).
Anyway, adapt as needed:
const tabContents = document.querySelectorAll('.tabs-content');
tabs.forEach(function (activeTab, activeIndex) {
activeTab.addEventListener("click", function (e) {
tabs.forEach(function (tab) {
tab.classList.toggle("active", tab == activeTab);
});
tabContents.forEach(function (tabContent) {
tabContent.style.display = tabContent.dataset.tab == activeIndex 1 ? "" : "none";
});
})
})
CodePudding user response:
As @Anurag Srivastava pointed out on comment, in your code this is how you get tab elements:
const tabs = document.querySelectorAll('.todo-tabs ul li');
const tabWrap = document.querySelector('.todo-tabs ul');
The method querySelector returns a single element, and querySelectorAll returns an iterable collection.
And this is why you're getting the error:
Uncaught TypeError: tabWrap.forEach is not a function
If you don't have to support internet explorer you could take a look at Element.insertAdjacentElement() to move elements from one tab to another.