Javascript variable scope hindering me - javascript

I cant seem to get this for the life of me. I cant access the variable "json" after I calll the getJson2 function. I get my json dynamically through a php script, and that works. But then its gone. there is a sample that I use as a guide at The InfoVis examples where the json is embedded in the init function. i am trying to get it there dynamically.
<script language="javascript" type="text/javascript">
var labelType, useGradients, nativeTextSupport,animate,json;
function getJson2()
{
var cd = getParameterByName("code");
$.get("tasks.php?code="+cd, function(data){
return data;
})
};
function getParameterByName(name)
{
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regexS = "[\\?&]" + name + "=([^&#]*)";
var regex = new RegExp(regexS);
var results = regex.exec(window.location.search);
if(results == null)
return "";
else
return decodeURIComponent(results[1].replace(/\+/g, " "));
}
(function() {
var ua = navigator.userAgent,
iStuff = ua.match(/iPhone/i) || ua.match(/iPad/i),
typeOfCanvas = typeof HTMLCanvasElement,
nativeCanvasSupport = (typeOfCanvas == 'object' || typeOfCanvas == 'function'),
textSupport = nativeCanvasSupport
&& (typeof document.createElement('canvas').getContext('2d').fillText == 'function');
//I'm setting this based on the fact that ExCanvas provides text support for IE
//and that as of today iPhone/iPad current text support is lame
labelType = (!nativeCanvasSupport || (textSupport && !iStuff))? 'Native' : 'HTML';
nativeTextSupport = labelType == 'Native';
useGradients = nativeCanvasSupport;
animate = !(iStuff || !nativeCanvasSupport);
})();
debugger;
var Log = {
elem: false,
write: function(text){
if (!this.elem)
this.elem = document.getElementById('log');
this.elem.innerHTML = text;
debugger;
this.elem.style.left = (500 - this.elem.offsetWidth / 2) + 'px';
}
};
function init(){
json = getJson2();
//init data
var st = new $jit.ST({
//id of viz container element
injectInto: 'infovis',
//set duration for the animation
duration: 800,
//set animation transition type ..................

function getJson2()
{
var cd = getParameterByName("code");
$.get("tasks.php?code="+cd, function(data){
return data;
})
};
getJson2() doesn't return anything. The callback function to $.get() returns something, but nothing is listening for that return.
It sounds like you want synchronous loading instead. $.get() is just shorthand for this $.ajax() call: (See docs)
$.ajax({
url: url,
data: data,
success: success,
dataType: dataType
});
And $.ajax() supports more features, like setting async to false.
$.ajax({
url: "tasks.php?code="+cd,
async: false,
dataType: 'json',
success: function(data) {
// data !
}
});
Which means, getJson2 then becomes:
function getJson2()
{
var cd = getParameterByName("code");
var jsonData;
$.ajax({
url: "tasks.php?code="+cd,
async: false,
dataType: 'json',
success: function(data) {
jsonData = data;
}
});
return jsonData;
};
var myJsonData = getJson2();
Or still use $.get async style, and use callbacks instead.
function getJson2(callback)
{
var cd = getParameterByName("code");
$.get("tasks.php?code="+cd, function(data){
callback(data);
});
};
getJson2(function(data) {
// do stuff now that json data is loaded and ready
});

The $.get call is asynchronous. By the time you call return data;, the function has already long since returned. Create a variable outside of your function's scope, then in the $.get callback handler, assign data to that variable.
var json;
function getJson2(){
// ...
$.get(...., function(response){
json = response;
}
});
Alternatively, you could do a sychronous Ajax call, in which case returning your data would work (but of course would block script execution until the response was recieved). To accomplish this, see the asynch argument to jQuerys $.ajax function.

A jQuery $.get call is asynchronous and actually returns a promise, not the data itself.
An elegant way to deal with this is to use the then() method:
$.get(...).then(function(data){...});
Alternately, change your ajax settings to make the call synchronous.

$.get("tasks.php?code="+cd, function(data){
return data;
})
$.get is asynchroneous. So your value is never returned. You would have to create a callback.
The same question appears here:
Return $.get data in a function using jQuery

Related

using javascript to load json data from google maps

So, this is the code I have, console.log gives me the right value, but the function doesn't return the value, even if the return is inside the timeout. I must be doing something wrong.
function countyfinder(address){
var rr =$.getJSON('https://maps.googleapis.com/maps/api/geocode/json?address=' + address.replace(" ", "%20")).done(function(data) {
var county = data.results[0].address_components[3].short_name;
//return county;//data is the JSON string
});return rr;};
function calculatetax(address, price){
var j = countyfinder(address);
setTimeout(function(){var k = j["responseJSON"]['results'][0]['address_components'][3]['short_name'];
console.log(k);//return k won't work in here either
}, 1000); return k
};
this is what I ended up with:
var jq = document.createElement('script');
jq.src = "//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js";
document.getElementsByTagName('head')[0].appendChild(jq);
function getCounty(address) {
var country;
var baseApiUrl = "https://maps.googleapis.com/maps/api/geocode/json";
var query = "?address=" + encodeURIComponent(address);
var queryUrl = baseApiUrl + query;
$.ajax({
url: queryUrl,
async: false,
dataType: 'json',
success: function(data) {
county = gmapsExtractByType(data, "administrative_area_level_2 political");
}
});
return countr.long_name;
}
function gmapsExtractByType(json, type) {
return json.results[0].address_components.filter(function(element) {
return element.types.join(" ") === type;
})[0];
}
console.log( getCounty("100 wacko lane ohio") );
I had to use a synchronous request by changing some settings in the ajax request. The drawback of this is that the browser will be locked up until you get a request response, which can be bad on a slow connection or a connection with an unreliable server. With google, most of the time, I don't think that will happen.

jQuery updating class variable values not working

I am writing a class in JavaScript for the first time and I am having some trouble writing new data to a class variable. I've been trying all sorts for hours but nothing seems to work!
function ClassName(productId) {
//create variables
this.productId = productId;
this.shop = [];
this.product = [];
//method that calls for response. On success will return {"status" : "success", "shop" : "someshop.com"}
this.auth = function() {
$.ajax({
url: "http://website.com/api/auth/",
dataType: "jsonp",
success: function(data) {
authCallback(data); //use callback to handle response
},
error: function() {
console.log("bad auth");
}
});
}
var authCallback = function(r) {
//using console.log(r) output the response OK
this.shop = r; //this runs with no errors
}
}
Now, as yo can see in the authCallback method I'm setting this.shop = r; but then if i refer back to this variable its still at its default value of [] .
var class = new ClassName(1);
class.auth();
console.log(class.shop); //this outputs []
I've also tried this in the Javascript console writing each line after each stage had been completed(waited for a response from class.auth() and output from authCallback() before then calling console.log(class.shop);
So, what am I doing wrong? Why isn't the variable updating to its new value?
When you just write:
authCallback(data);
then within authCallback you will have the wrong value of this, it'll either be null or the global object (depending on whether you're in strict mode or not).
Use:
success: authCallback.bind(this)
to ensure that this inside the callback actually represents your object.
You should also note that you cannot access this.shop until after the callback has completed. A more idiomatic implementation using modern jQuery techniques would be this:
this.auth = function() {
return $.ajax({
url: "http://website.com/api/auth/",
dataType: "jsonp"
}).done(this.authCallback.bind(this)).fail(function() {
console.log("bad auth");
});
};
this.authCallback = function(r) {
this.shop = r;
return this;
}
followed by:
var clazz = new ClassName(1);
clazz.auth().then(function(c) {
console.log(c.shop);
});

key in object returning undefind after AJAX call

I am doing an Ajax request on an XML file and mapping the XML into a JavaScript object my problem is that am logging the object and seeing the values I won't but when I try to return the values I keep getting undefined, even that all the code is inside the success callback of the AJAX request, my code is as bellow:
// Errors Object
var ErrorsObject = {};
var ErrorApplet = $('.AppletStyle1 table td');
// Ajax Request
$.ajax({
type: "GET",
url: "ECA_ADMIN_IO.xml",
dataType: "xml",
cache: false,
success: function (xml) {
$(xml).find('EcaAdminBc').each(function () {
var code = $(this).find('code').text();
var msg = $(this).find('msg').text();
ErrorsObject[code] = msg;
});
// Reformat Errors
if(ErrorApplet.length > 0) {
$(ErrorApplet).each(function(){
var Error = $(this).text();
if(Error.indexOf("SBL") >= 0){
var ErrorCode = Error.split('(')[1].replace(")","");
var ErrorText = ErrorsObject[ErrorCode];
// The Log is showing the values correctly but i cant access the object values
console.log(ErrorsObject);
// ErrorText And ErrorCode Are always undefined !!
if(typeof ErrorText != 'undefined'){
$(this).text(ErrorText);
}
}
});
}
}
});
I need additional context, but I guess what the problem is. You are trying to do some thing like this:
var myFunction = function(){
// Error Object
var ErrorsObject = {};
var ErrorApplet = $('.AppletStyle1 table td');
$.ajax(
type: "GET",
url: "ECA_ADMIN_IO.xml",
dataType: "xml",
cache: false,
success: function (xml) {
//using response to fill ErrorsObject
ErrorsObject['Ok'] = 'This key has Value!';
//more awesome code here
//... lets check again:
console.log(ErrorsObject['OK']); //Outputs 'This key has Value!'
}
);
return ErrorsObject;
};
var myAwesomeErrorObject = myFunction();
console.log(myAwesomeErrorObject['OK']); //undefined!
console.log(myAwesomeErrorObject); //Empty object!
The problem is that myFunction finished before the success callback function gets executed (the callback is asynchronous). That is why logging myAwesomeErrorObject['OK'] shows undefined. I guess that you also tried return ErrorsObject inside the success callback, but that won't work either.
In order to fix your code you must either:
Use the ErrorsObject inside the success callback (i.e. don't return it).
Call a second function from inside the success callback, passing it the ErrorsObject.
Pass a calback function to myfunction and execute it from inside the success callback.

Issue with code inner variable

I have a code like the one stated below, please how do I get the value for (getData), using a code like:
var instanceArray = myGraph.getInstances(component)
I was thinking myGraph.getInstances(component).getData will do it, but it failed
this.getInstances = function(component) {
var getData = {};
$.ajax({
url: "/rpc/alerts2/commonObj_rpc.cfc?method=getInstances",
data: {"component":component},
type: "POST",
async: true,
success: function(data) {
getData = $.parseJSON(data);
console.log("hey");
var $render_component_instance = $("#instances").empty();
$("#instances").append($("<option />").val("all").text("All Instances (Summed)"));
$.each(getData, function (cIndex, cItem){
var $instance = $("<option />").val(cItem.si_instance).text(cItem.si_label.toUpperCase());
$render_component_instance.append($instance);
})
$("#instances").multiselect("refresh");
}
});
};`
You can't, the get is asynchronous. getInstances returns before the GET completes, so it's impossible for getInstances to return the data. (See further note below.)
You have (at least) three options:
Use a callback
Return a blank object that will get populated later, and have the code that needs it poll it periodically
Use a synchronous get (not a good idea)
1. Use a callback
What you can do instead is accept a callback, and then call it when the data arrives:
this.getInstances = function(component, callback) {
$.ajax({
url: "/rpc/alerts2/commonObj_rpc.cfc?method=getInstances",
data: {"component":component},
type: "POST",
async: true,
success: function(data) {
var getData = $.parseJSON(data);
console.log("hey");
var $render_component_instance = $("#instances").empty();
$("#instances").append($("<option />").val("all").text("All Instances (Summed)"));
$.each(getData, function (cIndex, cItem){
var $instance = $("<option />").val(cItem.si_instance).text(cItem.si_label.toUpperCase());
$render_component_instance.append($instance);
})
$("#instances").multiselect("refresh");
callback(getData);
}
});
};
And call it like this:
myGraph.getInstances(component, function(data) {
// Use the data here
});
2. Return a blank object that will get populated later
Alternately, you can return an object which will be blank to start with, but which you'll add the data to as a property later. This may be closest to what you were looking for, from your comments below. Basically, there's no way to access a function's local variables from outside the function, but you can return an object and then add a property to it later.
this.getInstances = function(component) {
var obj = {};
$.ajax({
url: "/rpc/alerts2/commonObj_rpc.cfc?method=getInstances",
data: {"component":component},
type: "POST",
async: false, // <==== Note the change
success: function(data) {
var getData = $.parseJSON(data);
console.log("hey");
var $render_component_instance = $("#instances").empty();
$("#instances").append($("<option />").val("all").text("All Instances (Summed)"));
$.each(getData, function (cIndex, cItem){
var $instance = $("<option />").val(cItem.si_instance).text(cItem.si_label.toUpperCase());
$render_component_instance.append($instance);
})
$("#instances").multiselect("refresh");
// Make the data available on the object
obj.getData = getData;
}
});
return obj; // Will be empty when we return it
};
And call it like this:
var obj = myGraph.getInstances(component);
// ...later...
if (obj.getData) {
// We have the data, use it
}
else {
// We still don't have the data
}
3. Use a synchronous get
I do not recommend this, but you could make the call synchronous. Note that synchronous ajax requests will go away in a future version of jQuery. But just for completeness:
this.getInstances = function(component) {
var getData;
$.ajax({
url: "/rpc/alerts2/commonObj_rpc.cfc?method=getInstances",
data: {"component":component},
type: "POST",
async: false, // <==== Note the change
success: function(data) {
var getData = $.parseJSON(data);
console.log("hey");
var $render_component_instance = $("#instances").empty();
$("#instances").append($("<option />").val("all").text("All Instances (Summed)"));
$.each(getData, function (cIndex, cItem){
var $instance = $("<option />").val(cItem.si_instance).text(cItem.si_label.toUpperCase());
$render_component_instance.append($instance);
})
$("#instances").multiselect("refresh");
}
});
return getData;
};
And call it like this:
var getData = myGraph.getInstances(component);
But again, I don't advocate that. Synchronous ajax calls lock up the UI of the browser, leading to a bad user experience.

Let the $.post function return the response in the parent function

I got this code:
function server_request(module,section,action,data) {
data['module'] = module;
data['section'] = section;
data['action'] = action;
var responsetxt = null;
$.post('../application/server.php', data, function(data) {
responsetxt = data;
});
return responsetxt;
}
And it return's null ?
What i want is let the server_request function return the responseText?
But at some way it doesn't work, why? And how to let it work?
You're providing a callback function to $.post, which will be run when the request is returned. The server_request function returns immediately (i.e. before the response is available) so responsetxt will still be null.
To get around this you could add a callback parameter to server_request, then execute it in the anonymous function you provide to the $.post call:
function server_request(module,section,action,data,callback) {
data['module'] = module;
data['section'] = section;
data['action'] = action;
$.post('../application/server.php', data, function(data) {
callback(data);
});
}
You could then use this like:
$(function() {
var module = x, section = y, data = z;
server_request(module, section, data, function(response) {
$('#result').html(response); // do stuff with your response
});
});
Check out continuation passing style for more information ( http://en.wikipedia.org/wiki/Continuation-passing_style and http://matt.might.net/articles/by-example-continuation-passing-style/).
You could get the return value, but only when doing a synchronous call instead of an asynchronous one:
function server_request(module,section,action,data,callback) {
data['module'] = module;
data['section'] = section;
data['action'] = action;
responsetxt = $.ajax({
"url": '../application/server.php',
"async": false,
"type": "POST",
"data": data
}).responseText;
return responsetxt;
}
Remember that a synchronous call like this freezes the browser until the server responds.

Categories

Resources