Using ReqiureJS to have local instances of 3rd party libraries - javascript

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!

Related

Mediawiki add Jquery plugin via ReourceLoader

I'm trying to add a JQuery plugin which is not one of core plugins of mediawiki (twbsPagination)
The problem is mw.loader.using doesn't support URL so I can't pass url of twbsPagination to be loaded & mw.loader.load doesn't support callback to make me able to run my code after loading the plugin.
How can I load a jquery plugin and use it after the load in mediawiki 1.28 ?
To the best of my knowledge, you can't add to the list of what mw.loader.load or mw.loader.using support, but you can still use $.getScript() without loading anything extra, since jQuery itself comes as part of the default Mediawiki install. If you have cascading dependencies, such as a script that makes use of a $.getScript()-loaded plugin, simply nest each level of dependency inside the $.getScript().complete() callbacks just as you would with the callback you'd give mw.loader.using.
As a side note, using $.getScript to load javascript on pages outside of Common.js also allows you to use ES6 in those non-Common.js scripts. (Mediawiki still doesn't support ES6 on Common.js.)
For a live example, look at lines ~306-335 in https://stratics.com/w/index.php?title=MediaWiki:Common.js

In what cases or conditions jQuery.noConflict is needed?

I want to ask is there any practical reason where jQuery.noConflict function is needed utmost?
In layman terms I am asking, what is the reason behind the evolution of this function?
You are using another library which also using $.
You have to use multiple versions of jQuery, mostly because the
plugins depends on different version of jQuery.
The jQuery library and virtually all of its plugins are contained within the jQuery namespace. As a general rule, global objects are stored inside the jQuery namespace as well, so you shouldn't get a clash between jQuery and any other library (like prototype.js, MooTools, or YUI).
That said, there is one caveat: by default, jQuery uses $ as a shortcut for jQuery. Thus, if you are using another JavaScript library that uses the $ variable, you can run into conflicts with jQuery. In order to avoid these conflicts, you need to put jQuery in no-conflict mode immediately after it is loaded onto the page and before you attempt to use jQuery in your page.
for E.g
<script src="other_lib.js"></script>
<script src="jquery.js"></script>
<script>
$.noConflict();
// Code that uses other library's $ can follow here.
</script>
you can read more here http://learn.jquery.com/using-jquery-core/avoid-conflicts-other-libraries/

Generic way of handling conflicts between javascript libraries

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.

Rolling jQuery into another library?

I have a project that requires a custom JavaScript library to be included in end user's websites. Sort of a third party thing, think JavaScript tracking like Google Analytics.
We'll have no control over what other JS libraries/frameworks might also be loaded or what versions.
I'd like to be able to leverage jQuery's event delegation, selector and AJAX functionalities but:
Not cause any conflicts with other libraries or other versions of
jQuery that might be loaded
Not require the end user to have to think
about including jQuery separately.
So, rolling in all of jQuery sort of seems like overkill but again, event delegation, selector and AJAX are required. I know jQuery's sizzel engine is broken out in such a way that it's possible to include it in 3rd party libraries and there are plenty of tiny AJAX libraries but we need good event delegation support as well. Additionally, I foresee us needing to do some heavy DOM lifting with this library in the near future as well so it's arguable we do need most of jQuery's functionality.
Any suggestions on how to encapsulate jQuery in such a way that we don't trample over anyone's code? Also, how advisable is this? It does feel a tad iffy.
Also, what's the best wat to encapsulate it into another library? Is there a better way than this?:
(function(window){
window.myNamespace = {
_jq:null,
init: function(){
// Include jQuery
myNamespace.setJq();
},
setJq:function(){
/*! jQuery v1.8.2 jquery.com | jquery.org/license */
(function(a,b){function G(a){...}}) // <- minified jQuery
// Stash a local copy of jQuery
myNamespace._jq = jQuery;
// Return $ and jQuery namespace
$.noConflict(true);
}
}
})(window)
(We intend on offering a version of the library without jQuery for those savvy enough to know that it's already loaded on their page and what version they're using)
Have a look at jQuery in Parts: https://github.com/mythz/jquip
What about dong a conditional load... Test if $ exists. If it does, don't load the script. If it doesn't, then load it.
You could use the following pattern to make sure that the jQuery is being passed in to the function and then you can map it to the local variable $ without issues.
(function(window,$){
//use $ as a local jQuery variable
})(window,jQuery);

Using Prototype JS on pages that use jQuery

I am revamping a website that now uses jQuery. The process is more than half way done but for the time being I need to setup a demo as soon as possible. For this I will copy existing ASP code as-is and these particular pages require prototype plugins. Converting all prototype plugins to jQuery is in the todo list. So I am wodering if there is a workaround that I can use in the mean time to have both libraries working on same page. The workaround is temporary, I'll port the plugins to jQuery (or use a jQuery alternate) eventually.
Edit
OK, so I prefer to stick with $ = jQuery. My revised question is: does prototype have a no conflict option? I can wrap all prototype plugin code inside wrappers, so wondering if it is possible to do a:
(function(/* what comes here? */) {
// some code that uses $ and $$
})(/* what comes here? */);
You could read about Using jQuery with Other Libraries.

Categories