Building an Application with the Closure Library

This tutorial gives you hands-on experience using the Closure Library by walking you through the construction of a simple application. To do this tutorial you should have some experience with JavaScript and you should have already done the exercise in Getting Started with the Closure Library.

Use these links to download the two source files that are used in this tutorial:

Save these files to the same directory that contains the closure-library directory.

This tutorial explains the different parts of these source files step by step. Note that the provided notepad.html file will not work until you download it and link it to your copy of the Closure Library, as described below.

The Notes Application

This tutorial illustrates the process of building a simple application for displaying notes. The example:

  • creates a namespace for the application,
  • uses the Closure Library's goog.dom.createDom() function to create the Document Object Model (DOM) structure for the list, and
  • uses a Closure Library class in the note list to allow the user to open and close items in the list.

Creating a Namespace with goog.provide()

When you use JavaScript libraries from different sources, there's always the chance that some JavaScript file will redefine a global variable or function name that you use in your code. To minimize the risk of this sort of name collision, use the Closure Library's goog.provide() function to create a namespace for your code.

For example, the notes application uses Note objects created by a Note() constructor function. If any other JavaScript file defines a global Note function or variable, it could overwrite this constructor. Therefore the example creates a namespace for this constructor with the following call to goog.provide:

goog.provide('tutorial.notepad.Note');

The goog.provide() function ensures the existence of the JavaScript object structure indicated by its argument. It checks to see whether each object property in the path expression exists, and if it doesn't exist it initializes it. The above function call is equivalent to:

tutorial = tutorial || {};
tutorial.notepad = tutorial.notepad || {};
tutorial.notepad.Note = tutorial.notepad.Note || {};

Because goog.provide() only initializes properties if they don't already exist, it never overwrites properties.

Note that goog.provide() statements have the added advantage that the dependency resolution script calcdeps.py can use them. See Using the Dependency Calculation Script to learn how to use calcdeps.py

Once the tutorial.notepad.Note object structure exists, the example assigns the constructor function to the Note property.

tutorial.notepad.Note = function(title, content, noteContainer) {
  this.title = title;
  this.content = content;
  this.parent = noteContainer;
};

The Note constructor is now in the tutorial.notepad namespace created with goog.provide().

Creating a DOM Structure with goog.dom.createDom()

To display a Note in the HTML document, the example gives the Note class the following method:

tutorial.notepad.Note.prototype.makeNoteDom = function() {
  // Create DOM structure to represent the note.
  this.headerElement = goog.dom.createDom(goog.dom.TagName.DIV,
      {'style': 'background-color:#EEE'}, this.title);
  this.contentElement = goog.dom.createDom(goog.dom.TagName.DIV, null, this.content);
  var newNote = goog.dom.createDom(goog.dom.TagName.DIV, null,
      this.headerElement, this.contentElement);

  // Add the note's DOM structure to the document.
  goog.dom.appendChild(this.parent, newNote);
};

This method uses the Closure Library function goog.dom.createDom(). The following goog.require() statement includes the code for this function:

goog.require('goog.dom');

To include a function like goog.dom.createDom() that is not a constructor, pass the namespace containing the function to goog.require (just goog.dom in this case). You don't need to include the name of the function in the goog.require() statement unless you are requiring a class. Using a Closure Library Class illustrates a goog.require() statement for this case.

The function goog.dom.createDom() creates a new DOM element. For example, the following statement from makeNoteDom() creates a new div element.

  this.headerElement = goog.dom.createDom(goog.dom.TagName.DIV,
      {'style': 'background-color:#EEE'}, this.title);

The second argument in this createDom() call specifies attributes to add to the element, and the third argument specifies a child to add to the element (in this case a string). Both the second and third arguments are optional.

The makeNoteDom() method just makes a single Note argument. To make a list of notes, the example includes a makeNotes() function that takes an array of note data and instantiates a Note object for each item, calling the Note's makeNoteDom() method.

tutorial.notepad.makeNotes = function(data, noteContainer) {
  var notes = [];
  for (var i = 0; i < data.length; i++) {
    var note =
      new tutorial.notepad.Note(data[i].title, data[i].content, noteContainer);
    notes.push(note);
    note.makeNoteDom();
  }
  return notes;
};

Using a Closure Library Class

With just two lines of code the example makes each note a Zippy. A Zippy is an element that can be collapsed or expanded to hide or reveal content.

First the example adds a new require() statement for the Zippy class:

goog.require('goog.dom.TagName');
goog.require('goog.ui.Zippy');

Then it adds a line to the end of the makeNoteDom method:

tutorial.notepad.Note.prototype.makeNoteDom = function() {
  // Create DOM structure to represent the note.
  this.headerElement = goog.dom.createDom(goog.dom.TagName.DIV,
      {'style': 'background-color:#EEE'}, this.title);
  this.contentElement = goog.dom.createDom(goog.dom.TagName.DIV, null, this.content);
  var newNote = goog.dom.createDom(goog.dom.TagName.DIV, null,
      this.headerElement, this.contentElement);

  // Add the note's DOM structure to the document.
  goog.dom.appendChild(this.parent, newNote);

  // NEW LINE:
  return new goog.ui.Zippy(this.headerElement, this.contentElement);
};

The constructor call new goog.ui.Zippy(this.headerElement, this.contentElement) attaches a behavior to the note element that will toggle the visibility of contentElement when the user clicks on headerElement.

Using the Notepad in an HTML Document

Here is the complete JavaScript code for this example application:

goog.provide('tutorial.notepad');
goog.provide('tutorial.notepad.Note');

goog.require('goog.dom');
goog.require('goog.ui.Zippy');

/**
 * Iterates over a list of note data objects, creates a Note instance
 * for each one, and tells the instance to build its DOM structure.
 */
tutorial.notepad.makeNotes = function(data, noteContainer) {
  var notes = [];
  for (var i = 0; i < data.length; i++) {
    var note =
      new tutorial.notepad.Note(data[i].title, data[i].content, noteContainer);
    notes.push(note);
    note.makeNoteDom();
  }
  return notes;
};

/**
 * Manages the data and interface for a single note.
 */
tutorial.notepad.Note = function(title, content, noteContainer) {
  this.title = title;
  this.content = content;
  this.parent = noteContainer;
};

/**
 * Creates the DOM structure for the note and adds it to the document.
 */
tutorial.notepad.Note.prototype.makeNoteDom = function() {
  // Create DOM structure to represent the note.
  this.headerElement = goog.dom.createDom(goog.dom.TagName.DIV,
      {'style': 'background-color:#EEE'}, this.title);
  this.contentElement = goog.dom.createDom(goog.dom.TagName.DIV, null, this.content);
  var newNote = goog.dom.createDom(goog.dom.TagName.DIV, null,
      this.headerElement, this.contentElement);

  // Add the note's DOM structure to the document.
  goog.dom.appendChild(this.parent, newNote);
  return new goog.ui.Zippy(this.headerElement, this.contentElement);
};

You can get this code by downloading the file notepad.js (click to download).

The following HTML uses this notepad code to display a note list in a web page:

<html>
<head>
<title>Notepad</title>
<script src="closure-library/closure/goog/base.js"></script>
<script src="notepad.js"></script>
</head>
<body>

<div id="notes">
</div>

<script>
function main() {
  var noteData = [
    {'title': 'Note 1', 'content': 'Content of Note 1'},
    {'title': 'Note 2', 'content': 'Content of Note 2'}];

  var noteListElement = document.getElementById('notes');
  var notes = tutorial.notepad.makeNotes(noteData, noteListElement);
}
main();
</script>
</body>
</html>

You can get this page by downloading the file notepad.html (click to download).

This page:

  • includes a script tag for the Closure Library file base.js. The src attribute for this tag is the path from the HTML file to the library's base.js file.
  • includes a script tag for the file containing our notepad code.
  • includes a script in the page that initializes the note list with a call to makeNotes(). The makeNotes() function takes two arguments: an array of Objects, each containing the data for a note, and the DOM element under which to build the DOM structure for the note list.