Code Monkey home page Code Monkey logo

phase-0-the-dom-modifying-elements-lab's Introduction

Creating and Inserting DOM Nodes Lab

Learning Goals

  • Create DOM elements programmatically
  • Add elements to the DOM
  • Update elements using innerHTML
  • Change properties on DOM nodes
  • Remove elements from the DOM

Introduction

Now that you have an understanding of the DOM and powerful tools for selecting the right elements, it's time to learn how to:

  1. Create new nodes
  2. Delete nodes
  3. Update node properties

If you haven't already, fork and clone this lab into your local environment. Navigate into its directory in the terminal, then run code . to open the files in Visual Studio Code.

Create DOM Elements Programmatically

document.createElement()

Creating an element in JavaScript is an easy process. You simply call document.createElement('tagName'), where tagName is the name of any valid HTML tag ('p', 'div', 'span', etc.).

Open the index.html file in your browser and open up the browser's console. In the console, enter:

const element = document.createElement("div");

Then take a look at the Elements tab. The element doesn't show up on the page. Why not?

Add Elements to the DOM

To get an element to appear in the DOM, we have to append() it to an existing DOM node. To go back to our tree metaphor, we have to glue our new leaf onto a branch that's already there. We can start as high up on the tree as document.body, or we can find a more specific element using any of the methods we've learned for traversing the DOM.

append()

Let's append element to body to start:

document.body.append(element);

(Recall that element is a variable containing the div we created above.)

Now if you look at the Elements tab, you'll see our new (empty) <div> nested inside the body element.

Next, let's create an unordered list:

const ul = document.createElement("ul");

To populate our unordered list, we'll use a for loop to create three li's, give them some content, and append them to the ul:

for (let i = 0; i < 3; i++) {
  const li = document.createElement("li");
  li.textContent = (i + 1).toString();
  ul.append(li);
}

In each iteration of our loop, we calculate the value i + 1 (an integer), turn it into a string using JavaScript's toString() method, and assign the result as the value of the li's textContent attribute.

Note: although the textContent attribute must be a string, the code would still work even if we didn't use the toString() method — JavaScript will turn the value into a string for us. However, for clarity and completeness, it is best to set it to a string value explicitly.

Finally, we'll append the ul to the div we created:

element.append(ul);

You should now see the unordered list rendered on the page, and see the new elements in the "Elements" tab, like this:

<div>
  <ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
  </ul>
</div>

Note that, each time we create a new element, we create a variable and save a reference to it. That makes it quite easy to make additional updates and to add it to the DOM using append().

Add Elements to the DOM via innerHTML

Creating elements and then appending them into the DOM is a multi-step process. It's also the safest and most reliable way to add content to the DOM. Most repeated code can be removed by using variables, functions and loops. It's The Right Way.

That said, however, there's another process that will also work, using Element.innerHTML. Inside our loop above, we create an li element and set its textContent property to a simple number (expressed as a string) that represents the current iteration through the loop. Once we append the li to the ul and the ul to the document body, we see our unordered list in the browser window. This is a perfectly valid way to use textContent to add content to the DOM — essentially, textContent changes only what text shows up inside a DOM element:

li.textContent = "Hi there!";
// => <li>Hi there!</li>
console.log(li.textContent);
// => "Hi there!"

Imagine, however, that we want to add content that's more complicated.

Assume our HTML includes a main element with an id of "main." We can grab that element and set its innerHTML attribute to any HTML we like:

const main = document.getElementById("main");
main.innerHTML =
  "<h1>Poodles!</h1><h3>An Essay into the Pom-Pom as Aesthetic Reconfiguration of the Other from a post-Frankfurt School Appropriationist Perspective</h3><p><em>By: Byron Q. Poodle, Esq., BA.</em></p>";

Here we are using one big, long string, complete with multiple HTML tags, to create the following HTML in the DOM:

<main id="main">
  <h1>Poodles!</h1>
  <h3>
    An Essay into the Pom-Pom as Aesthetic Reconfiguration of the Other from a
    post-Frankfurt School Appropriationist Perspective
  </h3>
  <p><em>By: Byron Q. Poodle, Esq., BA.</em></p>
</main>

This process works but it is not recommended for several reasons. First, it's more error-prone, and the errors can be difficult to find. Second, it can negatively impact site performance. Finally, if you're inserting user-derived data (e.g., comments) into the DOM using innerHTML, you can expose your site to the risk of users injecting malicious code.

Programmatically creating and appending elements is safer and more efficient, and it results in code that's easier to read, easier to debug, and easier to maintain.

Change Properties on DOM Nodes

We can change the appearance of a DOM node using its style attribute. Try this out in the console:

const element = document.getElementById("main");
element.style.height = "300px";
element.style.backgroundColor = "#27647B";

You've changed what's on the screen!

Feel free to set as many properties as you'd like — this is a good chance to look around and explore different properties of DOM elements.

Let's adjust the display. Add some text:

element.textContent = "You've changed what's on the screen!";

Then change the style to see the effect:

element.style.fontSize = "24px";
element.style.marginLeft = "30px";
element.style.lineHeight = 2;

Perhaps the most common way to change how things appear in the DOM is by changing an element's class attribute. As you know from CSS, we often change the way a bit of rendered HTML appears by adding or removing a class.

For example, we could create an alert class that turns the text red (using the CSS color attribute) and makes it big (using the CSS font-size attribute). We can then use JavaScript to first grab the element and then add the class by updating the element's className property. This has the same effect as setting the class property in the HTML. The className property expects a String with one or more class names, separated by spaces:

element.className = "pet-listing dog";

Check out the Elements tab to see the effect of this change:

<main id="main" class="pet-listing dog"></main>

Another way to accomplish the same thing is by using the Element.classList property. This property has .add() and .remove() methods that can be used as follows:

element.classList.remove("dog");
element.classList.add("cat", "sale");

This approach allows you to easily add and remove classes programmatically, without having to create a long string of class names.

<main id="main" class="pet-listing cat sale"></main>

Separation of Concerns

An important thing to bear in mind is that we only want to use JavaScript to change the appearance of an element when we need to make a change dynamically, i.e., in response to user actions. This goes back to a fundamental programming concept about separating concerns between technologies:

  • HTML defines the structure of the website (not appearance or functionality)
  • JavaScript defines functionality of the website (not structure or styling)
  • CSS defines the visualization and style of the website (not structure or functionality)

Defining the base CSS should still happen in the CSS files that are loaded into the DOM when the page is opened.

Remove Elements from the DOM

We know how to add elements and change their attributes. What if we want to remove an element from a page?

removeChild()

We use removeChild(), as you might guess, to remove a particular child of an element:

someElement.removeChild(someChildElement);

Let's take a look at a more complex example:

const ul = document.getElementsByTagName("ul")[0];
const secondChild = ul.querySelector("li:nth-child(2)");
ul.removeChild(secondChild);

Here you can see the power of querySelector(): we can use it to find the second li element of ul. We then pass that element as the argument to our removeChild method, which removes the element from our ul.

What if we want to remove the whole unordered list (ul)?

element.remove()

We can just call remove() on the element itself:

ul.remove();

And it's gone!

Instructions

From this point forward, many of the labs will work a little differently from ones you've done before. Specifically, the tests will mock the process of 1) running JavaScript code in the browser and 2) seeing the results of that code represented in the DOM. Take a look at test/indexTest.js to see the tests' descriptions of the changes your code should be making to the DOM elements.

Note that you do not need to create functions for this lab. Just create the line or lines of JavaScript necessary to pass each test. As usual, you will write your code in the index.js file.

One final note: the last test in the test/indexTest.js file is looking for the text "YOUR-NAME is the champion" (with your name — or whatever text you choose — in place of YOUR-NAME) inside your newly created DOM node. While there are a number of ways you could accomplish this, you should use either the textContent or innerHTML property to set the text inside your DOM node. The innerText property would technically work as well; however, the tests won't pass if you use this approach, and generally it's not a good practice to use innerText when setting the contents of an element. This StackOverflow answer does a good job explaining some differences between these properties.

Resources

phase-0-the-dom-modifying-elements-lab's People

Contributors

alveem avatar bal360 avatar dependabot[bot] avatar graciemcguire avatar ihollander avatar jlboba avatar lizbur10 avatar maxwellbenton avatar professor-ben avatar rikkux491 avatar sgharms avatar thuyanduong-flatiron avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

phase-0-the-dom-modifying-elements-lab's Issues

"must" for using 'toString' or "should"? (And no context for "li.textContent")

Canvas Link

https://learning.flatironschool.com/courses/5506/assignments/170650?module_item_id=371104

Concern

On first reading of this:
The value that we set li.textContent to must be a String.

I was confused. What are you talking about? There was no context describing intention. Why are we even talking about using "li.textContent"?

Statement says "must be a String." Fine, I ran the suggested code and it works as expected. But then I ran it again without the ".toString()" part and it works fine.

Additional Context

No response

Suggested Changes

Include a statement with something like "Now, let's add a list of three numbers to our

".

And for the "must", maybe soften this with verbiage describing how using "toString()" is a good practice, but the browser might let you be sloppy and go without?

npm test results broken

Thanks for raising this issue! Future learners thank you for your diligence. In
order to help the curriculum team address the problem, please use this template
to submit your feedback. We'll work on addressing the issue as soon as we can.

Please fill out as much of the information below as you can (it's ok if you
don't fill out every section). The more context we have, the easier it will be
to fix your issue!

Note: you should only raise issues related to the contents of this lesson.
If you have questions about your code or need help troubleshooting, reach out to
an instructor/your peers.


Link to Canvas

Add a link to the assignment in Canvas here.

Describe the bug

Write a clear and concise description of what the bug is. Include the file and
line number(s) if possible.
Initial npm test input results in:

$ npm test

[email protected] test
mocha -R mocha-multi --timeout 5000 --reporter-options spec=-,json=.results.json

  1. "before all" hook

0 passing (11s)
1 failing

  1. "before all" hook:
    Error: Timeout of 5000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
    at Object.done (node_modules/mocha-jsdom/index.js:70:7)
    at /mnt/d/Programming/FlatironSchool/code/phase0/phase-0-the-dom-modifying-elements-lab/node_modules/jsdom/lib/jsdom.js:312:18
    at processTicksAndRejections (node:internal/process/task_queues:78:11)

What is the expected behavior?

Write a clear and concise description of what you expected to happen.

Screenshots

If applicable, attach screenshots to help explain your problem.

What OS are you using?

  • OS X
  • WSL
  • [ x] Linux

Any additional context?

Add any other context about the problem here.

The arguments for using 'toString()' is not convincing...

Canvas Link

https://learning.flatironschool.com/courses/5185/assignments/179265?module_item_id=396161

Concern

I don't understand the nuance of this paragraph:
If we don't call the toString() method on (i + 1), the lists would still be populated. But they would be stored as strings in the DOM. JavaScript tries to convert the value to a string automatically.

The first sentence says the lists will be populated even if we don't use 'toString()'.
The second sentence says "but they will be stored as strings." So what's the problem since it sounds like they will be stored as strings whether or not we use 'toString()'.

Additional Context

No response

Suggested Changes

Clarify?

Typo in read.me

Link to Canvas

https://learning.flatironschool.com/courses/4384/assignments/141847?module_item_id=297268

Issue Subtype

  • Master branch code
  • Solution branch code
  • Code tests
  • Layout/rendering issue
  • Instructions unclear
  • [ x] Other (explain below)

Describe the Issue

Source

Small typo here: "Inside our loop above, we create an li element and set its innerHTML property to a simple number (expressed as a string) that represents the current iteration through the loop."
It says innerHTML, but in the "loop above" .textContent is used. 

Concern

Just a small typo.

(Optional) Proposed Solution

What OS Are You Using?

  • [x ] OS X
  • Windows
  • WSL
  • Linux
  • IllumiDesk

Any Additional Context?

Issues With 'Creating and Inserting DOM Nodes Lab'

Canvas Link

https://learning.flatironschool.com/courses/5282/assignments/162793?module_item_id=349467

Concern

The tests presented seem very off.

Whoever wrote this didn't think to maybe write the prompt a bit clearer, or maybe not to use 'newHeader' over 3 times for three different directives.

Honestly, this really should be re-written. Very off putting, as it doesn't have to be this complicated for simple DOM based methods that can be learned in minutes.

The prompts for the tests themselves are just flat out confusing.

Additional Context

No response

Suggested Changes

Same as 'Concern'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.