JavaScript and the DOM

JavaScript and the DOM

The file below is from the online series JS & The DOM on YouTube.. As I was watching the movies I thought I would make a comprehensive cheat sheet, summarizing the code from each of the lessons. But then at the end of the last movie there was a link to this same sheet that someone had already made. It must have been a great idea, someone already did it.

USAGE: Copy and paste each of the files below into a local directory and open the index.html in a browser (and open the console/inspector window). Ideally you'll follow each of the 18 Youtube movies and review the code....

app.js

// To query the DOM, there are two main methods:
document.querySelector();

document.querySelectorAll(); 

// Ex. 1
const wmf = document.querySelector("#book-list li:nth-child(2) .name");

// console.log(wmf);
// This allows us to go into the element with the id #book-list, access the second child of the li with class name. 


// Ex. 2
const books = document.querySelectorAll("#book-list li .name");

console.log(books);

// Iterating over node list returned by querySelectorAll:
    books.forEach(function(book){
      console.log(book);
    })


// Converting the collection of elements (known as a "NODE LIST") returned by querySelectorAll() into an array: 
// OPTIONAL - Not required at all, UNLESS we use document.getElementsByClassName();
      x = Array.from(books);

      x.forEach(function(book){
        console.log(book);
      })

    // Can be done at one go:
      Array.from(books).forEach(function(book){
        console.log(book);
      })

// Logging the text content only:
      books.forEach(function(book){
        console.log(book.textContent);
      })

      // Replacing text content:
      books.forEach(function(book){
        book.textContent = ("This is a test");
      })

      // Appending text content (more useful), just use "+=" :
      books.forEach(function(book){
        book.textContent += ("This is a test");
      })

//Appending new HTML elements. To replace the original HTML, use '=' instead of '+='
const bookList = document.querySelector("#book-list");
bookList.innerHTML += '

This is how you add HTML

'; // Cloning a node: const banner = document.querySelector("#page-banner"); const clonedBanner = banner.cloneNode(true); // true is used to clone the entire node, nested nodes and all. // "Node" is an interface that is implemented by multiple other objects, including "document" and "element". // All objects implementing the "Node" interface can be treated similarly. // The term "node" therefore (in the DOM context) means any object that implements the "Node" interface. // Most commonly that is an element object representing a HTML element. // To find parent node const bookList = document.querySelector("#book-list"); console.log('the parent node is ', bookList.parentNode); // You can chain them together to find the parent of the parent // we just found above console.log('the parent node is ', bookList.parentNode.parentNode); // To find node children isn't useful (they include line breaks), so we use this instead: console.log(bookList.children); // To find element sibling: const bookList = document.querySelector("#book-list"); console.log('book-list next element sibling is: ', bookList.nextElementSibling); // To find previous element sibling: console.log('book-list previous element sibling is: ', bookList.previousElementSibling); // Example use case: bookList.previousElementSibling.querySelector('p').innerHTML += '
Too cool for everyone else!
' // You can chain the properties and methods together // EVENT LISTENERS const h2 = document.querySelector('#book-list h2'); h2.addEventListener('click', function(e){ console.log(e.target); console.log(e); }); // Example use case: Deleting a list object using the removeChild() method const btns = document.querySelectorAll('#book-list .delete'); btns.forEach(function(btn){ btn.addEventListener('click', function(e){ const li = e.target.parentElement; li.parentNode.removeChild(li); }) }) // PREVENTING DEFAULT BEHAVIOUR // In this example, preventing the default behaviour of a link const link = document.querySelector('#page-banner a'); link.addEventListener('click', function(e){ e.preventDefault(); console.log('Navigation to ', e.target.textContent, ' was prevented'); }); // Lesson #10: // Attaching event listeners to the ul instead of each li for efficiency // Adding an event listener to each li is "expensive" and inefficient const list = document.querySelector('#book-list ul'); // delete books list.addEventListener('click', function(e){ if (e.target.className == 'delete'){ const li = e.target.parentElement; list.removeChild(li); // li.parentNode.removeChild(li); NOTE: This line of code does the exact same thing as list.removeChild(li); } }) // Lesson #11 // Query the DOM for form elements: document.forms // Returns a HTML collection document.forms[0] // Accesses the first form element document.forms['add-book'] // Access the form with id #add-book // Add book list const addForm = document.forms['add-book']; // Forms have a 'submit' event that we can listen for. They also refresh the page by default // That explains e.preventDefault(); below addForm.addEventListener('submit', function(e){ e.preventDefault(); const value = addForm.querySelector('input[type="text"]').value; console.log(value); }); // Lesson #12 and #13 (Adding to code from #11) // Creating elements and adding them to the document addForm.addEventListener('submit', function(e){ e.preventDefault(); const value = addForm.querySelector('input[type="text"]').value; // create elements const li = document.createElement('li'); const bookName = document.createElement('span'); const deleteBtn = document.createElement('span'); // add content deleteBtn.textContent = 'delete'; bookName.textContent = value; // add classes bookName.classList.add('name'); deleteBtn.classList.add('delete'); // append to document (with appendChild) li.appendChild(bookName); li.appendChild(deleteBtn); list.appendChild(li); // list is a global variable defined in an earlier lesson (see lesson #10) so we can use it here }); // Lesson #14 Get and Set attributes var book = document.querySelector('li:first-child.name'); book.getAttribute('class'); // Returns the class of the elements: 'name' in this case book.setAttribute('class', 'name-2'); // Replaces the original class of 'name' with a new class of 'name-2' // setAttribute takes two arguments, the first is the one we want to replace, the second is what it will be replaced with // Check if an element has an attribute book.hasAttribute('class'); // Returns a boolean value. In this case, it's true // Remove attributes book.removeAttribute('class'); // Lesson #15: Reacting to a change event. Example: Checkboxes or radio buttons const hideBox = document.querySelector('#hide'); hideBox.addEventListener('change', function(e){ if(hideBox.checked){ list.style.display = "none"; } else { list.style.display = "initial"; } }); // Lesson #16 Custom Search Filter const searchBar = document.forms['search-books'].querySelector('input'); searchBar.addEventListener('keyup', function(e){ const term = e.target.value.toLowerCase(); const books = list.getElementsByTagName('li'); Array.from(books).forEach(function(book){ const title = book.firstElementChild.textContent; if (title.toLowerCase().indexOf(term) != -1){ book.style.display = 'block'; } else { book.style.display = 'none'; } }); }); // Lesson #17 Tabbed Content const tabs = document.querySelector('.tabs'); const panels = document.querySelectorAll('.panel'); tabs.addEventListener('click', function(e){ if (e.target.tagName == "LI") { const targetPanel = document.querySelector(e.target.dataset.target); // .dataset looks for data attributes like the data-target attr in the HTML // the second .target is a custom name. It couldn've been dataset.beans for example. panels.forEach(function(panel){ if (panel == targetPanel) { panel.classList.add('active'); } else { panel.classList.remove('active'); } // The block above adds a class of 'active' if the target of the click is the target panel }) // if not, it removes the class of 'active' } }); // Lesson #18 DOM Content Loaded document.addEventListener('DOMContentLoaded', function(){ } // If the script tags are not at the bottom of your HTML, Javascript code won't work, // (because event listeners can't attach to something that doesn't yet exist). To get around this, // add all of the JS code into the event listener above and it will only run once the DOM content has loaded. // Thanks for stopping by! I hope you found this summary useful!

index.html

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <link href="styles.css" rel="stylesheet" />
        <script src="app.js"></script><!-- should be at bottom of page but up here for DOMContentLoaded event exercise-->
        <title>JavaScript DOM Tutorials</title>
      </head>
      <body>
        <div id="wrapper">
            <header>
                <div id="page-banner">
                    <h1 class="title">Bookorama</h1>
              <p>Books for Ninjas</p>
              <form id="search-books">
                <input type="text" placeholder="Search books..." />
              </form>
                </div>
            </header>
            <div id="book-list">
                <h2 class="title">Books to Read</h2>
                <ul>
                    <li>
                        <span class="name">Name of the Wind</span>
                        <span class="delete">delete</span>
                    </li>
                    <li>
                        <span class="name">The Wise Man's Fear</span>
                        <span class="delete">delete</span>
                    </li>
                    <li>
                        <span class="name">Kafka on the Shore</span>
                        <span class="delete">delete</span>
                    </li>
                    <li>
                        <span class="name">The Master and the Margarita</span>
                        <span class="delete">delete</span>
                    </li>
                </ul>
            </div>
            <form id="add-book">
            <input type="checkbox" id="hide" />
            <label for="hide">Hide all books</label>
                <input type="text" placeholder="Add a book..." />
                <button>Add</button>
            </form>
          <div id="tabbed-content">
            <ul class="tabs">
              <li data-target="#about" class="active">About</li>
              <li data-target="#contact">Contact</li>
            </ul>
            <div class="panel active" id="about">
              <p>Content for about tab...</p>
              <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum id nunc porta urna ornare rhoncus. Ut convallis ante at.</p>
            </div>
            <div class="panel" id="contact">
              <p>Content for contact tab...</p>
              <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum id nunc porta urna ornare rhoncus. Ut convallis ante at.</p>
            </div>
          </div>
        </div>
      </body>
    </html>
    

styles.css

    body{
    font-family: Tahoma;
    color: #444;
    letter-spacing: 1px;
    }

    h1, h2{
        font-weight: normal;
    }

    #wrapper{
        width: 90%;
        max-width: 960px;
        margin: 20px auto;
        border-radius: 6px;
        box-shadow: 0px 1px 6px rgba(0,0,0,0.2);
        box-sizing: border-box;
        padding: 0 0 20px;
        overflow: hidden;
        border: 1px solid lightgray;
    }

    #page-banner{
        background: #eee ;
        padding: 10px 0;

    }

    #page-banner h1, #page-banner p{
        width: 100%;
        text-align: center;
        margin: 10px 0;
    }

    #page-banner input{
        width: 90%;
        max-width: 300px;
        margin: 20px auto;
        display: block;
        padding: 8px;
        border: 1px solid #ddd;
        border-radius: 4px;
        font-size: 16px;
        color: #444;
    }

    #book-list, #add-book, #tabbed-content{
        margin: 30px;
    }

    #book-list ul, #tabbed-content ul{
        list-style-type: none;
        padding: 0;
    }

    #book-list li{
        padding: 20px;
        border-left: 5px solid #ddd;
        margin: 20px 10px;
    }

    #book-list li:hover{
        border-color: #9361bf;
    }

    .delete{
        float: right;
        background: #9361bf;
        padding: 6px;
        border-radius: 4px;
        cursor: pointer;
        color: white;
    }

    .delete:hover{
        background: #333;
    }

    #add-book{
        width: 400px;
        margin: 0 auto;
    }

    #add-book input{
        display: block;
        margin: 20px 0;
        padding: 10px;
        border: 1px solid #ccc;
        font-size: 16px;
        border-radius: 4px 0 0 4px;
        box-sizing: border-box;
        width: 300px;
        float: left;
        clear: both;
    }

    #add-book button{
        border: 1px solid #9361bf;
        background: #9361bf;
        padding: 10px 20px;
        font-size: 16px;
        display: inline-block;
        margin: 0;
        border-radius: 0 4px 4px 0;
        cursor: pointer;
        width: 100px;
        float: left;
        margin: 20px 0;
        border-left: 0;
        color: white;
    }

    #add-book:after{
        content: '';
        display: block;
        clear: both;
    }

    #add-book #hide{
      width: 30px;
    }

    #add-book label{
      line-height: 52px;
    }

    /*
    #tabbed-content li{
        display: inline-block;
        padding: 10px 14px;
        background: #ddd;
        border-radius: 4px;
        cursor: pointer;
        margin-right: 10px;
    }
    #tabbed-content .tab{
        display: none;
        border: 1px solid #ddd;
        padding: 0 10px;
        border-radius: 4px;
    }
    #tabbed-content .tab.active{
        display: block;
    }
    */
    

Link your website to this page! Copy and paste the URL below:
http://www.cfsnap.com/javascript/javascript-and-the-dom/
Copyright 2018. All Rights Reserved.