Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

JavaScript

How to track changes in the DOM?

I would like to add a button below <ul><li></ul> list, it should show only when new <li> elements are added by users. Basically it's a to-do list, and <li> elements are added only when a user decides to add a new item and created by a function placed inside event listeners. So a "traditional" IF statement with the condition won't work, because the script will run and <li> elements could be added in any time.

Item.addEventListener ('blur', (e) => {


     if (Item.value) {


        CreateLi();


    }

screen: https://imgur.com/IlMx6Rd

2 Answers

Brendan Whiting
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Brendan Whiting
Front End Web Development Techdegree Graduate 84,696 Points

Can you share the rest of the code?

One solution could be:

  • you have some container for your clearList button, which starts off being empty
  • you have a function that can append the clearList button to its container
  • you have a function that can remove the clearList button
  • when you add or remove todos, you run a function that checks to see how many todos there are at the end of the operation. If there are 0 todos, remove the clearList button. If there are more than 0 todos, add the clearList button. If the button's already there, don't add another one.

Thank you Brendan for your support, below you can find full code, there are several event listeners and that's it. I was trying to put the if condition into the function and outside, bu it still doesn't work.

HTML

<!DOCTYPE html>
<html lang="pl">
<head>

<!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">



    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">


    <!-- Google Fonts -->

   <link href="https://fonts.googleapis.com/css?family=Roboto|Signika" rel="stylesheet">
   <link href="https://fonts.googleapis.com/css?family=Chivo|Comfortaa" rel="stylesheet">
   <link href="https://fonts.googleapis.com/css?family=Gudea|Open+Sans" rel="stylesheet">
   <link rel="stylesheet"  type="text/css" href="styles.css">


<title>Page Title</title>
</head>
<body>
<div class="container-fluid h_back">
    <div class="row">
            <div class="col-lg-12 ">
                <h1 class="text-center  ">Easy ToDO</h1>
            </div>
            <div class="col-lg-2 mt-2 ">

            </div>
    </div>
</div>
<div class="container">
    <div class="row">
        <div class="col-lg-4 offset-lg-4">
            <div class="input-group input-group-sm mb-3 mt-3">
                <input type="text" class="form-control addItemInput" aria-label="Sizing example input" aria-describedby="inputGroup-sizing-sm" value= '+ Add an item...' id='AddItem'> 
            </div>
        </div>
        <div class="col-lg-1 offset-lg-2 mt-3">

                <p class="small text-center PrintMe"><img src="Icons/001-printer.png" class="mx-auto d-block" >Print list</p>
        </div>
        <div class="col-lg-1  mt-3">
            <p class="small text-center PrintMe"><img src="Icons/009-email-1.png" class="mx-auto d-block" ><a href="mailto:name@email.com">Send list</a></p>
        </div>
    </div>
    <div class="row">
        <div class="col-lg">
            <ul class="list-group">

            </ul> 
        </div> 



    </div> 

        <div class="row">
            <div class="col-lg-12 text-center mt-3 createButton">
                <button type="button" class="btn btn-danger col-lg-2 d-none" id="ClearList">Clear list</button>
            </div>
        </div>

</div>



<script src='script.js'></script>
</body>
</html>

JAVASCRIPT

//MAIN VARIABLES

let Item = document.getElementById('AddItem');
let UpItem = document.getElementById('GoUp');
let DownItem = document.getElementById('GoDown');
let PrintPage = document.getElementsByClassName('PrintMe')[0];
let ul = document.querySelector('ul');
let RemoveItemButton = document.querySelectorAll('button.removeItem')[0];
let ClearListButton = document.getElementById('ClearList');
let BackgroundImages = document.getElementsByClassName('BackgroundImage')[0];
let xyz = document.querySelector("[alt='doodle']");
let li = document.querySelector('li');

function CreateLi() {

    let li = document.createElement('li');
    li.className = 'list-group-item list-group-item-action font-weight-bold';
    let paragraph = document.createElement('p');
    paragraph.className = 'd-inline';
    let label = document.createElement('label');
    label.className = 'd-none d-print-inline-block checkbox-inline';
    let InputDiv = document.createElement('div');
    InputDiv.className = 'input-group';
    let TextDiv = document.createElement('div');
    TextDiv.className = 'input-group-text mr-2';
    let InputElement = document.createElement('input');
    let ButtonDiv = document.createElement('div');
    ButtonDiv.className = 'btn-group mr-2 float-right';
    let RemoveButton = document.createElement('button');
    RemoveButton.className = 'btn btn-outline-danger btn-sm remove d-print-none';
    let DownButton =document.createElement('button');
    DownButton.className = 'btn btn-outline-primary btn-sm GoDown d-print-none';
    let UpButton =document.createElement('button');
    UpButton.className= 'btn btn-outline-primary btn-sm GoUp d-print-none';
    let ButtonDiv1 = document.createElement('div');
    ButtonDiv1.className = 'btn-group mr-2 float-right';
    let RemoveDiv = document.createElement('div');
    RemoveDiv.className = 'btn-group mr-2 float-right';
    paragraph.textContent = Item.value;
    ul.appendChild(li);
    li.appendChild(label);
    label.appendChild(InputDiv);
    InputDiv.appendChild(TextDiv);
    TextDiv.appendChild(InputElement);
    InputElement.setAttribute("type", "checkbox"); 
    InputElement.setAttribute("aria-label", "Checkbox for following text input");
    li.appendChild(paragraph);
    li.appendChild(RemoveDiv);
    li.appendChild(ButtonDiv);
    li.appendChild(ButtonDiv1);
    DownButton.textContent = "Down";
    UpButton.textContent = 'Up';
    RemoveButton.textContent = "Remove";
    ButtonDiv1.appendChild(UpButton);
    UpButton.setAttribute("type", "button");
    ButtonDiv.appendChild(DownButton);
    DownButton.setAttribute("type", "button");
    RemoveDiv.appendChild(RemoveButton);
    RemoveButton.setAttribute("type", "button");


    if (ul.children[0]) {ClearListButton.className = 'btn btn-danger col-lg-2';}



} 

if ( li == null) {ClearListButton.className = 'btn btn-danger col-lg-2 d-none'; }


//GET THE ITEM UP

ul.addEventListener ('click', (e) => {

    //Checks if an clicked element is a button and has a class "remove"
    if (event.target.tagName === 'BUTTON' &&  event.target.classList.contains('GoUp')) {
        let button = event.target.parentNode;
        let div = button.parentNode;
        let li = div.parentNode;
        let liTarget = event.target.parentNode.parentNode;
        let prevLi = liTarget.previousSibling;
    if (prevLi) {

        ul.insertBefore(liTarget , prevLi);


    }



}

});



//GET THE ITEM DOWN

ul.addEventListener ('click', (e) => {

    //Checks if an clicked element is a button and has a class "remove"
    if (event.target.tagName === 'BUTTON' &&  event.target.classList.contains('GoDown')) {
        let button = event.target.parentNode;
        let div = button.parentNode;
        let li = div.parentNode;
        let liTarget = event.target.parentNode.parentNode;
        let prevLi = liTarget.previousSibling;
        let nextLi = liTarget.nextSibling;
    if (nextLi) {

        ul.insertBefore(nextLi , liTarget);


    }



}

});




//ADD ITEM INPUT FEATURE



Item.addEventListener ( 'focus',  () => {

    if (Item.value == Item.value) {

        Item.value = '';
    }

});



Item.addEventListener ('blur', (e) => {


     if (Item.value) {


        CreateLi();


    }

//Clears input value and avoid default value adding to the list

    if (Item.value == Item.value) {

        Item.value = '';


    }


    Item.value = '+ Add an item...';    


}); 


Item.addEventListener ('keyup', (e) => {

    const EnterInput= e.key;

if (EnterInput == 'Enter') {

if (Item.value ) {


    CreateLi();

    Item.value = '+ Add an item...';    




    }




//Clears input value and avoid default value adding to the list

if (Item.value == Item.value) {

        Item.value = '';


    }




}




});




Item.addEventListener ('keydown', (e) => {

    if (e.keyCode == 32) {

        e.preventDefault();





        }



}); 




//REMOVE ITEM FEATURE 

ul.addEventListener ('click', (e) => {

    //Checks if an clicked element is a button and has a class "remove"
    if (event.target.tagName === 'BUTTON' &&  event.target.classList.contains('remove')) {


        let button = event.target.parentNode;
        let div = button.parentNode;
        let li = div.parentNode;
        let ulb = li.parentNode;
        let targeted1 = event.target.parentNode.parentNode;




ul.removeChild(targeted1);



}



});