Taking JavaScript to the Browser

The BOM, DOM, window and everything JavaScript in between.

Scroll down...

Content

Resources

Comments

JavaScript wasn't designed to be a stand-alone programming language -- its home is in the web browser. In this course, that's where we'll use it.

This brief lesson will introduce you to the tight relationship between JavaScript and your browser. Our goal is partially for you to pick up some useful functions but mostly for you to get an understanding of what it really means to interface with a web browser in the first place. Having a good mental model of BOM-DOM-JavaScript interactions is an important first step to actually applying JavaScript to more than just syntax exercises.

We're focusing on "pure" JavaScript here but upcoming lessons will show you how the jQuery library makes all of this much easier. The goal of this lesson is to familiarize you with the browser environment and how JavaScript interacts with it. You'll see the properties that you can pull off the Window object. All of these things will come in handy during upcoming sections.

What is a Browser?

Let's take a step back and think about what a browser does. It is a piece of software that runs on your client machine and is tasked with making HTTP requests and rendering the results it receives. Browsers have a relatively simple mandate which is naturally far more complex than you'd suspect beneath the surface.

When the browser renders an HTML file, it compiles all the HTML tags into the Document Object Model (DOM), which is the browser's representation of the full hierarchy of objects that make up a web page. This translation from markup to DOM is a core feature of every browser. As you know, when the browser gets to <style> tags (whether inline or imported), it uses that information to determine how the DOM is actually displayed by its rendering function.

When the browser gets to a <script> tag, it immediately runs whatever code is inside that tag. You could put a simple console.log statement in there or a full set of instructions for accomplishing something more difficult. The browser has a JavaScript interpreter, so it is able to interpret the code you've included and run it in the context of the browser window.

Running the JavaScript provided by <script> tags doesn't do much good if it can only do harmless things like outputting to the console or opening alert boxes. The much more powerful side of all this is that the browser exposes the DOM for modification by your code. The browser provides a package of methods and DOM objects that you're able to poke, prod, and otherwise modify with your JavaScript.

It's more than that, though. JavaScript has a direct line into your browser itself via its many APIs. It's able to:

  • Make HTTP requests
  • Refresh the page
  • Access the browser history
  • Set bookmarks or cookies
  • Implement streaming audio and video
  • ...and so on

You can think of your browser as one giant interface to the DOM and those APIs. <iframe> tags, for instance, use the browser API to implement a mini browser-within-a-browser.

If you're thinking of JavaScript as just a way to move HTML elements around, you're grossly underestimating its power. With JavaScript, you've got your fingers in every corner of the browser's functionality.

JavaScript Browser Interactions: The "BOM"

It's not an official spec like the DOM, but the compilation of a web browser's many APIs is commonly referred to as the "Browser Object Model" or BOM. We'll take a look at how you can interact with it.

The Window Object

The core object that browsers give you access to is the Window. It represents the full browser window and it's the default context in which JavaScript functions run. Any variable you define in the global scope becomes a property of window and any function you define in the global scope becomes a method of window.

For instance, that's why inspecting this inside a top-level function in a previous lesson outputted a Window object:

function foo(){ return this; }
foo();
//=> Window {top: Window, window: Window, location: Location, external: Object, chrome: Object…}

You can work with the window object directly. In your console, you can visually investigate the properties and functions the object contains by clicking the little arrow that appears next to it or use your understanding of objects to dig into its properties with bracket-style or dot-style calls:

// just a sample of the window object
// ...lots of properties and methods!
window;
//=> Window {top: Window, window: Window, location: Location, external: Object, chrome: Object…}
Infinity: Infinity
AnalyserNode: function AnalyserNode() { [native code] }
ApplicationCache: function ApplicationCache() { [native code] }
ApplicationCacheErrorEvent: function ApplicationCacheErrorEvent() { [native code] }
Array: function Array() { [native code] }
ArrayBuffer: function ArrayBuffer()
... many many properties ...
SpeechRecognitionEvent() { [native code] }
webkitStorageInfo: DeprecatedStorageInfo
webkitURL: function URL() { [native code] }
window: Windowx: a#altovatext
__proto__: Window


// Access random properties
window["ApplicationCache"];
//=> function ApplicationCache() { [native code] }
window.AnalyserNode;
//=> function AnalyserNode() { [native code] }

You can interact with this object just like any other object. Because it's so large, it's obviously helpful to know a few handy methods which you can use later. We'll cover a few of these below.

Inspecting the DOM

The most popular way to interact with the BOM is if you want to inspect the DOM, or "Document Object Model". The DOM's root "document" object is the direct child of window:

window.document;
//=> #document
< !DOCTYPE html><html lang=​"en-US" style=​"height:​ 100%;​">​…​</html>​

HTML DOM Diagram

The HTML Dom structure, from W3Schools

Once you know how to access document, you can start digging into your DOM and mucking around to your heart's content. In particular, the getElementById function should be interesting to you -- it parses the DOM and returns the element you're looking for by its ID. There are other similar finders for returning collections of objects based on their tag, element type, and so on:

// Grab a single element by searching on its ID
window.document.getElementById("some-id");


// Grab collections of objects by searching on
// various other criteria
// This is done on a random webpage, YMMV
window.document.getElementsByTagName("div");
//=> HTMLCollection[110]
window.document.getElementsByClassName("notranslate");
[ <div id=​"topnavTut" class=​"notranslate">​…​</div>​,
  <div class=​"code notranslate">​…​</div>​,
  <div class=​"code notranslate">​…​</div>​,
  <div class=​"example_code notranslate jsHigh">​…​</div>​]

Because functions operate by default in the scope of the window, you can omit the window from the invocation:

document.getElementById("demo").innerHTML = "Paragraph changed!";

Once you've located an object that you want to modify, it's trivial to use JavaScript to modify its properties. As you saw in the example above, each browser element has a property called its innerHTML which contains any text and elements inside of it. You'll often find yourself using this to change the contents of items on your pages.

You likely won't use the finders we just looked at (e.g. getElementById) directly yourself because jQuery will provide convenience wrappers for them. The idea of showing them off is to de-mystify what jQuery will be doing for you behind the scenes and to show you that all you're working with is a bunch of normal JavaScript objects that your browser gives you access to.

Other Window Properties

If you're moving elements around on the page, there are some other useful properties of the window which you'll likely find yourself accessing from time to time. Some of window's child objects are also quite useful -- screen provides information about the user's screen. Because it's in the global scope, you can call it with window.screen or simply screen.

Here are a few examples of useful properties on window and some of its children. You'll see that you have access to more than just physical properties -- there are also location properties. You don't need to memorize these, but try to visualize all the little hooks you have into the browser and the types of information they give you access to.

Note that these are properties not methods, so you access them like any other object's properties.

// *** PHYSICAL PROPERTIES ***

// Get window height and width in pixels
// This refers to the viewable area inside
// the browser
window.innerHeight;
window["innerHeight"];
window.innerWidth;
window["innerWidth"];


// open a new window
window.open();


// close the current window
window.close();


// move the current window
window.moveTo();


// resize the current window
window.resizeTo();


// Examine the `screen` properties, which
// refer to the properties of the User's monitor
screen.width;         //=> 1280
screen.height;        //=> 800


// Width/height not including the top bar
// with the file menu and system tray
screen.availWidth;    //=> 1280
screen.availHeight;   //=> 774


// Other screen properties, in bits
screen.colorDepth;    //=> 24
screen.pixelDepth;    //=> 24


// *** NAVIGATION PROPERTIES ***

// Where are we now?  Let's break down the URL...
location.href;        //=> "http://www.w3schools.com/js/js_window_location.asp"
location.hostname;    //=> "www.w3schools.com"
location.pathname;    //=> "/js/js_window_location.asp"
location.protocol;    //=> "http:"


// A function to load a new HTML document
// This is the same as inputting to your address bar
// and clicking ENTER !!!
location.assign;      //=> function () { [native code] }
location.assign("http://www.google.com");
//=> redirected to https://www.google.com/?gws_rd=ssl


// History functions give you limited access
// (for privacy reasons) to the browser history
// In this case, we can use it to redirect appropriately
history.back();       //=> "click" back button
history.forward();    //=> "click" forward button


// The `navigator` object gives you *unreliable*
// information about a user's browser.  Instead of
// asking for their browser, it's best practices to
// instead query for the *functionality* of that browser
navigator.appName     //=> "Netscape"

There is a list of examples of using this behavior at W3 Schools but, again, you really only need to take away the kinds of things you can do at this point.

Browser Compatability

For many of the functions and properties we just looked at, you'll need to consider the context in which it's run. In particular, which browser your user is running. This is one area where front-end development is a real pain compared with backend development. Server side, you control 100% of your environment.

On the client side, you may have people trying to access your site via mobile devices, outdated browsers, or poorly build third-party browsers. Regardless, they will blame YOU if their experience suffers.

While most things have been standardized across most browsers, just like in CSS, you'll find yourself needing to add a few extra lines of code here and there to handle additional support.

For instance, the innerWidth property is different in some older browsers:

var w = window.innerWidth
|| document.documentElement.clientWidth
|| document.body.clientWidth;

Don't be alarmed, it's to be expected.

The DOM Object and its Nodes

We talked about the window object and that's useful for grabbing overall settings. Most of your daily work will be with the DOM object and its many children so we'll take a look at that as well.

Each element in the DOM tree is called a "Node" and, as you know, there's a hierarchy structure to them. All Element Nodes are descendants of the Document Node and you're probably most familiar with these since they represent HTML tags. Inside each Element Node, though, certain properties are themselves nodes -- attributes of an element are "Attribute Nodes", the element's text is a "Text Node" and so on.

Essentially, every atomic piece of a typical HTML element is actually its own Node, which is really just a standard JavaScript-style object. Each of those different types of nodes has a slightly different set of properties. For example, an Attribute Node gives you access to its name, value, and whether it has actually been set via the specified property.

If you pull up an Attribute Node, you can inspect it easily. You can often poke around inside of it and change properties of its child node objects yourself. In the example below, we do both these things:

// See the "Named Node Map" (list) of all attribute
// nodes on our first paragraph
document.getElementsByTagName("p")[0].attributes;
//=> NamedNodeMap {0: class, 1: style, length: 2, getNamedItem: function, setNamedItem: function, removeNamedItem: function, item: function…}


// Grab the first attribute node by digging into
// the `NamedNodeMap` object.  It represents the class.
//=> class=​"scroll-prompt"
var attrNodeObj = document.getElementsByTagName("p")[0].attributes[0];

// Inspect all the available properties and methods
// of this object by inspecting its `keys`
Object.keys(attrNodeObj);
//=> [  "localName",
        "namespaceURI",
        "prefix",
        "ownerElement",
        "textContent",
        "nodeValue",
        "value",            // useful
        "specified",        // useful
        "name",             // useful
        "parentElement",
        "baseURI",
        "ownerDocument",
        "nextSibling",
        "previousSibling",
        "lastChild",
        "firstChild",
        "childNodes",
        "parentNode",
        "nodeType",
        "nodeName" ]


// Inspect our Attribute Node at bit using
// some of those properties
attrNodeObj.name;
//=> "class"
attrNodeObj.value;
//=> "scroll-prompt"
attrNodeObj.specified;
//=> true


// Modify our Attribute Node's `value` property
attrNodeObj.value = "funky-scroll-prompt";
//=> "funky-scroll-prompt"


// Verify that it's changed
// You can visually verify the change by
// inspecting the element in your browser
attrNodeObj.value;
//=> "funky-scroll-prompt"


// Or do it the easy way by just asking the
// Element Node what its class is with the
// `className` property
document.getElementsByTagName("p")[0].className;
//=> "funky-scroll-prompt"

You certainly don't need to memorize all the properties of all the nodes and you probably won't ever write code like we just did in your everyday life. The useful takeaway from our example is understanding that the properties of your HTML DOM elements are just stored as properties of JavaScript-accessible objects tucked inside the node hierarchy. It's all there, even if it's not quite in plain sight.

That's the other takeaway -- all the information you need to get or set for your DOM elements is there for you to access but it's buried pretty deep within the nested Node objects. It's a pain to go digging around the DOM the manual way. Wouldn't it be great if someone made a library that did all this work for you..?

Though you'll rarely need to actually use these directly, it can be interesting to browse through the list of properties and methods for element nodes to see what they give you access to. Many of these will come back in jQuery form later on.

A Demo

This YouTube video (~20min, can be sped up) shows how to build a browser calculator using straight JavaScript:

Code Review

The important bits of code from this lesson

// Access a random window property
window.innerWidth;
window["innerWidth"];

// Access that property with the implicit `window`
innerWidth;

// A few "getters" for the DOM
document.getElementById("foo");
document.getElementsByTagName("div");
document.getElementsByClassName("notranslate");

// `window` properties
window.innerHeight;
window.innerWidth;

// `window` methods
window.open();
window.close();
window.moveTo();
window.resizeTo();

// User's `screen` (monitor) properties
screen.width;         //=> 1280
screen.height;        //=> 800
screen.availWidth;    //=> 1280
screen.availHeight;   //=> 774
screen.colorDepth;    //=> 24
screen.pixelDepth;    //=> 24

// `location` navigation properties
location.href;        //=> "http://www.w3schools.com/js/js_window_location.asp"
location.hostname;    //=> "www.w3schools.com"
location.pathname;    //=> "/js/js_window_location.asp"
location.protocol;    //=> "http:"

// `location` method to redirect
location.assign("http://www.google.com");

// Go back or forward methods on `history`
history.back();       //=> "click" back button
history.forward();    //=> "click" forward button

// Unreliable `navigator` object
navigator.appName     //=> "Netscape"

// Use the Element Node's `className`
// to modify its class name
var firstP = document.getElementsByTagName("p")[0];
firstP.className = "foo";

// Modify class name directly on the Attribute Node
firstP.attributes[0].value = "foo";

Wrapping Up

This was a brief but necessary look and the DOM and the BOM and a few handy properties and methods for interacting with them. Hopefully, you're pleasantly surprised by the reach and power that JavaScript has within the browser environment. Few casual developers truly understand how JavaScript uses the Window, interacts with the DOM object, or accesses the browser's many other APIs.

At this point, you should be well prepared (and eager) to dive into jQuery, which makes all this stuff much easier for you.



Sign up to track your progress for free

There are ( ) additional resources for this lesson. Check them out!

Sorry, comments aren't active just yet!

Next Lesson: The Basics of jQuery