Accessing a global dictionary in a function - javascript

My webpage uses ajax requests to fetch info of different items in my store. However, as of now, everytime you click an item (even the same item) it will reload the data, which is unnecessary as the data is somewhat static. So I tried to fix the problem like so;
var loaded = {}; //save loaded items in dictionary, so it is not necessary to load them again.
function loaditem(item){
if(item.text() in loaded){
postdata = {
item: item.text()
};
$.ajax({
type: "POST",
url: "iteminfo/fetch.php",
data: postdata,
dataType: "json",
success: function(data) {
loaddata(data);
loaded[item.text()] = data; //item.text() is the name of the item in this case
},
error: function() {
console.log('Something went wrong');
}
});
} else {
loaddata(loaded[item.text()]);
}
So to explain the function: the function gets item, which is iniated by html like so: <li onclick="loaditem($(this))">item</li>. The function checks if the name of the item is in loaded (key checking) and if it isn't, it will load the data and save it into loaded.
Problem statement: however, when an item is clicked I get this error:
Uncaught TypeError: Cannot use 'in' operator to search for 'itemname' in undefined
So I searched the web, including StackOverflow, for an answer but I stumbled upon this answer which doens't even give a bloody answer (only an explanation) to the question! How can I access the global var 'loaded' from my function?

Related

Load AJAX in parent page, give access to variables in child pages

I've got a parent page that houses a series of iframes. These all reside on the same domain.
I've got an AJAX call that runs within each iframe when it loads and it retrieves some JSON for me that I'm using to populate inputs that reside within it. It's the same information being retrieved by each iframe.
Currently, I'm running that AJAX call inside of each iframe. This doesn't strike me as particularly performant and I'm encountering issues with this. In some cases depending on the order the DOM loads, one iframe will have the correct data available while another won't have any at all.
My thought now (and open to suggestion) is to load the AJAX once within the parent page, store the data I need as local storage variables and then call those from within each iframe. Idea being it loads once (before the iframes are called) so that the data is there and defined, every time.
As a rough proof of concept I've got this;
Parent page
$.ajax({
url: 'https://www.urlofsite.com/mylookupfile.php',
type: 'POST',
dataType : 'text',
data: {Finder: finderID},
success: finderAccess,
error: finderDecline
});
function finderAccess(data) {
console.log("sucessful send:");
// Parsing the returned data from the DB into a JSON object
var useableData = $.parseJSON(data);
console.log(useableData);
// Set the session variables that will be used by each form
localStorage.setItem('fName', useableData.fname);
const sessfName = localStorage.getItem('fName');
localStorage.setItem('lName', useableData.lname);
const sesslName = localStorage.getItem('lName');
}
//error function and some other non-related scripts follow
So now I've got my session vars set and it works within the parent page. If I call something like
$(".class-name-of-a-p").html(sessfName);
The paragraph with that class properly displays the value stored in the variable.
Moving onto the iframe now...
Iframe
$("#person_first_name").val(sessfName);
$("#person_last_name").val(sesslName);
My understanding of the HTML Local Storage method of creating local storage variables is that they are available as long as the domain is the same. That's the case here, but, in the iframe the console tells me the variables don't exist and throws an error.
Store the Ajax request in the window object (in your top-level frame):
window.lookup = $.ajax({
url: 'https://www.urlofsite.com/mylookupfile.php',
type: 'POST',
dataType : 'text',
data: {Finder: finderID},
});
Now, in each of your child frames, you can do
window.parent.lookup.done(function (data) {
// work with data
});
and all iFrames will receive the request as soon as it's there.
This works because $.ajax returns a promise. This promise is stored in window.lookup. You register as many .done() callbacks with a promise as you like - all of them will be notified when the promised result (the Ajax request in this case) is available. It also caches the data - frames that load later (or are created later) will receive the result immediately.
If you want to do some pre-processing before you hand down the data to your child frames, use .then() in the main top frame:
window.lookup = $.ajax({
url: 'https://www.urlofsite.com/mylookupfile.php',
type: 'POST',
dataType : 'text',
data: {Finder: finderID},
}).then(function (data) {
var modifiedData = doSomethingWith(data);
return modifiedData;
});
Now all child frames will receive modifiedData.
Error handling can be done in the top frame (this error handler will be called once):
window.parent.lookup.done(function (data) {
// work with data
}).fail();
url: 'https://www.urlofsite.com/mylookupfile.php',
type: 'POST',
dataType : 'text',
data: {Finder: finderID},
}).fail(function (jqXHR, textStatus, errorThrown) {
finderDecline();
});
or in the child frame (this will be called once per frame):
window.parent.lookup.done(function (data) {
// work with data
}).fail(function (jqXHR, textStatus, errorThrown) {
// do something appropriate
});
or in both.

How to handle API call error with jQuery AJAX?

I am making a weather app as a school project. I have an input through which the user is supposed to enter a name of a city to get the weather from an API. If the user misspells the name of the city I get an error in the console. I'd like to catch this when it happens and display some message to inform the user to correct the input. I searched other questions on StackOverflow and jQuery site as well, but didn't get my answer so that's why I'm here.
My code looks like this:
$.ajax({
type: 'GET',
url: 'http://api.openweathermap.org/data/2.5/find?q=' + valueFromInput + '&units=metric&type=like&mode=json&APPID=cdb7ecf86aa724f19f723f964e5f15ae',
dataType: 'json',
success: function (weatherData) {...//code}
I tried putting the ajax inside a try/catch block and added error: function().. beneath success, it still doesn't display an error message.
Why isn't this working? Is this easier to do in plain javascript?
Add an if statement to your success function to check if the list has elements in it. Otherwise you will get an error trying to get the name of an element that doesn't exist.
success: function (weatherData) {
if (weatherData.list.length > 0)
document.getElementById("cityNameCountry_").appendChild(document.createTextNode((weatherData.list[0].name)));
}
From your comment it seems that you go and use this:
weatherData.list[0].name
your response as you mentioned is like this
"message":"like","cod":"200","count":0,"list":[]
You should check your response in order to see if you have any server errors.
My guess from what you have provided seems like you don't take into consideration neither the response code nor the number of items. You should change your ajax success handler to something like the following.
$.ajax({
type: 'GET',
url: 'http://api.openweathermap.org/data/2.5/find?q=' + valueFromInput + '&units=metric&type=like&mode=json&APPID=cdb7ecf86aa724f19f723f964e5f15ae',
dataType: 'json',
success: function (result) {
// Error handling
if (result.code != '200'){
alert('some kind of error');
return false;
}
// Checking the number of list items
if (result.list.length > 0){
document.getElementById("cityNameCountry_").appendChild(document.createTextNode((result.list[0].name)));
}
}
});

Getting null in return when executing Ajax request

Ajax request is executing, but it returns not curent_day variable but null.
Js:
$.ajax({
url: 'planing/next-day',
data: {new_curent_day: $('.owl-item.center .slide_day').text()},
dataType: 'json',
type: 'POST',
success: function(curent_day) {
alert(curent_day);
},
error: function(xhr, status, error) {
alert(xhr.responseText + '|\n' + status + '|\n' +error);
}
});
Controller:
public function actionNextDay() {
if (Yii::$app->request->isAjax){
$this->planing_model->curent_day = Yii::$app->request->post('new_curent_day');
return Json::encode($this->planing_model->curent_day);
}
}
May be the problem is your are sending the POST data as JSON so your not able get it through
Yii::$app->request->post('new_curent_day');
Try this they have updated JSON parser set and to get the JSON value through yii.
Error in accessing post json data in yii2
Use the Javascript console and debugger in your browser to see what $('.owl-item.center .slide_day') contains. Make your API endpoint log what it gets in the post variables.
The typos in variable names make me worry that you might refer to the wrong thing. planing has two n's, curent has two r's. This code looks consistent at least but if I came across this code I would suspect current and curent got mixed up.

Ajax call via JSON returning variables that aren't there and I can't delete or change

I have a script making an AJAX call:
$.ajax({
url: pageURL,
data: loadData,
type: 'POST',
cache: false,
dataType: 'json',
success: function (data) { //if the call was successful
console.log(successFunc);
dataNew = data;
delete dataNew.total;
console.log(dataNew);
console.log(dataNew.total);
successFunc(dataNew);
},
error: function (xhr, status, errorThrown) { //throw errors if we fail
$('#loading').css('display', 'none'); //hide loading popup
$("#login").modal('hide');
if (typeof errorFunc !== "undefined") errorFunc(); //if there is a function associated with failing call it
scripts.throwNetworkError(xhr, status, errorThrown, errorType);
},
timeout: 15000 // wait 15 seconds before failing
});
It calls to a PHP page that returns a JSON encoded object:
$returnData = json_encode($retData);
echo $returnData;
The problem is, I was having trouble with a particular variable, $retData->total, that was treating numbers like strings and adding them together like "543" instead of 12. But no matter what I did, I couldn't fix it.
So I removed every mention to the variable "total" in the PHP script. Changed the name to "totalNum". So in the JSON object, totalNum would come through, but ALSO "total", even though that variable doesn't exist!
Below is the result of the console.log(dataNew) that was returned:
Object
cart: [Object, Object] (2)
mark0: "XXA"
message: "delete"
name: null
out_of_stock: null
part_num: "854210"
quantity: null
total: "0196.443.08"
totalNum: 199.52
vendor: null
You can see "total" is still there.
Also, before I called:
console.log(dataNew);
I tried:
delete dataNew.total;
But it's still there.
I can't get rid of this variable from either end.
How do I get rid of it? Keeping in mind, ideally, I want the nice numeric variable "totalNum" to be "total", but "total" in its current form won't be altered, edited, or deleted no matter what I try.
Looks like there are some Global Ajax Event Handlers like ajaxSuccess modifying your request.responseText.

jQuery AJAX and JSON Performance Query

I am storing some JSON data in a text file to query using jQuery Ajax in my page. Currently, my text file contains around 10 facets of data (which could contain an additional 30 facets of data). The JSON data contains a questions and answers to those questions.
In my JavaScript files, I have setup different functions to get specific bits of data.
For example:
function GetAnswer(questionName) {
var correctAnswer = null;
jQuery.ajax({
type: "GET",
url: "../content/questions.txt",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: "",
async: false,
success: function (result) {
$.each(result, function (i, q) {
if (q.questionID == questionName) {
correctAnswer = q.correctAnswer;
return false;
}
});
},
error: function () { },
complete: function () { }
});
return correctAnswer ;
}
As you can see from my code-snippet, I am looping through my JSON to get the data I need. I have other functions coded in a similar fashion to get the question type, question name etc.
What I am finding is that I am calling these functions one after another to get the data I need. I think the way I am querying my JSON data is not good from a performance point-of-view since I am looping through the whole of my JSON dataset until I find a match.
Is there a better way to query my JSON data?
NOTE: I am having to use a text file to store questions due to restrictions of the technology I am using (SCORM 1.2).
Looping through your JSON object is relatively quick. What is slow (comparatively) is loading in that text file each time (though it may be cached).
Either way, I would suggest loading in the JSON either the first time the user initiates a question/answer situation, or just load it in on page load (you can do it asynchronously) and store it for later use.
Example of the latter:
jQuery(document).ready(function(){
var questions = '';
jQuery.ajax({
type: "GET",
url: "../content/questions.txt",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: "",
async: false,
success: function (result) {
questions = result;
},
error: function () { },
complete: function () { }
});
function GetAnswer(questionName) {
var correctAnswer = null;
$.each(questions, function (i, q) {
if (q.questionID == questionName) {
correctAnswer = q.correctAnswer;
return false;
}
});
return correctAnswer ;
}
});
The problem is that you have async set to false. This is bad. This halts the browser while it waits for your requests, and will cause the performance to feel very laggy.
Why not change the structure of your Q&A object to include an id for each question, and make the id an attribute in the object? Then you could pass the id to GetAnswer() and just have it go directly to the right question by referencing the correct attribute? The object could look like this:
{"myQuiz" :
"Q1" :
{ "q" : "What color was George Washington's white horse?",
"a" : "White"
},
"Q2" :
{ "q" : "In what city would you find the Leaning Tower of Pisa?",
"a" : "Pisa"
}
}
If this is assigned to result, and an id of Q2 was passed to GetAnswer(id), you could easily return result.myQuiz[id].a;
As an alternative, if the order of the questions is consistent, you could use an object that contains an array of q and a pairs, and refer to them by index rather than id.
Why not move the logic to a server-side script like PHP that can take in POST parameters and perform the queries against the JSON set and return only the record(s) you wish to receive. Or, if you are intent on keeping this in all js, you could simply store the JSON (as long as it is non-sensitive data) in a local variable and query against it locally.
You could make somekind of mechanism on the server to load data. Then you could send parameters like QuestionName and filter data. This will lower payload sent on the wire.

Categories