This is really strange and I've never encountered it before. I have a javascript script tag that I'm using on one of my xenforo pages, but it's not showing up so I commented it out for testing. Here's what's weird:
When I comment the code, view page source shows the code as commented, but when I go to uncomment it again then page source shows no trace of it and it's just removed.
Has anyone ever experienced this? This is the only javascript tag I can see that's doing this, but I can add anything else in its place and it shows properly, but given the fact that it shows when commented I just can't seem to figure out what's going on.
Does this sound familiar to anyone?
UPDATE: adding code
<head>
<script type="text/javascript">
console.log('test function')
</script>
<script type="text/javascript">
(function(){
console.log('in function now');
var site_id = 0000;
var data_site_id = 0;
var sn_cb = new Date().getMonth();
var snack_hb = document.createElement('script');
snack_hb.src = 'https://cdn-header-bidding.snack-media.com/assets/js/snack-loader/'+site_id+'?cb='+sn_cb;
snack_hb.id = 'snack_ads';
if(data_site_id){
snack_hb.setAttribute('data-site-id',data_site_id);
}
console.log(snack_hb);
document.body.appendChild(snack_hb);
snack_hb.onerror = function(){
document.body.removeChild(snack_hb);
var snack_hb2 = document.createElement('script');
snack_hb2.src = 'https://cdn2-header-bidding.snack-media.com/assets/js/snack-loader/'+site_id+'?cb='+sn_cb;
snack_hb2.id = 'snack_ads';
if(data_site_id){
snack_hb2.setAttribute('data-site-id',data_site_id);
}
document.body.appendChild(snack_hb2);
};
})();
</script>
</head>
If I run this, then I see the 'test function' print in console, but the script below it literally doesn't exist on the page
I am trying to change the entire layout of my site when the submit button is pressed. So I find it easier to switch between two JS scripts rather than trying to cram everything into one, but the page isn't responding to change in script, even though the console shows the change in the script reference. I have added the relevant snapshots below. Thank you for reading my problem...
<script src="prac.js"></script>
button.addEventListener('click', function(e){
document.getElementsByTagName('script')[0].src = 'main.js';
console.log(document.getElementsByTagName('script')[0]);
});
EDIT : I am new to this forum so I did not know about the code insertion. I'm sorry about that. Also the console message essentially showed an expexted change in script reference but the website layout did not change.
EDIT 2 : The suggested deletion and appending of new script does indeed work, but can someone explain why altering the current script tag ends in failure?
Remove the script element from DOM and add another script like this:
<html>
<head>
<script src="demo1.js"></script>
</head>
<script>
window.onload = function(){
var firstScript = document.getElementsByTagName('script')[0]; //get first script
document.getElementsByTagName('head')[0].removeChild(firstScript); //removing it from DOM <head> tag
var secondScript = document.createElement('script'); //creating another script
secondScript.src = "demo2.js"; //adding source to it
document.getElementsByTagName('head')[0].appendChild(secondScript); //adding script to DOM
};
</script>
</html>
Okay so I'm trying to load a backup .js file synchronously in the event of a script dependency being unavailable, and everything seems to be working fine except for the fact that said script doesn't actually load, even though the element itself with the src is created:
[etc]
<head>
<script id = 'self'>
if (typeof jQuery === 'undefined') {
function insertAfter(referenceNode, el) {
referenceNode.parentNode.insertBefore(el, referenceNode.nextSibling);
}
var loadjq = document.createElement('script');
// backup CDN
loadjq.src = 'https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js';
loadjq.type = 'text/javascript';
// loadjq.async = false;
insertAfter(document.getElementById('self'), loadjq);
}
</script>
// element IS created here: <script src = 'https://ajax.google...' type = 'text/...'></script>
// but nothing is executed
<script>
console.log($); // Reference Error
</script>
</head>
[etc]
Do note that I have not put this within a DOMContentLoaded event or anything, but I feel this should be working.
I tested with Chrome and Firefox, and it's not a caching error. Any suggestions?
Note, this isn't ideal, however if you absolutely need to you can use the following.
Use document.write to achieve this synchronously.
<script>
document.write(`jQuery is: ${typeof(jQuery)}.`);
</script>
<script>
document.write(`<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"><\/script>`);
</script>
<script>
document.write(`jQuery is: ${typeof(jQuery)}.`);
</script>
Note that you cannot have </script> in the string directly as this will terminate the actual script tag.
I have a script that dynamically loads jQuery, by inserting it in <head> element:
// pseudo code
headElelement.insertBefore(script, firstChild);
However, immediately after that call, I start to use jQuery, but at that moment it is undefined. How is that possible ?
That's because jQuery is not fully loaded yet. You may need to execute your jQuery code only after jQuery has been loaded by attaching an event handler to the onload event of your dynamically created script element as shown below.
script.onload = function() {
// Put your jQuery code here.
console.log(jQuery);
};
Cross-Browser solution for supporting older browsers like IE8 and below:
script.onload = script.onreadystatechange = function(event) {
event = event || window.event;
if (event.type === "load" || (/loaded|complete/.test(script.readyState))) {
script.onload = script.onreadystatechange = null;
// Put your jQuery code here.
console.log(jQuery);
}
};
If you would post your relevant code it would be easier ;-) but anyways, this is one possible way of doing it:
<html>
<head>
<script type="text/javascript" src="path_to_js/jquery.js"></script>
<script type="text/javascript" src="path_to_js/your_js_code.js"></script>
...
</head>...
and in the file your_js_code.js you'll have:
... /* All your modules and functions here */
/* DOM loading ready */
$(document).ready(function () {
call_your_methods_here();
});
By the way, it is usually better to load your JS files at the very end of the <body> in the HTML, that way your HTML starts displaying first and the user "sees" your page faster, while the JS code is still loading.
There's a div called "Content":
<div id="content"></div>
It should be filled with data from a PHP file, by AJAX, including a <script> tag. However, the script inside this tag is not being executed.
<div id="content"><!-- After AJAX loads the stuff that goes here -->
<script type="text/javascript">
//code
</script>
<!-- More stuff that DOES work here -->
</div>
I used this code, it is working fine
var arr = MyDiv.getElementsByTagName('script')
for (var n = 0; n < arr.length; n++)
eval(arr[n].innerHTML)//run script inside div
JavaScript inserted as DOM text will not execute. However, you can use the dynamic script pattern to accomplish your goal. The basic idea is to move the script that you want to execute into an external file and create a script tag when you get your Ajax response. You then set the src attribute of your script tag and voila, it loads and executes the external script.
This other StackOverflow post may also be helpful to you: Can scripts be inserted with innerHTML?.
If you load a script block within your div via Ajax like this:
<div id="content">
<script type="text/javascript">
function myFunction() {
//do something
}
myFunction();
</script>
</div>
... it simply updates the DOM of your page, myFunction() does not necessarily get called.
You can use an Ajax callback method such as the one in jQuery's ajax() method to define what to execute when the request finishes.
What you are doing is different from loading a page with JavaScript included in it from the get-go (which does get executed).
An example of how to used the success callback and error callback after fetching some content:
$.ajax({
type: 'GET',
url: 'response.php',
timeout: 2000,
success: function(data) {
$("#content").html(data);
myFunction();
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert("error retrieving content");
}
Another quick and dirty way is to use eval() to execute any script code that you've inserted as DOM text if you don't want to use jQuery or other library.
Here is the script that will evaluates all script tags in the text.
function evalJSFromHtml(html) {
var newElement = document.createElement('div');
newElement.innerHTML = html;
var scripts = newElement.getElementsByTagName("script");
for (var i = 0; i < scripts.length; ++i) {
var script = scripts[i];
eval(script.innerHTML);
}
}
Just call this function after you receive your HTML from server. Be warned: using eval can be dangerous.
Demo:
http://plnkr.co/edit/LA7OPkRfAtgOhwcAnLrl?p=preview
This 'just works' for me using jQuery, provided you don't try to append a subset the XHR-returned HTML to the document. (See this bug report showing the problem with jQuery.)
Here is an example showing it working:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>test_1.4</title>
<script type="text/javascript" charset="utf-8" src="jquery.1.4.2.js"></script>
<script type="text/javascript" charset="utf-8">
var snippet = "<div><span id='a'>JS did not run<\/span><script type='text/javascript'>" +
"$('#a').html('Hooray! JS ran!');" +
"<\/script><\/div>";
$(function(){
$('#replaceable').replaceWith($(snippet));
});
</script>
</head>
<body>
<div id="replaceable">I'm going away.</div>
</body>
</html>
Here is the equivalent of the above: http://jsfiddle.net/2CTLH/
Here is a function you can use to parse AJAX responses, especially if you use minifiedjs and want it to execute the returned Javascript or just want to parse the scripts without adding them to the DOM, it handles exception errors as well. I used this code in php4sack library and it is useful outside of the library.
function parseScript(_source) {
var source = _source;
var scripts = new Array();
// Strip out tags
while(source.toLowerCase().indexOf("<script") > -1 || source.toLowerCase().indexOf("</script") > -1) {
var s = source.toLowerCase().indexOf("<script");
var s_e = source.indexOf(">", s);
var e = source.toLowerCase().indexOf("</script", s);
var e_e = source.indexOf(">", e);
// Add to scripts array
scripts.push(source.substring(s_e+1, e));
// Strip from source
source = source.substring(0, s) + source.substring(e_e+1);
}
// Loop through every script collected and eval it
for(var i=0; i<scripts.length; i++) {
try {
if (scripts[i] != '')
{
try { //IE
execScript(scripts[i]);
}
catch(ex) //Firefox
{
window.eval(scripts[i]);
}
}
}
catch(e) {
// do what you want here when a script fails
// window.alert('Script failed to run - '+scripts[i]);
if (e instanceof SyntaxError) console.log (e.message+' - '+scripts[i]);
}
}
// Return the cleaned source
return source;
}
If you are injecting something that needs the script tag, you may get an uncaught syntax error and say illegal token. To avoid this, be sure to escape the forward slashes in your closing script tag(s). ie;
var output += '<\/script>';
Same goes for any closing tags, such as a form tag.
This worked for me by calling eval on each script content from ajax .done :
$.ajax({}).done(function (data) {
$('div#content script').each(function (index, element) { eval(element.innerHTML);
})
Note: I didn't write parameters to $.ajax which you have to adjust
according to your ajax.
I had a similiar post here, addEventListener load on ajax load WITHOUT jquery
How I solved it was to insert calls to functions within my stateChange function. The page I had setup was 3 buttons that would load 3 different pages into the contentArea. Because I had to know which button was being pressed to load page 1, 2 or 3, I could easily use if/else statements to determine which page is being loaded and then which function to run. What I was trying to do was register different button listeners that would only work when the specific page was loaded because of element IDs..
so...
if (page1 is being loaded, pageload = 1)
run function registerListeners1
then the same for page 2 or 3.
My conclusion is HTML doesn't allows NESTED SCRIPT tags. If you are using javascript for injecting HTML code that include script tags inside is not going to work because the javascript goes in a script tag too. You can test it with the next code and you will be that it's not going to work. The use case is you are calling a service with AJAX or similar, you are getting HTML and you want to inject it in the HTML DOM straight forward. If the injected HTML code has inside SCRIPT tags is not going to work.
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"></head><body></body><script>document.getElementsByTagName("body")[0].innerHTML = "<script>console.log('hi there')</script>\n<div>hello world</div>\n"</script></html>
you can put your script inside an iframe using the srcdoc attribute
example:
<iframe frameborder="0" srcdoc="
<script type='text/javascript'>
func();
</script>
</iframe>
Another thing to do is to load the page with a script such as:
<div id="content" onmouseover='myFunction();$(this).prop( 'onmouseover', null );'>
<script type="text/javascript">
function myFunction() {
//do something
}
myFunction();
</script>
</div>
This will load the page, then run the script and remove the event handler when the function has been run. This will not run immediately after an ajax load, but if you are waiting for the user to enter the div element, this will work just fine.
PS. Requires Jquery