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/
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.
I have the following to snippets of code:
$(document).ready(function() {
document.head.appendChild(
$('<script />').attr('src', 'source.js').on('load', function() {
...
})[0]
);
});
This will fire the load handler.
Whereas using the normal jQuery append():
$(document).ready(function() {
$('head').append(
$('<script />').attr('src', 'source.js').on('load', function() {
...
})
);
});
This will not fire the load hander.
What am I missing: why does jQuery append() not work?
Is using document.head.appendChild() a bad idea?
NOTE: I can't use $.getScript(). The code will run on a local file system and chrome throws cross site script errors.
Update
Some people had trouble reading the compact style, so I used extra line feeds to clarify which objects where calling which methods. I also made it explicit that my code is inside a $(document).ready block.
Solution
In the end I went with:
$(document).ready(function() {
$('head')[0].appendChild(
$('<script />').attr('src', 'source.js').on('load', function() {
…
})[0]
);
});
I think #istos was right in that something in domManip is breaking load.
jQuery is doing some funny business in its DOM manipulation code. If you look at jQuery's source, you'll see that it uses a method called domManip() inside the append() method.
This domManip() method creates a document fragment (it looks like the node is first appended to a "safe" fragment) and has a lot of checks and conditions regarding scripts. I'm not sure why it uses a document fragment or why all the checks about scripts exist but using the native appendChild() instead of jQuery's append() method fires the event successfully. Here is the code:
Live JSBin: http://jsbin.com/qubuyariba/1/edit
var url = 'http://d3js.org/d3.v3.min.js';
var s = document.createElement('script');
s.src = url;
s.async = true;
$(s).on('load', function(e) {
console.log(!!window.d3); // d3 exists
$(document.body).append('<h1>Load fired!</h1>');
});
$('head').get(0).appendChild(s);
Update:
appendChild() is a well supported method and there is absolutely no reason not to use it in this case.
Maybe the problem is when you choose DOM appendChild, actually you called the function is document.on('load',function(){});, however when you choose jQuery append(), your code is $('head').on('load', function(){}).
The document and head are different.
You can type the code below:
$(document).find('head').append($('<script />').attr('src', 'source.js').end().on('load', function() {
...
}));
You should probably make sure that the jquery append is fired when the document is ready. It could be that head is not actually in the dom when the append fires.
you don't have to ditch jquery completely, you could use zeptojs. Secondly, I couldn't find out how and why exactly this behavior is happening. Even though i felt answer was to be found in links below. So far i can tell that if you insert element before definig src element then load won't fire.
But for manual insertion it doesn't matter. (????)
However, what i was able to discover is that if you use appendTo it works.
Code :http://jsfiddle.net/techsin/tngxnkk7/
var $ele = $('<script />').attr('src', link).load(function(){ abc(); }) ).appendTo('head');
New Info: As is understood adding script tag to dom with src attribute on it, initiates the download process of script mentioned in src. Manual insertion causes page to load external script, using append or appendTo causes jquery to initiate downloading of external js file. But event is attached using jquery and jquery initiates download then event won't fire. But if it's the page itself initiates the download then it does. Even if event is added manually, without jquery, adding via jquery to dom won't make it fire.
Links in which i think should be the answer...
Append Vs AppendChild JQuery
http://www.blog.highub.com/javascript/decoding-jquery-dommanip-dom-manipulation/
http://www.blog.highub.com/javascript/decoding-jquery-dommanip-dom-manipulation/
https://github.com/jquery/jquery/blob/master/src/manipulation.js#L477-523
http://ejohn.org/blog/dom-documentfragments/
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.
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.
I have a website with a form that uses TinyMCE; independently, I use jQuery. When I load the form from staging server on Firefox 3 (MacOS X, Linux), TinyMCE doesn't finish loading. There is an error in Firefox console, saying that t.getBody() returned null. t.getBody(), as far as I understand from TinyMCE docs, is a function that returns document's body element to be inspected for some features. Problem doesn't occur when I use Safari, nor when I use Firefox with the same site running from localhost.
Original, failing JavaScript-related code looked like this:
<script type="text/javascript" src="http://static.alfa.foo.pl/json2.js"></script>
<script type="text/javascript" src="http://static.alfa.foo.pl/jquery.js"></script>
<script type="text/javascript" src="http://static.alfa.foo.pl/jquery.ui.js"></script>
<script type="text/javascript" src="http://static.alfa.foo.pl/tiny_mce/tiny_mce.js"></script>
<script type="text/javascript">
tinyMCE.init({ mode:"specific_textareas", editor_selector:"mce", theme:"simple", language:"pl" });
</script>
<script type="text/javascript" src="http://static.alfa.foo.pl/jquery.jeditable.js"></script>
<script type="text/javascript" src="http://static.alfa.foo.pl/jquery.tinymce.js"></script>
<script type="text/javascript" charset="utf-8" src="http://static.alfa.foo.pl/foo.js"></script>
<script type="text/javascript">
$(document).ready(function(){
/* jQuery initialization */ });
</script>
I tried changing script loading order, moving tinyMCE.init() call to the <script/> tag containing $(document).ready() call—before, after, and inside this call. No result. When tinyMCE.init() was called from within $(document).ready() handler, the browser did hang on request—looks like it was too late to call the init function.
Then, after googling a bit about using TinyMCE together with jQuery, I changed tinyMCE.init() call to:
tinyMCE.init({ mode:"none", theme:"simple", language:"pl" });
and added following jQuery call to the $(document).ready() handler:
$(".mce").each( function(i) { tinyMCE.execCommand("mceAddControl",true,this.id); });
Still the same error. But, and here's where things start to look like real voodoo, when I added alert(i); before the tinyMCE.execCommand() call, alerts were given, and TinyMCE textareas were initialized correctly. I figured this can be a matter of delay introduced by waiting for user dismissing the alert, so I introduced a second of delay by changing the call, still within the $(document).ready() handler, to following:
setTimeout('$(".mce").each( function(i) { tinyMCE.execCommand("mceAddControl",true,this.id); });',1000);
With the timeout, TinyMCE textareas initialize correctly, but it's duct taping around the real problem. The problem looks like an evident race condition (especially when I consider that on the same browser, but when server is on localhost, problem doesn't occur). But isn't JavaScript execution single-threaded? Could anybody please enlighten me as to what's going on here, where is the actual problem, and what can I do to have it actually fixed?
The browser executes scripts in the order they're loaded, not written. Your immediate scripts -- tinyMCE.init(...) and $(document.ready(...)); -- can execute before the files finish loading.
So, the problem is probably network latency -- especially with 6 separate scripts (each requiring a different HTTP conversation between the browser and server). So, the browser is probably trying to execute tinyMCE.init() before tiny_mce.js has finished being parsed and tinyMCE is fully defined.
If don't have Firebug, get it. ;)
It has a Net tab that will show you how long it's taking all of your scripts to load.
While you may consider the setTimeout to be duct taping, it's actually a decent solution. Only problem I see is that it assumes 1 second will always fix. A fast connection and they could see the pause. A slow connection and it doesn't wait long enough -- you still get the error.
Alternatively, you might be able to use window.onload -- assuming jQuery isn't already using it. (Can anyone else verify?)
window.onload = function () {
tinyMCE.init(...);
$(document).ready(...);
};
Also, was that a direct copy?
<script type="text/javascript">
$(document).ready(function(){
/* jQuery initialization */ }
</script>
It's missing the ) ending ready:
<script type="text/javascript">
$(document).ready(function(){
/* jQuery initialization */ })
</script>
Missing punctuation can cause plenty of damage. The parser is just going to keep reading until it finds it -- messing up anything in between.
Since this is the first page which came in google when I asked myself the same question, this is what i found about this problem.
source
There's a callback function in tinyMCE which is fired when the component is loaded and ready. you can use it like this :
tinyMCE.init({
...
setup : function(ed) {
ed.onInit.add(function(ed) {
console.log('Editor is loaded: ' + ed.id);
});
}
});
If you are using jquery.tinymce.js then you don't need tiny_mce.js because TinyMCE will try to load it with an ajax request. If you are finding that window.tinymce (or simply tinymce) is undefined then this means that the ajax is not yet complete (which might explain why using setTimeout worked for you). This is the typical order of events:
Load jquery.js with a script tag (or google load).
Load TinyMCE's jQuery plugin, jquery.tinymce.js, with a script tag.
Document ready event fires; this is where you call .tinymce(settings) on your textareas. E.g.
$('textarea').tinymce({ script_url: '/tiny_mce/tiny_mce.js' })
Load tiny_mce.js this step is done for you by TinyMCE's jQuery plugin, but it could happen after the document ready event fires.
Sometimes you might really need to access window.tinymce, here's the safest way to do it:
$(document).tinymce({
'script_url': '/tiny_mce/tiny_mce.js'
'setup': function() {
alert(tinymce);
}
});
TinyMCE will go so far as to create a tinymce.Editor object and execute the setup callback. None of the editor's events are triggered and the editor object created for the document is not added to tinymce.editors.
I also found that TinyMCE's ajax call was interfering with my .ajaxStop functions so I also used a setTimeout:
$(document).tinymce({
'script_url': '/tiny_mce/tiny_mce.js'
'setup': function() {
setTimeout(function () {
$(document).ajaxStart(function(e) {/* stuff /});
$(document).ajaxStop(function(e) {/ stuff */});
}, 0);
}
});