Defining a scope for JQuery variables, different js - single page - javascript

I have 2 js on a single page. In one of the js I am doing var jQuery = $.noConflict(true); and after that using all the jQuery methods using jQuery object, like jQuery("#div").hide();
In another js, I am using the traditional $ variable & accessing the jQuery methods as $("#div").hide();
When on a page I use either of the 2 js', things work fine. However, when I include both, the $ in the second js seems to be overwritten by jQuery. for example, in js 2 I can no longer do $("#div").hide() but if I use jQuery instead of $, it works fine - jQuery("#div").hide();!
Why am I experimenting this is because the first div will be distributed to different websites as a plugin, and the second js could be the Jquery written by that website developer.
Please help me figure out where am I going wrong..
Thanks.

You're using noConflict, which releases jQuery's hold on $. Doesn't matter if it's in separate scripts, since it's the same global environment.
In the script where you want to use $, define that variable inside your .ready() handler.
jQuery(function($) {
$('foo').bar();
});

The easiest way to solve this is to use a pattern that plugin authors employ.
(function($) {
// Use $ safely within the function
})(jQuery); // Passes in jQuery object
This is function is created and invoked immediately, and at the same time allows you to pass a variable into the scope of the function. Using this, you can carry on referring to $ in your code and not worry about overwriting it or conflicting.
The jQuery documentation advises this pattern

Files do not have scope, you dereferenced $ with noConflict for your entire page. Anything

Related

Avoid $ conflict with jQuery

I am pretty sure this must have been asked in another form, but searching for the $ sign does not yield any results here.
I have already made a big system, and used jQuery extensively, referencing it with the $. At this point, I don't want to go back.
My problem is that now I have implemented CKEditor, which also references itself with the $, like many other JavaScript frameworks. So now I get a conflict and lots of:
Uncaught TypeError: cannot get property 'any_function' of undefined
I don't want to go through the CKEditor code, searching and replacing, since I will be updating in the future. I also want to keep using $ for jQuery, but nothing else.
Off course I cannot simply use:
$.noConflict()
Without breaking my scripts.
Is there a way where I can keep using $ for jQuery whenever I want, while letting my JavaScript frameworks use $ internally?
What is my best/easiest solution here?
You can wrap either sets of your code in an IIFE and pass the relevant object to it.
(function($) {
// Code that uses jQuery
})(jQuery);
I'd also suggest assigning CKEditor to something else right after it's been loaded so that you can follow a similar pattern for CKEditor code.
// Right after loading CKEditor
var CKEditor = $;
// Code that uses CKEditor
(function($) {
...
})(CKEditor);
Although it'd be more sustainable to just reassign CKEditor to another variable and only use that variable.

Possible to load jQuery only inside closure?

I don't think this can be done, though I know requirejs can do something similar, and I was wondering if this might be possible outside of require.
I'm writing a piece of SaaS JavaScript code that will most likely need jQuery to run cross browser. Some sites have it, some don't, but I don't want to stick jQuery on the window object if they aren't using it. Though I could individually create alternatives for everything I use jQuery for... I was wondering if there is a way I can load jQuery only for use inside my closure. Is this possible?
When you load the standard release of jQuery, by default jQuery assigns itself to the global names jQuery and $. If you load your version of jQuery before your closure file within the page, then within your closure do
var $ = jQuery.noConflict(true);
It will undo whatever modifications your version of jQuery did to the global object.
It is worth noting, however, that this produces a race condition. If any events or timeouts fire between the time that your jQuery file loads and your closure calls jQuery.noConflict(true) they will accidentally use the version of jQuery that you loaded.
An alternative is to edit the jQuery file that you are using to include a call to jQuery.noConflict(true) at the bottom of the jQuery file. You can assign the result to an arbitrary name that no one else would ever think to use, like "abcRandomNumberHere". Then you can retrieve your instance of jQuery from that global name within your closure assigning it to a local variable named jQuery and/or $ and delete the global reference at that time.
// Your jQuery file on your server
// ...
// End of file:
someRandomGlobalName = jQuery.noConflict(true);
// The file that contains your closure:
(function() {
var $, jQuery;
$ = jQuery = someRandomGlobalName;
delete window.someRandomGlobalName;
// Your code that uses jQuery here
} ());
This is a rough approximation of what RequireJS does to keep jQuery out of the global namespace. Recent versions of jQuery have built-in code that detects the existence of a script loader like RequireJS and rather than assigning to global names jQuery passes a reference to itself into RequireJS and leaves the global object untouched. That way RequireJS contains the reference to jQuery internally, but the global.requirejs variable is modified instead.
Creating your own non-conflicting global name for your jQuery version and your closure to "rendezvous" on is analogous to RequireJS' functionality. The name RequireJS uses is the "global name": requirejs.s.contexts._.jQuery (not exactly, but something like this).
Call jQuery.noConflict(true) and it will re-assign $ and jQuery to wherever it was.
Then, you can pass the reference returned by the above expression into your closure.
(function(jQuery) {
})(jQuery.noConflict(true));
Yes, calling jQuery.noConflict(true) will completely remove anything that jquery added from the global namespace reverting it back to what it was previously allowing for conflicting libraries and/or multiple versions of jQuery.
<script src="jquery.min.js"></script>
<script>
(function($){
$("el").doSomething();
})(jQuery.noConflict(true));
</script>

Rails/Javascript selectors won't find elements

I am in the process of installing the asset pipeline into an older rails app. I am getting some really strange results though. I can see that the page is rendering all of the css and the jquery that is in the app/assets directory but its having a hard time interacting with the html.
For instance if i inspect the page and in the console call $("html").html(); to try grab all the html it returns TypeError: Cannot call method 'html' of null same when trying to grab any element that is being rendered? but the page is there. if i call jQuery it will return fine. so its not like it jQuery isnt there.
$ is just a shorthand way of writing jQuery. If the latter works but the former doesn't, then another script in your pipeline is probably conflicting with jQuery and trying to use the $ symbol for something else.
Are you using any other plugins or libraries that might be trying to use $? Or have you accidentally overwritten it yourself by writing $ = (something) anywhere? Without more information it's hard to know where the problem is exactly.
If all else fails you can just stick to using jQuery() for all your calls. In your external script file you could also circumvent this by passing the jQuery object to a wrapper function, e.g.:
(function ($) {
$('div').append('You can use $ here without having to worry about conflict.');
}(jQuery))

Mixing javascript and jquery within namespace

Was having trouble a few weeks ago getting jquery to run in firebug (esp on drupal sites). Apparently the issue was that Drupal was grabbing the $ variable, so I got a little namespace snippet (function($)...(Jquery)); that reclaimed the $. I have been using the namespace in firebug but geting inconsistent results, especially when mixing pure javascript and Jquery within the namespace. I understand that all Jquery is javascript and they work together, but looking at samples I see some weird variations in the way people deploy this namespace. As a general question but also specifically within Firebug context, is there any need to place javascript in any particular relation to namespaced Jquery (inside the namespace, function calls inside, function out, or any other convention)?
Thanks
If you meant preventing the $ from being reclaimed, there is no convention but there is a way. other frameworks also use the $ name. anything declared later to use $ will take over $. however, you can prevent it or get around it.
jQuery offers a lot of ways to prevent it via its noConflict() method. but my preferred method is just wrap them in a function. jQuery also uses the jQuery namespace. $ is a shorthand alias, a very common one too. so functions like $.each() is also jQuery.each(). what crazy framework uses jQuery as its namespace anyway?
an example of wrapping in a function is like this:
(function($){
//inside here, "$" is jQuery
}(jQuery)); //pass "jQuery"

Help understanding jQuery

jQuery(function ($) {..}
I am trying to learn jQuery and came across some code that started like the above statement. What does that mean?
That is a shortcut for:
jQuery(document).ready(function($) {
// ...
});
It sets up an event handler for when the document is ready to have its DOM manipulated. It's good practice to initiate your jQuery code after the document is ready. The first parameter $ references the jQuery object so you can use $ in place of jQuery in your code.
I believe this allows you to abstract $ into an anonymous function. As a few different javascript libraries use the $ syntax you don't want to create conflicts. So instead you call jQuery using its explicit identifier jQuery and pass in $. Now you can use $ all you want inside the anonymous function and not need to worry about conflicting with other libraries.
Jacob is correct.
Other variations you will see along with jQuery(function($){..} are
$(document).ready(function(){...}
jQuery(document).ready(function(){...}
$(function(){...}
All wait until your DOM has fully loaded.
Passing a function to a call to jQuery() has the effect of executing that function when the dom is ready.
The function is passed a reference to jQuery as the first parameter. So, Setting the name of the arg in that function to $ allows you to use $ as shorthand for jQuery from within your function. $ is a global reference to jQuery by default, so you only need to specify $ as a parameter in your function if you are overriding $ elsewhere, for example by using jQuery.noconflict(). This is common practice for plugin developers, since they can't be guaranteed that $ has not been overridden by the plugin consumer.

Categories

Resources