Skip to content

Instantly share code, notes, and snippets.

@millermedeiros
Created February 10, 2011 22:19
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save millermedeiros/821476 to your computer and use it in GitHub Desktop.
Save millermedeiros/821476 to your computer and use it in GitHub Desktop.
RequireJS Image Plugin
/*
* Example #1 : usage example
* - Image paths are relative to the HTML file.
* - Support absolute paths as well.
* - Appending `!bust` to the end of the file name will avoid caching the image.
*/
require(['image!lol_cat.gif', 'image!http://tinyurl.com/4ge98jz', 'image!dynamic_image.jpg!bust'], function(cat, awesome, dynamic){
//add loaded images to the document!
document.body.appendChild(awesome);
document.body.appendChild(cat);
document.body.appendChild(dynamic);
});
/*
* Example #2 : multiple requires for the same file.
*/
require(['image!http://tinyurl.com/4ge98jz'], function(awesome){
document.body.appendChild(awesome); //add loaded image to the document!
//require same image again
require(['image!http://tinyurl.com/4ge98jz'], function(awesomeToo){
//requireJS will return same image object unless you use `!bust`,
//which means it will remove old reference from the document
//and append it into the new target node.
document.body.appendChild(awesomeToo); //no visible changes (since image was already in the document)
});
//require same image again
require(['image!http://tinyurl.com/4ge98jz'], function(awesomeToo){
//requireJS will return same image object unless you use `!bust`,
//so we need to "deep-clone" the Element to be able
//to insert it multiple times into the same document
document.body.appendChild(awesomeToo.cloneNode(true)); //insert a clone of the image
});
});
/**
* @license RequireJS Image Plugin <https://gist.github.com/821476>
* @author Miller Medeiros
* @version 0.0.4 (2010/02/14)
* Released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
*/
(function(){
var CACHE_BUST_QUERY_PARAM = 'bust',
CACHE_BUST_FLAG = '!bust';
function cacheBust(url){
url = url.replace(CACHE_BUST_FLAG, '');
url += (url.indexOf('?') < 0)? '?' : '&';
return url + CACHE_BUST_QUERY_PARAM +'='+ (new Date()).getTime();
}
//as of RequireJS 0.22 - define method for plugins needs to be a literal object
//to be able to work together with the optimizer (see: https://github.com/jrburke/requirejs/issues#issue/70)
define({
load : function(name, req, onLoad, config){
var img;
if(config.isBuild){
onLoad(null); //avoid errors on the optimizer since it can't inline image files.
}else{
img = new Image();
img.onload = function(evt){
onLoad(img);
delete img.onload; //release memory - suggested by John Hann
};
img.src = name;
}
},
normalize : function (name, normalize) {
//used normalize to avoid caching references to a "cache busted" request.
return (name.indexOf(CACHE_BUST_FLAG) < 0)? name : cacheBust(name);
}
});
}());
@unscriptable
Copy link

Very nice! Very simple! Just one suggestion: remove the onload property of the image like this:

        img.onload = function(evt){
            onLoad(img);
            delete img.onload;
        };

I am not 100% sure, but doing this could release a significant amount of memory since the function has closure over the surrounding functions and could be keeping their execution states in memory. It's just good housekeeping anyways. :)

-- J

@millermedeiros
Copy link
Author

Thanks for the suggestion it was good that I noticed another problem on it, the references to the "modules" was being cached even if the image had the !bust flag... now it should work fine.

My only doubt now is what would happen if the image takes too long to load... I don't know how timeout works on RequireJS and didn't had time to test it and/or look at the source code to find out, maybe I will update it later if I need it.

Cheers!

@unscriptable
Copy link

The default timeout in RequireJS is 7 seconds. You can adjust this (globally) by using the waitSeconds config parameter.

@millermedeiros
Copy link
Author

I want to avoid changing the global waitSeconds, I will try to find a way to bypass the timeout if the file is loaded using the image plugin and also add error handling.. - probably after I finish my current project... Thanks.

@millermedeiros
Copy link
Author

just noticed that this plugin will break the optimizer since it will try to inline the content of the images...

@jrburke
Copy link

jrburke commented Feb 13, 2011

I suggest using config.isBuild to know if the plugin is being used in the build system. In that, case, I suggest just calling onLoad with null or something. So inside the load: function:

if (config.isBuild) {
    onLoad(null);
} else {
    //Do the normal thing here.
}

Or you could provide a pluginBuilder module that is used in the build, but I suggest the above because it is simpler to just deliver one file instead of two and the overhead is not high.

@millermedeiros
Copy link
Author

Fixed optimizer integration by changing define to a literal object (see bug report)

Thanks for the tip about config.isBuild and onLoad(null)

@millermedeiros
Copy link
Author

moved all my plugins to a new repository: https://github.com/millermedeiros/requirejs-plugins

@xDrgh
Copy link

xDrgh commented Nov 12, 2013

Hi experts,
does anybody live here? )
can i take image in binary format from it?

thanks in advanse, Andrew.

@samueljseay
Copy link

@xDrgh you would need to convert the image to binary yourself using JavaScript.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment