0

I am working with Chris Imrie's iteration of RequireJS for ExpressionEngine making all my fieldtypes compatible. One thing I don't understand is how to call the functions that are defined in RequireJS.

https://github.com/ckimrie/RequireJS-for-EE

Here is a basic example of what I am trying to do...

var loadImage = function() {
    console.log('loaded');
}

define(function () {
    return loadImage;
});

How do I actually access the loadImage function? My code worked 100%, but when I started using RequireJS, the libraries behave differently. Below is a snippet from a library I am using, it's completely forked for RequireJS. If I delete the fork and use the standard jQuery call, it works without issue (even with RequireJS loading all the scripts).

Does not work:

if (typeof define === 'function' && define.amd) {
    define(function () {
        return loadImage;
    });
} else {
    $.loadImage = loadImage;
}

Does Work

$.loadImage = loadImage;

Why would jQuery libraries fork the code like this? I am concerned I am overlooking something simple, but given the context that all this code is with ExpressionEngine Fieldtypes, I don't have a problem altering the libraries.

2 Answers 2

6

A few things to try:

Your define function needs to have an array as the first argument, since this is where you specify any module dependencies for this module. If your module does not require any other scripts or modules to work, then this array is left empty like so:

define([], function(){
    //Your code here
});

Now this is the slightly confusing part, since the way RequireJS works is that it uses the module path as the module name. This is really powerful since it makes your module highly portable, but also makes the act of specifying the module you need and where it is located the same thing.

So if the module defined above was located at "mymodule/js/component.js" you would be able to load it and use it asynchronously in another script like so:

//some existing script that then needs a JS module that has not been loaded yet
require(['mymodule/js/component'], function(component){
   //All loaded modules are provided as arguments in the 
   //order they are specified in the require array
   var a = component();
});

So your example becomes the following:

//This script located at mymodule/js/loadImage.js
if (typeof define === 'function' && define.amd) {
    define([], function () {
        return loadImage;
    });
} else {
    $.loadImage = loadImage;
}

//Script located in another file that needs the loadImage module
require(['mymodule/js/loadImage'], function(loadImage){
    loadImage();
});

As a final note, you can give your modules short snappy names if you like by specifying the name as the first argument of the define call. This isnt that recommended since you will need to specify the path to the file the first time you need it since RequireJS wont know where it is from just a short name. Places where this is suitable is when you are loading all your scripts up front instead of as and when they are needed (which is recommended since everything is loaded on demand). But nonetheless here is how you specify a "short" name for module:

//This script located at mymodule/js/loadImage.js
if (typeof define === 'function' && define.amd) {
    define("loadImage", [], function () {
        return loadImage;
    });
} else {
    $.loadImage = loadImage;
}

If you KNOW that the loadImage module has been loaded, the above technique allows you to do the following:

//Even if loadImage has been already fetched, this is good practice since you can
//add more modules to be the dependency array if you need
require(['loadImage'], function(loadImage){
    loadImage();
});
//or sometimes this can be convenient:
var loadImage = require("loadImage")
loadImage();

UPDATE

Forgot to mention that if you ever wanted to create a module that needed the loadImage module to function, you would do it like so:

//By providing the module dependencies in the first argument, RequireJS will
//fetch it and load it if needed
define(['mymodule/js/loadImage'], function(loadImage){
    loadImage();
})
Sign up to request clarification or add additional context in comments.

1 Comment

All of this makes sense, and is the correct answer. The one thing that puzzles me is the fact that I posted code from a particular library. I am just wondering how people are using the library in the context of RequireJS without changing the library's code. Here is the particular library in question: github.com/blueimp/JavaScript-Load-Image. Again, all my code works with a couple minor tweaks, was mainly wondering how to get it to work without the tweaks (if it's even possible).
5

Apologies for the answer above, I think I understand now what you are trying to do. Basically that library you are referring to (Javascript-Load-Image) has implemented AMD support (the define function you referred to) into their library and you are looking to use it in your own scripts?

RequireJS can be confusing sometimes because it is capable of loading normal scripts but also AMD JS modules. If you have a JS file that contains a JS constructor or function you are looking to make available as an module to be used by other parts of your code, its as simple as adding the define() call you mentioned above. The important part is that you need to ensure it is requested by RequireJS as an AMD module, otherwise it wont have a module name. This is as simple as omitting the ".js".

So as the example above:

//In your script that needs the loadimage library you would load it by 
//specifying the path to the JS file and omitting the ".js" extension
require(["path/to/loadimage"], function(loadimage){
    loadimage();
});


//If you KNOW that the library has already been loaded by RequireJS
//you can fetch it synchronously from RequireJS' memory by specifying 
//its path without the .js
var loadimage = require("path/to/loadimage");
loadimage()

2 Comments

Looks like I have a lot of work to do in Theme Loader to get it to support all this arbitrary stuff.
Not at all, theme loader works perfectly. As long as the base URL is correct, then RequireJS does the rest.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.