# Chapter 15. JavaScript in Web Browsers The JavaScript language was created in 1994 with the express purpose of enabling dynamic behavior in the documents displayed by web browsers. The language has evolved significantly since then, and at the same time, the scope and capabilities of the web platform have grown explosively. Today, JavaScript programmers can think of the web as a full-featured platform for application development. Web browsers specialize in the display of formatted text and images, but, like native operating systems, browsers also provide other services, including graphics, video, audio, networking, storage, and threading. JavaScript is the language that enables web applications to use the services provided by the web platform, and this chapter demonstrates how you can use the most important of these services. The chapter begins with the web platform’s programming model, explaining how scripts are embedded within HTML pages (§15.1) and how JavaScript code is triggered asynchronously by events (§15.2). The sections that follow this introductory material document the core JavaScript APIs that enable your web applications to: - Control document content (§15.3) and style (§15.4) - Determine the on-screen position of document elements (§15.5) - Create reusable user interface components (§15.6) - Draw graphics (§15.7 and §15.8) - Play and generate sounds (§15.9) - Manage browser navigation and history (§15.10) - Exchange data over the network (§15.11) - Store data on the user’s computer (§15.12) - Perform concurrent computation with threads (§15.13) CLIENT-SIDE JAVASCRIPT In this book, and on the web, you’ll see the term “client-side JavaScript.” The term is simply a synonym for JavaScript written to run in a web browser, and it stands in contrast to “server-side” code, which runs in web servers. The two “sides” refer to the two ends of the network connection that separate the web server and the web browser, and software development for the web typically requires code to be written on both “sides.” Client-side and server-side are also often called “frontend” and “backend.” Previous editions of this book attempted to comprehensively cover all JavaScript APIs defined by web browsers, and as a result, this book was too long a decade ago. The number and complexity of web APIs has continued to grow, and I no longer think it makes sense to attempt to cover them all in one book. As of the seventh edition, my goal is to cover the JavaScript language definitively and to provide an in-depth introduction to using the language with Node and with web browsers. This chapter cannot cover all the web APIs, but it introduces the most important ones in enough detail that you can start using them right away. And, having learned about the core APIs covered here, you should be able to pick up new APIs (like those summarized in §15.15) when and if you need them. Node has a single implementation and a single authoritative source for documentation. Web APIs, by contrast, are defined by consensus among the major web browser vendors, and the authoritative documentation takes the form of a specification intended for the C++ programmers who implement the API, not for the JavaScript programmers who will use it. Fortunately, Mozilla’s “MDN web docs” project is a reliable and comprehensive source1 for web API documentation. LEGACY APIS In the 25 years since JavaScript was first released, browser vendors have been adding features and APIs for programmers to use. Many of those APIs are now obsolete. They include: - Proprietary APIs that were never standardized and/or never implemented by other browser vendors. Microsoft’s Internet Explorer defined a lot of these APIs. Some (like the innerHTML property) proved useful and were eventually standardized. Others (like the attachEvent() method) have been obsolete for years. - Inefficient APIs (like the document.write() method) that have such a severe performance impact that their use is no longer considered acceptable. - Outdated APIs that have long since been replaced by new APIs for achieving the same thing. An example is document.bgColor, which was defined to allow JavaScript to set the background color of a document. With the advent of CSS, document.bgColor became a quaint special case with no real purpose. - Poorly designed APIs that have been replaced by better ones. In the early days of the web, standards committees defined the key Document Object Model API in a language-agnostic way so that the same API could be used in Java programs to work with XML documents on and in JavaScript programs to work with HTML documents. This resulted in an API that was not well suited to the JavaScript language and that had features that web programmers didn’t particularly care about. It took decades to recover from those early design mistakes, but today’s web browsers support a much-improved Document Object Model. Browser vendors may need to support these legacy APIs for the foreseeable future in order to ensure backward compatibility, but there is no longer any need for this book to document them or for you to learn about them. The web platform has matured and stabilized, and if you are a seasoned web developer who remembers the fourth or fifth edition of this book, then you may have as much outdated knowledge to forget as you have new material to learn. ## 15.1 Web Programming Basics This section explains how JavaScript programs for the web are structured, how they are loaded into a web browser, how they obtain input, how they produce output, and how they run asynchronously by responding to events. ### 15.1.1 JavaScript in HTML `` tags. Here, for example, is an HTML file that includes a script tag with JavaScript code that dynamically updates one element of the document to make it behave like a digital clock: ```html Digital Clock

Digital Clock

``` Although JavaScript code can be embedded directly within a ` ``` A JavaScript file contains pure JavaScript, without `` tags. Note that the closing `` tag is required in HTML documents even when the src attribute is specified: HTML does not support a ` ``` Both the defer and async attributes are ways of telling the browser that the linked script does not use document.write() to generate HTML output, and that the browser, therefore, can continue to parse and render the document while downloading the script. The defer attribute causes the browser to defer execution of the script until after the document has been fully loaded and parsed and is ready to be manipulated. The async attribute causes the browser to run the script as soon as possible but does not block document parsing while the script is being downloaded. If a ` ``` This two-line script extracts input from the “name” query parameter of the document URL. It then uses the DOM API to inject an HTML string into the first `

` tag in the document. This page is intended to be invoked with a URL like this: ``` http://www.example.com/greet.html?name=David ``` When used like this, it displays the text “Hello David.” But consider what happens when it is invoked with this query parameter: ``` name=%3Cimg%20src=%22x.png%22%20onload=%22alert(%27hacked%27)%22/%3E ``` When the URL-escaped parameters are decoded, this URL causes the following HTML to be injected into the document: ``` Hello ``` After the image loads, the string of JavaScript in the onload attribute is executed. The global alert() function displays a modal dialogue box. A single dialogue box is relatively benign but demonstrates that arbitrary code execution is possible on this site because it displays unsanitized HTML. Cross-site scripting attacks are so called because more than one site is involved. Site B includes a specially crafted link (like the one in the previous example) to site A. If site B can convince users to click the link, they will be taken to site A, but that site will now be running code from site B. That code might deface the page or cause it to malfunction. More dangerously, the malicious code could read cookies stored by site A (perhaps account numbers or other personally identifying information) and send that data back to site B. The injected code could even track the user’s keystrokes and send that data back to site B. In general, the way to prevent XSS attacks is to remove HTML tags from any untrusted data before using it to create dynamic document content. You can fix the greet.html file shown earlier by replacing special HTML characters in the untrusted input string with their equivalent HTML entities: ```js name = name .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'") .replace(/\//g, "/") ``` Another approach to the problem of XSS is to structure your web applications so that untrusted content is always displayed in an `