Access Keys:
Skip to content (Access Key - 0)

Overlay

Work In Progress
Both this documentation and the code itself is a work in progress.
The API may change at any time, but the version number (version.txt) will be bumped when this happens.
There may be errors in this documentation (or in the code), please study the source before using any feature. Feedback will be most welcome.
Project Details
Overlay complex JavaScripts objects over one another.

Source: github
Version: 0.6
Author: Mark Gibson

Introduction

Consider a JavaScript application that holds all it's data in a complex object (ie. contains nested objects) possibly loaded via JSON or DWR. The application will make changes to this object when the user performs an action or edit of some kind.

Essentially this gives us two layers of data: the original data loaded from the server (Saved), and the modifications made by the user (Mods).

The changes could be applied directly to the original, but we then lose the ability to revert changes. We may also wish to add another layer, default values for example (Defaults), then we don't need to keep the extra data in the Saved layer.

So we could keep an object for each layer, but the application would have to check each layer object in order (Mods, Saved, Defaults) until it found a value.

We could create an API to do this, which would require some kind of registration mechanism and get/set functions, etc.

Lucky JS has everything we need to do this for us: prototypes.

We just need change the prototype of overlaying layer to the layer beneath.

Overlaying simple objects

I'll use the following object throughout this section:

	var a = {
		one: 1,
		two: 2
	};

	var b = {
		two: 'two',
		three: 'three'
	};

We want to overlay b over a, so that b inherits all properties of a that it doesn't have itself.

Now, this is really easy in Firefox:

	b.__proto__ = a;

but that's not very cross browser, other browsers don't allow changing of the prototype on the fly, it must be set before the object is created.

So we create a dummy object constructor:

	function A() {};

and assign it object a as the prototype:

	A.prototype = a;

then we can then create a new object from this which will inherit all the properties of object a.

	var b_tmp = new A();

b_tmp now inherits all properties from a, but it doesn't contain any of it's own, so now we need to copy the properties from b into it. Lucky jQuery provides the extend function that can do this for us:

	b = jQuery.extend(b_tmp, b);

This has copied all the properties from b into b_tmp, returning b_tmp which we then replace b with.

Douglas Crockford in his book JavaScript: The Good Parts suggests a beget function, along the lines of:

	function beget(o) {
		function F() {};
		F.prototype = o;
		return new F();
	}

jquery.overlay.js implements this as jQuery.beget.

Which could reduce this whole thing to just:

	b = jQuery.extend(jQuery.beget(a), b);

There is flaw to all of this though: Nested objects.

Overlaying of nested objects

Take these objects as an example:

	var super = {
		id: "SUPER",
		details: {
			name: "Super",
			type: "thing",
			color: "blue"
		}
	};
	
	var sub = {
		id: "SUB",
		details: {
			name: "Sub",
			color: "orange"
		}
	};

In the latest jQuery extend does supports deep copies, but would use plain objects only for the nested objects (ie. details) whereas we need it to beget all of these too.

This is where the jQuery Overlay plugin comes into play:

	sub = jQuery.overlay( super, sub );

sub and it's nested objects (details) will overlay super.

So sub.details.type will inherit its value from super.details.type, and if the value in super changes, it will be reflected in sub. Equally we can change the value within sub without it affecting super.

Summary

  • jQuery.beget( o )
  • jQuery.overlay( original, overlay, options )

By default, undefined values will not be copied, whereas null values will. The notNulls options can be used to ignore nulls.

A utility function getPrototype() is automatically added to the returned object so that the original object can be found from the overlay - this provides a cross-browser equivalent to the __proto__ property in Firefox. This can be disabled with the noProto option.

A set of boolean options may be given in the third argument, these are:

  • notNulls - Don't copy null values from the overlay
  • notEqual - Don't copy a value if it's equal (using ===) in the overlay and original
  • onlyOwn - Only copy overlays own properties (using hasOwnProperty())
  • onlyOriginal - Only copy properties from the overlay that exist in the original
  • noProto - Don't add the getPrototype() function to the returned objects

Example use of options:

	b = jQuery.overlay( a, b, { notNulls:true, noProto:true } );
Toggle Sidebar

jQuery plugins

JavaScript

Author

Browse

Adaptavist Theme Builder Powered by Atlassian Confluence