Jump to main content
Menu

window, location, history, and screen Objects

Introducing the Browser Object Model

  • The Browser Object Model (BOM) is an API that provides JavaScript with access to the various properties and methods of the browser window.
  • The DOM is at the page level; the BOM is at the browser level.
  • The BOM existed first as a de facto standard, since much of it was first introduced in an early version of the Netscape browser and subsequent browsers have supported it. If new browsers dropped support a lot of existing pages would break.
  • As the years passed, the Web Hypertext Application Technology Working Group (WHATWG) authored a living standard that included these objects.
  • If you check your browser preferences there is invariably a section related to JavaScript that lists BOM properties / methods that you can prevent JavaScript from accessing.
    • For example, you could prevent windows from being moved or resized via JavaScript.

The window Object

  • While ECMAScript does not specify what the global object (the object that contains all functions and variables in your code) should be, in web browsers this is window and represents the browser window.
  • Every global variable is located directly below that global object.
  • A global variable named testVariable is accessible via window.testVariable or simply via testVariable, because the JavaScript interpreter will move up the object tree until it reaches the very top (which is window).
  • If it moves all the way up to window and cannot find a match then an error is thrown.
  • Most of the time window does not need to be listed, because the object lookup occurs.
    • This is a tradeoff between streamlining code (omitting window reduces code) and performance (moving up the object tree takes time).
    • Although rare, it is possible that omitting window for methods will lead to code behaving in unanticipated ways. Those are cases where an object you encounter along the way to window has a method with the same name. Typically this is the document object.
    • One other consideration is code portability - if your JavaScript is going to run in an environment with a different global object, then hard-coding window will very likely break your code.
  • self is synonymous with window
  • In frames-based layouts window is also synonymous with top and parent. Let's hope you never have to work with frames.
  • Every browser window, frame, and iframe has its own separate window object.

Object Hierarchy

The object hierarchy for the Browser Object Model is:

  • window
    • document
    • history
    • location
    • navigator
    • screen

window Object Properties and Methods

Method / Property Description Code Example
alert() Displays a dialog box with the indicated message (a string object).

Used for situations such as warnings to the user; also used for troubleshooting coding errors/issues.

JavaScript processing (except for web workers) is halted until this is acknowledged.

alert('your message');
close() Closes the current window; users might disable this capability in their browser preferences.

JavaScript-opened windows will close automatically or may prompt the user.

When this is attempted on windows that users opened they will get a prompt asking if the window can close or the browser could simply ignore the command.

Specify as window.close() as there is also document.close() and just specifying close() could result in unanticipated outcomes.

window.close();
closed Returns false if the window has not been closed. If it has been closed, then it returns true. window.closed
confirm() Passed a string object containing a message / question for the user that is displayed in a dialog box with 'OK' and 'Cancel' buttons.

As soon as the code is parsed the dialog box appears.

If the user confirms (clicks 'OK') then true is returned.

If the user does not confirm (clicks 'Cancel') then false is returned.

JavaScript processing (except for web workers) is halted until this is acknowledged.

const answer = confirm('Should we continue?');
defaultStatus Sets a new default for the status bar text. This default is shown until an anchor is moused over (the status bar then displays the href value of that anchor).

Many browsers allow users to disable this property as it can reduce usability and annoy users. Browsers may also have the status bar display entirely turned off.

This property is best avoided.

window.defaultStatus = 'Welcome to my site!';
status Alters the text in the status bar temporarily; like defaultStatus this is best avoided. window.status = 'Hi';
stop() Shuts down the window loading process. window.stop();
innerHeight This property tracks the vertical space inside the browser window; other ways to measure this exist. alert(window.innerHeight);
innerWidth This property tracks the horizontal space inside the browser window; other ways to measure this exist. alert(window.innerWidth);
moveBy() Requires x and y parameters (number objects) to be passed and moves the browser window horizontally and vertically that number of pixels, based on the current location.

No size units (such as px) are given because this is always in pixels.

Many browsers allow users to disable this functionality.

moveBy(10,10);
moveTo() Requires x and y parameters (number objects) to be passed and moves the browser window to that location, regardless of the current location.

No size units (such as px) are given because this is always in pixels.

Many browsers allow users to disable this functionality.

moveTo(100,200);
name The name assigned to the window.

Typically specified as a parameter of window.open(), this ties in with the target attribute for links and the name attribute specified in a <frame /> tag.

window.name = 'newWindow';
open() Opens a new browser window.

Users might disable this in their browser preferences or a pop-up blocker may block all windows opened via JavaScript.

Passed three parameters:

  1. String object for the URL to display in the new window.
  2. String object with the name for the window.
  3. String object with attributes for the window.

Specify as window.open() as there is also document.open() and just specifying open() could result in undesirable outcomes.

window.open('https://www.google.com', '_blank', 'scrollbars=1,resizable=1,location=1');
opener This property only exists for newly opened browser windows; it references the window that opened the new window. See the code examples for communicating across windows.
postMessage() This method allows for messages (text strings) to be passed between windows on different domains. Read more about the postMessage() method. See the code examples for communicating across windows.
prompt() Displays a dialog box where the user is able to enter data.

Passed two string objects as parameters:

  1. The first is the message / prompt to display in the dialog box.
  2. The second is the default text in the text input field.

If you would rather not have any default text, set this second value to an empty string ("" or '').

If 'Cancel' is clicked the value returned is either null or undefined (depending on browser).

JavaScript processing (except web workers) is halted until this is resolved.

let name = prompt('What is your name?', 'Enter name here');
print() Opens the browser's print dialog. print();
resizeBy() Requires x and y parameters (number objects) to be passed and resizes the window by that number of pixels, based on the current dimensions of the window.

No size units (such as px) are given because this is always in pixels.

Many browsers allow users to disable this functionality.

resizeBy(5,5);
resizeTo() Requires x and y parameters (number objects) to be passed and resizes the window to that pixel size, regardless of the current dimensions of the window.

No size units (such as px) are given because this is always in pixels.

Many browsers allow users to disable this functionality.

resizeTo(400,400);
scrollBy() Requires x and y parameters (number objects) and scrolls the browser window horizontally and vertically by that amount.

No size units (such as px) are given because this is always in pixels.

scrollBy(0,300);
scrollTo() Requires x and y parameters (number objects) and scrolls the browser window horizontally and vertically to that location, regardless of the current scroll position.

No size units (such as px) are given because this is always in pixels.

scrollTo(0,300);
setInterval() Calls a function / method repeatedly, at the indicated interval.

The first parameter is the function / method name.

If you pass a parameter or parameters you must surround the function / method name in quotation marks.

The second parameter is a number object for the interval, which is in milliseconds.

This is very useful in XHR and Fetch setups to send / receive data at the indicated interval.

const theTimer = setInterval(aFunctionName, 5000);

or

const theTimer = setInterval("aFunctionName('param')", 5000);
clearInterval() Used to clear the interval created via setInterval().

The parameter passed is the variable representing the interval.

clearInterval(theTimer);
setTimeout() Calls a function / method a single time, when the interval elapses.

The first parameter is the function / method name.

If you pass a parameter or parameters you must surround the function / method name in quotation marks.

The second parameter is a number object for the timeout, which is in milliseconds.

This is very useful for timeouts on screens and redirecting to other screens after a certain period of time.

const aTimer = setTimeout(aFunctionName, 5000);

or

const aTimer = setTimeout("aFunctionName('param')", 5000);
clearTimeout() Used to clear the interval created via setTimeout().

The parameter passed is the variable representing the timeout.

clearTimeout(aTimer);
requestAnimationFrame() Instructs the browser that an animation will occur.

A single parameter is passed to this method, which is a reference to the callback function that will create the animation (through modifying CSS).

That callback function, in turn, receives a single parameter, which is the number of milliseconds reflecting the current time.

Read more about requestAnimationFrame().

requestAnimationFrame(callback);

Additional Considerations with Timeouts / Intervals

  • JavaScript runs as a single process / thread in the browser.
  • That means that the JavaScript interpreter can only do one thing at a time.
  • Web Workers are an exception to this, as they run in separate threads that operate in parallel with the main thread where JavaScript is running. We are not exploring Web Workers in this article, so the rest of these considerations deal with the main thread JavaScript.
  • Timeouts and intervals are scheduled on a timeline out into the future that reflects, at best, an approximate time when they will occur.
  • If something else is occupying the main thread JavaScript interpreter at the moment when a timeout or interval elapses, whatever needs to happen when that timer expires will be delayed until the interpreter can get to it. The function will be called eventually, but it will not be at precisely the moment desired.
  • Even under good conditions expect the code to execute 10 - 100 milliseconds after the timer has elapsed.
  • Any JavaScript dialog box, such as alert(), confirm(), or prompt(), will also freeze the timeline until those are addressed by the user, so all timers are frozen until those are handled.
  • From a performance perspective it is faster to call a function than to pass a string, because the function can be optimized during compilation and the string being passed cannot be optimized.

window Events

Event Triggered By
afterprint Fires when the print preview has been closed and/or the document has started printing.
beforeprint Fires when the print preview is about to open and when the document is about to print.
beforeunload Fires when the document is about to be unloaded (so before the unload event fires). Mainly used to trigger a warning about losing unsaved data if the user reloads or tries to navigate away after entering data or editing data.
blur Fires when the window loses focus (when another window gains focus).
error Fires when a JavaScript error occurs (such as a security violation or trying to use a non-existent object) or if an object download fails (such as an image not being found).
focus Fires when the window gains focus.
hashchange Fires when the # sign part of the URL changes.
load Fires after everything else on the page has been loaded (HTML, CSS, images, videos, etc.).
resize Fires when the browser window is resized. Resizing by as little as 1 pixel fires this event. A debounce / throttle function is often used to prevent overloading the interpreter, timeline, and browser. These rely on setTimeout(), discarding the vast majority of calls until the timer has elapsed.
scroll Fires when the browser window is scrolled. Scrolling by as little as 1 pixel fires this event. A debounce / throttle function is often used to prevent overloading the interpreter, timeline, and browser. These rely on setTimeout(), discarding the vast majority of calls until the timer has elapsed.
unload Fires when the document in the browser window changes. This event has been deprecated, so browsers may no longer support it. There are better alternatives (such as beforeunload) that function more reliably across a variety of usage scenarios.

Attributes for window.open()

  • The third parameter passed to window.open() is a list of the attributes controlling the window's location and appearance, separated by commas.
  • These can be included in any sequence and not all need to be specified.
  • Make sure that there are no spaces between attributes and that only one set of quotation marks (either single or double) encloses all the attributes.
  • Keep in mind that it is very annoying if an overly large window opens up and its edges are off the side of the user's monitor or viewport. That is a major blow to the user experience.
  • Think carefully before disabling location, scrollbars, and resizable, again due to usability concerns.
Attribute Values Details
copyhistory
  • 1 (true)
  • 0 (false)
Transfers the old window's history to the new window (if 1 is the value).

Generally not important, but there are times when it is useful.

directories
  • 1 (visible)
  • 0 (not visible)
Controls whether the Favorites bar / Personal bar is visible.

Usually not important.

height
  • Integer without sizing unit (e.g., 300)
Height (in pixels) of the content area, which does not include space needed for toolbars and other chrome.
left
  • Integer without sizing unit (e.g., 200)
The number of pixels the window is from the left edge of the monitor.
location
  • 1 (visible)
  • 0 (not visible)
Controls whether the location field is visible.

Some browsers allow users to block JavaScript access to this attribute.

menubar
  • 1 (visible)
  • 0 (not visible)
On Windows this can turn on (1) or turn off (0) the menu bar at the top of the window.

Macs generally ignore this attribute and have the menubar visible.

resizable
  • 1 (resizable)
  • 0 (not resizable)
Controls whether the user can resize the window.

Either they can (value of 1) or they cannot (value of 0).

scrollbars
  • 1 (visible)
  • 0 (not visible)
Controls whether there are scrollbars visible.
status
  • 1 (visible)
  • 0 (not visible)
Controls whether the status bar at the bottom of the layout is visible.

Some browsers allow users to block JavaScript access to this attribute.

toolbar
  • 1 (visible)
  • 0 (not visible)
Controls whether the toolbar at the top of the layout is visible.
top
  • Integer without sizing unit (e.g., 200)
The number of pixels the window is from the top edge of the monitor.
width
  • Integer without sizing unit (e.g., 500)
The width (in pixels) of the content area, not counting scrollbars or anything else in the browser chrome.

Opening New Windows

While CodePen is the preferred environment for hosting code examples for this website (because it allows for the examples to be edited), working with new windows doesn't work well with their architecture.

That is why the code is shown here and is hosted on this domain instead.

Structure (new_window.html)

<!DOCTYPE html>
<html lang="en-us">
<head>
  <title>Opening New Windows</title>
  <meta charset="utf-8" />
</head>
<body>
<ul>
  <li><a href="https://www.google.com">Google</a></li>
  <li><a href="https://www.amazon.com" class="nWin">Amazon</a></li>
  <li><a href="https://www.indeed.com">Indeed</a></li>
</ul>

<script src="new_window.js"></script>
</body>
</html>

Behavior (new_window.js)

"use strict";

const openNew = {

  theBody : document.getElementsByTagName('body')[0],

  // attributes for new windows
  params : 'top=5,left=5,width=400,height=400,scrollbars=1,resizable=1,location=1',

  init : function() {
   
    this.theBody.addEventListener('click', this.openIt, false);

  },
  
  openIt : function(evt) {
    
    // pinpoint the anchor clicked
    const linkClicked = openNew.findTarget(evt, 'a', this);  
   
    // stop if an anchor was not clicked or the anchor lacks the 'nWin' class
    if (!linkClicked || !linkClicked.classList.contains('nWin')) { return; }
    
    // shut down the default behavior of the anchor
    // without this the existing window also changes its address
    evt.preventDefault();
    
    // open the new window
    window.open(linkClicked.href, '_blank', openNew.params);
    
  },

  findTarget : function(evt, targetNode, container) {
    let currentNode = evt.target;
    while (currentNode && currentNode !== container) {  
      if (currentNode.nodeName.toLowerCase() === targetNode.toLowerCase()) { 
        return currentNode; }
      else { currentNode = currentNode.parentNode; }     
    }
    return false;
  }

}

openNew.init();

See how this new window example renders

Communicating Across Windows

Two examples are provided, showing different approaches. The first example uses DOM references for updating one window's content based on information from another window.

The second example uses postMessage() for passing information.

The examples are again hosted on this domain rather than CodePen, as their architecture doesn't work well with cross-window communication.

Example #1: window.opener and DOM Lookups

Structure of Starting Page (cross_window.html)

<!DOCTYPE html>
<html lang="en-us">
<head>
  <title>Communicating Across Windows</title>
  <meta charset="utf-8" />
  <link rel="stylesheet" href="cross_window.css" />
</head>
<body>

<form method="post" action="">
  <label for="language">Select a language:</label>
  <span id="lang_holder"></span>
  <input type="button" id="language" value="Choose..." />
</form>

<script src="cross_window.js"></script>
</body>
</html>

Structure of Popup Page (language_list.html)

<!DOCTYPE html>
<html lang="en-us">
<head>
  <title>Language List</title>
  <meta charset="utf-8" />
  <link rel="stylesheet" href="cross_window.css" />
</head>
<body>

<table id="language_list">
<thead>
<tr>
  <th scope="col">Language</th>
  <th scope="col">Full Name</th>
  <th scope="col">Side</th>
</tr>
</thead>
<tbody>
<tr>
  <td scope="row"><a href="#">HTML</a></td>
  <td>Hypertext Markup Language</td>
  <td>Client</td>
</tr>
<tr>
  <td scope="row"><a href="#">CSS</a></td>
  <td>Cascading Style Sheets</td>
  <td>Client</td>
</tr>
<tr>
  <td scope="row"><a href="#">JavaScript</a></td>
  <td>JavaScript</td>
  <td>Client</td>
</tr>
<tr>
  <td scope="row"><a href="#">PHP</a></td>
  <td>PHP: Hypertext Preprocessor</td>
  <td>Server</td>
</tr>
</tbody>
</table>

<script src="cross_window.js"></script>
</body>
</html>

Presentation for Both Pages (cross_window.css)

body, input {font: 75% verdana, sans-serif;}
input {font-size: 100%;}
table {border-collapse: collapse;}
td, th {padding: 1em; text-align: left; vertical-align: top; border: 1px solid #000;}
#lang_holder {padding-right: 2px;}

Behavior for Both Pages (cross_window.js)

"use strict";

const crossWindow = {

  // depending on which of these element nodes is found
  // we know which page we are on
  languageButton : document.getElementById('language'),
  languageList : document.getElementById('language_list'),

  // attributes for new windows
  params : 'top=40,left=40,width=500,height=500,scrollbars=1,resizable=1,location=1',

  init : function() {
    
    // if we are not on the correct page languageButton is null
    if (this.languageButton) {
      
      this.languageButton.addEventListener('click', this.openWin, false);
    
    }

    // if we are not on the correct page languageList is null    
    else if (this.languageList) {
    
      this.languageList.addEventListener('click', this.passValueBack, false);
    
    }
   
  },
  
  openWin : function() {
        
    // open the new window and have a variable referencing it
    const newWindow = window.open('language_list.html', '_blank', crossWindow.params);
    
    // give the new window focus, on the off chance something put it
    // into the background
    newWindow.focus();
    
  },
  
  passValueBack : function(evt) {
  
    const linkClicked = crossWindow.findTarget(evt, 'a', this);
    
    if (!linkClicked) { return; }
    
    // pinpoint the span element node in the other window
    const holder = window.opener.document.getElementById('lang_holder');
    holder.innerHTML = linkClicked.firstChild.nodeValue;
    
    // shut down the new window
    window.close();

    // shut down the href of the anchor clicked
    evt.preventDefault();
  
  },

  findTarget : function(evt, targetNode, container) {
    let currentNode = evt.target;
    while (currentNode && currentNode !== container) {  
      if (currentNode.nodeName.toLowerCase() === targetNode.toLowerCase()) { 
        return currentNode; }
      else { currentNode = currentNode.parentNode; }     
    }
    return false;
  }

}

crossWindow.init();

See how this first cross window example renders

Example #2: window.opener and postMessage()

The structural markup and the CSS have remained the same (other than altering CSS and JS file names).

Revised JavaScript (post_message.js)

"use strict";

const crossWindow = {

  // depending on which of these element nodes is found
  // we know which page we are on
  languageButton : document.getElementById('language'),
  languageList : document.getElementById('language_list'),
  languageHolder : document.getElementById('lang_holder'),

  // attributes for new windows
  params : 'top=40,left=40,width=500,height=500,scrollbars=1,resizable=1,location=1',

  init : function() {
    
    // if we are not on the correct page languageButton is null
    if (this.languageButton) {
      
      this.languageButton.addEventListener('click', this.openWin, false);
    
    }

    // if we are not on the correct page languageList is null    
    else if (this.languageList) {
    
      this.languageList.addEventListener('click', this.generateMessage, false);
    
    }

    // listen for post messages
    window.addEventListener("message", this.updateText, false);
   
  },

  // the data property of this event contains the text of the message
  updateText : function(evt) {

    if (crossWindow.languageHolder) {

      crossWindow.languageHolder.innerHTML = evt.data;

    }

  },
  
  openWin : function() {
        
    // open the new window and have a variable referencing it
    const newWindow = window.open('language_list.html', '_blank', crossWindow.params);
    
    // give the new window focus, on the off chance something put it
    // into the background
    newWindow.focus();
    
  },
  
  generateMessage : function(evt) {
  
    const linkClicked = crossWindow.findTarget(evt, 'a', this);
    
    if (!linkClicked) { return; }

    const theMessage = linkClicked.firstChild.nodeValue;

    // send the message to the opening window
    // for security reasons the domain must match what is specified
    window.opener.postMessage(theMessage, "https://learningtocode.info");
    
    // shut down the new window
    window.close();

    // shut down the href of the anchor clicked
    evt.preventDefault();
  
  },

  findTarget : function(evt, targetNode, container) {
    let currentNode = evt.target;
    while (currentNode && currentNode !== container) {  
      if (currentNode.nodeName.toLowerCase() === targetNode.toLowerCase()) { 
        return currentNode; }
      else { currentNode = currentNode.parentNode; }     
    }
    return false;
  }

}

crossWindow.init();

location Object Properties and Methods

  • This object represents the address currently being accessed.
  • You must reference location as part of these properties and methods.
  • Note that some of the properties for this object are read-only.
  • A generic representation of the location is:

    protocol://host:port/pathname#hash?search

  • In detailing the properties this URL will be used:

    https://learningtocode.info/js/?p=bom-window#evts

Method / Property Description Code Example
protocol The communication protocol in use. alert(location.protocol);

will display:

https:
host The host and domain name visited. alert(location.host);

will display:

learningtocode.info
port The server's communication port used for the protocol (usually port 80 for HTTP). alert(location.port);
pathname The directory and file path. alert(location.pathname);

will display:

/js/
hash The anchor name in the address (e.g., for within-page sections).

Each time the hash changes a new entry is added in the browser history.

There is a hashchange event that fires when the hash (the part after the #) is modified.

alert(location.hash);

will display:

#evts
search The question mark and everything following it; used for passing variables and their values via the URL.

There is a URLSearchParams API that allows you to work with the variables passed via location.search; this is easier than using string methods to split apart the search data (you would remove the ? and then split the data by ampersand, then split those values by the = character).

alert(location.search);

will display:

?p=bom-window
href The entire URL; very useful when redirecting to a new page / address.

This is done by assigning a new URL to location.href. A 302 (temporary redirect) header is used.

alert(location.href);

will display:

https://learningtocode.info/js/?p=bom-window#evts
hostname The host:port part of the URL. alert(location.hostname);

will display:

learningtocode.info
reload() Forces a reload of the current page.

No parameter is passed.

location.reload();
replace() Loads the specified URL (passed as a string object to this method) and replaces the old page in the browser history.

This makes it impossible to use the browser's Back button to return to the previous page.

Before implementing this the key question is whether a user needs to go back. If they do not, this is a good approach. If they do need to go back, this is a major usability issue.

location.replace('https://www.google.com');

history Object Properties and Methods

This object provides very limited access to the browser's history data and some history-related functionality.

Method / Property Description Code Example
back() Moves back one page in the browser history, assuming that a page exists there.

If no page exists, nothing will happen.

This is used for 'Back' buttons that are part of the web page (not the one built into the browser).

history.back();
forward() Moves ahead one page in the browser history, assuming that a page exists there.

If no page exists, nothing will happen.

history.forward();
go() Passed a number object representing the number of pages to move forward (positive number) or backward (negative number).

Passing -1 has the same effect as history.back();

Passing 1 has the same effect as history.forward();

Passing 0 reloads the page.

This will not work if there is no page at the indicated position in the history.

history.go(-2);
length This property tracks the total number of items in the browser history for that page.

It is not possible to read the values in the history (due to privacy concerns).

alert(history.length);

The History API

  • There is also a History API that allows you to store a lot of data about a given URL variation in a state object.
  • This is used extensively in single-page web applications and the URL variations are generally the hash value changing.
  • I have used this in filtered product search results (there were around 10 filters that could be used in varying combinations):
    • The hash changed each time a filter was added or removed
    • The state (basic info about the results; the product id / name / image path, as well as the state of the filters in play) was saved with that new URL variation.
    • As the user hit the browser back button the hash would change and I would load the previous results and restore the filter selections.
    • Without that setup the back button would have taken the user directly out of the filtered product results, and delving into a product and then hitting the back button would have lost all the filters.
    • This also alleviated the need to hit the database again to determine the matches, because the state objects held the product info.
    • If there was no data stored for a given hash, then the results were fetched from the database.
    • This setup allowed for a remarkably fast search / filter from a dataset with millions of products.
  • Read more about working with the History API.

screen Object Properties

  • This object provides information about the user's computer screen. This information is often used by web analytics (it is stored in order to learn more about user settings).
  • Unfortunately, this is not very useful unless you are altering the layout based on resolution.
Property Description Code Example
availHeight Provides the vertical screen resolution with taskbars and other browser chrome removed. alert(screen.availHeight);
availWidth Provides the horizontal screen resolution with scrollbars and other browser chrome removed. alert(screen.availWidth);
colorDepth Provides the number of bits per pixel (e.g., 16-bit, 32-bit), although it only reports back the number (such as 32). alert(screen.colorDepth);
height Provides the vertical resolution of the screen alert(screen.height);
width Provides the horizontal resolution of the screen alert(screen.width);