I'm having trouble getting a nested AJAX call to work properly. All I want is to have the inner AJAX call executed if and after the outer AJAX call completed successfully.
var diningHours = $("#diningHours");
var facStaffDiningData = $("#facStaffDiningData");
var diningCommonsData = $("#diningCommonsData");
if($.trim(diningHours.html()).length == 0) {
var season;
//This call executes fine (tested it with console logging)
$.get("data/dining-hours.php", {summer: "check"}, function(seasonData, seasonStatus) {
if(seasonStatus == "success") {
season = seasonData;
//This is the call that isn't being executed
$.get("data/dining-hours.php", function(hoursData, hoursStatus) {
if(hoursStatus == "success") {
var hours = $(hoursData).find("hours dining");
var html = hoursFeed(hours, season);
diningHours.append(html).collapsibleset("refresh");
}
});
}
});
}
Am I doing something wrong?
I'd try something like this:
var diningHours = $("#diningHours"),
facStaffDiningData = $("#facStaffDiningData"),
diningCommonsData = $("#diningCommonsData");
if(!$.trim(diningHours.html()).length) {
var XHR = $.get("data/dining-hours.php", {summer: "check"});
XHR.success(function(seasonData) {
var season = seasonData,
XHR2 = $.get("data/dining-hours.php");
XHR2.success(function(hoursData) {
var hours = $(hoursData).find("hours dining"),
html = hoursFeed(hours, season);
diningHours.append(html).collapsibleset("refresh");
});
});
}
The question is, what exactly is hours dining, and how do you expect the find() function to find it ?
I think seasonStatus is redundant, because the callback will be executed on success.
This should works
var season;
//This call executes fine (tested it with console logging)
$.get("data/dining-hours.php", {summer: "check"}, function(season, seasonStatus) {
console.log('CB1',season);
$.get("data/dining-hours.php", function(hoursData) {
console.log('CB2',hoursData);
var hours = $(hoursData).find("hours dining");
var html = hoursFeed(hours, season);
diningHours.append(html).collapsibleset("refresh");
});
}
});
Digging deeper into the issue I found the true source of my problem. The XML document had a bunch of encoding errors (there were things like reserved and copyright symbols in with the data). Removing these and replacing them with the correct entities fixed the problem. My original code that I thought was the issue now works perfectly fine.
Related
First of all, I'm using JQuery. Take a look:
$(document).ready(function() {
var btcusd = 600;
function getRate() {
$.get("rate.php", function(data) {
var btcArr = JSON.parse(data, true);
btcusd = btcArr["last"];
//This will give me the correct value
console.log(btcusd);
});
}
setInterval(function() {
//This will say 600 every time
console.log(btcusd);
//Update rate for next loop
getRate();
}, 3000);
});
Chrome console gives me the 600 every 3 seconds. If I do this manually in the chrome live console, I will get a real value, like 595.32.
Why does this not work like intended?
Thanks for help.
I think #Tobbe is quite on point here. One thing you can do to confirm, is to add something like console.log( btcArr ) and that should show you whether you're getting anything back.
I set up a not too different demo that should that once the ajax callback successfully updates the value, it never goes back to 600, showing that indeed the value does get changed in the callback and the new value is available outside the ajax callback.
The ajax code I used is:
function getRate() {
var gafa = "https://ajax.googleapis.com/ajax/services/feed/load?v=1.0&num=100&q=";
var url = gafa + encodeURI('http://news.yahoo.com/rss/sports/')+"&callback=?";
$.getJSON(url, function(data) {
//var btcArr = JSON.parse(data, true);
var xData = data.responseData.feed.entries
//btcusd = btcArr["last"];
btcusd = xData.length;;
//This will give me the correct value
console.log(btcusd);
});
}
The rest of the code is yours: WORKING JSFIDDLE DEMO
I'm using WebSockets to connect to a remote host, and whenever I populate realData and pass it to grapher(), the JavaScript console keeps telling me realDatais undefined. I tried checking the type of the data in the array, but it seems to be fine. I've called grapher() before using an array with random data, and the call went through without any problems. With the data from the WebSocket, however, the call will always give me "error: realData is not defined". I'm not sure why this is happening. Here is the code I used:
current.html:
var command = "Hi Scott"
getData();
function getData()
{
console.log("getData is called");
if("WebSocket" in window)
{
var dataCollector = new WebSocket("ws://console.sb2.orbit-lab.org:6100",'binary');
dataCollector.binaryType = "arraybuffer";
console.log(dataCollector.readyState);
dataCollector.onopen = function()
{
//alert("The WebSocket is now open!");
console.log("Ready state in onopen is: " + dataCollector.readyState);
dataCollector.send(command);
console.log(command + " sent");
}
dataCollector.onmessage = function(evt)
{
console.log("onmessage is being called");
var realData = new Uint8Array(evt.data);
console.log(realData);
grapher(realData); //everything up to this point works perfectly.
}
dataCollector.onclose = function()
{
alert("Connection to Server has been closed");
}
return (dataCollector);
}
else
{
alert("Your browser does not support WebSockets!");
}
}
graphing.js:
function grapher(realData)
{
console.log("grapher is called");
setInterval('myGraph(realData);',1000); //This is where the error is. I always get "realData is not defined".
}
function myGraph(realData)
{
/*
for(var i = 0; i < SAarray.length; i++) // Loop which will load the channel data from the SA objects into the data array for graphing.
{
var data[i] = SAarray[i];
}
*/
console.log("myGraph is called");
var bar = new RGraph.Bar('channelStatus', realData);
bar.Set('labels', ['1','2','3','4','5','6','7','8']);
bar.Set('gutter.left', 50);
bar.Set('gutter.bottom', 40);
bar.Set('ymax',100);
bar.Set('ymin',0);
bar.Set('scale.decimals',1);
bar.Set('title','Channel Status');
bar.Set('title.yaxis','Status (1 is on, 0 is off)');
bar.Set('title.xaxis','Channel Number');
bar.Set('title.xaxis.pos',.1);
bar.Set('background.color','white');
bar.Set('colors', ['Gradient(#a33:red)']);
bar.Set('colors', ['red']);
bar.Set('key',['Occupied','Unoccupied']);
bar.getShapeByX(2).Set('colors',barColor(data[0]));
bar.Draw();
}
Because strings (as code) passed to setInterval execute in the global scope, therefore the realData parameter isn't available. There's rarely a good reason to pass a string to setInterval. Instead, use:
setInterval(function () {
myGraph(realData);
}, 1000);
Reference:
https://developer.mozilla.org/en-US/docs/Web/API/window.setInterval
Try it without it needing to evaluate a string:
setInterval(function() {
myGraph(realData);
},1000);
Any time you are using setTimeout or setInterval, you should opt for passing an actual function instead of a string.
I'm working with some pretty old code and the following is being used to monitor session status. If the user is inactive for X minutes (determined by check_session.php), they are logged out.
The server side stuff works fine. Actually, the existing javascript appears to work OK as well, but looks like it needs cleaning up.
Here's the existing javascript:
function checkSessionStatus()
{
session_http.open('GET', '/check_session.php', true);
session_http.onreadystatechange = handleSessionHttpResponse;
session_http.send(null);
}
function handleSessionHttpResponse()
{
if (session_http.readyState == 4)
{
results = session_http.responseText;
if (results == 'inactive')
{
window.location='/logout.php';
document.getElementById('session_divbox').innerHTML = results;
}
}
}
function get_session_HTTPObject()
{
var xml_session_http;
if (!xml_session_http && typeof XMLHttpRequest != 'undefined')
{
try
{
xml_session_http = new XMLHttpRequest();
}
catch (e)
{
xml_session_http = false;
}
}
return xml_session_http;
}
var session_http = get_session_HTTPObject();
function init_page_header()
{
window.setInterval( 'checkSessionStatus();', 30000);
}
This seems incredibly long for what it is doing.
I am still learning jquery and am able to do some basic ajax calls like this one, which places a returned value in a div:
$(document).ready(function()
{
$('#users_online').load('/show_users_online.php');
var refreshId = setInterval(function()
{
$('#users_online').load('/show_users_online.php');
}, 2000);
$.ajaxSetup({ cache: false });
});
The issue with the first bit of code is that it returns a value of 'inactive', which is then acted on by the client (window redirect).
Is it possible to do this in Jquery without winding up with dozens of lines of code? I may already know how to do this and am not seeing the forest for the trees -- some guidance here is appreciated.
Even if its very vampiric question style, should look like
$.get('/check_session.php', function( data ) {
if( data === 'inactive' ) {
window.location='/logout.php';
document.getElementById('session_divbox').innerHTML = data;
}
});
Okay, so I have an javascript function that retrieves some HTML...
function updateQuestions(i){
var url = 'getQuestions.php?sys=' + i;
if (receiveReq.readyState == 4 || receiveReq.readyState == 0) {
receiveReq.open("GET", url, true);
receiveReq.onreadystatechange = handleQuestionsUpdate;
receiveReq.send(null);
}
}
function handleQuestionsUpdate() {
if (receiveReq.readyState == 4) {
var a=receiveReq.responseText;
document.getElementById('questions').innerHTML=a;
checkSpeakers(); //Error Occurs Here, even though checkSpeakers() is a function in the returned HTML chunk.
}
}
This HTML is not just HTML, but it is more specifically a form and a chunk of javascript. The javascript is hard-coded into the HTML and not referenced by <script src="..">
Is it normal that this retrieved JS code isn't recognized upon call-time? If so, what is my alternative if I need the JS to change every time the div is update?
This is the text being returned to the javascript function.
function checkPillowSpeakers()
{
var pillowSpeakers = document.getElementById('Q9').value + document.getElementById('Q10').value;
document.getElementById('PS1').style.display = ((pillowSpeakers > 0)? '' : 'none');
document.getElementById('PS2').style.display = ((pillowSpeakers > 0)? '' : 'none');
}~ARRAYSEPERATOR~<html>....</html>
The JS Code is seperated from the HTML code by an ~ARRAYSEPERATOR~ tag. The issue is that I don't want to EXECUTE the code at this time, I just want it queued so I can call it on command.
You should first try to get the JavaScript part from the HTML content.
Then you can easily execute it using eval() function from JavaScript;
My answer from How To Call Javascript In Ajax Response? IE: Close a form div upon success
// response is the data returned from the server
var response = "html\<script type=\"text/javascript\">alert(\"foo\");<\/script>html";
var reScript = /\<script.*?>(.*)<\/script>/mg;
response = response.replace(reScript, function(m,m1) {
var fn = new Function(m1); // this will make the eval run in the global scope
fn(); //will run alert("foo");
return "";
});
alert(response); // will alert "htmlhtml"
After doing a whole lot of research, it seems Eval() has some memory issues... so I actually came across this solution:
//Firstly, create a div called codeHolder
var javascriptCode="function test(){.....}";
var JSONCode=document.createElement("script");
JSONCode.setAttribute("type","text/javascript");
JSONCode.text=javascriptCode;
var cell=document.getElementById("codeHolder");
if ( cell.hasChildNodes() )
while ( cell.childNodes.length >= 1 )
cell.removeChild( cell.firstChild );
cell.appendChild(JSONCode);
you should realy think of using an js-lib for ajax for browser-compatibilty and less memory leaks - but if you want to do this by yourself, you have to eval() the passed back javascript before you can use it.
There is also responseXML:
receiveReq.responseXML.getElementsByTagName('input')
etc., etc.
I grabbed a bit of code to do some paging with jQuery, via Luca Matteis here
Paging Through Records Using jQuery
I've made some edits to the paging script so that I can use the same code to provide paging of different content in different locations on the same site.
For the most part, I think it works, except that I get a jsonObj is undefined error in firebug.
When I use alert(jsonObj.toSource()), I am shown the variables that I am trying to populate, but at the same time, the script dies because of the error.
I can't figure out why I am getting this conflict of 'undefined' and yet I can easily out put the 'undefined' values in an alert. I can even say alert(jsonObj.name), and it will give me that value, but still launch an jsonObj is undefined error.
Here's the code I'm using
var pagedContent = {
data: null
,holder: null
,currentIndex : 0
,init: function(data, holder) {
this.data = data;
this.holder=holder;
this.show(0); // show last
}
,show: function(index) {
var jsonObj = this.data[index];
if(!jsonObj) {
return;
}
var holdSubset='';
for(i=0;i<=4; i++){
jsonObj=this.data[index+i];
this.currentIndex = index;
if(this.holder=='div#firstList'){
var returnedId = jsonObj.id;
var returnedName = jsonObj.name;
var calcScore=this.data[index+i].score/this.data[0].score*100;
var resultInput="<div ' id='"+returnedId+"'><div class='name'>"+returnedName+"</div><div class='score'><div style='width:"+calcScore+"%;'></div></div>";
}
if(this.holder=='div#secondList'){
var name=jsonObj.name;
var city=jsonObj.city;
var region=jsonObj.state;
var resultInput='<li><div>'+name+'</div<div>'+city+'</div><div>'+region+'</div></li>';
}
holdSubset= holdSubset+resultInput;
}
jQuery(this.holder).html('<br/>'+holdSubset);
if(index!=0){
var previous = jQuery("<a>").attr("href","#").click(this.previousHandler).text("< previous");
jQuery(this.holder).append(previous);
}
if(index+i<this.data.length){
var next = jQuery("<a style='float:right;'>").attr("href","#").click(this.nextHandler).text("next >");
jQuery(this.holder).append(next);
}
}
,nextHandler: function() {
pagedContent.show(pagedContent.currentIndex + 5);
return false;
}
,previousHandler: function() {
pagedContent.show(pagedContent.currentIndex - 5);
return false
}
};
I call the function like this
pagedContent.init(json.users.locations, 'div#secondList');
The json looks like this
{"locations" : [ {"id":"21319","name":"Naugatuck American Legion","city":"Ansonia","region":"Connecticut"},{"id":"26614","name":"Studio B789","city":"Acton","region":"Maine"},{"id":"26674","name":"Deering Grange Hall","city":"Bailey Island","region":"Maine"},{"id":"27554","name":"Accu Billiards","city":"Acushnet","region":"Massachusetts"}]}
I may have found the problem with your code:
for(i=0;i<=4; i++){
jsonObj=this.data[index+i];
(...)
When you call show(0) you set index to 0. You expect a fixed number of items in the array (5 in the range [0..4]) but there are only 4 locations in your data.
If you are using console.log to trace the problems in firebug you might find that it is a problem with firebug. Try just running console.log on it's own.
If it is a problem with firebug try updating it. There are some development versions around which might fix the problem.
I had a similar problem and fixed it by doing the above.