Search code examples
javascriptrequirejsamdjqwidget

RequireJS way of creating a copy of object


Our project is really huge, singe-page enterprise app, based on RequireJS and Backbone.js, and for some complex UI we use jqWidgets.

In particular, these jqWidgets are what is causing us problems. There are many app features implemented using older jqWidgets 3.3, and for all new ones we would like to use 3.6, but porting old features to 3.6 is very tricky and will cost us time that we don't have at the moment.

What we would like to do to save this time, is having both 3.3 and 3.6 working alongside without creating any problems, and do the porting part later when we can.

What I have tried so far:

requirejs.config({
    paths: {
        "jquery": "vendor/jquery",
        "jqx": "vendor/jqwidgets/3.3",
        "jqx3.6": "vendor/jqwidgets/3.6",
        ... other libs...
    },
    shim: {
        ... other shims ...
        // jqWidgets3.3
        "jqx/jqxcore": {
             deps: ["jquery"]
        },
        "jqx/<<some_plugin>>": {
             deps: ["jqx/jqxcore"],
             exports: "$.fn.<<some_plugin>>"
        },
        // jqWidgets3.6
        "jqx3.6/jqxcore": {
             deps: ["jquery"]
        },
        "jqx3.6/<<some_plugin>>": {
             deps: ["jqx3.6/jqxcore"],
             exports: "$.fn.<<some_plugin>>"
        },
    }
});

Usage in old feature:

require(["jquery", "jqx/<<some_plugin>>"], function($) {
     $('<<some_selector>>').<<some_plugin>>(...options...);
});

Usage in new feature:

require(["jquery", "jqx3.6/<<some_plugin>>"], function($) {
     $('<<some_selector>>').<<some_plugin>>(...options...);
});

Since both plugins are applied to same jQuery object referencing them with different names/paths works but creates lots of bugs. Example: if first feature you used in app was loaded using jqWidgets 3.3, then next used feature using 3.6 would probably broke, and vice-versa. It only works if you refresh the page after every feature use -- which is kind of pointless since it is single-page app.

So my question is: is it possible to make both jqWidgets 3.3 and 3.6 work alongside by each one of then depend on their own jQuery object so this conflict does not happen?

// Appendix 1: I think potential solution lies in comment of this question: RequireJS - jQuery plugins with multiple jQuery versions I'll take a closer look and post here a solution if I find one.


Solution

  • You can use 'map' feature of requirejs, Map allows you to map the same dependency to different files based on the module which uses dependency. so you config your build file like this:

    requirejs.config({
        paths: {
            "jquery": "vendor/jquery",
            "jqueryForjqx3.6": "toNoConflictJQueryModule",
            "jqx": "vendor/jqwidgets/3.3",
            "jqx3.6": "vendor/jqwidgets/3.6",
        ... other libs...
        },
        map:{
            '*':{
                 .....
            },
            'jqx':{
                'jquery' : 'jquery'
            },
            'jqx3.6':{
                 // map jquery to no conlict jquery
                'jquery' : 'jqueryForjqx3.6'
            },
            'jqueryForjqx3.6':{
                'jquery' : 'jquery'
            }
        },
        shim: {
            ... other shims ...
            // jqWidgets3.3
            "jqx/jqxcore": {
                 deps: ["jquery"]
            },
            "jqx/<<some_plugin>>": {
                 deps: ["jqx/jqxcore"],
                 exports: "$.fn.<<some_plugin>>"
            },
            // jqWidgets3.6
            "jqx3.6/jqxcore": {
                 deps: ["jquery"]
            },
            "jqx3.6/<<some_plugin>>": {
                 deps: ["jqx3.6/jqxcore"],
                 exports: "$.fn.<<some_plugin>>"
            },
        }
    });
    

    This configuration maps jquery dependency to different files based on module which uses it.

    The content of no conflict version can be like this:

    define(['jquery'], function($){
        return $.noConflict();
    });
    

    You can use http://requirejs.org/docs/jquery.html#noconflictmap about how to use jquery no-conflict and requirejs