📣 Attention Salesforce Certified Trailblazers! Link your Trailhead and Webassessor accounts and maintain your credentials by December 14th. Learn more.
close
trailhead

Understand JavaScript in the Browser

Learning Objectives

After completing this unit, you'll be able to:

  • Describe the interaction between JavaScript and the browser.
  • Explain the role of web APIs.
  • Use basic Document Object Model APIs.`
  • Describe ways Lightning components abstract the DOM.

How JavaScript Works in the Browser

You just learned a little about the JavaScript runtime engine and language. You also learned a few things that everyone writing JavaScript should know. In this module, we focus on the relationship between JavaScript and the browser, with a special focus on how your web page looks in JavaScript. 

The JavaScript Runtime Is Not the Browser, Nor Is the Browser JavaScript

So the JavaScript runtime engine runs in many different places, but it’s most often hosted in a browser. So what’s the difference between JavaScript and the browser? 

A browser’s primary job is to act as a client for a web server. It requests resources over the Internet, using one of several protocols (usually HTTP/HTTPS). Once a server passes it some of those resources, the browser needs to do something with them. At a minimum HTML and CSS are rendered into a page. When a resource contains some JavaScript, the browser reaches over to the JavaScript runtime engine to parse, evaluate, and execute that code. 

Likewise, while a script is executing it can also reach back to the browser to do things like modify the web page, interact with the local environment, or interact with other web resources.

JavaScript Engine with APIs

To make these interactions work, the browser surfaces APIs. In fact a large part of what people think of as client-side JavaScript is actually these APIs. 

Web APIs

Standards

It shouldn’t be surprising that there are APIs to interact with the browser. Just like any other programming language or platform surfaces APIs to interact with the environment it runs on, so too does your browser. 

While over half of browser internet traffic comes from Google Chrome, roughly another 30 percent comes from five other browsers. This underscores the importance of the web standards for these APIs, so that JavaScript can be written once and run anywhere. 

Adding Web APIs to the Picture

Previously we created a picture of the JavaScript runtime. 

  • Requests execute on the stack using a single thread.
  • A request holds the thread until it is done executing all synchronous logic for that request.
  • New requests are queued until the thread is ready.
  • The event loop moves the next queued request into the stack when it becomes available.

We’re now adding web APIs to our picture of JavaScript. These extend the core JavaScript language. They surface interfaces that perform much of the work that is critical to the user experience of the modern web. For example, browser APIs can: 

  • Interact with the structure of the current page rendered in the browser (Document Object Model or DOM API)
  • Perform asynchronous requests to the server without leaving the current page (Fetch API)
  • Interact with audio, video, and graphics
  • Interact with device features surfaced to the browser (geolocation, device orientation, client-side data storage)

Most of the time it is these APIs that add new requests to the queue. 

Note

Note

We’re sidestepping an important piece of the JavaScript ecosystem: third-party APIs and JavaScript libraries or frameworks that abstract out the complexity of many of the APIs that ship with browsers. Learning about these frameworks should be part of any journey to learn JavaScript, and there are plenty of resources out there.

For our purposes in the context of Salesforce, we cover our JavaScript framework: the Lightning component framework.

Take an example. You have a list of notes on a web page with a form. You fill out some fields on the form, click a button to save that data, and a new item is added to the list. For fun, let’s say also that you will cache this new record locally to speed up future requests involving that record. 

This simple use case would interact with the following browser APIs

  • Fetch API (to save the record)
  • DOM API (to add a new item to an HTML list)
  • Client-Data Storage (to cache the data locally)

Let’s dive into the DOM API, since it represents what the user sees within JavaScript. 

The Document Object Model

The DOM: Your Page on JavaScript

When a page is requested and then received by a browser, the browser parses the HTML and create a description, or a model, of that page. This model is used to draw the page in the browser’s viewport. It’s also surfaced to JavaScript through the DOM. 

Think of the DOM as a tree. It starts at the root of the browser’s display functionality: the window. From there, the page is encapsulated in window.document, with the page’s body in window.document.body. Then the tree fans out to every bit of content represented on the page. Most web pages have a very complex tree with many nodes finally ending in leaf nodes as the most granular pieces of the hierarchy. 

As an API, the DOM is vast, and lets you touch every part of this tree. It also has a number of methods to optimize interaction with the DOM. Let’s look at a simple example. 

This example includes:

  • An input field
  • An Add Item button
  • An unordered list

Each time you click the button, the code reaches into the input field, reads its value, converts it to a text node, creates a new li element, inserts the text node into the li node, and finally sticks the new li-and-text node into the ul

Note

Note

For extra fun, and if you want to practice some of the principles discussed so far, see if you can modify the jsbin to do the following.

  • Check if the text input has data in it or not
  • If it doesn’t, do not add a new li to the list
  • Once the new li is added, clear the text input

If the suspense is killing you, check out the modified code.

As you can see, just this simple example requires the developer to perform a bunch of manual steps. And it doesn’t even store any data on a server, or interact with a server in any other way. For this reason, JavaScript libraries (reactjs, jQuery) and frameworks (Angular, vuejs) have become the standard for interactive pages. Such frameworks abstract away and simplify DOM interactions, and often automatically apply polyfills for missing features. The Lightning component framework is no different. 

Lightning Components and the DOM

Note

Note

This section addresses Lightning components and DOM manipulation, but the Lightning component framework abstracts a lot of other concerns as well. It is solving for component-based UI architecture, component event handling, server interaction, security, data retrieval and persistence to Salesforce, modular UI building with App Builder, client data caching, CSS leak prevention, and much more.

Each unit from this point forward will have a similar section with some examples to illustrate the tie-in to the Lightning component framework. If you want to apply what you’re learning, now is a great time to begin the Lightning Components Basics module on Trailhead.

Automatic DOM Updates

The fundamental value of Lightning components is in building a custom UI driven by Salesforce data. This ties in to DOM manipulation because the DOM itself is updated as data changes and events occur.

This component demonstrates this principle in its simplest form. 

The entire code of this component looks like this.

<aura:component implements="flexipage:availableForAllPageTypes">
  <aura:attribute name="text" type="String"/>
  <lightning:card title="Basic DOM Example" iconName="utility:hierarchy">
    <div class="slds-card__body slds-card__body-inner">
      <p>
        <lightning:formattedText value="{!v.text}"/>
      </p>
      <p>
        <lightning:input aura:id="inputText" type="text" value="{!v.text}"/>
      </p>
    </div>
  </lightning:card>
</aura:component>

If your first reaction is, “Where’s the JavaScript?”—that’s precisely the point. Although this is a contrived example, the point stands. As data changes, the DOM of the page is updated. 

There are plenty of other Lightning base components that wrap and abstract away DOM manipulation. But now when that toast appears or the modal window pops up, you know Lightning is doing a lot of work for you! 

Explicit DOM Manipulation

Manual DOM manipulation shouldn't be your first strategy when building a Lightning component, but more sophisticated components may require you to do so. This is an advanced topic, but it’s worth scratching the surface of how this works before signing off on the DOM. 

Conditional Rendering with aura:if

You can use the aura:if tag to conditionally display items. 

<aura:attribute name="show" type="Boolean" default="true"/>
<aura:if isTrue="{!v.show}">
  <p>Peek-a-boo!</p>
  <aura:set attribute="else">
    <p>I’m hiding!</p>
  </aura:set>
</aura:if>

In this code sample, the text Peek-a-boo! appears when the show attribute has a value of true and by default. When false, the text I’m hiding! appears. 

Other Ways to Manually Manipulate the DOM

In addition to the aura:if component there are other ways to approach this. You can manipulate a component's appearance with CSS. You can also dynamically render components using the $A.createComponent() Lightning component JavaScript API. It’s beyond the scope of this module to dive into these topics, but you can find details in the Lightning component developer guide.

Resources

Code Sample Project for This Module

Trailhead Module: Lightning Components Basic

Lightning Component Developer Guide: Modifying the DOM

Lightning Component Developer Guide: aura:if

Lightning Component Developer Guide: $A.createComponent

UI Frameworks:

Third party web APIs

retargeting