3

In YUI3 is it possible to overwrite a method from e.g. the Node module? For example, I want to do something like this:

Y.Node.prototype.get = function () {
    // Do some stuff then call the original function
};

That works perfectly (as you would expect) when Y is the globally available instance of YUI that I presume is created by the library. It does not work when you use the module loader and pass a callback:

YUI().use("*", function (DifferentY) {
    DifferentY.Node.prototype.get === Y.Node.prototype.get; // false
});

I've spent a while digging through the YUI source but have so far failed to work out where and how DifferentY in the previous example is created (and by extension, where DifferentY.Node is created).

I have never used YUI before so it may be that I'm going about this in the completely wrong way.

James Allardice
  • 164,175
  • 21
  • 332
  • 312

2 Answers2

5

Ok If I look at that example there seems to be a misunderstanding about Y. In YUI3 every thing is sandboxed, so you can have multiple instances of YUI running simultaneously. Y is not a global variable, it will be instantiated when you call the YUI().use method and only exists inside that function. That's why in the code of SO only DifferentY exists, but not Y.

YUI().use('node', 'event', function (Y) {
    // The Node and Event modules are loaded and ready to use.
    // Y exists in here... 
});

So if you want to enhance YUI "from outside" I would build on YUI's module strategy and create a YUI module with YUI.add()

if (YUI) {
  YUI.add('node-enhancement', function (Y) {
    Y.Node.prototype.get = function () {
      // Do some stuff then call the original function
    };
  }, '0.0.1', {
    requires: [Node]
  });
}

and let the developer load the enhancement as a module (how he would do it anyway with yui3)

YUI().use('node-enhancement'), function(Y) {
    // just use YUI as allways
});

for an explanation of how the global YUI object works, this overview might help: http://yuilibrary.com/yui/docs/yui/

nyfelix
  • 301
  • 2
  • 5
  • Thanks, this definitely makes sense. What's confusing me is the apparent availability of an instance of `YUI` outside the `use` callback: http://jsfiddle.net/whMhq/ – James Allardice Oct 10 '13 at 06:33
  • @JamesAllardice the YUI object is global (it is both an object and a function) but each instance of YUI is assigned to the Y variable that is passed in to the function that is the last parameter of your .use statement. The Y instance is only assigned the modules that you specified in the .use call. – PottyBert Oct 10 '13 at 13:43
  • @Kris - In the fiddle I linked to there is a `Y` object globally available that appears to be an instance of `YUI`. Where does that come from and what's the point of it if you're meant to use a `use` call? – James Allardice Oct 10 '13 at 17:54
  • @James the Y object is created by JSFiddle, it wraps all your YUI code in a Y.use('node', function(Y){...}); – PottyBert Feb 25 '14 at 15:27
0

Here is an usage example of monkey patching technique.

Check out the console output here: http://jsfiddle.net/jslayer/XmF6L/

YUI.add('node-custom-module', function(Y){
    console.warn('Override Y.Node');

    Y.Node.YOUR_NODE = 'custom Node';
});

YUI.add('widget-custom-module', function(Y){
    console.warn('Override Y.Widget');

    Y.Widget.YOUR_WIDGET = 'custom Widget';
});

YUI.GlobalConfig = {
    modules : {
        'node-custom-module' : {
            condition : {
                name    : 'node-custom-module',
                trigger : 'node',
                test    : function(){
                    return true;
                }
            }
        },
        'widget-custom-module' : {
            condition : {
                name    : 'widget-custom-module',
                trigger : 'widget',
                test    : function(){
                    return true;
                }
            }
        }
    }
};

YUI().use('node', function(Y) {
    console.group('Node');
    console.log('Y.Node.YOUR_NODE : ', Y.Node.YOUR_NODE);
    console.groupEnd('Node');
});

YUI().use('widget', function(Y) {
    console.group('Widget');
    console.log('Y.Node.YOUR_NODE : ', Y.Node.YOUR_NODE);
    console.log('Y.Widget.YOUR_WIDGET : ', Y.Widget.YOUR_WIDGET);
    console.groupEnd('Widget');
});

Surely it is not necessary to use YUI.GlobalConfig.

Also, it is comfortably to use groups (http://yuilibrary.com/yui/docs/yui/loader.html) inside YUI config's

groups : {
  patches : {
    modules : {
      /* Define your mp modules here */
    }
  }
}
jslayer
  • 484
  • 3
  • 11