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 trial

JavaScript Interactive Web Pages with JavaScript Traversing and Manipulating the DOM with JavaScript Perform: Appending and Removing Elements

What causes the 2 inputs to appear once you click on add button?

Hello!

After you run this code, and you press the add button, you see 2 input fields appear on the screen. I cant understand what part of the script is doing that.

addTask calls createNewTaskElement("some other elements");, but in that function, we create, append and return a list of elements, so I dont understand why only two inputs elements are created when we press the add button.

Cheers!!

<!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>
    <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>
var taskInput = document.getElementById("new-task");
var addButton = document.getElementsByTagName("button")[0];
var incompleteTasksHolder= document.getElementById("incomplete-tasks");
var completedTasksHolder = document.getElementById("completed-tasks");

var addTask = function(){
console.log("Add task...");
var listItem = createNewTaskElement("some other elements");
incompleteTasksHolder.appendChild(listItem);
}
var editTask = function(){
console.log("Edit task...");

}
var deleteTask = function(){
console.log("Delete task...");

}
var taskComplete = function(){
console.log("Completed task...");

}
var taskIncomplete = function(){
console.log("Incomplete task...");

}

var bindTasksEvents = function(taskListItem, checkBoxEventHandler)
{

    var checkBox =taskListItem.querySelector("input[type=checkbox]");
    var editButton = taskListItem.querySelector("button.edit");
    var deleteButton = taskListItem.querySelector("button.delete");

    editButton.onclick = editTask; 
    deleteButton.onclick = deleteTask;
    checkBox.onchange = checkBoxEventHandler;
}

var createNewTaskElement = function(taskString){
var listItem = document.createElement("li");
var checkBox = document.createElement("input");
var label = document.createElement("label");
var editInput = document.createElement("input");
var deleteButton = document.createElement("button");
var editButton = document.createElement("button");

listItem.appendChild(checkBox);
listItem.appendChild(label);
listItem.appendChild(editInput);
listItem.appendChild(deleteButton);
listItem.appendChild(editButton);
return listItem;
}
addButton.onclick = addTask;




for(var i=0; i < incompleteTasksHolder.children.length; i++)
{

bindTasksEvents( incompleteTasksHolder.children[i], taskComplete);

}

for(var i=0; i < completedTasksHolder.children.length; i++)
{

bindTasksEvents( completedTasksHolder.children[i], taskIncomplete);

}






</script>

</body>
</html>

7 Answers

Jack Blankenship
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Jack Blankenship
Full Stack JavaScript Techdegree Graduate 39,036 Points

1) The code below is actually adding that list by going to the incompleteTasksHolder and appending a child using the object listItem that was built in other parts of your script.

 incompleteTasksHolder.appendChild(listItem);

2) Since there are multiple types of input fields, you need to specify which one you want or you get the default of type="text". Which is why you were getting two input fields. Therefore, you only need to specify the checkbox field's type as checkbox via

checkBox.setAttribute('type', "checkbox");

For your label, deleteButton and editButton, there needs to be a .textContent value set like this

// use the string variable sent during createNewTaskElement function //
label.textContent =taskString; 
editButton.textContent = "Edit";
deleteButton.textContent = "Delete";

BTW. Thanks for putting the full copy of your code in your question so I could copy/paste and fiddle with it while trying to remember the exact syntax of all the Document Object Model stuff.

Spoiler Alert!!

modify your code of

var listItem = createNewTaskElement("some other elements');

to be

var listItem = createNewTaskElement(taskInput.value);
Jack Blankenship
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Jack Blankenship
Full Stack JavaScript Techdegree Graduate 39,036 Points

You are executing function createNewTaskElement. However, attributes for the objects are not being set. For example I added

checkBox.setAttribute('type', "checkbox");

and then your page correctly renders a checkBox field.

label.textContent = "your text";

adds a label that I am guessing you want to pull from your new-task input field. Your deleteButton and editButton also need .textContent values set.

Hello Jack,

I am actually following the lecture video, and I stopped after running this section of the code so that is why the attributes don't appear. As for the inputs that show, can you please point out which specific part of function createNewTaskElement that is causing them to . Wait now, that I am starring again at this code.

var listItem = document.createElement("li"); var checkBox = document.createElement("input");

listItem.appendChild(checkBox);

1) Are these 3 lines above causing the 2 inputs to appear on the screen?

2) So the label, edit and delete button, and checkbox dont appear because I need to use elementType.setAttribute('type', "checkbox"); on all of them, right?

thanks!!

Hello Jack!

I guess I should say thanks, but I thought every one posted the code used in the lecture videos as is, so that there is no confusion. Anyway, I always put the code so that it is easier for me to ask a question, and it refreshes the memory of the person who has taken the course....

BTW, in this case what is the difference betwen innerHTML and textContent? Why not:

deleteButton.innerHTML = "Delete";

Thanks for the clear explanations thus far!!

Jack Blankenship
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Jack Blankenship
Full Stack JavaScript Techdegree Graduate 39,036 Points

it looks like innerHTML will actually interpret HTML and textContent will treat the passed values as just text. If you are allowing people to enter text that shows back up on your page, the concern would be we are now open to an injection attack using innerHTML. PHP has an awesome function htmlspecialchars() that prevents this. However, I have not found anything similar for JavaScript yet.

Hello Jack for just for a final confirmation of the above code, the reason I am seeing 2 input fields is beacuse,

1) althought I created many elements in createNewTask, only checkbox, and editInput show. The show bcause I have appended them to listItem and return it to addTask, which appends them to incompleteTasksHolder.

2) the other elements I created dont appear at this stage, because I need to use setAttribute(), right?

Cheers!!

Jack Blankenship
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Jack Blankenship
Full Stack JavaScript Techdegree Graduate 39,036 Points

Correct, browsers have default settings for everything. Input like checkbox and input fields automatically are long enough to show on your page.

I think for those two, you either need to use innerHTML or textContect as they rendered with a length of zero.

If this has been helpful, please up vote or set one of these as best answer.

Thanks.