Export Angular JQLite as $/jQuery - javascript

I occasionally find plugins that try to detect if JQuery is present, or might have 1-2 lines of code that uses $. I am wondering if it's possible to make Angular's JQLite available outside of angular apps somehow? My first tries of simply seeing if JQLite was available did not work. Basically I would like either the variable $ or jQuery to be available anywhere (or at least within my ng-app area) to see if it contains enough functionality to let these jquery plugins/code work.
Here's the source https://github.com/angular/angular.js/blob/master/src/jqLite.js

Actually, you can, but it almost certainly won't help.
If you wanted to "export" it, you'd simply need to add this after the Angular JavaScript is loaded:
window.jQuery = window.$ = angular.element;
Now calling $() or jQuery() will run jqLite. Here's why it most likely won't work: jqLite doesn't support selectors, meaning you can't do
angular.element('.foo').html();
You'll just get an error stating that Selectors not implemented.
Here's a jsFiddle showing it working when used on elements directly, but failing with the selector.
Edit
Based on Yashua's suggestion below, here's an update using his trick to enable selectors. It's a nice trick/hack if jqLite is good enough.
Personally, I don't agree that you should just include jQuery. It's another large library to depend on, and if you are only performing a couple of one-liners, you should be able to integrate them into Angular directly using proper directives. I'd take the time to see if you can rewrite the existing code.

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.

How does angular determine whether jQuery is present?

Because I'm getting the weird situation that angular objects like element in the link function of a controller ends up being a jQLite object although jQuery is definitely present as in being loaded in memory and successfully used elsewhere on the same page.
The Angular FAQ is rather vague on that question:
Yes, Angular can use jQuery if it's present in your app when the application is being bootstrapped. If jQuery is not present in your script path, Angular falls back to its own implementation of the subset of jQuery that we call jQLite.
So what exactly does 'present' mean?
Angular.js will use jQuery if it's included first, otherwise it will use it's own jqLite. If you load jQuery after AngularJS, AngularJS attaches itself to jqLite but you can still access jQuery through $.
See below the code used by angular.js to determine if jquery is loaded:
// bind to jQuery if present;
jQuery = window.jQuery;
// Use jQuery if it exists with proper functionality, otherwise default to us.
// Angular 1.2+ requires jQuery 1.7+ for on()/off() support.
// Angular 1.3+ technically requires at least jQuery 2.1+ but it may work with older
// versions. It will not work for sure with jQuery <1.7, though.
if (jQuery && jQuery.fn.on) {
jqLite = jQuery;
extend(jQuery.fn, {
scope: JQLitePrototype.scope,
isolateScope: JQLitePrototype.isolateScope,
controller: JQLitePrototype.controller,
injector: JQLitePrototype.injector,
inheritedData: JQLitePrototype.inheritedData
});
Changing the order of script tags may not happen very often, but it could occur if you start modularising the codebase. In particular, this issue has happened while using some module loaders like RequireJS.

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"

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

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

Categories

Resources