1

I'm having some trouble with requirejs, jquery and an embeddable widget that I've written. The widget is loaded via a javascript (that contains a minified version of jQuery).

The problem is that the host site is using requirejs and tries to load jquery. Somehow, requirejs seems to think that jquery is already loaded (because of the minified version in the loader script) and skips loading of jquery. It uses the version that is included by the loader script. This will (due to timing issues?) make the loading of bootstrap fail, because it cannot find jquery.

How can I get requirejs on the host site to load jquery anyway? Why is it affected by the version of jquery that is included by my embeddable widget?

The host site with reqiurejs and the script that loads the widget:

<body>
    ...
    <script async="" src="http://example.com/WidgetLoaderScript.js"></script>
    ...
    <script src="/Scripts/require.js"></script>
    <script>
        requirejs.config({
            baseUrl: "../../Scripts",
            paths: {
                jquery: "jquery-1.10.2.min",
                bootstrap: "bootstrap.min"
            },
            shim: {
                bootstrap: {
                    deps: ["jquery"]
                }
            }
        });

        require(["jquery", "bootstrap"], function ($) {
            // Do stuff
        });
    </script>
</body>

Part of the loader script:

(function (window, document, undefined) {

    // Load minified version of jQuery
    (function(e,t){var n,r,i ......;

    var $abc = $.noConflict();

    // Use $abc to append widget into host site
    ...
 })(window, document);
Joel
  • 8,502
  • 11
  • 66
  • 115
  • Check [this](http://stackoverflow.com/questions/2731897/loading-jquery-twice-causes-an-error) ,this will help you to load your dependencies. – gaurav bhavsar Apr 30 '15 at 12:19
  • Adding multiple versions of jquery can cause problems. Why do u have to include the complete jquery in your widget. Why not just declcare the dependency... – Vishwanath Apr 30 '15 at 12:56

3 Answers3

1

Check this

(function () {

    var paths = { ... };

    //HANDLE JQUERY IF LOADED ALREADY TO AVOID OVERWRITING EXISTING JQUERY PROPERTIES AND PLUGINS
    //CHECK FOR OLD VERSIONS OF JQUERY
    var oldjQuery = !!(window.jQuery && !!window.jQuery.fn.jquery.match(/^1\.[0-4]/));

    //LOAD JQUERY IF NOT AVAILABLE OR BELOW MIN
    if (!window.jQuery || oldjQuery) {
        paths.jquery = [
            '//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min',
            //If the CDN location fails, load from this location
            'libs/jquery/jquery.min'
        ];
    } else {
        //REGISTER THE CURRENT JQUERY
        define('jquery', [], function () { return window.jQuery; });
    }

    //CONFIGURE REQUIRE JS
    require.config({
        ...
        paths: paths,
        ...
    });

    //START REQUIRE JS
    require([
        'jquery',
        'app'
    ], function ($, App) {
        //HANDLE MULTIPLE JQUERY VERSIONS IF NECESSARY
        if (oldjQuery) $.noConflict(true);

        //INITIALIZE APP
        App.init();
    });
})();
gaurav bhavsar
  • 2,033
  • 2
  • 22
  • 36
0

Require.js is basically a script loader so why don't you use it to load your widget. Take a look at the docs in the path fallback section for an example. You will be able to specify a JQuery dependency for your plugin also.

requirejs.config({
    paths: {
        ....(other script definitions).....
        'myWidget': 'http://example.com/WidgetLoaderScript'
    },
    shim: {
       'myWidget': ['jquery']
    }
});
devconcept
  • 3,665
  • 1
  • 26
  • 40
  • Thank you for your answer, but this is not an option. The widget is supposed to be used like any html widget. You copy paste the script tag into the page where you wan't the widget to appear. So I'm only experiencing this error since I'm trying to use the widget myself on a page that I've made – Joel Apr 30 '15 at 12:23
  • I don't know if this can be an option but if you are the writer of the widget you can use the jQuery noConflict function to get you out of trouble. Think that anyone that use your widget will end up with the same problem. – devconcept Apr 30 '15 at 12:49
  • Yeah. I tried using noConflict() but RequireJS on the host site still thinks jQuery is already loaded. I guess that it's because it defines an AMD module? Anyway, I'll try to rewrite the loader script without jquery. I think that will be the best solution in this case – Joel Apr 30 '15 at 13:06
  • What i mean was using noConflict in your widget. Making a widget or new library independent of any specific external script is a good practice. – devconcept Apr 30 '15 at 13:27
  • I thought that's what I did. Take a look at the code in the loader script. Am I using noConflict wrong? – Joel Apr 30 '15 at 13:30
  • .noConflict(true) is different than just writing .noConflict() try that instead – devconcept Apr 30 '15 at 13:38
-1

The problem I had was due to the fact that jQuery registers itself as an AMD module and this will mess with the host site (if it is using an AMD loader like RequireJs). So I don't want jQuery to do that in my widget loader script.

My solution is the following:

// Set define.amd to false while loading jQuery, so that it won't register itself as an AMD module.
var tempDefineAmd = false;
if (typeof define === "function") {
    tempDefineAmd = define.amd;
    define.amd = false;
}

// Load minified version of jQuery
(function(e,t){var n,r,i ......;

// Done loading jQuery. Restore the value of define.amd for targets sites using an AMD loader
if (typeof define === "function" && tempDefineAmd !== false) {
    define.amd = tempDefineAmd;
}
Joel
  • 8,502
  • 11
  • 66
  • 115