Introduction
You face constant frustration when static web pages fail to engage users or validate input before submission. Different browsers interpret code inconsistently, leaving your audience with broken interfaces and missing features.
Danny Goodman presents the definitive guide to mastering core syntax, object-oriented concepts, and document object models in JavaScript Bible. You learn how client-side scripting enhances user interfaces while maintaining compatibility across diverse browser environments.
The following questions guide your path through the book:
- How do you structure scripts for maximum accessibility?
- What mechanisms control document object models and form validation?
- How do you handle runtime errors and user events effectively?
1. JavaScript's Role in the World Wide Web
Client-side JavaScript enhances user interfaces and processes interactions locally, while server-side programming handles database storage and persistent data.
Client-side scripting operates independently in the browser after a page loads, making interactions faster, while server-side programming handles database storage and file management.
JavaScript cannot directly write files on the server or access a database without a backend server script. Server-side technologies like PHP, ASP, .NET, JSP, and ColdFusion must process data submissions and database queries, while JavaScript enhances the user interface locally.
Standards and Evolution
The core syntax and capabilities of JavaScript are standardized internationally through ECMA to ensure cross-browser compatibility. The European standards body ECMA publishes the official specification known as ECMA-262, defining data types, operators, and syntax rules. Both Netscape's JavaScript and Microsoft's JScript adhere to this underlying standard.
Modern web development requires strict separation between HTML structure, CSS presentation, and JavaScript behavior to ensure accessibility and maintainability. HTML 4.01 and HTML5 focus on assigning context and meaning to content rather than specifying visual styles. Cascading Style Sheets handle layouts, colors, and fonts, while JavaScript interacts with the document's markup elements and DOM.
Client-side JavaScript has intentional security boundaries that prevent it from accessing local client hardware or executing unauthorized privacy-invasive actions. Unless you grant explicit permissions in a modern browser, JavaScript cannot read or write local client files, launch external desktop applications, alter main browser preferences, or capture live data streams.
2. Developing a Scripting Strategy
Web developers face significant compatibility challenges due to uneven browser implementations and fast-paced commercial developments that often outpace standards. Different browser brands and operating systems interpret specifications differently or introduce proprietary features before standards are published, causing errors for users running alternative browsers. Early browser battles involved companies like Netscape and Microsoft introducing unique HTML extensions and proprietary features before standards bodies could review them.
Progressive enhancement and separation of development layers ensure your web applications remain accessible across diverse user agents.
Progressive Enhancement
Progressive enhancement ensures core content is accessible to all user agents while adding advanced interactive features for capable browsers. Instead of building exclusively for high-end browsers and retrofitting fixes, you should build sites to run in all user agents first, layering on enhancements for sophisticated browsers to protect accessibility.
- Provide all fundamental content, hyperlinks, and form fields using standard HTML markup.
- Ensure server-side scripting handles the core client-server dialog.
- Use JavaScript to enhance the user interface and quicken response times only after the foundation is built.
Compatibility and DOCTYPE
Major browser makers use DOCTYPE switching to let authors determine whether documents render in quirks mode or standards-compatible mode. Including specific DOCTYPE header elements at the top of a document forces modern browsers to adopt standards-compliant rendering rather than falling back to older, non-standard behaviors.
- Include a DOCTYPE element at the top of every document specifying a valid HTML or XHTML transitional, frameset, or strict DTD statement.
- Create separate files for your HTML markup, JavaScript scripts, and CSS style sheets.
3. Programming Fundamentals
Every piece of information in programming is a value belonging to a formal data type. You must understand these core types to store and manipulate data correctly.
JavaScript handles information through core data types, variables initialized with the var keyword, and operators that evaluate expressions.
Data Types and Variables
A string is characters in quotes, a number is unquoted, boolean represents true or false, and null is devoid of content but still a value. Other core types include Object and Function. Variables act as baskets holding information in computer memory.
Variables are initialized using the equal sign assignment operator alongside the var keyword. Variable names follow strict rules regarding punctuation and reserved words.
- Use the var keyword to declare a new variable.
- Use descriptive multiword names in CamelCase or interCap format for variables.
Operators and Expressions
An expression evaluates to its contents or value whenever it is used in a statement. JavaScript evaluates expressions such as string concatenation or arithmetic operations from left to right to determine the final outcome.
Arithmetic operators include addition, subtraction, multiplication, and division. The plus sign serves dual roles for addition and string concatenation. Comparison operators test values and return true or false.
Because form inputs are stored as strings, adding them directly results in string concatenation rather than arithmetic addition. Built-in functions convert string representations into true numbers.
- Pass the string value as a parameter into parseInt() or parseFloat() to convert it to a number.
- Add an empty string to a number in parentheses to explicitly convert a number to its string equivalent.
- Use a pair of equal signs (==) to test whether two items are equal.
- Ensure proper word spacing is included when concatenating strings with the plus operator.
4. Control Structures and Functions
Control structures direct the execution flow of a script through conditions that evaluate to a Boolean value. Statements like if, if...else, and for loops evaluate conditions containing comparison operators to determine whether to execute specific code blocks or repeat actions.
Control structures direct execution flow, repeat loops manage iterations, and functions encapsulate reusable blocks of deferred code.
An if...else construction determines the number of days in February for a given year by checking if it divides evenly by 4 using the modulus operator.
Conditions and Loops
The for loop is a repeat loop that utilizes an initial expression, a condition, and an update expression to execute code a specific number of times. The initial expression sets a counter variable, the condition dictates when the loop stops, and the update expression runs at the end of each iteration to modify the counter. A loop counter i initialized at startValue increments by 1 using the ++ operator until it exceeds maxValue.
- Set an initial expression to start a counter variable
- Define a condition that forces the loop to stop
- Provide an update expression to execute after nested statements complete
An array stores a sequential list of data elements in a single-column structure accessed via numeric index values starting at zero. Arrays are created using the new keyword and the Array() object, where each row holds a distinct piece of data referenced by an index enclosed in square brackets. An array named USStates is initialized with a size of 51 to store state names from index 0 to 50, which includes 51 elements in the USStates array representing 50 states plus Washington D.C., with 50 as the highest index value.
- Create an array object and assign it to a variable using the new Array() syntax
- Access and assign data to each row using square brackets with zero-based indexing
Parallel arrays use matching index values across multiple tables to relate different pieces of information about the same entity. By maintaining the same sequence and length, matching index numbers across separate arrays allow scripts to cross-reference related data points without complex database lookups. The USStates array and the stateEntered array use the same index to connect a state name with its corresponding admission year across 51 elements in parallel state and year arrays.
- Build multiple arrays with corresponding rows representing related attributes
- Iterate through a primary array using a for loop to find a matching index
- Apply the located index to a parallel array to retrieve associated data
Scope and Parameters
Functions define a set of deferred actions that can be invoked repeatedly by event handlers or other statements. Functions are reusable blocks of code that can accept parameters, carry out operations, and optionally return values back to the calling statement. A greeting function receives a string parameter and displays an alert box.
- Use multiword names with CamelCase or interCap formatting starting with a verb
- Keep the focus of each function as narrow as possible
Parameters pass values from a calling statement into a function without requiring the var keyword for initialization. When a function is called with arguments, those values are automatically assigned to the variable names specified within the function definition's parentheses. The sayHelloFirst function accepts three string parameters (a, b, and c) and displays an alert using the first parameter.
Variables defined outside functions have global scope, while those defined inside functions using var are local to that function. Global variables are accessible across the entire document, whereas local variables can only be accessed within their defining function, allowing variable names to be safely reused without conflicts. Declaring a local variable inside demo() with the same name as a global variable overrides the global variable for all statements within that function.
Browsers automatically generate arrays of like document objects based on their loading order in the HTML markup. Document elements such as forms can be accessed via browser-generated arrays using bracket notation or DOM methods like getElementsByTagName(). A document containing multiple form elements allows references like document.forms[0] or document.forms[1].
- Reference form elements using indexed array syntax like document.forms[0]
- Capture form collections using the getElementsByTagName() method
5. Window and Document Objects
The top-level window object encapsulates all browser elements, while the document object manages page content and node hierarchies.
The Window Object
The top-level browser object model is structured hierarchically, with the window object serving as the master container for all visible content and browser elements. Its scope includes the document content area as well as window chrome like scrollbars, toolbars, and status bars. Each frame in a frameset is treated as an individual window object holding its own document.
Scripts can generate subwindows using the window.open() method, which returns an object reference that must be saved in a global variable for subsequent control. The window.open() method creates a new subwindow based on specified parameters for URL, target name, and physical appearance. Because the method returns a genuine object reference, this value must be assigned to a global variable so that other functions can manipulate or close the subwindow later. Initializing the variable as null allows scripts to safely test whether the subwindow exists before calling methods on it.
Listing 10-1 demonstrates opening and closing a blank subwindow by assigning the result of window.open() to a global variable named newWindow.
- Declare a global variable to store the window reference.
- Define a function that calls window.open() and assigns the returned object reference to the global variable.
- Define a closing function that checks if the variable evaluates to true, invokes the close() method on the reference, and resets the variable to null.
JavaScript provides built-in methods on the window object to display modal alert, confirm, and prompt dialog boxes that facilitate user interaction. Browser makers restrict customization of these user interfaces to prevent deceptive practices, meaning you cannot alter their visual layout or button labels. The confirm() method returns a boolean value based on your choice, while prompt() returns either the typed string or null if canceled.
- Use alert('text') to display a message with a single OK button.
- Use confirm('text') within an if condition to capture a true or false user decision.
- Use prompt('message', 'default') to collect user text input and evaluate the returned string or null value.
The location object represents the URL of the loaded window, and setting its href property is the primary mechanism for navigating to new web pages. While the document object holds the visual content of a page, the location object represents its address. Assigning a new URL string to location.href instructs the browser to load that specific page.
Setting location.href = 'contact.html'; navigates you to a relative URL within the current web site.
- Reference the location object directly or via a specific window reference like newWindow.location.href.
- Assign an absolute or relative URL string to the href property to trigger navigation.
The Document Object and DOM
The document object provides core W3C DOM methods like getElementById() and getElementsByTagName() to reference specific elements or collections on a page. The document.getElementById() method retrieves a single element matching a unique ID string. Meanwhile, document.getElementsByTagName() collects an array-like list of elements sharing a specific tag name, and can be scoped locally to any container element.
Calling oGallery.getElementsByTagName('img') gathers all image objects contained strictly inside an element with the ID 'gallery'.
- Pass a quoted element ID string into document.getElementById() to isolate a single node.
- Pass a tag name string into getElementsByTagName() on the document or a container element to gather a collection.
- Access individual items in the resulting collection using array index notation and check its total count via the length property.
New HTML elements and text nodes can be dynamically created in memory using document.createElement() and document.createTextNode(), then inserted into the document tree. The document.createElement() method instantiates a new element node in memory based on a tag name string. Separately, document.createTextNode() generates text content that must be appended to the element before inserting the complete node into the live document body via appendChild().
- Create a new element by passing a tag name string to document.createElement().
- Assign attributes to the new element using setAttribute().
- Generate a text node using document.createTextNode() and append it to the element using appendChild().
- Insert the assembled element into the document tree by calling appendChild() on document.body or another container.
Scripts should wait for the window load event to fire before accessing document elements to ensure all page assets have fully downloaded. Attempting to access document elements before the browser has finished parsing images and plugins can trigger script errors.
- Write an initialization function containing DOM manipulation logic.
- Attach the initialization function to the window load event using a cross-browser event handler like addEvent(window, 'load', initialize).
Legacy document collection properties like forms and images allow you to reference groups of page elements by numeric indices or string identifiers. The document.forms and document.images properties allow access to these elements via numeric offsets or string values matching their name or id attributes.
Checking if (document.images) verifies whether a legacy or modern browser supports image objects before executing image-swapping scripts.
- Check the existence of document.images in a conditional statement to safely run image manipulation scripts.
- Reference a form using document.forms['formName'] or document.formName as a shorthand property.
While document.write() provides a quick way to output markup during initial page loading, its use after parsing is discouraged because it wipes out existing content. Invoking it after a page has finished loading opens a new data stream that completely erases the current document.
Listings 10-2 and 10-3 demonstrate assembling full HTML markup strings using the += operator and blasting them into the current window or a subwindow via document.write().
- Accumulate new markup string content into a variable using the += operator.
- Invoke document.write(newContent) with the assembled string.
- Call document.close() immediately afterward to properly close the layout output stream.
6. Forms and Form Elements
Forms act as vital gateways for user input, requiring careful handling of text fields, checkboxes, radio buttons, and client-side prevalidation.
Form Controls
You can target a form using document.getElementById('id'), getElementsByTagName('form'), or the legacy document.forms array which supports referencing forms by index number or by their name/id string. Text-related elements such as text, password, hidden fields, and textareas expose their contents via the value property, which always returns a string that can be manipulated using JavaScript string functions like toUpperCase().
Listing 11-2 where entering text into a converter field and navigating away or pressing Enter triggers a function that converts the string to uppercase.
- Attach an event listener to the target text input field for the change event.
- Retrieve the current contents of the text field using the value property.
- Pass the string to the toUpperCase() method to transform the characters.
- Assign the transformed string back to the input field's value property.
Assigning identical name attributes to a group of radio buttons forces the browser to group them into an array where the group name becomes the array name, and individual items are checked via their index and the checked property. Listing 11-4 uses a stooges radio group where a loop checks each button's checked property and extracts the value property containing names like Moe Howard, Larry Fine, or Curly Howard.
- Assign the same name attribute to all radio buttons in a related group.
- Iterate through the radio button collection using a for loop up to the length of the group.
- Check the checked property of each button in the iteration.
- Extract the value property from the selected button to use its data.
The select object uses selectedIndex to identify the active item's position number, which is then used as an index for the options array to access the option's text and value properties. Listing 11-5 implements select navigation where choosing a destination from a drop-down list extracts the option's value property and assigns it to location.href to redirect the browser.
- Point to the select list element using its ID.
- Access the selectedIndex property of the select object.
- Retrieve the value or text property from options[selectedIndex].
- Assign the extracted value to location.href to execute page redirection.
Prevalidation and Submission
Using this inside an event handler references the specific element that triggered the event, and this.form provides a direct link from any control to its parent form, reducing reliance on global variables. Listing 11-6 uses this to verify song input fields and process form data in the Beatle Picker application.
Attaching a validation function to the form's onsubmit event allows scripts to loop through elements, check for empty fields, and cancel submission using evt.preventDefault() in W3C browsers or returning false in Internet Explorer. Listing 11-7 checks all text input fields in a form when submitted, halting submission and alerting the user if any required field is blank.
- Attach an event listener for the submit event on the form object.
- Iterate through the form's elements collection inside the validation function.
- Verify if control types are text and if their values are empty strings.
- Display an alert message if validation fails.
- Cancel submission using evt.preventDefault() or by returning false.
7. Strings, Math, and Dates
Core language objects provide robust tools for text manipulation, advanced mathematical calculations, and localized date-time arithmetic.
String Parsing
The string.indexOf() method determines if a smaller string is contained within a larger string by returning its starting zero-based index or -1 if no match is found. By checking that the returned value is not equal to -1, a script can verify the presence of specific keywords or characters inside a larger block of text.
Checking if an input message contains the word "complaint" by evaluating sMsg.indexOf("complaint") != -1.
Regular expressions integrated with match(), replace(), and search() methods provide advanced text analysis and search-and-replace capabilities. The match() method returns an array of matching substrings based on a RegExp object. The replace() method allows global search-and-replace operations when the g flag is applied. The search() method returns the offset character number of the first match.
- Enter a main string into the designated input control
- Enter a regular expression pattern to match
- Check or uncheck the case-sensitive checkbox to configure search flags
- Click the execute button to generate the RegExp object and perform the method
- Review the resulting array or text area along with the match count
Math and Date Objects
The Math object in JavaScript is a static object whose properties and methods can be called directly without instantiating separate copies. Properties like Math.PI and Math.SQRT2 provide constant values, while methods handle mathematical, trigonometric, and rounding operations.
Generating a random integer between 1 and 6 for a dice game using Math.floor(Math.random() * 6) + 1.
Internally, JavaScript Date object instances store time as the number of milliseconds elapsed since January 1, 1970, in Greenwich Mean Time. Because dates are tracked internally via milliseconds, comparing, adding, and subtracting date values is most reliably accomplished by working with millisecond totals or using dedicated set and get methods.
- Invoke new Date() without parameters to take a snapshot of the PC internal clock
- Use dTodaysDate.setDate(dTodaysDate.getDate() + 7) to add time intervals without manual millisecond conversion
8. Images, Canvas, and Dynamic HTML
Pre-caching images and utilizing canvas elements or style sheet modifications enable responsive visual feedback and dynamic layouts.
Image Pre-caching and Rollovers
Constructing an image object in memory using the Image constructor and assigning a URL to its src property forces the browser to fetch and cache the image immediately. Assigning this cached source to a visible image element later results in an instantaneous visual change. Listing 14-1 demonstrates a select list that replaces a thumbnail image on the page with any of four pre-cached images (Bands, Clips, Lamp, and Erasers).
- Create a memory-only image object using the constructor function var myImage = new Image(width, height);
- Assign the file path or URL to the src property of the memory image object.
- Assign the cached image's src property to the src property of the document image element.
Canvas and Dynamic Content
The canvas element provides a rectangular graphical region on a web page that can be drawn to programmatically via JavaScript. Developers must obtain a two-dimensional context using the getContext() method before performing drawing operations. Listing 31-8 draws a simple bar chart with red, green, yellow, and blue bars using canvas stroke and path methods.
- Create a canvas element in HTML with specified width and height attributes.
- Define a draw function that executes upon page load.
- Retrieve the canvas element using document.getElementById().
- Obtain a two-dimensional context by calling canvas.getContext('2d').
- Execute path, stroke, and fill methods relative to the context.
9. Event Objects and Exception Handling
Event objects capture user interactions across propagation phases, while try-catch-finally blocks manage runtime errors gracefully.
Event Propagation and Binding
When an action occurs, the browser creates an event object in memory with read-only properties describing the event. Older Netscape 4 used inward event capture, Internet Explorer popularized outward event bubbling, and the W3C DOM combines both phases. To bind events cleanly via script, you can use a robust cross-browser helper function:
- Check if elem.addEventListener exists and call it with evtType, func, and false.
- Otherwise, check if elem.attachEvent exists and call it with "on" + evtType and func.
- Otherwise, assign the function directly to elem["on" + evtType].
You can block default browser behaviors like form submissions by setting return values or calling methods. Inside event handlers, you can inspect character codes against ASCII boundaries like 48 and 57.
- Inspect the event property or character code inside the event handler function.
- Assign false to event.returnValue in Internet Explorer to block the default action.
- Call evt.preventDefault() in W3C DOM browsers to block the default action.
Exception Handling
The try-catch-finally triumvirate provides a controlled environment to catch runtime errors and handle exceptions gracefully.
You place statements that might throw errors inside a try block. If an exception occurs, execution jumps to the catch block to receive an error object. A generic element appender function can catch specific DOM exceptions like HIERARCHY_REQUEST_ERR and WRONG_DOCUMENT_ERR. The finally block executes regardless of whether an exception occurred.
10 Key Ideas
- Client-side scripting operates independently in the browser after a page loads, making interactions faster, while server-side programming handles database storage and file management.
- Progressive enhancement and separation of development layers ensure your web applications remain accessible across diverse user agents.
- JavaScript handles information through core data types, variables initialized with the var keyword, and operators that evaluate expressions.
- Control structures direct execution flow, repeat loops manage iterations, and functions encapsulate reusable blocks of deferred code.
- The top-level window object encapsulates all browser elements, while the document object manages page content and node hierarchies.
- Forms act as vital gateways for user input, requiring careful handling of text fields, checkboxes, radio buttons, and client-side prevalidation.
- Core language objects provide robust tools for text manipulation, advanced mathematical calculations, and localized date-time arithmetic.
- Pre-caching images and utilizing canvas elements or style sheet modifications enable responsive visual feedback and dynamic layouts.
- Event objects capture user interactions across propagation phases, while try-catch-finally blocks manage runtime errors gracefully.
- The try-catch-finally triumvirate provides a controlled environment to catch runtime errors and handle exceptions gracefully.