I have created buttons within JavaScript. Above these buttons, items are displayed. When I am on the first page, the button titled 'Back' is disabled.
When I am on the last page, the button titled 'Next' should be disabled.
I have this code:
const items = [
{name: "item1"},
{"name: item2"},
{"name: item3"},
{"name: item4"},
{"name: item5"},
]
I have displayed the items using this code:
const nav = document.getElementById('nav');
const content = document.getElementById('content');
let pageIndex = 0;
let itemsPerPage = 3;
loadItems();
function loadItems() {
content.innerHTML = "";
for (let i = pageIndex * itemsPerPage; i < (pageIndex * itemsPerPage) + itemsPerPage; i++) {
const item = document.createElement('div');
item.innerHTML = `
<p>$item[i].name</p>
`;
content.append(item);
}
minusPage();
loadPageNav();
plusPage();
}
function loadPageNav() {
for (let i = 0; i < items.length / itemsPerPage; i++) {
const button = document.createElement('button');
button.classList.add('btn');
button.innerHTML = i + 1;
button.addEventListener('click', (e) => {
pageIndex = e.target.innerHTML - 1;
loadItems();
});
nav.append(button);
}
}
function plusPage() {
const button = document.createElement('button');
button.classList.add('btn');
button.innerHTML = "Next";
button.addEventListener('click', () => {
pageIndex = pageIndex + 1;
loadItems();
});
nav.append(button);
}
function minusPage() {
nav.innerHTML = "";
const button = document.createElement('button');
button.classList.add('btn');
button.innerHTML = "Back";
button.addEventListener('click', () => {
pageIndex = pageIndex - 1;
loadItems();
});
nav.append(button);
if (pageIndex === 0) {
button.style.backgroundColor = "#cccccc";
}
}
I now want to add a different colour to the Next button when the user is on the last page. How can I find out when the user is on the last page.
Related
How to correct the javascript code to create li dynamically
to make loops?
I use this code, how to do it?
Because in this code I have to repeat for each section
let content = document.createElement('span');
let liststart = document.createElement('span');
let listelement1 = document.createElement('li');
let listelement2 = document.createElement('li');
let listelement3 = document.createElement('li');
let listelement4 = document.createElement('li');
listelement1.innerHTML = "section 1";
listelement2.innerHTML = "section 2";
listelement3.innerHTML = "section 3";
listelement4.innerHTML = "section 4";
let section1 = document.getElementById("section1");
let section2 = document.getElementById("section2");
let section3 = document.getElementById("section3");
let section4 = document.getElementById("section4");
listelement1.addEventListener("click", function() {
section1.scrollIntoView(true);
section1.classList.add("my-active");
section2.classList.remove("my-active");
section3.classList.remove("my-active");
section4.classList.remove("my-active");
});
listelement2.addEventListener("click", function() {
section2.scrollIntoView(true);
section1.classList.remove("my-active");
section2.classList.add("my-active");
section3.classList.remove("my-active");
section4.classList.remove("my-active");
});
listelement3.addEventListener("click", function() {
section3.scrollIntoView(true);
section1.classList.remove("my-active");
section2.classList.remove("my-active");
section3.classList.add("my-active");
section4.classList.remove("my-active");
});
listelement4.addEventListener("click", function() {
section4.scrollIntoView(true);
section1.classList.remove("my-active");
section2.classList.remove("my-active");
section3.classList.remove("my-active");
section4.classList.add("my-active");
});
liststart.appendChild(listelement1);
liststart.appendChild(listelement2);
liststart.appendChild(listelement3);
liststart.appendChild(listelement4);
content.appendChild(liststart);
let navbar__list = document.querySelector('#navbar__list');
navbar__list.append(content);
let tabs = document.getElementsByTagName("li");
for (let i = 0; i < tabs.length; i++) {
tabs[i].addEventListener("click", function() {
let current = document.getElementsByClassName("active");
current[0].className = current[0].className.replace("active");
this.className += "active";
});
}
Hopefully this will work as an example for you:
let content = document.createElement('span');
let liststart = document.createElement('span');
var sections = [];
for(let i = 1; i <= 4; i++) {
const listElement = document.createElement('li');
listElement.innerText = `Section ${i}`
const section = document.getElementById(`section${i}`)
sections.push(section)
listElement.addEventListener("click", () => {
section.scrollIntoView(true)
sections.forEach(el => el.classList.remove("my-active"))
section.classList.add("my-active")
})
liststart.appendChild(listElement)
}
content.appendChild(liststart);
let navbar__list = document.querySelector('#navbar__list');
navbar__list.append(content);
let tabs = document.getElementsByTagName("li");
for (let i = 0; i < tabs.length; i++) {
tabs[i].addEventListener("click", function() {
let current = document.getElementsByClassName("active");
current[0].className = current[0].className.replace("active");
this.className += "active";
});
}
If I was to do this myself, knowing there were an "unknown" number of sections, I would use JavaScript code that used every section whose id started with "secton":
let content = document.createElement('span');
let liststart = document.createElement('span');
// this line puts all elements that have an id starting with 'section' into an array
var sections = [...document.querySelectorAll('[id^=section]')]
sections.forEach(section => {
const listElement = document.createElement('li');
listelement.innerText = `Section ${i}`
listElement.addEventListener("click", () => {
section.scrollIntoView(true)
sections.forEach(el => el.classList.remove("my-active"))
section.classList.add("my-active")
})
liststart.appendChild(listElement)
})
content.appendChild(liststart);
let navbar__list = document.querySelector('#navbar__list');
navbar__list.append(content);
let tabs = document.getElementsByTagName("li");
for (let i = 0; i < tabs.length; i++) {
tabs[i].addEventListener("click", function() {
let current = document.getElementsByClassName("active");
current[0].className = current[0].className.replace("active");
this.className += "active";
});
}
This solution is quite similar, but to me is a bit more readable.
the js code for frontarrow is written but it displays only second record page
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
<title>
Records
</title>
<link rel="stylesheet" href="StyleSheet2.css" />
</head>
<body>
<main>
<div class="list" id="list"></div>
<container class="container " id="containerPager">
<button class="button" id="buttonFrontArrow">>></button>
<button class="button" id="buttonThreeDots">...</button>
<div class="pagenumbers" id="pagination">
</div>
<button class="button" id="buttonBackArrow"><<</button>
<button id="ShowingRecords"></button>
</container>
</main>
<script >// JavaScript source code
const ArrowBack = document.getElementById('buttonBackArrow');
const ArrowFront = document.getElementById('buttonFrontArrow');
const list_items = ["item1", "item2", "item3", "item1", "item2", "item3", "item2", "item3", "item1", "item2", "item3","item10"];
const list_element = document.getElementById('list');
const pagination_element = document.getElementById('pagination');
let current_page = 1;
let rows = 2;
function DisplayList(items, wrapper, rows_per_page, page) {
wrapper.innerHTML = "";
page--;
let start = rows_per_page * page;
let end = start + rows_per_page;
let paginatedItems = items.slice(start, end);
for (let i = 0; i < paginatedItems.length; i++) {
let item = paginatedItems[i];
let item_element = document.createElement('div');
item_element.classList.add('item');
item_element.innerText = item;
wrapper.appendChild(item_element);
}
const ShowingRecords = document.getElementById('ShowingRecords');
ShowingRecords.innerHTML = "Showing Records " + (start+1) + " to " + end + " of " + (items.length );
}
function SetupPagination(items, wrapper, rows_per_page) {
wrapper.innerHTML = "";
let page_count = Math.ceil(items.length / rows_per_page) + 1;
for (let i = page_count-1; i >0; i--) {
let btn = PaginationButton(i,items);
wrapper.appendChild(btn);
}
}
function PaginationButton(page,items) {
let button = document.createElement('button');
button.innerText = page;
if (current_page == page) {
button.classList.add('active');
}
button.addEventListener('click', function () {
current_page = page;
DisplayList(items, list_element, rows, current_page);
let current_btn = document.querySelector('.pagination button.active');
current_btn.classList.remove('active');
button.classList.add('active');
});
ArrowFront.addEventListener('click', function () {
current_page = page;
let current_pageArr = current_page + 1;
DisplayList(items, list_element, rows, current_pageArr);
let current_btn = document.querySelector('.pagination button.active');
current_btn.classList.remove('active');
button.classList.add('active');
current_pageArr = current_pageArr + 1;
});
return button;
}
DisplayList(list_items, list_element, rows, current_page);
SetupPagination(list_items, pagination_element, rows);
</script>
</body>
</html>
I need the prev and next button to change my records on page, but not the webpage itself. I have created pagination that is custom, my page number links are working but not my prev and next arrow links. I want js code that can help me change the records on my page.
You need to set the click event ArrowFront only once. Since it is inside a function, it is being set with different values every time the function is being called. Here is a revised version of the script
<script>// JavaScript source code
const ArrowBack = document.getElementById('buttonBackArrow');
const ArrowFront = document.getElementById('buttonFrontArrow');
const list_items = ["item1", "item2", "item3", "item4", "item5", "item6", "item7", "item8", "item9", "item10", "item11", "item12"];
const list_element = document.getElementById('list');
const pagination_element = document.getElementById('pagination');
let current_page = 1;
let rows = 2;
let max_page = Math.ceil(list_items.length / rows);
ArrowFront.addEventListener('click', function () {
if(current_page < max_page){
current_page++;
DisplayList(list_items, list_element, rows, current_page);
}
});
ArrowBack.addEventListener('click', function () {
if(current_page > 1){
current_page--;
DisplayList(list_items, list_element, rows, current_page);
}
});
function DisplayList(items, wrapper, rows_per_page, page) {
console.log(page);
wrapper.innerHTML = "";
page--;
let start = rows_per_page * page;
let end = start + rows_per_page;
let paginatedItems = items.slice(start, end);
console.log(start, end)
console.log('paginatedItems', paginatedItems)
for (let i = 0; i < paginatedItems.length; i++) {
let item = paginatedItems[i];
let item_element = document.createElement('div');
item_element.classList.add('item');
item_element.innerText = item;
wrapper.appendChild(item_element);
}
const ShowingRecords = document.getElementById('ShowingRecords');
ShowingRecords.innerHTML = "Showing Records " + (start + 1) + " to " + end + " of " + (items.length);
}
function SetupPagination(items, wrapper, rows_per_page) {
wrapper.innerHTML = "";
let page_count = Math.ceil(items.length / rows_per_page) + 1;
for (let i = page_count - 1; i > 0; i--) {
let btn = PaginationButton(i, items);
wrapper.appendChild(btn);
}
}
function PaginationButton(page, items) {
let button = document.createElement('button');
button.innerText = page;
if (current_page == page) {
button.classList.add('active');
}
button.addEventListener('click', function () {
current_page = page;
DisplayList(items, list_element, rows, current_page);
let current_btn = document.querySelector('.pagination button.active');
current_btn.classList.remove('active');
button.classList.add('active');
});
return button;
}
DisplayList(list_items, list_element, rows, current_page);
SetupPagination(list_items, pagination_element, rows);
</script>
I am making a task planner using classes.
These tasks are saved in the form of dynamically appended cards.
I am adding three cards in the array in class CardManager.
When I am selecting a card to delete by pressing a delete button the id is retrieved correctly, but in the last delfunc function which has a for loop, I am getting wrong array length.
So splice is not working.
The problem is in the loop of last function called delfunc().
class Card {
constructor(id, cname, pic, description, assignee, dDate, st) {
this.id = id;
this.cname = cname;
this.pic = pic;
this.description = description;
this.assignee = assignee;
this.dDate = dDate;
this.st = st;
// this.info=info;
}
}
class CardManager {
constructor() {
this.cardArr = [];
this.currentId = 1;
}
addcard(cname, pic, description, assignee, dDate, st) {
const nCard = new Card(this.currentId++, cname, pic, description, assignee, dDate, st); //creates
an instance of class card
this.cardArr.push(nCard);
}
}
const cardDeck = new CardManager(); //create an instance of card manager to access the members
// cardDeck.addcard("laundry","test","testing","Saeed","thursday","to do");
let tname = document.querySelector("#text1"); //accepting user input from form
let tdes = document.querySelector("#des");
let assignee = document.querySelector("#assignee");
let dDate = document.querySelector("#dDate");
let sTatus = document.querySelector("#stAtus");
let addButton = document.querySelector("#addButton");
addButton.onclick = function () {
alert("here i am card deck");
cardDeck.addcard(tname.value, "test", tdes.value, assignee.value, dDate.value, sTatus.value);
$('#myModal').modal('hide');
}
let btn1 = document.querySelector("#btn1");
let buttonCount = 1;
btn1.onclick = function displayListHtml() {
let html = "";
alert(cardDeck.cardArr.length);
for (let i = 0; i < cardDeck.cardArr.length; i++) {
html = `<div class="card">
<h1>${cardDeck.cardArr[i].cname}</h1>
<img src="sample.jpg" alt="Denim Jeans" style="width:100%">
<p>${cardDeck.cardArr[i].description}</p>
<p>${cardDeck.cardArr[i].assignee}</p>
<p>${cardDeck.cardArr[i].dDate}</p>
<p>${cardDeck.cardArr[i].st}</p>
<p>${cardDeck.cardArr[i].id}</p>
<p><button class="delete btn btn-primary" id="dbutton_${cardDeck.cardArr[i].id}">
Delete</button></p>
<p><button class="Edit btn btn-primary" id="ebutton_${cardDeck.cardArr[i].id}">
Edit</button></p>
</div>`;
buttonCount++;
}
const taskcontainer = document.querySelector("#taskcontainer");
const element = document.createRange().createContextualFragment(html);
element.querySelector("button.delete")
.addEventListener("click", delfunc);
element.querySelector("button.Edit")
.addEventListener("click", edifunc);
// element.addEventListener("click",yourClickEventHandler);
taskcontainer.append(element);
}
function delfunc() {
alert("i am in delete function");
const taskElement = event.target.closest(".delete"); //see line 74.
let delIdArr = taskElement.id.split("_"); //spliting the id by underscore. i.e . dbuton_id
let retreiveId = delIdArr[1];
for (let j = 0; j < this.cardDeck.cardArr.length; j++) {
if (retreiveId === j) {
this.cardDeck.cardArr.splice(retreiveId, 1);
}
}
}
Here is minimal version your concern. But looks like splice call doing as expected.
const del = (cardArr, retreiveId) => {
for (let j = 0; j < cardArr.length; j++) {
if (retreiveId === j) {
cardArr.splice(retreiveId, 1);
}
}
};
const cardArr = [2, 3, 4];
// delete the index 1
del(cardArr, 1);
console.log(cardArr);
// Case where delete index out of array index
const a = [1];
del(a, 1)
console.log(a);
function delfunc() {
alert("I am in delete function");
const taskElement = event.target.closest(".delete");//see line 74.
let delIdArr = taskElement.id.split("_");
let retrieveId = delIdArr[1];
var arr=[];
for (let j = 1; j <= cardDeck.cardArr.length; j++ ) {
if (retrieveId == j) {
arr = cardDeck.cardArr.splice(retreiveId, 1);
}
I want to add to my pagination the next and prev button functionality so i can also move the pages through them. in my code i only manage to display the next or prev page and see the content from the second page on click but without also moving the selected number of the button from 1 to 2, or the next page if there are more and so on. same for the prev. also, if i cannot go next/prev i want to have the next/prev button disabled.
any help with this, please?
here is what i have till now:
window.onload = function(){
var data = {
"headings": {
"propBook": "Book",
"propAuthor": "Author",
"propYear": "Year",
},
"items": [{
"fields": {
"propBook": "The Great Gatsby",
"propAuthor": "F Scott Fitzgerald",
"propYear": "1925",
},
"button": {
"name": "View book",
"propURL": "https://google.com"
}
},
{
"fields": {
"propBook": "The Grapes of Wrath",
"propAuthor": "John Steinbeck",
"propYear": "1939",
},
"button": {
"name": "View book",
"propURL": ""
}
},
{
"fields": {
"propBook": "A Wild Sheep Chase",
"propAuthor": "Haruki Murakami",
"propYear": "1982",
},
"button": {
"name": "View book",
"propURL": "https://google.com"
}
}
]
}
const HEADINGS = data.headings;
const ITEMS = data.items;
const TABLE_WRAPPER = document.querySelector('.book-component .table-wrapper');
const TABLE = document.createElement('table');
TABLE.setAttribute('class', 'pagination');
TABLE.setAttribute('data-pagecount', 2);
TABLE_WRAPPER.appendChild(TABLE);
for (const field in data) {
const TABLE_ROW = document.createElement('tr');
TABLE_ROW.setAttribute('id', 'myRow');
if (field == 'headings') {
for (const child in HEADINGS) {
const HEADER_CELL = document.createElement('th');
TABLE_ROW.appendChild(HEADER_CELL);
HEADER_CELL.setAttribute('class', 'sort-cta');
HEADER_CELL.innerText = HEADINGS[child];
TABLE.appendChild(TABLE_ROW);
}
} else if (field == 'items') {
for (const child in ITEMS) {
const TABLE_ROW = document.createElement('tr');
let item = ITEMS[child].fields;
let btn = ITEMS[child].button;
for (const row in item) {
const TABLE_DATA = document.createElement('td');
TABLE_ROW.appendChild(TABLE_DATA);
TABLE_DATA.innerText = item[row];
TABLE.appendChild(TABLE_ROW);
}
if (btn.propURL !== '') {
let link = document.createElement('a');
link.setAttribute('href', btn.propURL);
link.innerHTML = btn.name;
x = TABLE_ROW.insertCell(-1);
x.appendChild(link);
} else {
let link = document.createElement('span');
link.innerHTML = 'Reserved';
x = TABLE_ROW.insertCell(-1);
x.appendChild(link);
}
}
}
}
let perPage = 10;
function genTables() {
let tables = document.querySelectorAll('.pagination');
tables.forEach((table) => {
perPage = parseInt(table.dataset.pagecount);
createFooters(table);
createTableMeta(table);
loadTable(table);
});
}
// based on current page, only show the elements in that range
function loadTable(table) {
let startIndex = 0;
if (table.querySelector('th')) startIndex = 1;
const START = parseInt(table.dataset.currentpage) * table.dataset.pagecount + startIndex;
const END = START + parseInt(table.dataset.pagecount);
const TABLE_ROWS = table.rows;
for (var x = startIndex; x < TABLE_ROWS.length; x++) {
if (x < START || x >= END) TABLE_ROWS[x].classList.add('inactive');
else TABLE_ROWS[x].classList.remove('inactive');
}
}
function createTableMeta(table) {
table.dataset.currentpage = '0';
}
function createFooters(table) {
const COUTING_WRAPPER = document.createElement('div');
COUTING_WRAPPER.setAttribute('class', 'counting-wrapper');
const COUNTING_MSG = document.createElement('p');
COUTING_WRAPPER.appendChild(COUNTING_MSG);
let TABLE_WRAP = document.querySelector('.table-wrapper');
TABLE_WRAP.appendChild(COUTING_WRAPPER);
let hasHeader = false;
if (table.querySelector('th')) hasHeader = true;
let ROWS = table.rows.length;
if (hasHeader) ROWS = ROWS - 1;
let NUM_PAGES = ROWS / perPage;
let pager = document.createElement('div');
// add an extra page
if (NUM_PAGES % 1 > 0) NUM_PAGES = Math.floor(NUM_PAGES) + 1;
pager.className = 'pager';
let nextPage = document.createElement('button');
nextPage.innerHTML = 'next';
nextPage.className = 'item';
let prevPage = document.createElement('button');
prevPage.innerHTML = 'prev';
prevPage.className = 'item';
pager.appendChild(prevPage);
pager.appendChild(nextPage);
nextPage.addEventListener('click', () => {
table.dataset.currentpage = parseInt(table.dataset.currentpage) + 1;
loadTable(table);
});
prevPage.addEventListener('click', () => {
table.dataset.currentpage = parseInt(table.dataset.currentpage) - 1;
loadTable(table);
})
for (var i = 0; i < NUM_PAGES; i++) {
var page = document.createElement('button');
page.innerHTML = i + 1;
page.className = 'pager-item';
page.dataset.index = i;
if (i == 0) page.classList.add('selected');
page.addEventListener('click', function () {
var items = pager.querySelectorAll('.pager-item');
for (var x = 0; x < items.length; x++) {
items[x].classList.remove('selected');
}
this.classList.add('selected');
table.dataset.currentpage = this.dataset.index;
loadTable(table);
});
pager.appendChild(page);
}
// insert page at the top of the table
table.parentNode.insertBefore(pager, table);
}
genTables();
};
tr.inactive {
display: none;
}
.table-wrapper {
display: flex;
flex-direction: column-reverse;
}
.pager {
display: flex;
justify-content: center;
padding: 0;
margin-top: 10px;
font-weight: 800;
}
.pager-item.selected {
outline: none;
border-color: #0077cc;
background: #0077cc;
color: #fff;
cursor: default;
}
<div class="book-component">
<div class="table-wrapper">
</div>
</div>
Your loadTable function is updating the DOM based on the current state of your application. You can extend this to set the disabled state of the prev/next buttons, and to set the selected class of the page number button.
Here's an example where the button state is set by the loadTable function. The click event handlers should only update the current page (ie. set the state of the app). Then you can do your rendering of the state in the loadTable function.
// based on current page, only show the elements in that range
function loadTable(table) {
let startIndex = 0;
if (table.querySelector('th')) startIndex = 1;
const START = parseInt(table.dataset.currentpage) * table.dataset.pagecount + startIndex;
const END = START + parseInt(table.dataset.pagecount);
const TABLE_ROWS = table.rows;
for (var x = startIndex; x < TABLE_ROWS.length; x++) {
if (x < START || x >= END) TABLE_ROWS[x].classList.add('inactive');
else TABLE_ROWS[x].classList.remove('inactive');
}
// You should move this calculation outside of the function
const ROWS = table.rows.length - 1;
const NUM_PAGES = Math.ceil(ROWS / perPage);
const prevPage = document.getElementsByName('pagination-prev-button')[0];
const nextPage = document.getElementsByName('pagination-next-button')[0];
const isNextDisabled = +table.dataset.currentpage >= NUM_PAGES - 1;
const isPrevDisabled = +table.dataset.currentpage === 0;
if (isNextDisabled) {
nextPage.setAttribute('disabled', true);
} else {
nextPage.removeAttribute('disabled');
}
if (isPrevDisabled) {
prevPage.setAttribute('disabled', true);
} else {
prevPage.removeAttribute('disabled');
}
const items = document.querySelectorAll('.pager-item');
for (var x = 0; x < items.length; x++) {
if (x === +table.dataset.currentpage) {
items[x].classList.add('selected');
} else {
items[x].classList.remove('selected');
}
}
}
Here's the full working example.
https://jsfiddle.net/aloshea/r68gtvmc/
I am working on a T- Do list in JavaScript. It adds a new task to the list with delete and complete buttons. When the complete button is clicked, the task will be marked in red. There is also a tasks counter on the top and a remove all tasks button on the bottom. All of these features work fine. But I would like the tasks to be added based on the priority given. Priority should be an integer between 1 and 10, where 10 is top priority and 1 is least. Unfortunately, the code I wrote for that part doesn't seem to be working. I added a new variable called index that stores info where the new item should be added. Can you help me find out which part of the code has to be changed? Here it is:
document.addEventListener("DOMContentLoaded", function () {
var add = document.getElementById("addTaskButton");
var removeFinished = document.getElementById("removeFinishedTasksButton");
var task = document.getElementById("taskInput");
var list = document.getElementById("taskList");
var body = document.querySelector("body");
var prior = document.getElementById("taskPriority");
//To do counter
var toDo = document.createElement("span");
body.insertBefore(toDo, list);
var allTasks = document.querySelectorAll("li");
var counter = allTasks.length;
toDo.innerHTML = "Tasks to do: " + counter;
//Add task
add.addEventListener("click", function () {
if (task.value.length >= 5 &&
task.value.length <= 100 &&
prior.value > 0 &&
prior.value <= 10) {
//Add task to the list
var newTask = document.createElement("li");
newTask.dataset.priority = prior.value;
var all = document.querySelectorAll("li");
for (var i = 0; i < all.length; i++) {
var index = all.length;
if (parseInt(newTask.dataset.priority) < parseInt(all[i].dataset.priority)) {
index = i;
break;
}
}
list.insertBefore(newTask, list[index]);
var taskName = document.createElement("h1");
newTask.appendChild(taskName);
taskName.innerHTML = task.value;
//Add delete button
var delBtn = document.createElement("button");
newTask.appendChild(delBtn);
delBtn.innerHTML = "Delete";
delBtn.classList.add("delete");
//Add complete button
var complBtn = document.createElement("button");
newTask.appendChild(complBtn);
complBtn.innerHTML = "Complete";
complBtn.classList.add("complete");
counter++;
toDo.innerHTML = "Tasks to do: " + counter;
//Mark completed in red and adjust counter
complBtn.addEventListener("click", function () {
if (this.parentElement.style.color === "") {
this.parentElement.style.color = "red";
this.parentElement.setAttribute("done", "yes");
counter--;
toDo.innerHTML = "Tasks to do: " + counter;
} else if (this.parentElement.style.color === "red") {
this.parentElement.style.color = "";
this.parentElement.removeAttribute("done");
counter++;
toDo.innerHTML = "Tasks to do: " + counter;
}
});
//Delete selected item and adjust counter
delBtn.addEventListener("click", function () {
this.parentElement.parentNode.removeChild(this.parentElement);
counter--;
toDo.innerHTML = "Tasks to do: " + counter;
});
task.value = "";
prior.value = "";
} else {
event.preventDefault();
alert("Task should have from 5 to 100 characters. Priority should be an integer between 1 and 10");
}
});
//Remove completed items
removeFinished.addEventListener("click", function () {
var tasks = document.querySelectorAll("li");
for (var i = 0; i < tasks.length; i++) {
if (tasks[i].hasAttribute("done")) {
tasks[i].parentNode.removeChild(tasks[i]);
}
}
});
});
And here is the HTML:
<body>
<input id="taskInput" placeholder="Place your task here"><br>
<input id="taskPriority" placeholder="Place task priority (1-10)"><br>
<button id="addTaskButton">Add task</button>
<ul id="taskList">
</ul>
<button id="removeFinishedTasksButton">Remove finished tasks</button>
</body>
First thing is that index was being declared inside a loop so it could not be used outside of it. You need to declare index and the default value for index outisde of the loop for your function to work.
Second thing was that the value for list was never getting updating after the document was loaded for the first time. You need to use the all array to find the proper element to insert before, not list. list was assigned outside of your event handler so it did not have fresh data, also it is not a collection of li elements which is what you needed in this case.
document.addEventListener("DOMContentLoaded", function () {
var add = document.getElementById("addTaskButton");
var removeFinished = document.getElementById("removeFinishedTasksButton");
var task = document.getElementById("taskInput");
var list = document.getElementById("taskList");
var body = document.querySelector("body");
var prior = document.getElementById("taskPriority");
//To do counter
var toDo = document.createElement("span");
body.insertBefore(toDo, list);
var allTasks = document.querySelectorAll("li");
var counter = allTasks.length;
toDo.innerHTML = "Tasks to do: " + counter;
//Add task
add.addEventListener("click", function () {
if (task.value.length >= 5 &&
task.value.length <= 100 &&
prior.value > 0 &&
prior.value <= 10) {
//Add task to the list
var newTask = document.createElement("li");
newTask.dataset.priority = prior.value;
var all = document.querySelectorAll("li");
var index = all.length;
for (var i = 0; i < all.length; i++) {
if (parseInt(newTask.dataset.priority) < parseInt(all[i].dataset.priority)) {
index = i;
break;
}
}
list.insertBefore(newTask, all[index]);
var taskName = document.createElement("h1");
newTask.appendChild(taskName);
taskName.innerHTML = task.value;
//Add delete button
var delBtn = document.createElement("button");
newTask.appendChild(delBtn);
delBtn.innerHTML = "Delete";
delBtn.classList.add("delete");
//Add complete button
var complBtn = document.createElement("button");
newTask.appendChild(complBtn);
complBtn.innerHTML = "Complete";
complBtn.classList.add("complete");
counter++;
toDo.innerHTML = "Tasks to do: " + counter;
//Mark completed in red and adjust counter
complBtn.addEventListener("click", function () {
if (this.parentElement.style.color === "") {
this.parentElement.style.color = "red";
this.parentElement.setAttribute("done", "yes");
counter--;
toDo.innerHTML = "Tasks to do: " + counter;
} else if (this.parentElement.style.color === "red") {
this.parentElement.style.color = "";
this.parentElement.removeAttribute("done");
counter++;
toDo.innerHTML = "Tasks to do: " + counter;
}
});
//Delete selected item and adjust counter
delBtn.addEventListener("click", function () {
this.parentElement.parentNode.removeChild(this.parentElement);
counter--;
toDo.innerHTML = "Tasks to do: " + counter;
});
task.value = "";
prior.value = "";
} else {
event.preventDefault();
alert("Task should have from 5 to 100 characters. Priority should be an integer between 1 and 10");
}
});
//Remove completed items
removeFinished.addEventListener("click", function () {
var tasks = document.querySelectorAll("li");
for (var i = 0; i < tasks.length; i++) {
if (tasks[i].hasAttribute("done")) {
tasks[i].parentNode.removeChild(tasks[i]);
}
}
});
});
<body>
<input id="taskInput" placeholder="Place your task here"><br>
<input id="taskPriority" placeholder="Place task priority (1-10)"><br>
<button id="addTaskButton">Add task</button>
<ul id="taskList">
</ul>
<button id="removeFinishedTasksButton">Remove finished tasks</button>
</body>