Search code examples
javascriptyui3

YUI3 - how to load modules synchronously?


In order to load missing modules, YUI allows us to specify them in use(...) method, pass in a callback and perform our actions when all modules are loaded - asynchronously. This presents a number of problems in my case. More specifically, I find it impossible to instantiate my class outside of the current file if I have my classes created inside the callback (no guarantee that they will be ready by the time "new" happens). My work-around was to wrap only certain method calls in YUI.use(...) but this creates another problem with extending objects. Ideally, what I need to do is load all modules synchronously before any of my code executes. Below is my code that currently fails succeeds (EDIT: Allow Rollups).

HTML:

<html>
<head>
<!-- Built using YUI dep configurator -->
<!-- JS -->
<script type="text/javascript" src="http://yui.yahooapis.com/3.3.0/build/yui/yui-min.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/3.3.0/build/oop/oop-min.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/3.3.0/build/event-custom/event-custom-base-min.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/3.3.0/build/event/event-base-min.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/3.3.0/build/dom/dom-min.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/3.3.0/build/dom/dom-style-ie-min.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/3.3.0/build/pluginhost/pluginhost-min.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/3.3.0/build/node/node-min.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/3.3.0/build/event/event-base-ie-min.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/3.3.0/build/event/event-delegate-min.js"></script>


<!-- My JS -->
<script type="text/javascript" src="test.js"></script>

<script type="text/javascript">
    var test = new MyNS.ExtendingClass();
</script>

</head>

<body>
    <h1>Hello World!</h3>
</body>
</html>

test.js

//namespace
if (!MyNS) var MyNS = {};

(function(){
    var Y = YUI().use('node', 'io', 'autocomplete');

    MyNS.BaseClass = function() {
        console.log('Base class newed. Y: ' + Y);

        var self = this;

        self.init();
    };

    MyNS.BaseClass.prototype = {
        init: function() {
            console.log('Initting! Y: ' + Y);
        }
        , test: function() {
            console.log('test fired!');
        }
    };
})();

(function(){
    var Y = YUI().use('node');

    MyNS.ExtendingClass = function() {
        console.log('Extended class newed. Y: ' + Y);

        var self = this;

        MyNS.ExtendingClass.superclass.constructor.call(self);
    };

    MyNS.ExtendingClass.prototype = {
        testExtended: function() {
            console.log('testExtended fired!');
        }
    };

    Y.extend(MyNS.ExtendingClass, MyNS.BaseClass);
})();

This code now works but requires 10 (!!!) js files to make it happen. Is there a way to make sure all dependencies are loaded dynamically and before my code is executed? There must be, right?


Solution

  • You can solve this by putting each of your classes inside their own YUI module and use YUI to do the namespacing.

    Create a new file my-classes.js, containing both your class definitions:

    YUI().add('baseClass', function(Y) {
        // constructor  
        Y.namespace('NS').BaseClass = function () {
            this.msg = 'hi!';
        }
    
    }, '1', {requires: ['oop', 'node', 'event']}); // dependencies for your class
    
    YUI().add('extendingClass', function(Y) {
        // constructor  
        Y.namespace('NS').ExtendingClass = function () {
            Y.NS.ExtendingClass.superclass.constructor.call(this);
            alert(this.msg);
        }      
    
        Y.extend(Y.NS.ExtendingClass, Y.NS.BaseClass);
    
    }, '1', {requires: ['baseClass']});
    

    Include the YUI seed file in your page:

    <script type="text/javascript" src="http://yui.yahooapis.com/3.3.0/build/yui/yui-min.js"></script>
    

    Also include your class file and an init file:

    <script type="text/javascript" src="my-classes.js"></script>
    <script type="text/javascript" src="my-init.js"></script>
    

    In your init file:

    YUI().use('extendingClass', function(Y) {
        Y.test = new Y.NS.ExtendingClass();
    })
    

    Now all the dependencies should be resolved and loaded up, before your code executes. It is asynchronous, however you asked for a solution that would ensure everything was loaded before your code executed.

    Hope this helps.