Sharing Static Data Between YUI 3 Instances

YUI 3 does an excellent job of sandboxing instances so that you cannot accidentally contaminate objects or data. However, sometimes you need to share data between instances, such as if you have a global click handler that dispatches events. Otherwise, each time you include the module, the global data or event is duplicated. Therefore, we need a good way to occasionally share data between instances.

How do it…

As with most problems, there are several solutions, but one that I think is best. We’ll walk through each scenario.

The first solution is to simply append a variable to the global window variable and share that variable between YUI instances:

var __myobject__ = {};

YUI({}).use('event', 'node', /*…,*/ function(Y) {
	// instance 1
	Y.Node.prototype.test = 'I am test';
	__myobject__.foo = 'bar';
});

YUI({}).use('event', 'node', /*…,*/ function(Y) {
	// instance 2
	alert(__myobject__.foo); // __myobject__.foo == 'bar';
	alert(Y.Node.prototype.test); // Y.Node.prototype.test != 'I am test';
});

That works, but I am not a fan of globals. So, the next progression is to attach the object to the global YUI variable:

YUI.namespace('__myobject__');

YUI({}).use('event', 'node', /*…,*/ function(Y) {
	// instance 1
	Y.Node.prototype.test = 'I am test';
	YUI.__myobject__.foo = 'bar';
});

YUI({}).use('event', 'node', /*…,*/ function(Y) {
	// instance 2
	alert(YUI.__myobject__.foo); // YUI.__myobject__.foo == 'bar';
	alert(Y.Node.prototype.test); // Y.Node.prototype.test != 'I am test';
});

This is good enough, but Ryan Grove points out that the core YUI code uses the YUI.Env property for sharing data. So the final iteration would be:

YUI.namespace('Env.__myobject__');

YUI({}).use('event', 'node', /*…,*/ function(Y) {
	// instance 1
	Y.Node.prototype.test = 'I am test';
	YUI.Env.__myobject__.foo = 'bar';
});

YUI({}).use('event', 'node', /*…,*/ function(Y) {
	// instance 2
	alert(YUI.Env.__myobject__.foo); // YUI.Env.__myobject__.foo == 'bar';
	alert(Y.Node.prototype.test); // Y.Node.prototype.test != 'I am test';
});

How it works…

In each case, the code attaches the data to a variable in the global namespace. The key point is where (which variable) should be used for attaching shared data. The answer is to attach globals to YUI.Env.__myobject__, where __myobject__ is the name of your global object (I usually use the name of the project or asset I am working on). The examples above each show how the data on the __myobject is shared, but changes to the Y.Node object is sandboxed by YUI 3.

There’s more…

A discussion I had on the YUI forum with Ryan Grove and Nate Cavanaugh (thanks guys) inspired this article: What is the best way to handle a global singleton in YUI 3?.

There is a fourth solution to use Y.Global, as pointed out by Luke Smith, but it requires that at least one Y.use statement has executed first. The Y.Global is used by the custom event system and is viable, but it is not as simple as using YUI.Env.