How to check when HTML fetched by AJAX is totally parsed? - javascript

I have a site where I fetch additional HTML with AJAX (and jQuery). I parse this HTML with jQuery.parseHTML() and add the parsed HTML into my site with the function append(). I also use animations for displaying the new content.
Now I have some display problems which happen, when the parsed HTML is big. When I reload the same site everything is fine (maybe because the HTML is cached by the Browser). So I think the problem may be that the HTML was not totally parsed and prerendered by the browser. How can I check, when the fetched HTML is totally parsed and ready for rendering? (Note: I append the new HTML in way, that it is not directly visible to the user. Just the animation slides the new content in).
The function ready() does not seem to work. Thanks for your replies!

With ajax you can append .success or .done see http://api.jquery.com/jquery.ajax/
$.ajax({
url: "http://fiddle.jshell.net/favicon.png",
beforeSend: function( xhr ) {
xhr.overrideMimeType( "text/plain; charset=x-user-defined" );
}
})
.done(function( data ) {
if ( console && console.log ) {
console.log( "Sample of data:", data.slice( 0, 100 ) );
}
});
the done(function(data){} will contain all data and you can do what you want with it. It is called as soon as it has finished loading

Related

jquery .load() does not load external JS

I am loading external content into a div element using jquery.load() without a selector. If the content loaded has embedded JS, the JS works as expected. HOWEVER, if the content includes a script tag with src=path-to-js-code the js-code is not loaded.
Am I correct in this observation and if so is there a good solution other than embedding the JS in the loaded content?
EDIT :
A few clarifications and observations:
To load the content I am using
$("#DivId").load("path/to/content.php", CallbackFunction(response, status, xhr) {
error checking and post processing code
});
Changing the load code to:
$.get("path/to/content.php", CallbackFunction(response, status, xhr) {
error checking
$("#DivId").html(response);
post processing
});
Does not seem to change the behavior (more on the behavior below)
I have not tried parsing the response to retreive the script src and then using getScript().
Now more on the behavior...
Using Firefox, it seems that the external JS is loaded but only if it has been about 2 min from the last load. I do not see an attempt in Firebug unless the refresh is about 2m after the last load of the external JS. (weird). When I was making JS code changes and hitting refresh, it was not loading my new code and thus the original question.
So i will withdraw my question in light of this clarified behavior (2m caching?).
Thanks.
Both the .load() and .html() jQuery methods utilise the .innerHTML property. This won't execute scripts added with <script> tag. Use a regular AJAX call e.g. .get() then in the callback use .append() to add your HTML string and the scripts will run once it's parsed e.g.
$.get("path/to/content.php", function(response, status, xhr) {
// error checking
$("#DivId").append(response); // Any <script> tags in the response string will execute
// post processing
});
Thing is you need to make sure you're running trusted code if it's added by .append()
I was wondering you can get the script src in the response text of $.load method with regular expressions, then use $.getScript() method to load the script, maybe something like this:
$("#DivId").load("path/to/content.php", function(response, status, xhr) {
var regexp = new RegExp('script.*?src="(.*?)"'),
execresults = regexp.exec(response);
if(execresults.length > 1)
{
// the first result is the entire match including
// the 'script..src=', so abandon it
var matches = execresults.slice(1);
$.each(matches, function(){
$.getScript(this, function(){
// do something after load script
});
});
}
});
Hope this can help
This is the easy way to load an external JS to your jQuery
$.ajax({
type: "GET",
url: "path/to/content.php",
dataType: "script"
success:CallbackFunction(response, status, xhr)
});

Reloading page with the html received as a result of AJAX call

I am using AJAX calls and getting JSON as response then it is used to perform various operations. However there are times when I will get HTML response instead of AJAX(a full HTML page), in such cases I want to reload the page with the HTML content (as if a redirection happened). I am able to find out whether a response is HTML or JSON, however I am unable to find a way in which I can reload the page with HTML content received as part of response so that user only sees the HTML content received as part of AJAX response.
Here is the code:
function redirectIfHTML(xhr,data){
var ct = xhr.getResponseHeader("content-type") || "";
if (ct.indexOf('html') > -1) {
// Need to reload the data on current window
}
}
You can nuke and rewrite the entire content of the page using document.write():
document.write("<html><body><p>Hello world!</p></body></html>");
If you want to keep the <head> (and therefore your CSS and so forth) a cleaner solution is to replace the content of the body:
$('body').html("<p>Hello world!</p>");
I would never want to do something like this, but you can use some data-url to solve:
A data-URI with MIME-type text/html + the html you just received:
var myurl = 'data:text/html,' + <HTML HERE>
Then you do:
document.location.href = myurl
(i didn't really try it)

How to insert external javascript files in meteor js (0.9.2.2) template

I am using following code to insert javascript files in template :
_.each([
"/assets/global/plugins/jquery-1.11.0.min.js",
"/assets/global/plugins/jquery-migrate-1.2.1.min.js",
"/assets/global/plugins/jquery-ui/jquery-ui-1.10.3.custom.min.js",
"/assets/global/plugins/bootstrap/js/bootstrap.min.js",
"/assets/global/plugins/bootstrap-hover-dropdown/bootstrap-hover-dropdown.min.js",
"/assets/global/plugins/jquery-slimscroll/jquery.slimscroll.min.js",
"/assets/global/plugins/jquery.blockui.min.js",
"/assets/global/plugins/jquery.cokie.min.js",
"/assets/global/plugins/uniform/jquery.uniform.min.js",
"/assets/global/plugins/bootstrap-switch/js/bootstrap-switch.min.js"
], function(script, ready) { jQuery.getScript(script, function (data, textStatus, jqxhr){
console.log( data ); // Data returned
console.log( textStatus ); // Success
console.log( jqxhr.status ); // 200
console.log( "Load was performed." );
})
});
I am getting following results (only one sample out of 10), all 10 files showing success messages :
(function(){var t=[].slice;!fu"[…] admin.js:63
"success" admin.js:64
200 admin.js:65
"Load was performed."
But when I see "View Generated Source" in Firefox developer tool, I can't see any inserted JavaScript files in html code. Can some one guide me what I am doing wrong and how it can be rectified.
The code works fine for me. jQuery.getScript() does not seem to change anything in the DOM, it simply runs the code virtually. Try adding a file that has console.log('test'); as its contents.
By the way, in your posted code, you are loading jQuery using jQuery's own function. For this jQuery must already be loaded. It seems that you need to rethink how you are loading your scripts.
Why do you using ajax calls?
Did you know, Meteor merges head Tags of all html files. So you can make as example a 'scripts.html' File with content:
<head>
<script src=...
</head>

Why .html() method does not load data in the element?

$.get("progress.txt", null, function(data_aj){
if(data_aj.substr(0,14) == "<!-- MSG:: -->"){
$("#list").html("<li>"+data_aj+"</li>");
window.clearTimeout(timeOutId);
}else{
$("#list").html(data_aj);
}
});
I really have tried everything but can't figure out whats wrong. If I use alert(data_aj); it gives the desired output and just works fine but HTML(data_aj) just doesnt loads into a <ul> element #list using .html(). Can anyone tell me why?
Have you tried putting your code in a document ready, as your alert will fire fine but if your dom is not loaded then you cannot append to it. Also use .append() for lists not html
$(document).ready(function() {
$.get("progress.txt", null, function(data_aj){
if(data_aj.substr(0,14) == "<!-- MSG:: -->"){
$("#list").append("<li>"+data_aj+"</li>");
window.clearTimeout(timeOutId);
}else{
$("#list").append(data_aj);
}
});
});
Listen up...
$.get() is a shorthand for $.ajax().
So when you do this
$.get(uri, function(data){
//Your functionality
});
You're really doing this
$.ajax({
url: uri,
type: "GET",
success: function(data) {
//Your functionality
}
});
By default this returns the page as HTML. Or rather, by default, it first checks the MIME-type on the page, and if none is found, it returns HTML. As you are requesting a .txt file it will interpret it as a simple textfile. If you want to tell it what you would like to return (HTML), you can either do it in the MIME-type on the server page, or you could use $.getJSON().
An easy way to solve this is thus doing:
$.get(uri, function(data) {
//Your functionality
},
"html");
Which is the same as doing:
$.ajax({
url: uri,
type: "GET",
dataType: "HTML",
success: function(data) {
//Your functionality
}
});
Also it is not a good idea to use html() because you are replacing the existing html inside of your ul element every time you want to add an additional new node.
Try making use of:
$('#list').append('<li>' + data_aj + '</li>');
Basically you can just append the <li> to the <ul> itself.
Lastly make sure your dom has already been loaded by placing all your JQuery code into the
$(document).ready(function() {
//Your code...
});
Otherwise if your HTML is not fully loaded yet, your list might not exist yet so there is no way for JQuery to put some values into unexisting HTML.

dojo.io.iframe erroring when uploading a file

Hit an interesting problem today when trying to upload an image file < 2MB using dojo.io.iframe.
My function to process the form is called, but before the form is posted to the server I am getting the following error:
TypeError: ifd.getElementsByTagName("textarea")[0] is undefined
My function that is used to action the post of the form is :
function uploadnewlogo(){
var logoDiv = dojo.byId('userlogo');
var logoMsg = dojo.byId('uploadmesg');
//prep the io frame to send logo data.
dojo.io.iframe.send({
url: "/users/profile/changelogo/",
method: "post",
handleAs: "text",
form: dojo.byId('logoUploadFrm'),
handle: function(data,ioArgs){
var response = dojo.fromJson(data);
if(response.status == 'success'){
//first clear the image
//dojo.style(logoDiv, "display", "none");
logoDiv.innerHTML = "";
//then we update the image
logoDiv.innerHTML = response.image;
}else if(response.status == 'error'){
logoMsg.innerHTML = data.mesg;
}else{
logoMsg.innerHTML = '<div class="error">Whoops! We can not process your image.</div>';
}
},
error: function(data, ioArgs){
logoMsg.innerHTML = '<div class="error">' + data + '</div>';
}
});
}
The form is very basic with just a File input component and a simple button that calls this bit of javascript and dojo.
I've got very similar code in my application that uploads word/pdf documents and that doesn't error, but for some reason this does.
Any ideas or pointers on what I should try to get this to work without errors?
Oh I'm using php and Zend framework for the backend if that has anything to do with it, but I doubt it as it's not even hitting the server before it fails.
Many thanks,
Grant
Another common reason for this error is the server isn't packaging the data correctly. This means even if you have set "handleAs: json" you have to send that json wrapped in some html. This is what it should look like:
<html>
<body>
<textarea>
{ payload: "my json payload here" }
</textarea>
</body>
</html>
Your error was saying it couldn't find the textarea in your return from the server. For more look at http://docs.dojocampus.org/dojo/io/iframe
Since the load handler of dojo.io.iframe.send() has been triggered, the request should have been sent to the server and response is back. I think the response from server is not correct. Maybe the server returns an error page.
Use Firebug to inspect current page's DOM and find the transporting iframe created by Dojo and check its content. Firebug can capture iframe I/O too, check its Net tab. You may find the root cause of this issue.
Did you respect the constraint written in the doc ?
IMPORTANT: For all values EXCEPT html and xml, The server response should be an HTML file with a textarea element. The response data should be inside the textarea element. Using an HTML document is the only reliable, cross-browser way this transport can know when the response has loaded. For the text/html (Or XML) mimetype, just return a normal HTML/XML document. In other words, your services for JSON and Text formats should return the data wrapped as the following:

Categories