Subclassing DOM Elements in JavaScript

Ok, you actually can’t do that. But you can do something that feels the same.

The trick is to create a factory method, initialize the variables and functions that your subclass requires as local to the method and tie them to the DOM element instance using one or more closures. Using variables local to the factory function makes them “private” to the extent that such a concept exists in JavaScript, and you can use Object.defineProperty to allow”public” access to your new methods and properties.

For an example, I’ll create a subclass of the HTMLImageElement, and give it a setter called image. The setter receives an instance of a custom Image object that contains a src property and a title property. When the Image instance is set on the HTMLImageElement subclass instance, the source and alt text of the image are set implicitly.

First, the Image object.

/**
* Represents an Image.
* @param src The source URL of the image file.
* @param title The title of the image.
*/
function Image(src, title){
  this.title = title;
  this.src = src;
}
Image.prototype = new Object();

Now the “subclass.”

/**
* Creates a "subclass" of HTMLImageElement.
*/
function newImageElement(){

  // Create a regular img element.
  var img = document.createElement("img");

  // A variable to hold the Image instance.
  var _image = null;

  // Create a property. The get and set closures will keep
  // the _image variable in scope. The setter sets the properties
  // on the img element.
  Object.defineProperty(img, "image", {
    get : function(){
      return _image;
    },
    set : function(value){
      _image = value;
      this.src = value.src;
      this.alt = value.title;
    }
  });

  // Return the modified img element.
  return img;
}

You can do the same with methods:

/**
* Creates a "subclass" of HTMLImageElement.
*/
function newImageElement(){

  // Create a regular img element.
  var img = document.createElement("img");

  // The body of the setImage function
  var _setImage = function(value){
    _image = value;
    this.src = value.src;
    this.alt = value.title;
  }
  
  // The body of the getImage function
  var _getImage = function(){
    return _image;
  }

  // Create the public setImage property.
  Object.defineProperty(img, "setImage", {
    value : _setImage
  });

  // Create the public getImage property.
  Object.defineProperty(img, "getImage", {
    value : _getImage
  });

  // Return the modified img element.
  return img;
}

To use the factory method, do the following:

  
  // Create an img element.
  var img = newImageElement();

  // Create the image object.
  var image = new Image("http://farm6.static.flickr.com/5187/5774436039_28352f0d8f.jpg", "A cyclist.");

  // Set the image on the img.
  img.image = image;

  // Append the img on the document's body.
  document.body.appendChild(img);

Simple! Here’s a working example (view source to see the code.)

This entry was posted in DOM, JavaScript. Bookmark the permalink.

2 Responses to Subclassing DOM Elements in JavaScript

  1. Pingback: Studiare JS « Blog

  2. Pingback: Oggetti JS e HTML « Blog

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>