Let me give my question some context. I have a JavaScript widget. The widget includes a copy of jQuery from my site. This widget is placed on a third-party site. The widget parses a JSON feed and injects the contents into the DOM. Pretty simple stuff.
If the third-party page already has jQuery referenced and relies on jQuery plugins, conflicts could arise. Especially, when the third-party site references a different version of jQuery. $.noConflict() is useful, but the existence of plugins make it unreliable. From the $.noConflict() documentation:
If necessary, we can free up the
jQuery name as well by passing true as
an argument to the method. This is
rarely necessary, and if we must do
this (for example, if we need to use
multiple versions of the jQuery
library on the same page), we need to
consider that most plug-ins rely on
the presence of the jQuery variable
and may not operate correctly in this
situation.
To get around this issue, my idea is to reset the name of the jQuery global object. At the bottom of the jQuery source, there are these lines:
// Expose jQuery to the global object
window.jQuery = window.$ = jQuery;
Could I refactor the lines to:
// Expose jQuery to the global object
window.myjQuery = jQuery;
I've removed the shorthand $ variable, and I've changed jQuery to myjQuery. Now my code can look like this:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>myjQuery</title>
<script type="text/javascript" src="myjquery-1.4.js" />
<script type="text/javascript">
// .ready() can alias the jQuery object
// I can pass $ and write code as normal
myjQuery(document).ready(function($) {
$('p').css('color', 'red');
});
// Fails
jQuery(document).ready(function($) {
$('p').css('color', 'blue');
})
// Fails
$(document).ready(function() {
$('p').css('color', 'green');
})
</script>
</head>
<body>
<p>myjQuery changed my color to red.</p>
</body>
</html>
Is this a good idea? I don't know the internals of the library enough to say for sure. I understand the library is basically a closure, so I'm guessing this approach is OK. Thoughts?
EDIT: I've accepted Doug's answer because he provided code which is almost identical to an example on the $.noConflict() documentation page. I didn't notice it before. Here is the example:
// Completely move jQuery to a new namespace in another object.
var dom = {};
dom.query = jQuery.noConflict(true);
// Do something with the new jQuery
dom.query("div p").hide();
// Do something with another library's $()
$("content").style.display = 'none';
// Do something with another version of jQuery
jQuery("div > p").hide();
It's not normally a good idea to edit a released file if you don't need to. I read your question, and this solution will work for your needs. Don't edit the jQuery core at all. Do this:
<script type="text/javascript" src="jquery-1.4.js"></script>
<script type="text/javascript">
// Revert $ and jQuery to their original values:
window.myjQuery = jQuery.noConflict(true);
(function($){
// Inside here, $ = myjQuery
$(document).ready(function(){
});
})(window.myjQuery);
</script>
The important thing is for your widget to include jQuery, then immediately call noConflict(true) and store it in a variable.
If you follow these steps exactly, it will not affect existing jQuery instances or plugins on the page. It will only give you a private version of jQuery in the variable myjQuery for your own plugin.
Secondly, using a self executing anonymous function, you can create a private scope for your widget where $ equals your included jQuery file.
Related
I need to create code which can be used as snipped for every site.
When I copy paste this code to any html in the world this should work:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<script type="text/javascript"> my_jQuery = $.noConflict(true);</script>
<script type="text/jscript">
my_jQuery(document).ready(function () {
my_jQuery("#myDiv").html("Hello world");
});
</script>
<div id="myDiv">
</div>
Of Course in real world logic will be more complex but principle is same.
So this must work even if site already have JQuery, if have same version of JQuery,if have different version of JQuery, or even if does not have JQuery at all.
I want be sure that client does not use some old version of JQuery, so I want always use my JQuery.
What do you think, will this work or there is something that I have not consider?
I think that this question should be faced in an architectural way, knowing what libraries/frameworks are available is a design concern... Basically, you shouldn't need to check dependencies at runtime... if you write jQuery, you must be sure that jQuery exists!
By the way, there are some cases where you can't do it, for example, if you are writing a public/api (a snippet that runs in heterogeneous environments). In these cases, you can do:
mark jQuery as peer-dependencies
Check at runtime.
There is an example of runtime checking:
<script>
(function($) {
var jQueryUrl = 'https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js';
$ || (document.writeln('<script src="'+ jQueryUrl +'"></script>'));
})(window.jQuery);
</script>
In order to avoid conflicts, finally, you don't need to use jQuery.noConflict, you need to work with javascript scopes (closures)... basically, never try to access the global jQuery alias $ (never use global vars), simple pass it as function param:
(function($) { console.log('$', $); })(window.jQuery)
window.jQuery(document).ready(function($) { console.log('$', $); });
The first thing we need to do is check if jQuery is present on the website. jQuery is the global variable so it should be in window object if it is loaded. We can check it like this: if (window.jQuery) {}
If the jQuery not present we can dynamically load it adding script tag with desired jQuery version. So the snippet answering for checking if jQuery is loaded and loading if it's not would be like:
if (!window.jQuery) {
var jq = document.createElement('script');
jq.type = 'text/javascript';
jq.src = 'http://code.jquery.com/jquery-1.12.1.min.js';
document.getElementsByTagName('head')[0].appendChild(jq);
}
That would work for
So this must work even if site already have JQuery,
if have same version of JQuery,
if have different version of JQuery,
or even if does not have JQuery at all.
As you can see as per your code, that would work fine for all three situations but 4th one. For this case you have to have a check to find if window has jQuery object. That can be done with:
if(window.jQuery){
var my_jQuery = $.noConflict(true);
my_jQuery(document).ready(function () {
my_jQuery("#myDiv").html("Hello world");
});
}
Note:
<script type="text/jscript">
would not work in the browsers other than IE.
Im trying to run the below script to understand the Javascript object and inheritance but don't see anything being displayed.
<html>
<head>
<script>
$(document).ready(
function Person(){
alert('New Person Created');
}
Person.prototype.sayHello = new function(){
alert('Hello');
};
var x = new Person();
x.sayHello();
var newfunction = x.sayHello;
newfunction.call(Person);
);
</script>
</head>
<body>
</body>
</html>
$ is defined in jQuery, you need to include jQuery library before using the $
you can include jquery library using cdn like this,
<script src ="//code.jquery.com/jquery-1.10.2.min.js"></script>
The first line of your script is jQuery. If you want to use jQuery you should include it first (based on what you have written I strongly suspect you don't need or want it just yet).
Alternatively, just drop the $(document).ready part and its {}s and that should get you going.
Also, take a look at your developer tools menu and get your JavaScript console open. It will have told you about this error.
When you use a construct like $(document), you are calling a function $, which is defined as jQuery. You need a <script> tag in your document to load the correct version of jQuery. Also, check your browser console. You will see an error there about $
The only thing I can see wrong is that you are trying to use the jQuery library, but you've never actually included it.
I have a script src for a deprecated version of JQuery which I cannot control (controlled externally via a CMS, not cross-domain, just no access to changing it) and I'd like to change the script src to a newer version of Jquery.
Old code:
<script type="text/javascript" src="js/jquery-1.4.2.min.js"></script>
Replace with:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
Once an external script has loaded, it can't be removed as it's already loaded into memory, so changing the source would just load another version of jQuery without removing the first version, so you'd have two versions of jQuery, creating a conflict, and in many cases nothing will work.
There is a workaround if you absolutely have to:
$(function() {
$j_142 = $.noConflict(true);
$j_142.getScript('//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js', function() {
$j_191 = $.noConflict(true);
});
});
FIDDLE
now you have two versions of jQuery mapped, and to use them you'd do:
$j_191('#selector')
of course, this would cause issues with code already written, but you could probably get away with just mapping the second script to a new variable or something ?
EDIT:
You could use a closure to map one of those values back to the dollarsign within the closure:
(function($) { //anonymous self invoking function
// now you could use the dollarsign as normal
$(function() { // document ready function
});
})($j_191);
You can use
var oldJquery = document.querySelectorAll('script[src="js/jquery-1.4.2.min.js"]');
oldJquery.src = "//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"
Once you do this, it will automotically will download coz it is live dom element. All changes should be reflected immediately.
But I would suggest that long term this is not good idea. what if CDN from google is down.
You might be in trouble. Just take precaution while doing this changes.
That easy, this is your code:
$("script[src='js/jquery-1.4.2.min.js']").attr('src', '//ajax.googleapis.com/ajax/libs/jquery/1.9.2/jquery.min.js');
This is example http://jsfiddle.net/rebeen/KwLM3/
I am developing a site using Joomla 2.5 and since I'm going to be handing it off to a client who is less than code savvy, I don't want to have to make them try to remember how to add class=hyphenate to every <p> when they add / update content.
I'm trying to use JQuery to do it but it doesn't seem to be working. Here is my code that should add the class:
<script type="text/javascript">
$("p").addClass("hyphenate");
</script>
Any input / help is - as always - appreciated!
Thanks,
Cynthia
If your script tag is placed before the p elements, you need to wait for the document to be ready - like this:
$(document).ready(function(){
$("p").addClass("hyphenate");
});
Shorthand version:
$(function(){
$("p").addClass("hyphenate");
});
Sidenote: when mixing libraries, global variables (like the $) can get out of hand. So make your own scope, ensuring that the $ is jQuery:
(function($){ // $ = jQuery
$(function(){
$("p").addClass("hyphenate");
});
})(jQuery);
Also your Jquery May Conflict with Joomla Mootools, to overcome you can use JQuery noConflict
var JQ=jQuery.noConflict();
JQ(document).ready(function(){
JQ("p").addClass("hyphenate");
});
I am working in a large site that has 2 conflicting jquery plugins included for doing autocmplete.
1) jquery.autocomplete.js (not part of jquery ui) that does :
$.fn.extend({
autocomplete: function ...
2) jquery.ui.autocomplete.js (from the latest jquery ui library), that also uses the autocomplete keyword.
$.widget( "ui.autocomplete", { ...
Is there a way to specify that i am using only the second, jquery.ui widget
when calling
$( "#tags" ).autocomplete ...
without changing the 2 files?
As the second autocomplete is using the $.Widget method of registering itself with jQuery it'll be easiest to change the behaviour of the in-house one.
You won't be able to load both of them without making some sort of change to the jQuery object between the two script loads because they'll just conflict with (or overwrite) each other.
I would try this:
<script src="jquery.autocomplete.js"> </script>
<script>
// rename the local copy of $.fn.autocomplete
$.fn.ourautocomplete = $.fn.autocomplete;
delete $.fn.autocomplete;
</script>
<script src="jquery-ui.autocomplete.js"> </script>
Which will then make:
$().autocomplete()
use the jQuery UI version, and
$().ourautocomplete()
use your local version.
I tried to do it with the tabs function of jQuery UI, it should work the same for you.
A function is technically a js object, so you could simply rename it :
$.fn.tabs2 = $.fn.tabs;
delete $.fn.tabs;
$("#tabz").tabs2({});
Hope that helps!
Edit
Like Alnitak suggested, you also need to delete the previous function's name.
Also, I think .fn is required.