Some javascript libraries are distributed as a fully concatenated file, including all of the dependent libraries. Some libraries like JQuery provide a way to handle conflicts if multiple version of the library are being used. But if a compiled/concatenated javascript file contains a library that doesn't have a built in way of handling conflicts and I am using that same library (but a different version), is there a general way to wrap the version I am using and add a custom namespace to it? Or is that dependent on the library being used?
It depends on the library. If it provides all functions under one namespace, you can include your version first, store a reference to it under a different variable/name, (unset the original if conflict could occur) and include the other library afterwards.
It would look like this:
<script src="MyLibraryV1.js"></script>
<script>
// Assuming all functions are available under `$`
var MyLibraryV1 = $;
// Now the next script can overwrite `$`.
// Optionally we can also delete/undefine this symbol:
delete window.$;
</script>
<script src="OtherLibraryWithDependencies.js"></script>
<script>
// For easy access, you can use an immediate function to still let `$`
// refer to your library version. It should not affect the other code
// (but if it does you obviously have to use the other name)
(function($) {
// put all code that needs `MyLibraryV1` here
}(MyLibraryV1));
</script>
The better thing of course is if OtherLibraryWithDependencies would properly encapsulate all dependencies so that they don't leak into global scope.
Related
I am new to javaScript and am unsure how to go about creating a new js library and referencing this in another js file.
If I have a standalone file Utilities.js
var Utilities=
{
show: function(input)
{
alert(input);
}
};
Am I missing something as to how a library should be defined standalone?
My second question is how to use that is sub-sequent js files. What I did so far is:
<script type="text/javascript" src="resources/Utilities.js"></script>
In my index.html. Is this enough to reference it as:
Utilities.show("Hello");
In any other java script file?
I tested it in this fashion and got and error "Utilities is not defined"
NOTE: This is just an example and not my full and practical purpose.
Yes, including that Javascript file with that global variable declared is enough to call your methods this way Utilities.show("Hello"); from another Javascript file loaded after Utilities.js or inside a <script></script> section of your html.
But you can actually improve it a little, following the module pattern and exposing only the functions you really need to the global scope (you'll likely write some functions that the users of your library should not call directly, this allows you to do it in a clean way):
var Utilities=Utilities||(function () {
//Accessible only here
var privateArray=[];
//Cannot be called from outside this function
var privateFunction=function(){
}
//Return only what must be publicly accessible, in this
//case only the show() method
return {
show: function(input){
privateFunction();
alert(input);
}
}
})();
That (function () { /* Code */})();, defining a new scope for your code will also avoid name clashes with other global javascript object/functions.
It is OK to use object literals, but you can define libraries using other patterns (module, revealing module, constructors, etc).
I recommend these links to understand primitives, scopes, closures, object literals, etc.
http://bonsaiden.github.io/JavaScript-Garden/
http://jsbooks.revolunet.com/
To call the method inside index.html you need to add a tag.
<script>
Utilities.show("Hello");
</script>
But this approach it's not recommended. Instead of it, you can create a new JS file to run your library code.
<script type="text/javascript" src="resources/Utilities.js"></script>
<script type="text/javascript" src="resources/main.js"></script>
In main.js
Utilities.show("Hello");
Hope it helps.
Given the fact that you gave, within yout question, zero context of what you're trying to achieve, the best answer to your original question is that it depends.
If you just need a bunch of files and you're done (like in your example, Utilities.js and a few more) then you're ok with the way you're heading to.
But of course, you'll allways want to scale your front end and thus you should adhere to some architectural pattern. So, if you're building a client side (browser-side) application, then you should really implement your libraries using the module pattern, and begin your project from a good project example / scaffold.
On the other hand, if you're rendering the html on server (e.g. you're using PHP to render the final html file that will be sent to browser) and you just need some thin functionality in the browser, the way you begun can be okay if you're careful. Also, you can still implement the module pattern here too, although I strongly suggest that you should make use of namespacing to have a clear separation of concerns.
In browser based javascript you can't just call functions from different files yet. In Es6 there are ways. But not yet. Which mean just because you have some variable or function etc then you cant reference it automatically in another file.
Unless both files are loaded into one html and are loaded in order.
Alternatively you could run task runner like grunt and 'merge' them upon each build.
Javascript doesnt have special concept of library, in es6 it's a little different, everything is an object.
What you are doing is just creating an object. and yes it will work.
My application's JavaScript uses jQuery and jQuery plugins and running in "hostile" environment I have no control over (this is PHP extension for eCommerce platform). Thus no way to determine whether my jQuery code will be executed before someone will attach his instance of jQuery/plugins (introduced by other extension) or after this or someone will load jQuery dynamically after page rendered.
Basically the problem is that other extension could use jQuery (with plugins) also and just connecting jQuery with tag will not work.
I have a strong feeling that RequireJS might help me to load needed version of jQuery as far as particular versions of jQuery plugins into the encapsulated scope without polluting global scope (so other extensions will still function properly). Then I'll wrap all my code to "require" statements and it will run using it's own set of jQuery and plugins. I tried this and it kind of works (have not tested this in production environment though) but in some weird way. Seems like this question is kind of relevant to problems I have. Also answer suggesting to use AMD-compatible version of jQuery. But what about plugins? I don't think all plugins I use have such versions.
So questions:
Could RequireJS be used to cover such use case (running jQuery+plugins in undefined environment)? If RequireJS could be used there then any example code or explanation of how to do this properly will be greatly appreciated.
If there is no way to cover this with RequireJS what do you think would be best approach to handle issue?
Yes, I believe RequireJS can help you out here. To my knowledge you'll have to do some legwork, though. Take a look at the source of the (as of 2012-08-19) latest jQuery: link. At the bottom you can see that window.jQuery is being set, defining jQuery and $. The define call for AMD loaders happens after that, so jQuery is in the global scope no matter what. What you want to do is guarantee that your own version of jQuery and plugins stay isolated from other jQuery instances and plugins, correct?
Place your custom jQuery and plugins into their own directory (let's call it "jqcustom") and use that directory when specifying dependencies in your scripts' define calls. You'll want to modify your version of jQuery by wrapping it in a define call and returning the jQuery object at the very bottom, taking out jQuery's window.jQuery and window.$ assignments as well as its default define call in the process (these are both at the bottom, remember). Then you'll need to wrap all of your plugins in define calls and specify your own version of jQuery as the dependency. Example:
define(['jqcustom/jquery'], function(jQuery) {
//inside this method 'jQuery' will override any predefined global window.jQuery
//in case any plugins use the $ variable, define that locally too
var $ = jQuery;
//... plugin code ...
});
If you use RequireJS' optimizer, it can do the wrapping of the plugins for you with its shim config options. jQuery plugins work by adding methods to jQuery's prototype object, so I believe as long as you pass the same jQuery (your custom jqcustom/jquery one) to every plugin with your define wrapping, the plugins' extensions will all be set on the same object and be accessible in subsequent define calls specifying your custom jQuery or custom plugins as dependencies. Good luck!
Is there any way to access all loaded modules of require.js?
Background:
I want to automatically call an init() function of my javascript-modules after all of them are loaded, see require.js + backbone.js: How to structure modules that have an initialize function?
Without require.js I looped over my own module-storage and called each init() function.
I now want to do this with require.js. I'm aware that calling a my_custom_init_function_favoritecolor_petname_love123 of every loaded module (including external libraries) is dangerous. I hope that this will cause less trouble than manually keeping a list of all modules (and the requirements of these modules) up-to-date. Forgetting one module init() is much more likely than a third-party library having my custom function name (though the latter is probably harder to debug).
Or does anyone have a better idea of how to accomplish that?
Yes, require.s.contexts._.defined is an object which its keys are the module names and the values include the value returned from that module.
require.s.contexts._.defined includes all the modules (either define() or require() such as the Javascript file that is the starting point of the program and is indicated using data-main for RequireJS).
Just finished a similar behavior within my RequireJS project. require.s.contexts['_'].registry holds the list of the registered modules.
I am using Underscore.js for getting, filtering and iterating the list of modules. Maybe the following code fragment helps you:
var modules_registered = _.keys(require.s.contexts['_'].registry);
var modules_to_be_initialized = _.filter(modules_registered, function(module_title) {
return module_title.indexOf('modules') > -1;
});
_.each(modules_to_be_initialized, function(module_name) {
require([module_name], function(current_module) {
current_module.init();
});
});
I'm lazy, so I just did this:
var modulesToLoad = Object.keys(require.s.contexts['_'].registry);
require(modulesToLoad);
Based on other answers here.
Regarding AMD (Asynchronous Module Definition ) I read the phase like this:
The AMD format comes from wanting a module format that was better than
today's "write a bunch of script tags with implicit dependencies that
you have to manually order" and something that was easy to use
directly in the browser.
What is the the purpose in javascript context? Can you make some example? pro et contro of using AMD?
Long before JavaScript gained a native module system, the only way to put scripts onto a page were <script> elements. These executed in sequence, in the order they appear on the HTML. This means that if your script relied on jQuery, then jQuery's <script> has to come before your script's <script>. Otherwise, it blows up.
It's not uncommon to logically split an app into multiple files, especially as the app grows. But using this system of manually ordering scripts becomes a nightmare quickly. Your scripts have implicit dependencies whose management is defined elsewhere. This is where AMD comes in.
AMD is a module specification and RequireJS is an implementation of such system. Simply put, it's a wrapper around your code that 1) keeps your script inert until invoked, 2) allows your script to explicitly define its dependencies and, 3) allows the module system to work out which dependencies execute in what order.
Here's a rough example:
// your-app.js
define(['jquery', 'underscore'], function($, _){
// Your script sits in this "wrapper" function.
// RequireJS now knows app.js needs jquery and underscore.
// It loads and executes them first before your script.
})
// jquery.js
define('jquery', [], function(){
// jQuery stuff
return jQuery
})
// underscore.js
define('underscore', [], function(){
// underscore stuff
return underscore
})
// Then on your HTML, load up your app.
<script data-main="path/to/app.js" src="path/to/require.js"></script>
It's common for Javascript libraries that depend on each other to require that they are loaded in a specific order. For example, the script tag that includes the jQuery library has to come before the script tag that includes the jQuery UI library.
If the libraries were using AMD, they could be included in any order. The AMD library would take care of initialising the libraries in the correct order, because you specify which library depenends on which.
(Somewhat ironically, the script tag that includes the AMD library of course has to come before the code that include any libraries using AMD...)
I'm working on a new project in JavaScript that I want to release later. Besides other functionality, this script requires a little DOM manipulation. To make this XB (Cross-Browser) and not inventing the wheel again, I need help of a existing JavaScript library. Because of the large number of great libraries I don't want to force one library for this project. That's why I want to support multiple libraries in one script.
Knowing my jQuery, but other library I don't have enough experience. So I was wondering if theres a tutorial or article that gives light on the supporting multiple JavaScript libraries in a script?
I've read somewhere that the same is possible with CSS selector engines (Sizzle, Selector.js, Peppy, NWMatcher, cssQuery), but I don't know about JS.
Well, with jQuery, you can use the $.noConflict() function to remove the '$' and 'jQuery' variables from the global namespace, preventing possible issues if other parts of the page use another version of jQuery or another library that declares the '$' variable.
Here's a simple example...
<script src="/path/to/jquery.min.js" type="text/javascript"></script>
<!-- load plugins you require here -->
<script type="text/javascript">
var myUniquelyNamedVar = {};
myUniquelyNamedVar.jQuery = $.noConflict(true); // de-aliases jQuery, but gives you a private reference (if you need it)
(function($) {
// use an anonymous function and pass in your private jQuery instance; inside this function you can use $ like normal...
})(myUniquelyNamedVar.jQuery);
</script>
I've used this approach with JSR-168 portlets and had great success. It allows me to have several portlets on a page, each of which could be using a different version of jQuery or different plugins.
I don't think there's a lot about the common frameworks that's similar enough to usefully abstract them anyway. Stick to regular DOM as much as possible.
About the only useful, reusable operation I can think of that many frameworks provide in a similar fashion would be the selector engine. So something like:
function querySelectorAll(selector) {
if ('querySelectorAll' in document)
return document.querySelectorAll(selector); // native Selectors-API is best
if ('jQuery' in window)
return jQuery(selector); // returns a wrapper object, but it's enough like an array
if ('$$' in window)
return $$(selector); // prototype
if ('YAHOO' in window && 'util' in YAHOO && 'Selector' in YAHOO.util)
return YAHOO.util.Selector.query(selector); // yui
// others?
throw 'No selector engine found';
}
The second comment on this page gives an interesting answer: Swiss – a JavaScript framework framework.