← Back to team overview

launchpad-dev team mailing list archive

YUI sandboxes, event propagation and global namespaces

 

Hello

Part of the YUI changes done for the combo loader work involved
replacing our previous "single YUI instance across all pages approach".
The approach now is to sandbox each YUI block thus:

YUI().use('node', function(Y) {
   // code goes here
});

The code in each such YUI block above is sandboxed from other similarly
defined YUI blocks. This however created problems for our codebase,
since events by default do not propagate across sandboxes and our
previous approach to sharing data using a YUI namespace broke. Read on
if you want to know how these issues were/are being addressed.

1. Event propagation across YUI instances

When subscribing to events which are to be broadcast across instances,
here's how to do it:

// In the subscribing instance...
Y.Global.on('event_name', function(e) {
    // code goes here
});

To get the event to fire and be correctly broadcast, we first need to
publish it using the correct parameters:

// In the publishing instance....
Y.publish(
    'event_name',
    {broadcast: 2,
     emitFacade: true
    }
);

broadcast = 2 tells YUI to bubble the event up to the global namespace.
emitFacade ensures that our subscription function is passed an event (e)
as it's first argument.

Then to fire the event:

Y.fire('event_name');

Or, if we need to pass data in the event:

Y.fire('event_name', {foo: 'bar'});

in which case:

Y.Global.on('event_name', function(e) {
    bar = e.foo; //bar is assigned 'bar'
});
----------------------------------------------------------------------

2. Global namespaces

It used to be possible to define a namespace which could be used to
share data. I previously used this with the picker infrastructure to
allow validators to be defined outside of the yucky Javascript in the
tal for named picker instances.

var ns = Y.namespace('lp.app.picker.validation')
ns.assignee_validator = function() { // code};

However, namespaces used as above are sandboxed, and in another
instance, anything attached to the namespace is not visible. Luckily,
YUI provides a global Env namespace which works nicely:

// In instance 1.....
var ns = YUI.namespace('Env.lp.app.picker.validation');
ns.assignee_validator = ...

// In instance 2.....
var ns = YUI.namespace('Env.lp.app.picker.validation');
if (Y.Lang.isFunction(ns.assignee_validator)) {
    ns.assignee_validator();
}

So, you can see it's almost the same as previously, except we use
YUI.Env as the global namespace to attach our stuff to.

----

I hope the above makes, sense. It's a bit hard to explain it out of
context. If you have any questions, or want me to point to actual code
examples in lp (once landed), let me know.




Follow ups