Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

requirejs + jqueryui = $.widget not defined

I am using requirejs + jquery + jqueryui. I have read TONS of examples of how to do this. I think I understand the various approaches and it seems to me that my setup should be working correctly. However, I occasionally get a $.widget is not defined error in my custom modules that depend on jquery-ui. It is a pain because it is inconsistent and hard to reproduce so it is hard for me to test alternative approaches.

I am not shimming all of my jquery plugins because there are a lot. Instead, I am loading jquery with a separate requirejs call. Then, in the callback for that I load the rest of my stuff. This way I don't have to maintain a list of shims for all my jquery plugins.

For jquery-ui, I use a shim to make it depend on jquery. Then all my custom modules that use the widget factory have 'jquery-ui' in their dependency list.

In my templates...

requirejs.config({
    baseUrl: ATHLETE.siteConfig.jsBaseUrl,
    paths: {
        'jquery': '//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min',
        'jquery-ui': '//ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min'
    },
    shim: {
        "jquery-ui": ['jquery']
    },
    waitSeconds: 15
});

requirejs(['jquery'], function($) {
    requirejs(['site'], function() {
        requirejs(['mypage']);
    });
});

Note that I am loading site.js before mypage.js. They have some shared dependencies. In my build config, I exclude site.js from mypage.js, therefore the shared dependencies are compiled into site.js and not mypage.js. Therefore, I need to completely load site.js before loading mypage.js or else require might try to load those shared dependencies separately.

Here's a sample custom module of mine that depends on jquery-ui.

define([
    'jquery',
    'jquery-ui'
],function($) {
    $.widget('ui.viewAllSponsorsWidget', $.ui.dialog, {
        options: {
            autoOpen: false,
            dialogClass: 'view-all-sponsor-dialog-wrap',
            draggable: false,
            modal: true,
            resizable: false,
            width: 370,
            height: 400
        }
    });
});

The error $.widget is not defined is caused by the 5th line of this and similar custom modules of mine. Again, it is really inconsistent and hard to reproduce. More often than not, I do NOT get the error, even when I clear my cache. Can anyone think of a way that line 5 could possibly be getting executed before jquery-ui is fully loaded?

UPDATE Aug 16, 2013

I have been able to track this down a bit more. I created a simple module that depends on jquery and jquery-ui.

define([
    'jquery',
    'jquery-ui'
],function($) {
    console.log('$.widget is defined? ' + Boolean($.widget));
    console.log('jQuery.widget is defined? ' + Boolean(jQuery.widget));
});

The output of this is as follows:

LOG: $.widget is defined? false
LOG: jQuery.widget is defined? true

So somehow the global jQuery object has widget defined, but the copy provided to me by requirejs does not.

like image 600
Dustin Avatar asked Jul 22 '13 17:07

Dustin


2 Answers

These answers are getting a bit old. I hope to offer a little bit of an updated answer. jQuery UI now comes with AMD support built in. You can simply get it using

bower install jquery-ui

and then in requirejs.config simply add jquery_ui to the paths{} section. No shim is required anymore.

If you want to load only the small subsection of jquery-ui that you need then bower install jquery-ui and then use the build tool that requirejs provides to create a package. Otherwise if you only try to import one individual file then each of the jquery-ui files will try to load their dependencies and you'll get things like "widget not defined" or "cannot find file widget.js" etc. I did a quick writeup here: https://hendrixski.wordpress.com/2015/04/17/adding-only-the-parts-of-jquery-ui-that-you-need-into-your-requirejs-project/

Hope that helps.

like image 168
hendrixski Avatar answered Sep 30 '22 17:09

hendrixski


Change your shim to this:

shim: {
    'jquery-ui': ['jquery']
}

Here is an example of a bunch of Require.js configurations for popular libraries.

like image 21
Greg Franko Avatar answered Sep 30 '22 16:09

Greg Franko