Wait for AJAX responce to be fully ready/rendered - javascript

I have an ajax call returning html code which is inserted into a container.
Now I need to call a jQuery function to format the gallery, but I can't find a way to ensure that the jQuery function waits for returnedData to be fully loaded/rendered.
As you can see I have tried .ready() but it doesn't work. I have also tried setTimeout, which actually works, but as the returnedData can contain a lot of images, I can't use it as I don't know how long it would take to load all the images.
Any ideas?
$(document).ready(function() {
$.ajax(url, {type: 'POST', dataType: 'json', data: data, success: success_handler});
});
function success_handler(returnedData) {
$('.category-images-js').html(returnedData);
$('.category-images-js').ready(function() {
// Code to run after all data inside returnedData is fully ready/rendered
);
}
SOLUTION:
This thread: How to know if all elements in a DIV have been fully loaded? worked for me but I had to make a work-around as the code I run, when data inside returnedData is fully ready/rendered, makes the on load trigger 3 times per image.

I've made my own ajax function so i hope it fits you:
function xhr(u, c) {
var x = new XMLHttpRequest();
x.onreadystatechange = function (){
if (x.readyState == 4 && x.status == 200){
c(x.responseText)
}
};
x.open("GET", u, true);
x.send()
}
u = URL
c = Callback function

Related

AJAX GET Call Will work on the first call but not after other clicks

I have an ajax call in my javascript that returns and loads a partial view into a div. This function used to work but then all the sudden it stopped. I do not think I changed any code or anything that would cause issue but obviously something is going on. The Ajax call will work on the first time when you click on the button in which it is called but never again until you reload the page. I have tried adding more parameters and moving the javascript around but it still did not work. Is there any reason why this could happen?
I have tried moving the javascript out of the onOpen event and the same thing still happens. I have also put an alert call to make sure it is getting to the success call and the alert is called. I have also installed fiddler to check the call and the call is never made except on the first click of the button. This is a very frustrating error and all help is much appreciated.
Here is my Javascript:
#section scripts
{
<script type="text/javascript">
$(document).ready(function () {
$("#assets-button").on("click", function ()
{
$('#assets-container').bPopup(
{
modal: true,
onOpen: function () {
$.ajax({
type: 'GET',
url: '#Url.Action("EmployeeAssets", "Employee",new { id = Model.ID, empNo = Model.EmployeeNumber, username = Model.UserName })',
success: function (data) {
$('#assets-container').html(data);
}
});
},
onClose: function () {
var f = $('#assets-container').children('form');
var serializedForm = f.serialize();
var action = '#Url.Action("EmployeeAssets","Employee",new {empNo = Model.EmployeeNumber})';
$.post(action, serializedForm);
}
});
});
});
</script>
}
Here is the action that I am trying to call:
[HttpGet]
public ActionResult EmployeeAssets(int id, int empNo, string username = null)
{
var assets = _employeeDb.EmployeeAssets.FirstOrDefault(e => e.EmpNo == empNo);
if (assets == null)
{
var firstOrDefault = _employeeDb.EmployeeMasters.FirstOrDefault(e => e.EmployeeNumber == empNo);
if (firstOrDefault != null)
{
username = firstOrDefault.UserName;
}
var newasset = new EmployeeAsset()
{
EmpNo = empNo,
UserName = username
};
_employeeDb.EmployeeAssets.Add(newasset);
_employeeDb.SaveChanges();
assets = newasset;
}
return PartialView(assets);
}
You may try using the cache property of the settings object you are passing to the AJAX call. According to the jQuery documentation for .ajax the default for cache is set to true, so I wonder whether your browser is accessing a cached copy of the result after the first request. Looks like you could also set the dataType, and that will default the cache back to false.
Also, I would suggest putting your alert inside of the onOpen event handler in addition to the success handler just to be sure that's also being called. So that may help you debug a bit further.

Load Javascript into ajax loaded content

I am new to working with AJAX and have some experience with Java/Jquery. I have been looking around for an solution to my problem but i cant seem to find any.
I am trying to build a function in a webshop where the product will appear in a popup window instead of loading a new page.
I got it working by using this code:
$(".product-slot a").live('click', function() {
var myUrl = $(this).attr("href") + " #product-content";
$("#product-overlay-inner").load(myUrl, function() {
});
$("#product-overlay").fadeIn();
return false;
});
product-slot a = Link to the product in the category page.
product-content = the div i want to insert in the popup from the product page.
product-overlay-inner = The popup window.
product-overlay = The popup wrapper.
The problem that i now have is that my Javascript/Jquery isnt working in the productpopup. For example the lightbox for the product image or the button to add product to shoppingcart doesnt work. Is there anyway to make the javascript work inside the loaded content or to load javascript into the popup?
I hope you can understand what my problem is!
Thank you in advance!
EDIT: The platform im using has jquery-ui-1.7.2
I know this is an old thread but I've been working on a similar process with the same script loading problem and thought I'd share my version as another option.
I have a basic route handler for when a user clicks an anchor/button etc that I use to swap out the main content area of the site, in this example it's the ".page" class.
I then use a function to make an ajax call to get the html content as a partial, at the moment they are php files and they do some preliminary rendering server side to build the html but this isn't necessary.
The callback handles placing the new html and as I know what script I need I just append it to the bottom in a script tag created on the fly. If I have an error at the server I pass this back as content which may be just a key word that I can use to trigger a custom js method to print something more meaningful to the page.
here's a basic implementation based on the register route handler:
var register = function(){
$(".page").html("");
// use the getText ajax function to get the page content:
getText('partials/register.php', function(content) {
$(".page").html(content);
var script = document.createElement('script');
script.src = "js/register.js";
$(".page").append(script);
});
};
/******************************************
* Ajax helpers
******************************************/
// Issue a Http GET request for the contents of the specified Url.
// when the response arrives successfully, verify it's plain text
// and if so, pass it to the specified callback function
function getText(url, callback) {
var request = new XMLHttpRequest();
request.open("GET", url);
request.onreadystatechange = function() {
// if the request is complete and was successful -
if (request.readyState === 4 && request.status === 200) {
// check the content type:
var type = request.getResponseHeader("Content-Type");
if (type.match(/^text/)) {
callback(request.responseText);
}
}
};
// send it:
request.send(null); // nothing to send on GET requests.
}
I find this a good way to 'module-ize' my code into partial views and separated JavaScript files that can be swapped in/out of the page easily.
I will be working on a way to make this more dynamic and even cache these 'modules' for repeated use in an SPA scenario.
I'm relatively new to web dev so if you can see any problems with this or a safer/better way to do it I'm all ears :)
Yes you can load Javascript from a dynamic page, but not with load() as load strips any Javascript and inserts the raw HTML.
Solution: pull down raw page with a get and reattach any Javascript blocks.
Apologies that this is in Typescript, but you should get the idea (if anything, strongly-typed TypeScript is easier to read than plain Javascript):
_loadIntoPanel(panel: JQuery, url: string, callback?: { (): void; })
{
// Regular expression to match <script>...</script> block
var re = /<script\b[^>]*>([\s\S]*?)<\/script>/gm;
var scripts: string = "";
var match;
// Do an async AJAX get
$.ajax({
url: url,
type: "get",
success: function (data: string, status: string, xhr)
{
while (match = re.exec(data))
{
if (match[1] != "")
{
// TODO: Any extra work here to eliminate existing scripts from being inserted
scripts += match[0];
}
}
// Replace the contents of the panel
//panel.html(data);
// If you only want part of the loaded view (assuming it is not a partial view)
// using something like
panel.html($(data).find('#product-content'));
// Add the scripts - will evaluate immediately - beware of any onload code
panel.append(scripts);
if (callback) { callback(); }
},
error: function (xhr, status, error)
{
alert(error);
}
});
}
Plain JQuery/Javascript version with hooks:
It will go something like:
var _loadFormIntoPanel = function (panel, url, callback) {
var that = this;
var re = /<script\b[^>]*>([\s\S]*?)<\/script>/gm;
var scripts = "";
var match;
$.ajax({
url: url,
type: "get",
success: function (data, status, xhr) {
while(match = re.exec(data)) {
if(match[1] != "") {
// TODO: Any extra work here to eliminate existing scripts from being inserted
scripts += match[0];
}
}
panel.html(data);
panel.append(scripts);
if(callback) {
callback();
}
},
error: function (xhr, status, error) {
alert(error);
}
});
};
$(".product-slot a").live('click', function() {
var myUrl = $(this).attr("href") + " #product-content";
_loadFormIntoPanel($("#product-overlay-inner"), myUrl, function() {
// Now do extra stuff to loaded panel here
});
$("#product-overlay").fadeIn();
return false;
});

Best way to capture data from ajax and manipulate with it

I'm making a that should get images from database with ajax and then display it with some carousel plugin. Here is how it should work :
Image url is saved to database from admin
frontend script makes a ajax call to a php file and returns all url's from db.
Now when I have all images, the carousel plugin can be applied.
Images are now being displayed one by one.
The trick is that i want to make another ajax call when last image is displayed and repopulate container div with fresh images from database. Here is my code
function get_images(){
var data = {
"function_name" : "get_images",
"args" : ""
};
$.ajax({
type : "POST",
url : "http://localhost/.../functions.php",
data : data,
dataType : "JSON",
success : function(ret){
$(".container").html(ret);
$(".container").carousel(//When last call - function again);
}
});
}
And here is the problem. On ajax success carousel plugin is starting to rotate imgs, and when its finished, the get_images function should be call again. But this function is already in the another function and every time when it makes a call it will be one level deeper. Is there any way of doing this?
The best would be for the carousel to fire an event that it needs more images and listen to that event. You can then retrieve more images and return the new list to the carousel. There are carousel plugins that have all this build in. I often use this one: http://caroufredsel.dev7studios.com/
Maybe in your PHP script:
<?php
if ( isset($_POST['function_name']) ) {
if ( $_POST['function_name'] == 'get_images' ) {
// Get some URLs into an array...
// For the sake of the example we'll manually fill the array
$urls = ['img/image1.png', 'img/image2.png'];
echo json_encode($urls);
}
}
And in your JS:
function Carousel() {
this.getMoreImages();
}
Carousel.prototype.nextImage = function () {
if (this.i < this.images.length) {
this.showImage(); // Implement this.
this.i += 1;
this.spin():
}
else {
this.getMoreImages();
}
}
Carousel.prototype.spin = function () {
var self = this;
setTimeout(function () {
self.nextImage();
}, 5000);
}
Carousel.prototype.getMoreImages = function () {
var self = this;
$.ajax({
type : 'POST',
url : 'http://localhost/.../functions.php',
data : data,
dataType : 'JSON',
success : function (ret) {
self.images = JSON.parse(ret);
self.i = 0;
self.spin();
}
});
}
var myCarousel = new Carousel();
This Carousel object will request an array of images on instantiation, and show each image on a 5-second interval. When all the images have been exhausted, it will automatically make another AJAX call, retrieving images in the same manner as it did originally, and then continue looping through the new images. It will continue in this cycle forever.

How to update Ajax call (not content)

Look at this code please - how could I kill / update or restart an ajax call (not content that Ajax calls) after the content has already been called?
I mean the $('#posting_main') is called onclick and animated - how to stop ajax and make it another $('#posting_main') on another click?
$(document).ready(function() {
$("#img_x_ok").click(function(e){
e.preventDefault();
var post_text = $.trim($("#main_text_area").val());
var data_text = 'post_text='+ post_text;
if (post_text === "") return;
var xhr = $.ajax({
type: "POST",
url: "comm_main_post.php",
data: data_text,
cache: false,
success: function (data){
//content
$("#posting_main").fadeIn();
$("#posting_main").load("pull_comm.php");
$("#main_text_area").attr("value", "");
$("#posting_main").animate({
marginTop: "+=130px",
}, 1000 );
}
}); //ajax close
}); }); //both functions close
You can abort the current request with:
xhr.abort();
After having done that, you can run another $.ajax(...) to make a second request.
You could implement it like the following. Note that indenting code makes it a lot more readable!
$(document).ready(function() {
var xhr; // by placing it outside the click handler, you don't create
// a new xhr each time. Rather, you can access the previous xhr
// and overwrite it this way
$("#img_x_ok").click(function(e){
e.preventDefault();
var post_text = $.trim($("#main_text_area").val());
var data_text = 'post_text='+ post_text;
if (post_text === "") return;
if(xhr) xhr.abort(); // abort current xhr if there is one
xhr = $.ajax({
type: "POST",
url: "comm_main_post.php",
data: data_text,
cache: false,
success: function (data){
//content
$("#posting_main").fadeIn();
$("#posting_main").load("pull_comm.php");
$("#main_text_area").attr("value", "");
$("#posting_main").animate({
marginTop: "+=130px",
}, 1000 );
}
});
});
});
I am not sure I fully understand your question, however:
xhr.abort() will kill the AJAX request. After calling abort(), you could modify and resend the request, if desired.
$("#posting_main").stop() will stop the fadeIn animation. (And I think you might need to follow that with $("#posting_main").hide() to be sure it isn't left partially visible.)

Function scope within IF Statement

hoping some one can shed some light on my problem. Basicly I only want to execute a block of code if a certain DOM element exists. If it does I then perform a few bits and bobs and then call a function. However it complains that the function is not defined, suggesting that the function is not in scope. Below is the code :
$(document).ready(function ()
{
if ((document.getElementById("view<portlet:namespace/>:editSplash")!= null)) {
console.log("notifications scripted started");
// hide loading box/ notify on body load
$('.ajaxErrorBox').hide();
$('.loadingNotifications').hide();
$('.notifyWindow').hide();
getFeed();
// set up refresh button for reloading feed
$('.refreshFeed').click(function() {
$('.notifyWindow').hide();
$('.notifyWindow').empty();
console.log("notifications clicked");
getFeed();
});
// begin ajax call using jquery ajax object
function getFeed ()
{
$('.notifyWindow').empty();
console.log("ajax call for feed starting");
$.ajax ({
type: "GET",
url: "http://cw-pdevprt-05.tm-gnet.com:10040/notificationsweb/feed?username=uid=<%# taglib uri="/WEB-INF/tld/engine.tld" prefix="wps" %><wps:user attribute="uid"/>",
dataType: "text/xml",
timeout: 10000,
success: parseXml
});
};
// show loading box on start of ajax call
$('.notifyWindow').ajaxStart(function() {
$('.refreshFeed').hide("fast");
$('.notifyWindow').hide();
$('.ajaxErrorBox').hide();
$('.loadingNotifications').show("fast");
});
// hide loading box after ajax call has stopped
$('.notifyWindow').ajaxStop(function() {
$('.loadingNotifications').hide("slow");
$('.refreshFeed').show("fast");
});
$('.notifyWindow').ajaxError(function() {
$('.loadingNotifications').hide("slow");
$('.ajaxErrorBox').show("fast");
$('.refreshFeed').show("fast");
});
// parse the feed/ xml file and append results to notifications div
function parseXml (xml) {
console.log("xml parsing begining");
if (jQuery.browser.msie)
{
var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.loadXML(xml);
xml = xmlDoc;
}
$(xml).find("entry").each(function()
{
var $item = $(this);
var title = $item.find("title").text();
var linkN = $item.find("link").attr("href");
var output = "<a href='" + linkN + "' target='_self'>" + title + "</a><br />";
$(".notifyWindow").append($(output)).show();
});
}
}
else {
console.log("notifications not available");
return false;
}
});
If the DOM element exists I then try and call the getFeed function "getFeed();" however it comes back undefined. If anyone could shed some light on this it would be greatly appreciated.
Thanks in advance
It seems that you're calling getFeed before it is defined. Try moving the if statement to after the function definition. Note that this behaviour is actually implementation specific, so some browsers may work this way and some may not.
Oh - And seriously? view<portlet:namespace/>:editSplash for an id?
Problem solved - I moved my functions outside of the if statement. We live and learn lol :-)

Categories