Rails/Javascript selectors won't find elements - javascript

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))

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.

$ not working for jQuery in new website

I have been using jQuery for quite a few years now, and after I include the jQuery scripts in whatever site I am working on, I would always use the $ for jQuery objects. For example:
$('#my_selector').click(function(){...
I had built a website a few years ago in Joomla 1.6 with over 200 pages and jQuery used in almost all of them, all with the $. Now I am rebuilding the site in Joomla 3.3.0. The funny thing is, now sometimes the $ just doesn't work when identifying jQuery objects, but when I use jQuery it works. For example. the above code example would have to be changed to this:
jQuery('#my_selector').click(function(){...
And that works. And the final strangest thing is that on one page, it seems like the $ works for some of the jQuery but not all. The error that I see is this one:
TypeError: undefined is not a function
Seems like the problem occurs mostly on the functions that run after load complete circumstances. Anyway I am just wondering if people out there know why the $ would stop working with identifying the jQuery functions and objects.
Thanks!
You are most probably using a conflicting library, meaning: another script/library that declares (and thus overrides) the variable $. Wrap all your code in a closure, and you should be good:
(function($) {
$('#my_selector').doStuff();
})(jQuery)
Or, if it needs to be executed after document ready:
jQuery(document).ready(function($) {
$('#my_selector').doStuff();
});
Joomla 3.x is moving progressively to jQuery and replacing all MooTools dependencies along the way.
The default state is to load jQuery in noConflict() mode, but depending on features used on any given page by extensions (templates,plug-ins, components or modules) MooTools may also be loaded.
That means that on some pages, jQuery is defined and not $ and on other pages both are defined, obviously this will result in the issues you are seeing.
Add to that most third-party extensions from the 1.6 era (you have been upgrading to the 2.5.x line along the way right?) just ignored what-ever was going on and loaded whatever they needed (potentially blowing away other libraries) you generally will have to sort out all the conflicts first.
The only guaranteed way to use jQuery is by using the jQuery prefix.
You can read about using JavaScript frameworks with Joomla here, amongst other things it gives you future proof mechanism built-in to Joomla for loading jQuery.
To load jQuery, use: JHtml::_('jquery.framework');
To load the jQuery UI core call: JHtml::_('jquery.ui');
As has been mentioned you can wrap your JavaScript in a closure, in fact this is what the core com_banners does in /media/cbanner.js
var jQuery;
(function ($) {
$(document).ready(function () {
$('#jform_type').on('change', function (a, params) {
var v = typeof(params) !== 'object' ? $('#jform_type').val() : params.selected;
switch (v) {
case '0':
// Image
$('#image, #url').show();
$('#custom').hide();
break;
case '1':
// Custom
$('#image, #url').hide();
$('#custom').show();
break;
}
});
});
})(jQuery);
Are you or joomla using mootools or any other library with the $?
This would mean there is a conflict and the right way to solve it, is by using jQuery instead of $.

Export Angular JQLite as $/jQuery

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.

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

How to check if certain JS file was included in a webpage?

In my custom JS code file I use various plugins, for instance, the Masonry plugin for JQuery. However, I don't include the plugin on every page or at the master page file level (in some yes, in some no) but I do include my custom file on every page. Therefore, the code in my JS file will issue an error if the Masonry plugin is missing.
If someone could reply with a solution of how to:
Check if certain JS plugin was referenced (included) and only run the code then,
(optionally) include the file at runtime if it is missing.
I have it working with JQuery and JQuery UI because they both introduce a class into DOM structu (jquery and jquery.ui objects) but there are other plugin's like lightbox scripts, the forementioned Masonry etc..
Rather than checking whether a particular JavaScript file has been 'included', I'd just check if the functionality that you need is available (i.e. if you need a function named foo, just do something along the lines of typeof foo == 'undefined' to see if it is there ...).
What you are trying to do is probably a bad idea, but anyway here's how to determine if a given plugin has been defined. In jQuery they are just namespaces to the jQuery scope:
if(!jQuery().somePlugin) {
// the plugin is not loaded => load it:
jQuery.getScript('/url_of_the_plugin', function() {
// the plugin is now loaded => use it
});
}
You can only check if its class or methods are defined, in your case:
if (typeof($.fn.masonry) == 'undefined') ...
Anyway, I'll recommend including every script at every page, compressed into one file. The cost of downloading and parsing potentially not needed code is often far less than penalty of having multiple HTTP requests.

Categories

Resources