I am having an issue where I am loading ajax HTML content into an element on my page using JavaScript, and trying to execute JavaScript within the loaded content, which is not working.
I am not (and cannot) use jQuery on this project.
The JavaScript I am using to load the ajax content look like:
var loadedobjects = "";
var rootDomain = "http://" + window.location.hostname;
function ajaxPage(url, containerId){
var pageRequest = false;
pageRequest = new XMLHttpRequest();
pageRequest.onreadystatechange = function(){
loadpage(pageRequest, containerId);
}
preventCache = (url.indexOf("?")!=-1)? "&"+new Date().getTime() : "?"+new Date().getTime();
pageRequest.open('GET', url+preventCache, true);
pageRequest.send(null);
}
function loadpage(pageRequest, containerId){
if (pageRequest.readyState == 4 && (pageRequest.status==200 || window.location.href.indexOf("http") == -1)){
document.getElementById(containerId).innerHTML = pageRequest.responseText;
}
}
As you can see, I am passing a URL (of an HTML page) to the function ajaxPage()
The ajaxPage() function is being called in a separate .js file, like so:
ajaxPage('test.html', 'ajax-wrapper');
Which is working, test.html is being loaded in the element with id 'ajax-wrapper', but no JavaScript in the test.html page is working.
Here is what the test.html page looks like (just plain HTML):
<div class="t-page-title">
View Thread
</div>
<script>
alert('hello');
</script>
Even a simple alert('hello'); on the loaded HTML is not firing. The page is not being cached, so that is not the issue. I would know what to do if I was using jQuery, but I am a bit stumped with finding a JavaScript only solution. Any suggestions?
When you use innerHTML, the tags get copied to the destination element, but scripts are not executed. You need an additional eval step to execute the scripts.
jQuery has a function for that called globalEval, without jQuery you'll need to write your own.
[Update] Here is a variation with an iframe that might help address your issue: http://jsfiddle.net/JCpgY/
In your case:
ifr.src="javascript:'"+pageRequest.responseText+"'";
The standard behavior with a div: http://jsfiddle.net/JCpgY/1/
Related
I am trying to get a script from another website using jQuery then document.write it
here is my code
var url = "https://code.jquery.com/jquery-1.10.2.js";
var dam = $.getScript(url);
document.write(dam);
But this doesn't work!!
all what I get on the page is [object Object]
Can this be achieved without XHR?
jsfiddle
Don't use document.write, it does not do what you think it does. What it does not do is write some data at the end of the document. What it does instead, is pipe data into the current write stream. And if there is no write stream, it will make a new one, resetting the document's content. So calling document.write(dam) means you just wiped your document. document.write is a low level JS function from an earlier era of JavaScript, don't use it.
Instead, you want to use modern DOM manipulation functions, so in jQuery, that's stuff like:
$(document.head).append($("<script>").attr("src", url));
where
$("<script>")
builds a new script element,
$(...).attr("src", url)
sets the "src" attribute to what you need it to be, and:
$(document.head).append(...)
or
$(document.body).append(...)
to get the script loaded into your document. If it's a plain script with src attribute, it can basically go anywhere, and if it's a script with text content that should run, you can only make that happen through document.head.
Although if it's just a script you need to load in and run, you can use getScript, but then you don't need to do anything else, it's just:
var url = "https://code.jquery.com/jquery-1.10.2.js";
jQuery.getScript(url);
Done, jQuery will load the script and execute it. Nothing gets returned.
Of course, the code you're showing is loading jQuery, using jQuery, so that's kind of super-odd. If you just want to load jQuery on your page, obviously you just use HTML:
<!doctype html>
<html>
<head>
...
</head>
<body>
...
<script src="http://https://code.jquery.com/jquery-1.10.2.js"></script>
</body>
</html>
with the script load at the end so the script load doesn't block your page. And then finally: why on earth are we loading jQuery version 1.x instead of 2.x? (if you need to support IE8: that's not even supported by Microsoft anymore, so you probably don't need to).
And finally, if we don't want to load the script, but we really just want its content, as plain text, there's only a million answers on Stackoverflow already that tell you how to do that. With jQuery, that's:
$.get("http://https://code.jquery.com/jquery-1.10.2.js", function(data) {
$(document.body).append($("div").text(data));
});
But you knew that already because that's been asked countless times on Stackoverflow and you remembered to search the site as per the how to ask instructions before asking your question, right?
executing the script on the page is not my goal!. I want to get the
script content and put it a div (USING JAVASCRIPT - NO XHR) , is that
possible ?
Try utilizing an <iframe> element
<div>
<iframe width="500" height="250" src="https://code.jquery.com/jquery-1.10.2.js">
</iframe>
</div>
jsfiddle http://jsfiddle.net/snygv469/3/
Make it easier... use my fiddle
http://jsfiddle.net/wwwfzya7/1/
I used javascript to create an HTML element
var url = "https://code.jquery.com/jquery-1.10.2.js";
var script = document.createElement("SCRIPT"); //creates: <script></script>
script.src = url; //creates: <script src="long_jquery_url.js"></script>
document.body.appendChild(script); //adds the javascript-object/html-element to the page.!!!
Use this way, it can fix your problems.
$.get( "https://code.jquery.com/jquery-1.10.2.js", function( data ) {
alert(data);
});
You can try adding
<script src="http://code.jquery.com/jquery-1.8.3.min.js" ></script>
Then an AJAX call, but it pulls data from CACHE. It looks like an AJAX but when <script> is added file goes in cache, then read from cache in the ajax. In cases where it is not stored in cache read it using normal AJAX.
jQuery.cachedScript = function(url, options) {
// Allow user to set any option except for dataType, cache, and url
options = $.extend(options || {}, {
dataType: "text",
cache: true,
url: url
});
// Use $.ajax() since it is more flexible than $.getScript
// Return the jqXHR object so we can chain callbacks
return jQuery.ajax(options);
};
$(document).on('ready', function() {
// Usage
$.cachedScript("http://code.jquery.com/jquery-1.8.3.min.js").done(function(script, textStatus) {
console.log(script);
});
});
Normal Solution
If you are ready to use AJAX look at this fiddle
How to fetch content of remote file and paste it on your document and execute that js code
I guess you want to get content written on remote file and want to write that content in your HTML. to do this you can use load() function.
To do this follow the following steps:
1. Create a file index.html Write the following code in it:
<pre id="remote_script"></pre>
<script>
$(document).ready(function() {
//var url = "https://code.jquery.com/jquery-1.10.2.js";
var url = "remote_script.html";/* For testing*/
$('#remote_script').load(url,function(){
eval($('#remote_script').text()); /* to execute the code pasted in #remote_script*/
});
});
</script>
2. Create another file remote_script.html for testing write alert('a'); in it without any <script> tag and run the above code.
i have a problem with my page.
When i click on a link on my page, it will load a external html inside a div in the page. the div with the id="div1". (AJAX)
It works perfect.
the external html-page which has been loaded includes a div with the id="rex".
My Problem is:
i have a script, which must add content in the div (with the id="rex")
i wrote the script in the external file, but it doesn't run.
probably i must write my script in the page and not in the external html-file.
here the script Number 3:
$('#rex').ready(function() {
var url="genredetail.php";
var activitydetail = sessionStorage.activitydetail;
$.getJSON(url,function(json){
$.each(json.genredetail,function(i,item){
if(item.name == activitydetail){
$('<p class="excerpt">' + item.beschreibung3 + '</p>').appendTo('#rex');
}
});
});
});
This script must run when the external file (with the div id="rex") has been loaded. But it doesn't :-(
What can i do? Is the problem that the script runs before the page get the <div id="rex">?
Thanks in advance, and sorry my bad english :-S
A picture for more clearness
the script number 1 makes the link.
when i click on a link, the script number 2, let the site load in the div1.
The script number 3 must fill the div="rex" with informations. but it doesn't run.
try onload
$('div').on("load","#rex",function() {
do something
});
Try using setInterval, so it check the element rex every 0.5 s
var myInterval = setInterval(function(){
if ($("#rex").length)
{
var url="genredetail.php";
var activitydetail = sessionStorage.activitydetail;
$.getJSON(url,function(json){
$.each(json.genredetail,function(i,item){
if(item.name == activitydetail){
$('<p class="excerpt">' + item.beschreibung3 + '</p>').appendTo('#rex');
clearInterval(myInterval);
}
}, 500);
You need to reload the script if it is already loaded. As you said you are loading the external html inside a div, does it include the external js file you are using? if not please include it.
I have a site and I want it to randomly load a different HTML5 Javascript animation each time the page is loaded, JavaScript is by far one of the weakest of my skills and I appreciate any help in advance and if this happens to be duplicate (I've tried searching) then please vote for the question to be closed.
Basically the method I have used is a dirty one and most likely the reason its not working, basically I tried randommath and had no luck and put this down to my JS skills being extremely weak, the alternative method which looked easier doesn't work either and this is basically inserting a HTML on page load, so for example a.html and b.html which both contain different scripts.
This is what my code looks like:
HTML
<html>
<head>
<script src="js/insert.js"></script><!-- This inserts the Random Page -->
</head>
<body onload="loadExternalHTMLPage()">
<div id="injectjs"> </div>
<canvas="id"> </canvas>
<script src="js/animation-lib-pageA.js"></script><!--Library for pageA -->
<script src="js/animation-lib-pageB.js"></script><!--Library for pageB -->
</body>
</html>
Inject.js
function loadExternalHTMLPage() {
var xmlhttp;
var pagesToDisplay = ['a.html', 'b.html'];
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
} else {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
document.getElementById("jsinsert").innerHTML = xmlhttp.responseText;
}
}
var randomnumber = Math.floor(Math.random() * pagesToDisplay.length);
xmlhttp.open("GET", pagesToDisplay[randomnumber], true);
xmlhttp.send();
}
Most JS Guru's should be able to see that I'm randomly inserting a.html and b.html on page load, now this works but the problem is the scripts contained within a.html and b.html are not executing. (using firebug I can clearly see that the scripts are being inserted as intended).
so for example a and b looks like:
a.html
<script> window.onload = function () { }</script>
b.html
<script> window.onload = function () { } </script>
Basically the code within A and B are valid and work fine within this insert and I've filled the above examples as just a placeholder. A and B both contain JavaScript that executes animation contained within the canvas but it doesn't work at present and I suspect its something to do with the fact I'm loading the scripts after the page has been loaded. Thanks in advance.
You can randomly load the html for A or B and then run its animation.
This example uses jQuery which makes the task of loading remote html easier. Here is a link to the jquery .load function which replaces an existing elements html with the downloaded html: http://api.jquery.com/load/ If you want pure javascript, you can use that [messier!] alternative, but the logic remains the same.
These are the steps:
Be sure the web page has loaded,
Randomly pick A or B to load/execute,
Replace the html in #injectjs with htmlForA or htmlForB,
Wait until the html has been fully replaced,
Run the appropriate animationA or animationB.
Here is starter code. (Be sure you include the jQuery library)
<script>
window.onload(){
// randomly load html+animation A or B
if(Math.random()<.50){
$('#injectjs').load(
'yourSite.com/HtmlForA.html', // first load the html for A
function(){ animationA(); } // then run animationA
);
}else{
$('#injectjs').load(
'yourSite.com/HtmlForB.html', // first load the html for B
function(){ animationB(); } // then run animationB
);
}
}
</script>
You can always use eval() to execute the content you downloaded ... :) (not recommended).
Or you can modify the html page on server to include the random script you want before serving the page to the user (you don't state platform) since it's anyways changed at page load.
Edit: Just found out this is a chrome problem, the code works fine in firefox
I have an iframe on a webpage that shows a book formatted as html. I would like to insert some javascript within this iframe to make the book more dynamic (e.g. click on sentences, show animations etc). The iframe content is in the same domain as the parent page.
I can insert the javascript into the iframe but get an error calling a function in the inserted javascript. I've described the different bits of code below:
My parent page javascript is:
function iframeLoaded()
{
var iFrameID = document.getElementById('preview-iframe');
var jsLink = iFrameID.contentDocument.createElement("script");
jsLink.src="/tests/iframeAPI.js";
jsLink.type = 'text/javascript';
iFrameID.contentDocument.head.appendChild(jsLink);
iFrameID.contentWindow.initialiseApi()
}
and the html containing the iframe is:
<iframe id="preview-iframe" width="640" height="240" frameborder="0" src="./testpage.htm" onload="iframeLoaded()" scrolling="no"></iframe>
The contents of iframeAPI.js is:
window.initialiseApi = function() { alert("Hello world") }
Looking at the iFrame's html in the browser shows that the iFrameAPI.js tag is inserted ok into the iframe head, but I don't get the alert popup when the page is loaded. The error appears on the following line:
iFrameID.contentWindow.initialiseApi()
Uncaught TypeError: Object [object Window] has no method 'initialiseApi'
However I can run this line in the browser's javascript console and the alert popup works fine.
Any help would be much appreciated.
Thanks,
Brian
Edit: I've just tried with an onload event to make sure the page is loaded and I still have the problem:
My parent page javascript is now :
function iframeLoaded()
{
var iFrameID = document.getElementById('preview-iframe');
var jsLink = iFrameID.contentDocument.createElement("script");
jsLink.src="/tests/iframeAPI.js";
jsLink.type = 'text/javascript';
iFrameID.contentDocument.head.appendChild(jsLink);
jsLink.onLoad= iFrameLoaded();
}
function iFrameLoaded()
{
alert("Iframe loaded"); // Alert works ok
var iFrameID = document.getElementById('preview-iframe');
iFrameID.contentWindow.initialiseApi(); // Same error message on this line
}
It sounds like you are trying to use the function before the content has loaded.
try this instead:
var t = setTimeout(iFrameID.contentWindow.initialiseApi(),500);
This will wait half a second before trying the function which should give the page tiem to load. Delay times are given in milliseconds.
An even better approach is to try using Jquery and its ready() method but this requires the jquery library to be loaded as well. Its well worth it though in my opinion, see http://api.jquery.com/ready/.
You would try something like:
$("body",iFrameID.contentWindow.document).ready(iFrameID.contentWindow.initialiseApi())
You're executing it right away without giving the script a chance to load. Hook up an onload event to your script block and run your main function then.
Try, in the page included in the iFrame, accessing the main page by doing something like:
window.parent.xyz = something;
Where something is what you want exposed to the main page. Could be a function or an object of functions. Now in the main page you can just do:
something(); // or something.somefunction();
You could also send window references, I think, but I have not tried that.
The easiest way is to call the initialiseApi function in the iframeAPI.js itself as it will be called as soon as it's loaded. The iframeAPI.js could look like that:
function initialiseApi() {
alert("Hello world");
}
initialiseApi();
There is no callback or timeout needed.
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