Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialCarey Cooke
3,952 PointsGetting 2 bind list events then another below it in the console
Hey everyone. Everything works right but I have something odd going on. When I refresh the page the console shows a 2 next to 'bind list item events', but then on the line below that I have another line that says 'bind list item events'. So instead of this all being on 1 line with a 3 next to it it's on 2 lines.
So when I add a new task it works but then it adds a new blank task to the incomplete tasks. It's like somewhere the bindTaskEvents function is being called somewhere else but I can't find it. I don't get errors in the console, only odd behavior.
***JavaScript
// Problem: User interaction doesn't provide desired results
// Solution: Add interactivity so the user can manage daily tasks
var taskInput = document.getElementById("new-task"); // new-task input text box
var addButton = document.getElementsByTagName("button")[0]; // this grabs the first button tag which would be at index 0; [0]
var incompleteTasksHolder = document.getElementById("incomplete-tasks"); // incomplete-tasks
var completedTasksHolder = document.getElementById("completed-tasks"); // completed-tasks
// New Task list item
var createNewTaskElement = function(taskString) {
// create list item
var listItem = document.createElement("li");
// createElement creates a new element and adds it to the current list
// Input checkbox
var checkBox = document.createElement("input"); // checkbox
// Label
var label = document.createElement("label");
// Input (text)
var editInput = document.createElement("input");
// Button with class #edit
var editButton = document.createElement("button");
// Button with class #delete
var deleteButton = document.createElement("button");
// each element, needs modified
checkBox.type = "checkbox";
editInput.type = "text";
editButton.innerText = "Edit";
editButton.className = "edit";
deleteButton.innerText = "Delete";
deleteButton.className = "delete";
label.innerText = taskString;
// each element needs appended (added)
listItem.appendChild(checkBox);
listItem.appendChild(label);
listItem.appendChild(editInput);
listItem.appendChild(editButton);
listItem.appendChild(deleteButton);
return listItem;
}
// Add a new task
var addTask = function() {
console.log("Add task...");
// Create a new list item with text from #new-task input box
var listItem = createNewTaskElement(taskInput.value);
// Append new listItem to incompleteTasksHolder
incompleteTasksHolder.appendChild(listItem);
bindTaskEvents(listItem, taskCompleted)
taskInput.value = ''; // This clears out text box after ADD buton is pressed to add the event
}
// Edit existing tasks
var editTask = function () {
console.log("Edit task...");
var listItem = this.parentNode;
var editInput = listItem.querySelector("input[type=text]");
var label = listItem.querySelector("label");
var containsClass = listItem.classList.contains("editMode");
// If class of parent is .editMode
if (containsClass) {
// Switch from editMode
// Make label text become input value
label.innerText = editInput.value; // The lable becomes the value of the input in the box by the user
// Else
} else {
// Switch to .editMode
// Input value becomes label's text
editInput.value = label.innerText; // The text that is put in by the user becomes the new text
}
// Toggle .editMode
listItem.classList.toggle("editMode"); // Pressing the edit button allows us to edit or saves the text that is input and applies the new text to the label
}
// Delete an existing task
var deleteTask = function () {
console.log("Delete task...");
// When delete button is pressed
var listItem = this.parentNode;
var ul = listItem.parentNode; // call it a grandparent. We need to move up 2 parent levels by looking at HTML. So we traverse from the button to list to unordered list
// Remove parent list item from ul
ul.removeChild(listItem);
}
// Mark a task as complete
var taskCompleted = function() {
console.log("Complete task...");
// Append (add) task list item to completed-tasks when checbox is checked
var listItem = this.parentNode;
completedTasksHolder.appendChild(listItem);
bindTaskEvents(listItem, taskIncomplete);
}
// Mark a task as incomplete
var taskIncomplete = function() {
console.log("Incomplete task...");
// Append (add) to incomplete-tasks to completed checkbox is unchecked
var listItem = this.parentNode;
incompleteTasksHolder.appendChild(listItem);
bindTaskEvents(listItem, taskCompleted);
}
var bindTaskEvents = function(taskListItem, checkBoxEventHandler) {
console.log("Bind list item events");
// select taskListItem children
var checkBox = taskListItem.querySelector("input[type=checkbox]");
var editButton = taskListItem.querySelector("button.edit");
var deleteButton = taskListItem.querySelector("button.delete");
// bind editTask to edit button
editButton.onclick = editTask;
// bind deleteTask to delete button
deleteButton.onclick = deleteTask;
// bind checkBoxEventHandler to checkbox
checkBox.onchange = checkBoxEventHandler;
}
// Set click handler to the addTask function
addButton.onclick = addTask; // () are not added after addTask because we don't want the function to run UNTIL the user clicks the button. If we add () the function will run right away.
// ***** Cycle over incompletedTaskHolder ul list items
for ( var i = 0; i < incompleteTasksHolder.children.length; i +=1 ) {
// bind events to list items's children (taskIncomplete)
bindTaskEvents(incompleteTasksHolder.children[i], taskCompleted);
}
// This is what the bindTaskEvents function is doing
// select ul list items children
// bind editTask to edit button
// bind deleteTask to delete button
// bind taskCompleted to checkbox
var ajaxRequest = function() {
console.log("AJAX Request");
}
// Set the click handler to the addTask function
addButton.addEventListener("click", addTask);
addButton.addEventListener("click", ajaxRequest);
// ***** Cycle over completedTaskHolder ul list items
for ( var i = 0; i < completedTasksHolder.children.length; i +=1 ) {
// bind events to list items's children (taskCompleted)
bindTaskEvents(completedTasksHolder.children[i], taskIncomplete);
}
// This is what the bindTaskEvents function is doing
// select ul list items children
// bind editTask to edit button
// bind deleteTask to delete button
// bind taskCompleted to checkbox
*** HTML
<!DOCTYPE html>
<html>
<head>
<title>Todo App</title>
<link href='http://fonts.googleapis.com/css?family=Lato:300,400,700' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="css/style.css" type="text/css" media="screen" charset="utf-8">
</head>
<body>
<div class="container">
<p>
<label for="new-task">Add Item</label><input id="new-task" type="text"><button>Add</button>
</p>
<h3>Todo</h3>
<ul id="incomplete-tasks">
<li><input type="checkbox"><label>Pay Bills</label><input type="text"><button class="edit">Edit</button><button class="delete">Delete</button></li>
<li class="editMode"><input type="checkbox"><label>Go Shopping</label><input type="text" value="Go Shopping"><button class="edit">Edit</button><button class="delete">Delete</button></li>
</ul>
<h3>Completed</h3>
<ul id="completed-tasks">
<li><input type="checkbox" checked><label>See the Doctor</label><input type="text"><button class="edit">Edit</button><button class="delete">Delete</button></li>
</ul>
</div>
<script type="text/javascript" src="js/app.js"></script>
</body>
</html>
Any help would be greatly appreciated
Philip G
14,600 PointsPhilip G
14,600 PointsCould you maybe post everything including your HTML to Codepen or JSFiddle? That would make helping easier :)