0
votes

I'm struggling to get my head around a couple of JS patterns joined together: the revealing module pattern, and the chaining pattern.

What I would ideally like to be able to do is invoke multiple methods from a single initialising function like this:

components
    .loader()
    .menu()
    .toolbar();

And this works perfectly as long as any methods I define publicly return this;.

Things start to go wrong however when I need to nest revealing module patterns in order to expose deeper methods that are invoked outside of the initialisation like this:

components
    .menu
        .close();

The problem doing this is that menu no longer returns components, but instead returns it's child methods which means it breaks the chain at this point. Here is a "complete" example to illustrate what I am try to achieve:

var components = function () {

    var loader = function () {
        console.log("components.loader initialisation");

        return this;
    }

    var menu = function () {
        console.log("components.menu initialisation");

        var open = function () {
            console.log("components.menu.open");

            return this;
        }
        var close = function () {
            console.log("components.menu.close");

            return this;
        }

        return {
            open: open,
            close: close
        }
    }();

    var toolbar = function () {
        console.log("components.toolbar initialisation");

        return this;
    }

    return {
        loader: loader,
        menu: menu(),
        toolbar: toolbar
    }
}();

$(function () {

    components
        .loader()
        .menu()
        .toolbar();

    components
        .menu
            .open();

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

So I guess my question is, how can I use; nested, revealing modules and chaining together (if at all possible)?

1
first of all, what do you expect menu to be? a method of component or a module. Both (although possible) is kind of ambiguous.Thomas
So just to clarify, you expect components.menu to return components (along with the open and close methods) and components.menu.close() to also return components or just components.menu.close() to return components? Perhaps updating the post to include the output expected for a few a queries would be helpful.m-a-r-c-e-l-i-n-o
My apologies, I'll add some further examples for clarification.Chris Spittles
@Thomas I need menu to setup the code inside menu, so it has events for opening and closing etc. But I need to allow Open and Close to be called by other functions so a toolbar item might trigger a menu open or close for instance. Does that make sense?Chris Spittles

1 Answers

2
votes

var components = (function () {

var loader = function () {
    console.log("components.loader initialisation");

    return this;
};

var menu = function () {

    var menu = function () {
        console.log("components.menu initialisation");
		
        return this;
    };
	

    menu.open = function () {
        console.log("components.menu.open");

        return this;
    };

    menu.close = function () {
        console.log("components.menu.close");

        return this;
    };

    return menu;
};

var toolbar = function () {
    console.log("components.toolbar initialisation");
	
    return this;
};

return {
    loader: loader,
    menu: menu(),
    toolbar: toolbar
};
})();

$(function () {
components
	.loader()
	.menu()
	.toolbar();

components
	.menu
		.open();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>