DOM manipulation

How can you use JavaScript to create an HTML element and then add it to your webpage? How would you replace an existing element with it?

TWO STEP PROCESS


ONE - CREATE AND ADD ELEMENT (e.g. DIV or P) TO HTML

CREATE

​​​​createElement()

INSERT

​​​​appendChild()
​​​​replaceChild()
​​​​insertBefore()

TWO - INSERT CONTENT INSIDE NEW ELEMENT(e.g. text)

CREATE CONTENT (E.G TEXT)

​​​​    e.g. creatTextNode()

INSERT CONTENT (E.G TEXT)

​​​​    appendChild()
​​​​    replaceChild()
​​​​    insertBefore()




HTML elements often consists of both an element node and a text node.To create a header (e.g. h1), you must create both an h1 element and a text node.

Start with div

<div>
<h1>
</h1>
</div>`

Create new HTML element/node with document.createElement();
var paragraph = document.createElement("p");
<p></p>

We can add text if e.g. it's a new paragraph
var text = document.createTextNode("New paragraph");

<p>New paragraph</p>

Add text to paragraph with the appendChild method
paragraph.appendChild(text);

BUT this still wouldn't add the element on our document because we haven't specified WHERE the new element should be placed.

That's why we need to add the paragraph inside the DIV:
document.querySelector("div").appendChild(paragraph);

<div>
    <h1>
        Title
        </h1>
    <p>
        New paragraph
        </p>
</div>

! The appendChild() method adds the node (=HTML element) to the end of the list of children of a specified parent node

How would you add a <li> element to the start of a <ul>?

Create new element

var choc = document.createElement("li");

Create text node

var textChoc = document.createTextNode("Hot chocolate");

Insert the text inside of the list item

choc.appendChild(textChoc);

Adding new li item to start of the list

var list = document.querySelector("ul");

list.insertBefore(choc, list.childNodes\[0\]);

OR

list.insertBefore(choc, list.firstChild);

What is a JavaScript Event? What does event.preventDefault() do and why might you use it?

Javascrip lets you execute code when an event is detected.

An event can be (OnClick, mouseover ) a user interacton.

<button>Click me</button> <p>No handler here.</p> <script> let button = document.querySelector("button"); button.addEventListener("click", () => { console.log("Button clicked."); }); </script>

Prevent default or false will stop the current behaviour. This is useful so you can add you own javascrpt for the event to behave in a different way.

<a href="www.google.com" onclick="return false">Click here</a> <a href="www.google.com" onclick="event.preventDefault()">here</a>

Click here
here

What is a NodeList? How is it different from an Array?

The NodeList object is a collection of nodes

A Node is an interface that some DOM API object-types inherit; it allows these types to inherit the same set of methods

A NodeList is returned from: Node.childNodes, document.querySelectorAll()

  • Node.childNode() (read-only) property returns a live collection where Node is a html element

    • changes in the DOM are reflected in the collection
  • In other case like document.querySelectorAll() the NodeList is a static collection.

    • Subsequent changes in the DOM does not affect the content of the collection.
var parent = document.getElementById('parent'); var child_nodes = parent.childNodes; console.log(child_nodes.length); // let's assume "2" parent.appendChild(document.createElement('div')); console.log(child_nodes.length); // should output "3"

Here is a link to an article that further illustrates the comparison between Arrays, NodeList and HTMLCollections.

TL;DR:

  • An HTMLCollection is a list of nodes. An individual node may be accessed by either index or the node’s name or id attributes.
    Collections in the HTML DOM are assumed to be live meaning that they are automatically updated when the underlying document is changed.
  • A NodeList object is a collection of nodes. The NodeList interface provides the abstraction of an ordered collection of nodes, without defining how this collection is implemented.
  • NodeList objects in the DOM are live or static based on the interface used to retrieve them.
  • HTMLCollection nor NodeList support the array prototype methods like push pop or splice methods.
const childDivs = document.querySelectorAll('.divy') Array.isArray(childDivs) //=> false childDivs.constructor.name //=> NodeList const childDivsAgain = document.getElementsByClassName('divy') Array.isArray(childDivs) //=> false childDivs.constructor.name //=> HTMLCollection /*******************************************************/ // We can see that the HTMLCollection is literally live, // in the sense, any change to DOM is updated // automatically and available in the collection let parentDiv = document.getElementById('container') let nodeListDivs = document.querySelectorAll('.divy') // is a Static collection let htmlCollectionDivs = document.getElementsByClassName('divy') // is a Live collection nodeListDivs.length //=> 4 htmlCollectionDivs.length //=> 4 //append new child to container let newDiv = document.createElement('div'); newDiv.className = 'divy' parentDiv.appendChild(newDiv) nodeListDivs.length //=> 4 htmlCollectionDivs.length //=> 5 /*******************************************************/ // To convert the NodeList or HTMLCollection object to a // javascript array, you can do one of the following: const nodelist = document.querySelectorAll(‘.divy’) const divyArrayFrom = Array.from(nodelist) const divyArraySliced = Array.prototype.slice.call(nodelist) const divyArrayES6 = […document.querySelectorAll(‘.divy’)]

How is an NodeList different from Arrays

NodeList Array
constains Node js primatives
purpose DOM specifc js data structure

Properties

NodeList.length -> The number of nodes in the NodeList

Methods

NodeList.item() -> Returns an item in the list by index, or null if the index is out-of-bounds
Can be used as an alternative to simply accessing nodeList[idx](which instead returns undefined when idx is out-of-bounds).

NodeList.entries() -> Returns an iterator allowing to go through all key/value pairs contained in this object.

NodeList.forEach() -> Executes a provided once per NodeList element.

NodeList.keys() -> Returns an iterator allowing to go through all keys of the key/value paris contained in this object.

NodeList.values() -> Returns an iterator allowing all values of the key/value pair contained in this object

Using for...in or for each...in to enumerate the items in the list will also enumerate the length and item properties of the NodeList.

for...of loops will loop over NodeList objects correctly

What are the security concerns around Element.innerHTML and what could you use instead?

  • Setting innerHTML will destroy existing HTML elements that have event handlers attached to them, potentially creating a memory leak on some browsers.

HTML

<p id="cool"> I like food <span>oranges</span> </p>

Javascript

document.getElementById('cool').innerHTML = "This is the new paragraph."

Result

<p id="cool"> This is the new paragraph. </p>

Alternative

var data = getData(); var p = document.getElementById("p1"); var text = document.createTextNode(data); p.replaceChild(text); // to append p.appendChild(text); // instead of p.innerHTML += text;
  • text is a Text node.
  • data is a string containing the data to be put in the text node
Select a repo