I'm developing a website using PHP,MySQL,AJAX,Javascript,HTML5,css3... What I'm trying to do is load an external html file and have the Javascript that is embedded execute.
The ajax load I'm trying to use is this
<pre><code>
$(document).ready(function(){
$(".meny a").click(function(){
page=$(this).attr("href");
$.ajax({
url: "includes/"+page,
cache:false,
success:function(html){
afficher(html);
},
error:function(XMLHttpRequest,textStatus,errorThrown){
alert(testStatus);
}
})
return false;
});
});
function afficher(data){
$("#main").fadeOut(500,function(){
$("#main").empty();
$("#main").append(data);
$("#main").fadeIn(1000);
})
}
</code></pre>
when the content of the page is loaded directly javascript(or jQuery) functions working fine, but when the div tag that found in the content of another page loaded by AJAX, javascript(or jQuery) not working on this div, while jquery scripts are already stored in the "head" tag .
I think that the problem is the AJAX, since it's working fine when I call directly the page which contains the Javascript.
#kieran
no i never try this trick ! i think i figure out the real problem !
jQuery actually removes any javascript it encounters in an ajax call. They do it on purpose to prevent issues in IE. Here is the actual snippet from jQuery 1.8.3 (lines 7479-7481):
// inject the contents of the document in,removing the scripts
// to avoid any 'Permission Denied' errors in IE
.append( responseText.replace( rscript, "" ) )
In line 7291 is where it defines the rscript regex: rscript = /(?:(?!</script>)<[^<])*</script>/gi,
and you're right i have to add a callback function into the load ajax!
By default the javascript that is contained in the page you are retrieving by AJAX will not be executed, because it is treated like plain text.
You will want to evaluate the text as javascript. There is an inbuilt function in javascript that can achieve this called eval. Here is a good article on using eval with AJAX, thanks to technify.me.
However I must note that using eval is considered a bad practice. There is a well known saying "eval is evil" because it has poor performance, and can have vulnerabilities to XSS. So you may want to look at how to achieve a similar affect without directly using AJAX calls (maybe dynamically built script tags). However for your purposes eval will work if the response is purely javascript. Otherwise you will need to somehow extract the javascript from the HTML your $.get returns.
use
$(".meny a").on( 'click', ...
instead of
$(".meny a").click( ....
the $(".meny a") will be able to click now
Related
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/
I have a Firefox addon that injects/executes a jQuery script on every page at sub.example.com. The script doesn't work on one page of the site, because of bad design. Is there any way to stop the script from being executed if a certain element is located on the page?
EDIT: The script I am using has to be executed before the DOM loads. Is there any way to access the HTML file itself and find out if the element exists?
Since jQuery collections are just beefed up arrays, they each have a length property, which tells you how many elements it has matched:
jQuery(document).ready(function($)
{
if ( $('#someElement').length ) return;
// All of your code should go here...
});
Since you're using jQuery, I assume your script is wrapped in a $(document).ready callback, if so:
$(document).ready(function() {
if ($('#breakOnThisElem').length) {
return;
}
});
If your code isn't wrapped in a function like this: change it! :)
I am building a tumblr theme and have an ajax call that gets a video player, the video player code is returned and I log it out to the console (see #1). I write out the returned html to an element (#2) and then write out the contents of that element (#3) and the tags get parsed out.
Can anyone help me understand why the script tags are getting stripped and how I would get the script to run please?
console.log(data.posts[0]["video-player"]); //#1
$("#DOMWindow .post-inner .video-container").html(data.posts[0]["video-player"]); //#2
$("#DOMWindow .post-inner .video-container").html(); //#3
Below is the output in the console for data.posts[0]["video-player"]
<span id="video_player_21019988413">[Flash 10 is required to watch video.]</span><script type="text/javascript">renderVideo("video_player_21019988413",'http://penguinenglishlibrary.tumblr.com/video_file/21019988413/tumblr_m2f2kbQFzu1rsq78z',400,225,'poster=http%3A%2F%2Fmedia.tumblr.com%2Ftumblr_m2f2kbQFzu1rsq78z_r1_frame1.jpg,http%3A%2F%2Fmedia.tumblr.com%2Ftumblr_m2f2kbQFzu1rsq78z_r1_frame2.jpg,http%3A%2F%2Fmedia.tumblr.com%2Ftumblr_m2f2kbQFzu1rsq78z_r1_frame3.jpg,http%3A%2F%2Fmedia.tumblr.com%2Ftumblr_m2f2kbQFzu1rsq78z_r1_frame4.jpg,http%3A%2F%2Fmedia.tumblr.com%2Ftumblr_m2f2kbQFzu1rsq78z_r1_frame5.jpg')</script>
Below is the output from the .html() call with the elements stripped #3
<span id="video_player_21019988413">[Flash 10 is required to watch video.]</span>"
Below is the full ajax call that should be inserting the script tags into the page but doesn't:
$.ajax({
url: 'http://penguinenglishlibrary.tumblr.com/api/read/json?id=' + audioID,
dataType: 'jsonp',
timeout: 50000,
success: function(data){
var videoPlayer = data.posts[0]["video-player"];
$("#DOMWindow").find(".post-inner .video-container").html(videoPlayer);
}
});
The jQuery .load() function always strips out <script> tags, and on top of that when you use the "context" variation as you are it does not execute them.
That is,
$('#foo').load('http://what.ever.com/stuff .something', function() { /* ... */ });
That ".something" suffix after the URL triggers this weird "feature".
I logged a bug about this and the resolution was a documentation update. For various internal reasons it'd be pretty hard to make it work better.
edit — there's really no direct workaround other than to have your server do the work of separating out the page fragment you need. jQuery just won't cooperate, mostly (I think) because the library would have to somehow figure out what scripts from elsewhere in the retrieved page needed to be run.
Pointy said
For various internal reasons it'd be pretty hard to make it work better.
The internal reasons are that assigning to a DOM node's innerHTML property does not execute script element's content.
Can scripts be inserted with innerHTML? explains.
I am coding a big website but I have cut down my problem into the following tiny html file:
http://dl.dropbox.com/u/3224566/test.html
The problem is that if I (re)load with JQuery a content that features a facebook code, the latter won't appear, even if I reload the script (leading to a duplication of that all.js script, which is another issue).
How can I fix this?
Regards,
Quentin
Use the FB.XFBML.parse() docs after you load the new content
function loadPage() {
$('#test').load('test.html #test', function() {
FB.XFBML.parse( );
}).fadeOut('slow').fadeIn('slow');
}
Note, that loading a fragment with id test in a div with id test will create multiple (two) elements with the same id (nested in each other) in the page, which should never happen as it is invalid.
To avoid this use the more verbose $.get method
$.get('test.html',
function(data) {
var temp = $('<div>').html(data).find('#test');
$('#test').html(temp.html());
}
);
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I have a main page with 2 links that load external files via .load(). The first file has a simple JavaScript rollover, which works when the content is loaded. The second file has a jQuery plug-in that does not work when loaded via .load() - but works fine when the data file is viewed by itself.
Main file: http://gator1105.hostgator.com/~carc/test-load.html
Second data file that works by itself, but not from .load(): (same URL as above, but the file is test-load-two.html - StackOverflow will allow me to create only 1 hyperlink)
Rather than paste my source code here, you can just view it from the pages themselves.
How can I get the second file with the slideshow to work when loaded with .load()?
I acutally did something similar with a site I'm working on. What you'll want to do is make a callback function for each page for the $.load() call on the main page.
See the following code from the jquery.load() documenation:
$('#result').load('ajax/test.html', function() {
alert('Load was performed.');
});
In your particular case, you'd want something like this on the main test-load.html page.
$(document).ready(
function(){
$('li').click(function(){
var showThisContent = this.id;
$('#content').load('test-load-'+showThisContent+'.html', function(){
if (showThisContent == "one"){
//Do logic for test-load-one.html
//Pre-load your images here.
//You may have to assign a class to your anchor tag
//and do something like:
$('a.assignedClass').mouseover(function(){});
$('a.assignedClass').mouseout(function(){});
} //end if
if (showThisContent =="two"){
//Do logic for test-load-two.html here
$('.slideshow').cycle({
fx: 'fade',
speed: 500,
timeout: 0,
next: '.nextSSimg',
prev: '.prevSSimg',
pager: '#SSnav',
cleartype: true,
cleartypeNoBg: true
}); //end .cycle()
} //end if
); //end .load(location, callback function())
}); //end $('li).click()
}); //end $(document).ready()
Now, obviously I didn't convert all your code, but what's happening here is that once document.ready is complete, the callback function will run, and since the elements like '.slideshow' are now loaded into the DOM, you're callback code will bind to them appropriately.
You could switch this code around in several ways to have the same result (i.e., wrap 2 $.load()s into conditions rather than doing the conditional logic in the .load callback, and/or put a callbackOne() and callbackTwo() function above document.ready and then call them appropriately) but that's your preference. You should be able to do what you want to using the callback function argument of the $.load().
Ignore this answer
Your second file does its initialization in a "document.ready" block. That's not going to be run when your content loads via AJAX. Try taking the code in the second page that's inside "document.ready" out of that, so that it's just a bare script block.
[edit] Oh I see - not only is the script inside a "document.ready" block (well, it's not anymore), but that second page is a complete HTML document. You can't really load a complete HTML document into the middle of another document; it doesn't make sense, and jQuery is only going to grab what's in the body. Thus, try moving your script tag into the body and see what happens. (You still don't want "document.ready", I don't think.)
[edit again] actually I take that back - I don't think jQuery strips anything out; I just bet the browser gets confused.
[edit yet again] ok, ok I see that you've changed it again - let me take a really close look.
OK here's a better answer: for reasons I don't understand, when you load a fragment (or a whole page; whatever) with jQuery using the special "selector" trick to pluck out just a portion of the document:
var showThisContent = this.id;
$('#content').load('test-load-' + showThisContent + '.html #content-area');
the jQuery library strips out the scripts completely from the content, and doesn't ever run them. Why? I don't know.
I know that you probably don't trust me anymore, but here's what I did with your source code: I took that second file (test-load-two) and stripped out the head and stuff; basically I made it a fragment containing only the "content-area". (I also got rid of the script tag that loads jquery, as you don't really need that since the outer page already has it.) Then I changed the main page (test-load) so that when it calls "load" it just passes in the URL without that '#content-area' selector. That works.
[edit] I just posted a question to the jQuery forum: http://forum.jquery.com/topic/the-load-function-and-script-blocks
Don't go for $.load. Try $.get instead, which might seem less comfortable, but it worked for me in a different case. Sample code as following.
$(li).click(function() {
// your code for finding the id
$.get('test-load-' + id + '.html', function(responseHtml){
$('div#content-area').empty().append($(responseHtml)); // remove all elements from #content-area
// $('...').html(responseHtml) will not work
});
});
I hope this solves your problem.