Finding Your Way around the Closure Library

The Closure Library contains many different tools, from user interface widgets to communication utilities. The different parts of the library share a set of conventions that help organize the code and make it easy to use.

This article briefly describes the core conventions of the Closure Library codebase. After reading this article you should be familiar enough with these conventions to work through the Getting Started exercise and explore the library further.

Closure Library Namespace

The names of all Closure Library functions and properties begin with a dot-delimited path that prevents them from accidentally overlapping with names defined in non-Closure Library code. This path is called a namespace.

For example, the following Closure Library code defines the clamp() function within the goog.math namespace:

goog.math.clamp = function(value, min, max) {
  return Math.min(Math.max(value, min), max);
};

You can call this function like this:

  var clampedValue = goog.math.clamp(2, 3, 4);

The name goog is the root of the Closure Library namespace. All Closure Library names begin with goog.

Dependency Management: goog.require() and goog.provide()

All Closure Library JavaScript files begin with a section of code that looks like this:

goog.provide('goog.math');

goog.require('goog.array');
goog.require('goog.math.Box');
goog.require('goog.math.Coordinate');
goog.require('goog.math.Range');
goog.require('goog.math.Rect');
goog.require('goog.math.Size');

The goog.provide() statements at the start of a Closure Library file declare the public namespaces and classes provided by that file. The goog.require() statements indicate the other parts of the Closure Library that this file needs. Both goog.provide() and goog.require() are functions defined in the Closure Library file closure/goog/base.js.

Together goog.provide() and goog.require() supply the Closure Library's dependency management system. This system makes it easy to assemble the parts of the Closure Library that you want to use.

Use the goog.require() function in your own code to load the parts of the Closure Library that you need. See Getting Started with the Closure Library to learn how to load Closure Library packages with goog.require().

Inheritance

The Closure Library adds an inheritance mechanism to JavaScript with the function goog.inherits(). The Closure Library uses this function to organize its codebase into classes and subclasses.

For example, the following code defines the constructor for the MenuButton Closure Library class, which inherits from the Button class:

goog.ui.MenuButton = function(content, opt_menu, opt_renderer, opt_domHelper) {
  goog.ui.Button.call(this, content, opt_renderer ||
      goog.ui.MenuButtonRenderer.getInstance(), opt_domHelper);

  // Menu buttons support the OPENED state.
  this.setSupportedState(goog.ui.Component.State.OPENED, true);

  if (opt_menu) {
    this.setMenu(opt_menu);
  }
  this.timer_ = new goog.Timer(500);  // 0.5 sec
};
goog.inherits(goog.ui.MenuButton, goog.ui.Button);

The last statement in the above code, goog.inherits(goog.ui.MenuButton, goog.ui.Button), establishes MenuButton as a subclass of Button (you can see the implementation of goog.inherits() in closure/goog/base.js). Because of this call to goog.inherits(), you can call the method getValue() on a MenuButton instance even though there is no method goog.ui.MenuButton.prototype.getValue(), like this:

  var btn = new goog.ui.MenuButton('hi');
  var value = btn.getValue();

MenuButton inherits the getValue() method from Button.

Note that the first line of the MenuButton constructor calls the Button constructor, as shown below:

goog.ui.MenuButton = function(content, opt_menu, opt_renderer, opt_domHelper) {
  goog.ui.Button.call(this, content, opt_renderer ||
      goog.ui.MenuButtonRenderer.getInstance(), opt_domHelper);
  ...
};
goog.inherits(goog.ui.MenuButton, goog.ui.Button);

A call to the superclass constructor like this is necessary to properly establish inheritance. You can use goog.inherits() to create inheritance in your own code, but be sure to always call the superclass constructor with call().

The API documentation for each class shows you the inheritance hierarchy of that class, and also all methods inherited by the class from superclasses.

Closure Library Events

Modern browsers use events to trigger JavaScript functions in response to user actions. Unfortunately, different browsers have different event systems.

The Closure Library defines its own event framework, which works the same way in all browsers. Furthermore, this framework allows programmers to define and dispatch their own event types. The Closure Library uses its event framework throughout its codebase, allowing you to to listen to Closure Library objects for events just as you listen to DOM elements.

For example, the following line from the code for the library's collapsible element widget (goog.ui.Zippy) uses the event framework to attach a listener for user clicks:

goog.events.listen(this.elHeader_, goog.events.EventType.CLICK,
    this.onHeaderClick_, false, this);

This code attaches an event listener to the DOM element elHeader_. Because of this call to goog.events.listen(), user clicks on elHeader_ trigger the handler function onHeaderClick_. See the Events Tutorial to learn more about the other arguments in this call.

By using goog.events.listen() to handle browser events in your own code, you can avoid having to write special cases for the event systems of different browsers.

You can also use goog.events.listen() to listen to instances of Closure Library classes. For example, the Closure Library class goog.ui.Zippy dispatches the custom event shown below when a Zippy is opened:

  this.dispatchEvent(new goog.ui.ZippyEvent(goog.ui.Zippy.Events.TOGGLE,
      this, this.expanded_));

By listening for this event, your code can react to it, for example by sending an alert to the user, as shown below:

  var zippyHeader = document.getElementById('header');
  var zippyContent = document.getElementById('content');
  var zippy = new goog.ui.Zippy(zippyHeader, zippyContent);

  function react(e) {
    alert('The Zippy opened!');
  }
  goog.events.listen(zippy, goog.ui.Zippy.Events.TOGGLE, react);

See the Events Tutorial for more information about Closure Library events.