I am new to jquery. I am trying to append Jquery in an HTML page in java. To include jquery.js file I have written following code:
scriptTag += "var script = document.createElement('script');" +
"script.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js'; " +
"script.type = 'text/javascript'; " +
"document.getElementsByTagName('head')[0].appendChild(script);" +
and then I appended following js+jquery code with it
"var script2 = document.createElement('script'); window.onload = function() {" +
"$(document).ready(function() {" +
"$(\"#identity\").hide();});};" +
"script2.type = 'text/javascript'; " +
"document.getElementsByTagName('head')[0].appendChild(script2);";
So basically I am trying to write this :
var script = document.createElement('script');
script.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js';
script.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(script);
var script2 = document.createElement('script');
window.onload = function() {
$(document).ready(function() {
$("#identity").hide();
});
};
script2.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(script2);
What I want to do is that I want my function after window load. Somehow, writing $(document).ready(function() { alone does'nt work. I get an error that $ is not defined (looks like jquery.js is not ready yet).
To avoid this problem I have used window.onload = function() {. But now I am getting error: $(document).ready is not a function. I am really confused here on how to write this thing. Is this the correct approach? Any help/guidance is highly appreciated.
[Edit]
Please note that the following code (without jquery) works fine:
window.onload = function() {
document.getElementById('identity').style.visibility='hidden';
};
[Edit]
Actually I am making a web proxy, where I download page and serve them with custom look and field. The pages does not contain any jquery files nor can I include or write HTML. I can only add my Js dynamically using java etc.
Here is some code that shows how to load a script file dynamically and also delay calling of $(document).ready until that file is loaded:
http://jqfaq.com/how-to-load-java-script-files-dynamically/
The code you use to load jquery.min.js file is called asycnhroniously. Probably this file has not been loaded at the moment you try to execute jquery function.
Therefore you should make sure that the file is loaded using a callback function.
In the following link you can find an example on how to this:
http://blog.logiclabz.com/javascript/dynamically-loading-javascript-file-with-callback-event-handlers.aspx
Also here is a working example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>index</title>
<script type="text/javascript">
function loadScript(sScriptSrc, callbackfunction) {
//gets document head element
var oHead = document.getElementsByTagName('head')[0];
if (oHead) {
//creates a new script tag
var oScript = document.createElement('script');
//adds src and type attribute to script tag
oScript.setAttribute('src', sScriptSrc);
oScript.setAttribute('type', 'text/javascript');
//calling a function after the js is loaded (IE)
var loadFunction = function() {
if (this.readyState == 'complete' || this.readyState == 'loaded') {
callbackfunction();
}
};
oScript.onreadystatechange = loadFunction;
//calling a function after the js is loaded (Firefox)
oScript.onload = callbackfunction;
//append the script tag to document head element
oHead.appendChild(oScript);
}
}
var SuccessCallback = function() {
$("#identity").hide();
}
window.onload = function() {
loadScript('http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js', SuccessCallback)
};
</script>
</head>
<body>
<span id="identity"> This text will be hidden after SuccessCallback </span>
</body>
You should use this code in your scriptTag variable and then you can use eval() function to evaluate the script in this variable. Also you can load the second javascript file in the callback function using jquery's getscript function
Related
I try to add js files dynamically.
I found several guides for that and in Page inspector, they all seem like they work…
However, I cannot reference any code in the newly added files.
My three code examples that look like they work fine... but don't.
//v1
var th = document.getElementsByTagName('head')[0];
var s = document.createElement('script');
s.setAttribute('type', 'text/javascript');
s.setAttribute('src', scriptName);
th.appendChild(s);
DevExpress.localization.loadMessages(RddsDataNavigator_LanguagePack_en);
//v2
var s = document.createElement('script');
s.setAttribute('src', scriptName);
document.head.appendChild(s);
DevExpress.localization.loadMessages(RddsDataNavigator_LanguagePack_en);
//v3
let myScript = document.createElement("script");
myScript.setAttribute("src", scriptName);
document.head.appendChild(myScript);
DevExpress.localization.loadMessages(RddsDataNavigator_LanguagePack_en);
do i have to append the scripts differently or is my reference call wrong / not possible?
the Guides that exactly explain my requirement seem somehow not to work for me ?!
https://www.kirupa.com/html5/loading_script_files_dynamically.htm
Dynamically adding js to asp.net file
Thanks in advance for any help
The three methods to add a script element are essentially the same*.
As dynamically added script elements do not load the resources synchronously, you need to listen to the load event on the global object. DOMContentLoaded is another idea, but it fires too soon as it does not wait for resources to have loaded.
Here is a demo with loading jQuery asynchronously. The output shows the type of the jQuery variable, which will be "function" once that resource is loaded:
let scriptName = "https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.0/jquery.js";
// v3
let myScript = document.createElement("script");
myScript.setAttribute("src", scriptName);
document.head.appendChild(myScript);
console.log("Synchronous, jQuery =", typeof jQuery);
document.addEventListener("DOMContentLoaded", function () {
console.log("After DOMContentLoaded event, jQuery =", typeof jQuery);
});
window.addEventListener("load", function () {
console.log("After load event, jQuery =", typeof jQuery);
});
* The first version also defines the type attribute, but the HTML5 specification urges authors to omit the attribute rather than provide a redundant MIME type.
Consider this working example:
// dyn.js
window.zzz = 1;
<!--index.html-->
<html>
<head>
<script>
function includeJs(url)
{
if (!url) throw "Invalid argument url";
var script = document.createElement("script");
script.src = url;
document.head.appendChild(script);
}
includeJs("dyn.js");
function documentLoaded()
{
alert(window.zzz)
}
</script>
</head>
<body onload="javascript:documentLoaded()">
</body>
</html>
An obvious difference between your code and this is that the sample above loads the script during the document loading and the usage of the script code happens after the document has finished loading.
If you need to do a late-loading of a dynamic script depending on some run-time parameters, here are some options:
If you have control over the dynamically-loading script, you could add a function in your loader script and call it at the last line of the dynamically-loading script:
// dyn.js
window.zzz = 1;
if(typeof(dynamicLoadingFinished) != "undefined") dynamicLoadingFinished();
<!--index.html-->
<html>
<head>
<script>
function includeJs(url)
{
if (!url) throw "Invalid argument url";
var script = document.createElement("script");
script.src = url;
document.head.appendChild(script);
}
function documentLoaded()
{
includeJs("dyn.js");
window.dynamicLoadingFinished = function()
{
alert(window.zzz)
}
}
</script>
</head>
<body onload="javascript:documentLoaded()">
</body>
</html>
Another possible approach would be to use the good old XMLHttpRequest. It will allow you yo either force synchronous loading (which is not advisable because it will block all JavaScript and interactivity during loading, but in certain situations can be of use):
// dyn.js
window.zzz = 1;
<!--index.html-->
<html>
<head>
<script>
function includeJs(url)
{
if (!url) throw "Invalid argument url";
var request = new XMLHttpRequest();
request.open("GET", url, false);
request.send();
var script = document.createElement("script");
script.text = request.responseText;
document.head.appendChild(script);
}
function documentLoaded()
{
includeJs("dyn.js");
alert(window.zzz)
}
</script>
</head>
<body onload="javascript:documentLoaded()">
</body>
</html>
or load the script asynchronously and wait for the request to finish:
// dyn.js
window.zzz = 1;
<!--index.html-->
<html>
<head>
<script>
function includeJs(url, finished)
{
if (!url) throw "Invalid argument url";
var request = new XMLHttpRequest();
request.open("GET", url, true);
request.onreadystatechange = function ()
{
if (request.readyState == 4 || request.readyState == 0)
{
if (request.status == "200")
{
var script = document.createElement("script");
script.text = request.responseText;
document.head.appendChild(script);
return finished();
}
else throw request.responseText;
}
};
request.send();
}
function documentLoaded()
{
includeJs("dyn.js", () => alert(window.zzz));
}
</script>
</head>
<body onload="javascript:documentLoaded()">
</body>
</html>
I believe the AJAX samples could be written also with the more modern fetch API (https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API).
I'm having problems using faqbot.
The normal way of installing it is simple :
before the closing body tag insert this (i changed the keys in this example):
<script type="application/javascript">
var FAQBOT = {
PUBLIC_KEY: "0000000000000000",
AUTO_OPEN: 500
}
</script>
<div id="faqbot-00000000"></div>
<script src="https://faqbot.co/public/js/bundle.js"></script>
This works like a charm.
Now I want to do this using GTM, i'm positive my tag fires (on the DOM Rdy).
I first tried to just put the code inside the custom html tag because that should be a code injector on itself.. this didnt work..
Then I used the DOM Manipulation to achieve it and indeed when i check the source of my page, the tags are right there , BUT the bot doesn't work..
<script>
window.onload = function() {
var s = document.createElement('script');
s.type = 'application/javascript';
var code = 'var FAQBOT = { PUBLIC_KEY:"0000000000000000000",AUTO_OPEN: 500 }';
var d = document.createElement('div');
d.id ='faqbot-00000000';
var s2 = document.createElement('script');
s2.src = 'https://faqbot.co/public/js/bundle.js';
try {
s.appendChild(document.createTextNode(code));
document.body.appendChild(s);
} catch (e) {
s.text = code;
document.body.appendChild(s);
}
document.body.appendChild(d);
document.body.appendChild(s2);
}
</script>
Why is this not working , does it fire too late ?
I tried to put the following code in a custom HTML tag:
<script type="application/javascript">
var FAQBOT = {
PUBLIC_KEY: "0000000000000000",
AUTO_OPEN: 500
}
</script>
<div id="faqbot-00000000"></div>
<script src="https://faqbot.co/public/js/bundle.js"></script>
using this custom event as a trigger:
gtm.dom
and it seems to work properly:
Request URL: https://faqbot.co/public/js/bundle.js
Request Method: GET
Status Code: 200 OK
I'm trying to implement a map widget from 'Awesome Table' in the source code of an open-source CRM.
The piece of code I have to add is
<div data-type="AwesomeTableView" data-viewID="-KLtnY5OHJPgnEOX1bKf"></div>
<script type="text/javascript" src="https://awesome-table.com/AwesomeTableInclude.js"></script>
I try to do it with jQuery like this :
$(document).ready(function () {
var div = "<div data-type=\"AwesomeTableView\" data-viewID=\"-KLtnY5OHJPgnEOX1bKf\"></div>";
var scr = "<script type=\"text/javascript\" src=\"https://awesome-table.com/AwesomeTableInclude.js\"></script>";
$("body").append(div, scr);
});
But I got a problem : in the console the src appears like this:
http://127.0.0.1/edsa-EspoCRM-4.1.6/api/v1/https://awesome-table.com/AwesomeTableInclude.js
See what's wrong...
Before I tried with javascript but I had an almost identical result (nothing appeared and the script didn't worked)
var div = document.createElement("div");
div.id = "lacarte";
div.dataset.type = "AwesomeTableView";
div.dataset.viewid = "-KLtnY5OHJPgnEOX1bKf";
div.style.height = "200px";
var scr = document.createElement("script");
scr.type = "text/javascript";
scr.src = "https://awesome-table.com/AwesomeTableInclude.js";
var page = document.getElementById("content");
page.appendChild(div);
page.appendChild(scr);
If you have any idea?
You should use $.getScript to load and execute scripts dynamically.
And if your script is a prerequisite for your div, you can use the callback executed when the script is loaded end executed, to append the div.
Here is the documentation: http://api.jquery.com/jQuery.getScript/
$(document).ready(function () {
$.getScript("https://awesome-table.com/AwesomeTableInclude.js", function (data, textStatus, jqxhr) {
var div = '<div data-type="AwesomeTableView" data-viewID="-KLtnY5OHJPgnEOX1bKf"></div>';
$("body").append(div);
});
});
You have to escape the slashes in the script src, type and closing of the script /:
$(document).ready(function () {
var div = '<div data-type="AwesomeTableView" data-viewID="-KLtnY5OHJPgnEOX1bKf"></div>';
var scr = '<script type="text\/javascript" src="https:\/\/awesome-table.com\/AwesomeTableInclude.js"><\/script>';
$("body").append(div, scr);
});
The following code adds the two elements exactly as shown.
function byId(id){return document.getElementById(id);}
function newEl(tag){return document.createElement(tag);}
window.addEventListener('load', onDocLoaded, false);
function onDocLoaded(evt)
{
var div = newEl('div');
div.setAttribute('data-type', 'AwesomeTableView');
div.setAttribute('data-viewID', '-KLtnY5OHJPgnEOX1bKf');
var script = newEl('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', 'https://awesome-table.com/AwesomeTableInclude.js');
document.body.appendChild(div);
document.body.appendChild(script);
}
The resulting source is: https://awesome-table.com/AwesomeTableInclude.js
As seen here:
<body>
<div data-type="AwesomeTableView" data-viewid="-KLtnY5OHJPgnEOX1bKf"></div><script type="text/javascript" src="https://awesome-table.com/AwesomeTableInclude.js"></script>
</body>
Situation:
jQuery is dynamically loaded together with other scripts by one file javascripts.js in the <head> section of the html file
Each html file has it's own javascript code executed on jQuery(document).ready() in the <body> section of the html file
Problem:
Error: jQuery is not defined for javascript in the <body> section
Modifying the html file is not an option (+1000 files with same problem)
Example html file:
<html>
<head>
<title>JS test</title>
<script src="javascripts.js" type="text/javascript"></script>
</head>
<body>
<input type="text" class="date">
<script>
jQuery(document).ready(function() { // Error: jQuery not defined
jQuery('.date').datepicker();
});
</script>
</body>
</html>
javascripts.js:
// Load jQuery before any other javascript file
function loadJS(src, callback) {
var s = document.createElement('script');
s.src = src;
s.async = true;
s.onreadystatechange = s.onload = function() {
var state = s.readyState;
console.log("state: "+state);
if (!callback.done && (!state || /loaded|complete/.test(state))) {
callback.done = true;
callback();
}
};
document.getElementsByTagName('head')[0].appendChild(s);
}
loadJS('javascripts/jquery-1.8.3.min.js', function() {
var files = Array(
'javascripts/functions.js',
'javascripts/settings.js'
);
if (document.getElementsByTagName && document.createElement) {
var head = document.getElementsByTagName('head')[0];
for (i = 0; i < files.length; i++) {
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', files[i]);
script.async = true;
head.appendChild(script);
}
}
});
This is happening, as many in the comments have pointed out, because you are loading jQuery asynchronously. Asynchronous means the rest of the code is executed, and so your document-ready handler (DRH) line is running before jQuery is present in the environment.
Here's a really hacky way of resolving this. It involves making a temporary substitute of jQuery whose job is just to log the DRH callbacks until jQuery has arrived. When it does, we pass them in turn to jQuery.
JS:
//temporary jQuery substitute - just log incoming DRH callbacks
function jQuery(func) {
if (func) drh_callbacks.push(func);
return {ready: function(func) { drh_callbacks.push(func); }};
};
var $ = jQuery, drh_callbacks = [];
//asynchronously load jQuery
setTimeout(function() {
var scr = document.createElement('script');
scr.src = '//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js';
document.head.appendChild(scr);
scr.onload = function() {
$.each(drh_callbacks, function(i, func) { $(func); });
};
}, 2000);
HTML:
jQuery(document).ready(function() { alert('jQuery has loaded!'); });
Fiddle: http://jsfiddle.net/y7aE3/
Note in this example drh_callbacks is global, which is obviously bad. Ideally hook it onto a namespace or something, e.g. mynamespace.drh_callbacks.
I believe this simple solution should do the trick. The changed line in the html changes the jquery onload function to a regular function. The jquery onload function will sometimes happen before the jquery is loaded and we can't have that. It's unreliable. We need that function not to execute on page load, but AFTER the jquery has loaded.
To that end, the three lines I've added in the javascript.js are inside the code that is executed immediately after jQuery has finished loading. They test to see if the pageLoaded function has been defined (so you don't have to put one on every page, only the ones that need it) and then execute it if it's there.
Now, because the change to the HTML is simple, you can just do a regex search and replace on those 1000 files to fix them. Tools like Sublime, Eclipse or TextPad are suited for that task.
Cheers!
Example html file:
<html>
<head>
<title>JS test</title>
<script src="javascripts.js" type="text/javascript"></script>
</head>
<body>
<input type="text" class="date">
<script>
function pageLoaded() { // changed
jQuery('.date').datepicker();
} // changed
</script>
</body>
</html>
javascripts.js:
// Load jQuery before any other javascript file
function loadJS(src, callback) {
var s = document.createElement('script');
s.src = src;
s.async = true;
s.onreadystatechange = s.onload = function() {
var state = s.readyState;
console.log("state: "+state);
if (!callback.done && (!state || /loaded|complete/.test(state))) {
callback.done = true;
callback();
}
};
document.getElementsByTagName('head')[0].appendChild(s);
}
loadJS('javascripts/jquery-1.8.3.min.js', function() {
var files = Array(
'javascripts/functions.js',
'javascripts/settings.js'
);
if (document.getElementsByTagName && document.createElement) {
var head = document.getElementsByTagName('head')[0];
for (i = 0; i < files.length; i++) {
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', files[i]);
script.async = true;
head.appendChild(script);
}
}
if( typeof(pageLoaded) == "function" ){ // added
pageLoaded(); // added
} // added
});
You should try following workaround to load scripts synchronously:
function loadJS(src, callback) {
document.write('<scr'+'ipt src="'+src+'"><\/scr'+'ipt>');
callback();
}
IMPORTANT to note: this function should be called always before DOM is fully rendered.
I'm still learning by making my own loader; here's my progress:
<!DOCTYPE html>
<html>
<head>
<title>test</title>
(function( $ ){
$.plugin = {
loadJS: function(src, onload, onerror){
var script = document.createElement("script");
script.type = "text/javascript";
script.src = src;
script.onload = onload;
script.onerror = onerror;
script.onreadystatechange = function () {
var state = this.readyState;
if (state === 'loaded' || state === 'complete') {
script.onreadystatechange = null;
onload();
}
};
document.body.appendChild(script);
},
loader: function(o) {
var loaded = ({js:[],css:[]});
// http://www.crockford.com/javascript/private.html
var that = this;
var phase = 0;
$.each(o["js"], function(key,src) {
that.loadJS(src,
function(){
loaded['js'].push(src);
});
});
console.log(loaded['js'].length)
// IF JS ALL LOADED, this is the main problem
if (loaded['js'].length == o["js"].length) {
alert('problem solved')
that.loadJS(o["script"]);
};
}
};
})( jQuery );
</script>
</head>
<body>
<script>
$(document).ready(function() {
$.plugin.loader({
js: [
'1.js', // async
'2.js', // async
'3.js', // async
'4.js' // async
],
script: '5.js', // after js loaded
debug: 1
});
});
</script>
</body>
</html>
the problem is i still dont get how stuff work in js. above the same it will load my js randomly as its async* assuming its all alert('this is x.js loaded') inside the 1-5.js
something like
// check goes randomly here
1.js or 1 js loaded
3.js 2 js loaded
2.js 3 js loaded
4.js 4 js loaded
// it should be here
so the logic is when my all js is load if (loaded['js'].length == o["js"].length) {alert('problem solved')}; should work. but it doent attach to the event somehow.
How can we check if all my js is loaded?
Looks like your check to see if they are all loaded is being run at the end of the loader function, so it will run immediately the async calls have been started. You need to move that check part into the the callback function thats passed to the .each function.
I ran into problems under IE 6 with a large JavaScript heavy app where occasionally external script loading was aborted without any discernable network trouble, so I ended up doing
<script src="sourcefile-1.js"></script>
...
<script src="sourcefile-n.js"></script>
<script src="last-loaded.js"></script>
<body onload="if(!window.allLoaded){/*reload*/}">...</body>
where last-loaded.js just did
window.allLoaded = true;
and where the reload code would redirect to an error page if a reload hadn't fixed the problem after a few tries.
This isn't the dynamic loader problem, but a similar approach should work with a dynamic loader as long as you can identify a point after which all external code should have loaded and you can run a very simple inlined script at that point.