RequireJS executing jquery-ui inline widget

I have a jQuery widget that a partner is trying to implement. The problem that we get is that the partner uses requireJS and makes its widget.

The widget is in an anonymous function and requires jquery-ui inside. After debugging, we found that the jQuery user interface is removed after calling noConflict. Here is the code from the widget.

(function () {

    // Localize jQuery variable
    var jQueryWidget;

    /******** Load jQuery if not present *********/
    if (window.jQuery === undefined || window.jQuery.fn.jquery !== '3.2.1') {
        var script_tag = document.createElement('script');
        script_tag.setAttribute("type", "text/javascript");
        script_tag.setAttribute("src", "https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js");
        script_tag.onload = scriptLoadHandler;
        script_tag.onreadystatechange = function () { // Same thing but for IE
            if (this.readyState == 'complete' || this.readyState == 'loaded') {
                scriptLoadHandler();
            }
        };
        (document.getElementsByTagName("head")[0] || document.documentElement).appendChild(script_tag);
    } else {
        loadJQueryUi();
    }

    function scriptLoadHandler() {
        loadJQueryUi();    
    }

    function loadJQueryUi() {
    /******* Load UI *******/
        jQuery.getScript('https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js', function () {
          jQueryWidget = jQuery.noConflict(true);
          setHandlers(jQueryWidget);
        });


        /******* Load UI CSS *******/
        var css_link = jQuery("<link>", {
            rel: "stylesheet",
            type: "text/css",
            href: "https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/base/jquery-ui.css"
        });
        css_link.appendTo('head');
    }

    function setHandlers($) {
        $(document).on('focus', '#start-date, #end-date', function(){

      $('#start-date').datepicker({
        dateFormat: "M dd, yy",
        minDate: 'D',
        numberOfMonths: 1,
      });

            $('#end-date').datepicker({
                dateFormat: "M dd, yy",
                minDate:'+1D',
                numberOfMonths:1,
            });
    }
})();

Using the chrome debugger, we see that when calling getScript, it correctly adds jquery-ui to the loaded version. Its right after we call noConflict that it restores the previous jQuery, but the version no longer has jQueryUI.

Testing the widget on other sites without requireJS works correctly.

- ? , RequireJS, , .

.

+6
2

, , , . , :

  • . , , jQuery jQueryUI. , , jQuery. , , .

  • jQuery AMD. AMD define, , . , jQuery $ jQuery .

, , jQuery: , jQuery $ jQuery , :

jQuery.getScript('https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js', function () {
  jQueryWidget = jQuery.noConflict(true);
  setHandlers(jQueryWidget);
});

, jQuery , . , .getScript, - script, script, .getScript, callback. script, .getScript, script, RequireJS, .

, -, - , . , , RequireJS . RequireJS . , , context RequireJS . , , jQuery $ jQuery, jQuery, . , .

, , , . , , , , , , , , , . , : , , .

, , , , . ( , , ...). jQuery jQuery UI script. , define, , define. , , , RequireJS , jQuery script, define. ( jQuery, .)

, , , , - Webpack , define , , define. (. import-loader, .) , , , $ jQuery jQuery, .


, , Webpack, , (, IIFE , ). , , :

  • npm install webpack jquery jquery-ui imports-loader lite-server
  • ./node_modules/.bin/webpack
  • ./node_modules/.bin/lite-server

- , , . noConflict, Webpack, , Webpack, jQuery CommonJS DOM noGlobal, .

webpack.conf.js:

const webpack = require('webpack');
module.exports = {
    entry: {
        main: "./widget.js",
        "main.min": "./widget.js",
    },
    module: {
        rules: [{
            test: /widget\.js$/,
            loader: "imports-loader?define=>false",
        }],
    },
    // Check the options for this and use what suits you best.
    devtool: "source-map",
    output: {
        path: __dirname + "/build",
        filename: "[name].js",
        sourceMapFilename: "[name].map.js",
    },
    plugins: [
        new webpack.optimize.UglifyJsPlugin({
            sourceMap: true,
            include: /\.min\.js$/,
        }),
    ],
};

widget.js:

var $ = require("jquery");
require("jquery-ui/ui/widgets/datepicker");

var css_link = $("<link>", {
    rel: "stylesheet",
    type: "text/css",
    href: "https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/base/jquery-ui.css"
});
css_link.appendTo("head");

$(document).ready(function() {
    console.log("jQuery compare (we want this false)", $ === window.$);
    console.log("jQuery version in widget",  $.fn.jquery);
    console.log("jQuery UI version in widget", $.ui.version);
    $("#end-date").datepicker();
});

index.html:

<!DOCTYPE html>
<html>
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.5/require.js"></script>
    <script>
      require.config({
        paths: {
          jquery: "https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.0/jquery.min",
          "jquery-ui": "https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.0/jquery-ui"
        }
      });
      require(["jquery", "jquery-ui"], function(myJQuery) {
        console.log("jQuery compare (we want this true)", myJQuery === $); 
        console.log("jQuery version main", $.fn.jquery);
        console.log("jQuery ui version main", $.ui.version);
      })
    </script>
  </head>
  <body>
    <input id="end-date">
    <script src="build/main.min.js"></script>

    <!-- The following also works: -->
    <!--
    <script>
      require(["build/main.min.js"]);
    </script>
    -->
  </body>
</html>
+1

, jQueryWidget = jQuery.noConflict(true);

true jQuery .

jQuery.noConflict([removeAll]) : Boolean , , jQuery ( jQuery).

[noconflict] [1]

, , , .

2:   

<!DOCTYPE html>
        <html>

        <head>
            <title></title>
            <script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.5/require.js"></script>
            <script type="text/javascript">
            (function() {

                // Localize jQuery variable
                var jQueryWidget;
                /*
                *
                *
                *
                    This is plugin require config. Only used by plugin and
                    will not affect partner config.
                *
                *
                */
                var requireForPlugin = require.config({
                    context: "pluginversion",
                    paths: {
                        "jquery": "https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min",

                        "jquery.ui.widget": "https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min"

                    }
                });
                requireForPlugin(["require", "jquery", "jquery.ui.widget"], function() {
                    /******** Load jQuery if not present *********/
                    if (window.jQuery === undefined || window.jQuery.fn.jquery !== '3.2.1') {
                        scriptLoadHandler();
                    } else {
                        loadJQueryUi();
                    }

                    function scriptLoadHandler() {
                        loadJQueryUi();
                    }

                    function loadJQueryUi() {
                        jQueryWidget = jQuery.noConflict(true);
                        setHandlers(jQueryWidget);
                        var css_link = jQueryWidget("<link>", {
                            rel: "stylesheet",
                            type: "text/css",
                            href: "https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/base/jquery-ui.css"
                        });
                        css_link.appendTo('head');
                    }

                    function setHandlers($) {
                        $('#end-date').on('click', function() {
                            alert('JQUERY--' + $().jquery);
                            alert('JQUERY UI--' + $.ui.version);
                            $('#end-date').datepicker({
                                dateFormat: "M dd, yy",
                                minDate: '+1D',
                                numberOfMonths: 1,
                            });
                        });
                    }
                });
            })();
            </script>
            <script>
            //SAMPLE PARTNER APPLICATION CODE:

            /*
            *
            *
            *
                This is partner require config
                which uses diffrent version of jquery ui and
                jquery
            *
            *
            */
            require.config({
                paths: {
                    "jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.0/jquery.min",

                    "jquery.ui.widget": "https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.0/jquery-ui"

                }
            });
            require(["jquery", "jquery.ui.widget"], function() {
                $('#btn').on('click', function() {
                    alert('JQUERY--' + $().jquery);
                    alert('JQUERY UI--' + $.ui.version);
                });
            })
            </script>
        </head>

        <body>
            <div><span>FOCUS</span>
                <input type="text" name="" id="end-date" />
            </div>
            <button id="btn" style="width: 100px; height:50px; margin:10px">click me</button>
        </body>

        </html>

, jquery jquery ui ( requirejs).

script, . , requirejs config, .

jquery jquery ui.

, .

: jQuery Require.js http://requirejs.org/docs/api.html#multiversion

UPDATE3: webpack webpack js, jquery, .

webpack, jquery, jquery-ui npm , :

main.js , false

require('imports-loader?define=>false!./app.js');

app.js,

 (function() {

     var $ = require('jquery');
     require('jquery-ui');
     require('jquery-ui/ui/widgets/datepicker.js');

     function scriptLoadHandler() {
         loadJQueryUi();
     }

     $(document).ready(function() {
         scriptLoadHandler();
     });

     function loadJQueryUi() {
         setHandlers();
         var css_link = $("<link>", {
             rel: "stylesheet",
             type: "text/css",
             href: "https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/base/jquery-ui.css"
         });
         css_link.appendTo('head');
     }

     function setHandlers() {
         $('#end-date').on('click', function() {
             alert('JQUERY--' + $().jquery);
             alert('JQUERY UI--' + $.ui.version);
             $('#end-date').datepicker({
                 dateFormat: "M dd, yy",
                 minDate: '+1D',
                 numberOfMonths: 1,
             });
         });
     }
 })();

webpack.config.js

  var webpack = require('webpack');

  module.exports = {
  entry: "./main.js",
  output: {
  filename: "main.min.js"
     }
  };

sample.html

<!DOCTYPE html>
<html>

<head>
    <title></title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.5/require.js"></script> 
    <script src="main.min.js"></script> 
    <script>
    //SAMPLE PARTNER APPLICATION CODE:

    /*
    *
    *
    *
        This is partner require config
        which uses diffrent version of jquery ui and
        jquery
    *
    *
    */
    require.config({
        paths: {
            "jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.0/jquery.min",

            "jquery.ui.widget": "https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.0/jquery-ui"

        }
    });
    require(["jquery", "jquery.ui.widget"], function() {
        $('#btn').on('click', function() {
            alert('JQUERY--' + $().jquery);
            alert('JQUERY UI--' + $.ui.version);
        });
    })
    </script>
</head>

<body>
    <div><span>FOCUS</span>
        <input type="text" name="" id="end-date" />
    </div>
    <button id="btn" style="width: 100px;"></button>
</body>

</html>

webpack main.min.js, sample.html

-1

All Articles