Checking for undefined causes undefined error - javascript

Trying to check if some variables contain things, because they throw errors and break the ajax function when they don't. Problem is that just checking if data[2][0] contains something causes the following error:
Uncaught TypeError: Cannot read property '0' of undefined
I'd very much prefer not to check this in a previous stage. How do I check if data[2][0] is defined, without causing the actual checking to break my js?
Code:
//ajax ^
success: function(data){
var xp = data[0][0]; //Contains a string
var yp = data[1][0]; //Contains a string
var zp = data[2][0]; //Is not set, fails here
if(xp === ''){ //Tried using null & undefined here aswell
//Do nothing
} else {
var one = data[0][0];
var oneH = data[0][1];
var oneS = data[0][2];
}
if(yp === ''){
//Do nothing
} else {
var two = data[1][0];
var twoH = data[1][1];
var twoS = data[1][2];
}
if(zp === ''){
//Do nothing
} else {
var three = data[2][0];
var threeH = data[2][1];
var threeS = data[2][2];
}
//ajax continues v
Any help will be much appreciated.

You should check if a variable is undefined using typeof, not with an equality check against '':
if (typeof myVar === 'undefined')
You can also check if a variable is an array using Array.isArray(myVar)

I would check to see if data[2] exists first, and then redefine zp if it does.
var zp = data[2];
if (zp) zp = zp[0];

Related

Chrome Debugger can't access variable of static callback

I have a static class with only static method written in javascript. The pourpose of the calss and the method is to be a callback container for a certain kind of ajax call.
From the HTML page, sometimes an ajax call is raised and the static method of static class described above, is passed as callback argument.
All work just fine, i also remeber to have debugged the callback previously, but after the last chrome update, even if i can debug the callback, i can't see variable value.
I can't access variable value (when a breackpoint in the static callback is hit, so in the same scope of breakpoint) with the console nor with the watch.
This is the callback class with static method (it's a bit triky, but i prefer not simplify it because maybe the problem reside in the callback code)
/**
* List of defaults callback
* */
class CallbackDefaults {
/**
* Callback used to update price of priced articles
* #param {object} data Page of ArticleDto with actual prices
*/
static priceUpdateCallback = function (data) {
var callbackSource = "getPricesAndStock_callback";
try {
if (!data || data.Success == false || !data.ReturnData || !data.ReturnData.PageContent && data.ReturnData.PageContent.length > 0)
return;
for (var index = 0; index < data.ReturnData.PageContent.length; index++) {
var currentArticle = data.ReturnData.PageContent[index];
var item = document.querySelector(".cgi-priced[ref-code='" + currentArticle.Code + "']");
if (item && currentArticle && currentArticle.Attributes && currentArticle.Attributes.PriceData && currentArticle.Attributes.PriceData.TaxedPrice) {
var priceData = currentArticle.Attributes.PriceData;
var finalPrice = globals.isVatIncluded ? priceData.TaxedPrice : priceData.CalculatedPrice;
let precetageBadge = item.querySelector(".discount-percentage") || { textContent: "" };
let originalPrice = item.querySelector(".original-price") || { textContent: "" };
let discountedPrice = item.querySelector(".discounted-price") || { textContent: "" };
let buyButton = item.querySelector(".buy") || { disabled: false };
var percentage = globals.trustAS400Perc ?
finalPrice.DiscountPercentage :
finalPrice.CalculatedDiscountPercentage;
var percentageString = globals.trustAS400Perc ?
finalPrice.DiscountPercAsString :
finalPrice.CalculatedDiscountPercAsString;
if (!percentage || percentage <= 0)
precetageBadge?.classList?.add("d-none");
else
{
if (precetageBadge?.classList?.contains("d-none"))
precetageBadge?.classList?.remove('d-none');
precetageBadge.textContent = percentageString || "";
}
if (finalPrice.NetPriceAsStringWithCurrency == finalPrice.GrossPriceAsStringWithCurrency)
originalPrice?.classList?.add("d-none");
else
{
originalPrice.textContent = finalPrice.GrossPriceAsStringWithCurrency || "";
}
if (finalPrice.NetPriceAsStringWithCurrency)
discountedPrice.textContent = finalPrice.NetPriceAsStringWithCurrency || "";
else
buyButton.disabled = true;
//update quantity limit
var inSpinner = $(item).find("input[meta=original]");
if (inSpinner && inSpinner.length == 1) {
var updatedQuantity = currentArticle?.Attributes?.StockInformation?.AvailableQuantityFromCgi;
if (updatedQuantity && updatedQuantity > 0) {
inSpinner.inputSpinner("destroy");
inSpinner[0].max = updatedQuantity;
inSpinner.inputSpinner(globals.inputSpinnerConf);
}
}
}
}
}
catch (callbackErr) {
ClientLogManager.logError(callbackSource, callbackErr);
Toaster.getToast("tstTemplatePriceError");
}
};
}
In JQuery ajax success function i call the callback in the following way :
success: function (data) {
try
{
CallbackDefaults.priceUpdateCallback(data);
}
catch (callErr) {
ClientLogManager.logError(source, callErr)
}
}
When i place a breack point into priceUpdateCallback, for example on the following line :
var callbackSource = "getPricesAndStock_callback";
And the run code, the breakpoint will be hit, but i can't see the actual value of 'callbackSource' variable.
I can't get the value hovering, placing the variable in the watch or writing it into the console.
If i try to access the variable through console i get this error :
VM255:1 Uncaught ReferenceError: callbackSource is not defined
at eval (eval at priceUpdateCallback (CallbackDefaults.js:1:1), <anonymous>:1:1)
at priceUpdateCallback (CallbackDefaults.js:13:30)
at Object.success (ConnectionManager.js:169:25)
at c (jquery-3.6.0.min.js:2:28327)
at Object.fireWith [as resolveWith] (jquery-3.6.0.min.js:2:29072)
at l (jquery-3.6.0.min.js:2:79901)
at XMLHttpRequest.<anonymous> (jquery-3.6.0.min.js:2:82355)
I can't understand why, because i remember to have debugged that function before, and seems strange that the new chrome version just introduce a so blatant bug.
--Edit :
i am using Chrome 98.0.4758.102 (Official Build) (64-bit)

Trying to get if statement to determine 'context' of addon app

I'm working this Google Workspace Add-on app, I'm trying to get a function that sets the appropriate function for calling the document id depending on if it's called in the context of drive, docs, sheets, etc.
function checkContext(event){
var itemId;
Logger.log(event)
if (DocumentApp.getActiveDocument().getId() != null && DocumentApp.getActiveDocument().getId() != undefined)
{
itemId = DocumentApp.getActiveDocument().getId();
Logger.log(itemId);
}
else if (e.drive.selectedItems[0].id != null && e.drive.selectedItems[0].id != undefined){
var itemId = e.drive.selectedItems[0].id;
Logger.log(itemId);
}
else if (SpreadsheetApp.getActive().getId() != null && SpreadsheetApp.getActive().getId() != undefined){
var itemId = SpreadsheetApp.getActive().getId();
Logger.log(itemId);
}
else {
var itemId = SlidesApp.getActivePresentation().getId();
Logger.log(itemId);
}
As you can see, I've attempted to achieve this with a nested if statement, where the itemId variable is set to the appropriate context depending on which getId() does NOT fail. Despite my best efforts, I always get the
TypeError: Cannot read property 'getId' of null
error every time the my function is triggered.
This is the solution I ended up with, using Cooper's insight about commonEventObjects. This function returns the a string for getting a document ID in the appropriate context. The returned string can then be run with eval()to return a doc id in function with the same event.
function serveDocCall(event){
var context = event.commonEventObject.hostApp
var docCall;
if (context == "DOCS")
{docCall = 'DocumentApp.getActiveDocument().getId()';
Logger.log(docCall);}
else if (context == "DRIVE"){
var docCall = 'event.drive.selectedItems[0].id';
Logger.log(docCall);}
else if (context == "SHEETS"){
var docCall = 'SpreadsheetApp.getActive().getId()';
Logger.log(docCall);}
else {
var docCall = 'SlidesApp.getActivePresentation().getId()';
Logger.log(docCall);}
return docCall;
}

ViewerJS str.replace how to make it work

I was taking a look at ViewerJS and seems like a good fit the only problem i found was title came out with %20 instead of space. I know why, but I cannot figure out how to fix it.
so it looks like this code gets worked first. how would i fix it in here to make it display with no %20.
function getPDFFileNameFromURL(url) {
var reURI = /^(?:([^:]+:)?\/\/[^\/]+)?([^?#]*)(\?[^#]*)?(#.*)?$/;
// SCHEME HOST 1.PATH 2.QUERY 3.REF
// Pattern to get last matching NAME.pdf
var reFilename = /[^\/?#=]+\.pdf\b(?!.*\.pdf\b)/i;
var splitURI = reURI.exec(url);
var suggestedFilename = reFilename.exec(splitURI[1]) ||
reFilename.exec(splitURI[2]) ||
reFilename.exec(splitURI[3]);
if (suggestedFilename) {
suggestedFilename = suggestedFilename[0];
if (suggestedFilename.indexOf('%') !== -1) {
// URL-encoded %2Fpath%2Fto%2Ffile.pdf should be file.pdf
try {
suggestedFilename =
reFilename.exec(decodeURIComponent(suggestedFilename))[0];
} catch(e) { // Possible (extremely rare) errors:
// URIError "Malformed URI", e.g. for "%AA.pdf"
// TypeError "null has no properties", e.g. for "%2F.pdf"
}
}
}
return suggestedFilename || 'document.pdf';
}
var x = 'Some%20string%20with%20spaces';
x = x.replace(/%20/g, ' ');
console.log(x);

Error assigning value to JavaScript class property

I am getting an error while setting a class property in javascript class. I am using nodejs prompt module to get user input and setting it to the class property. But i am getting following error.
TypeError: Cannot read property 'resultAge' of undefined
I figured it out that it has something to do with synchronization, but i am not able to figure it out that how to implement it for this situation.
Also i want to prompt user again until he has entered a valid number (I can not use a do while loop, what might be the solution?)
var prompt = require("prompt");
var ageTotal = function(){
this.resultAge = 0;
this.getUserAge = function(){
prompt.start();
//i want to run this until valid input is entered
prompt.get(["age"], function(err, result){
//I know i have to convert userInput to int but thats for later
this.resultAge += result.age
});
}
}
ageTotal.prototype.displayTotalAge = function(){
return this.resultAge;
}
var a = new ageTotal();
a.getUserAge();
var age = a.displayTotalAge();
console.log(age); //This is running before the above function finishes
EDIT:
The problem setting resultAge is solved but now the problem is var age = a.displayTotalAge(); is evaluated after console.log(age) which results in 0;
You need to pass the scope of ageTotal into the prompt.get callback:
var ageTotal = function(){
this.resultAge = 0;
this.getUserAge = function(){
var that = this;
prompt.start();
prompt.get(["age"], function(err, result){
that.resultAge += result.age
});
}
}

Only display 'All fields must be completed' error once

I'm trying to make a page out of javascript. I'm pretty new to all this, so bear with me.
I have a form, and when you press submit I have the following bit to see if the fields are left blank:
function calculatePrice()
{
var GasPrice = document.getElementById("number1").value;
var Distance = document.getElementById("number2").value;
var Mileage = document.getElementById("number3").value;
var norepeat = false;
if (norepeat==false && (GasPrice =="" || Distance =="" || Mileage ==""))
{
var para=document.createElement("p");
para.setAttribute("class", "error");
var node=document.createTextNode("All fields must be completed");
para.appendChild(node);
var element=document.getElementById("content");
element.appendChild(para);
var norepeat = true;
}
I created the error as a paragraph tag that appears. The problem is that when I press submit more than once, it writes the error message every time. I tried the norepeat variable thing, but it doesn't seem to be working. Any help?
Though I'm not completely sure your intentions, it'd have to look something more like:
var norepeat = false;
function calculatePrice() {
if(!norepeat && (/* other conditions here */)) {
norepeat = true;
}
return !(/* other conditions above */);
}
Where norepeat is defined in a global scope. Also, remember to use === as opposed to ==. And trimming the string before testing it wouldn't be a horrible idea...
But, wouldn't you want the errors to still persist if the user hasn't corrected them - isn't that the point of validation?
I think what you are trying to do is this. This assumes you add a new div "myError" that holds your error message. You'll also need to consider not submitting the form too if validation doesn't pass.
function calculatePrice() {
var GasPrice = document.getElementById("number1").value;
var Distance = document.getElementById("number2").value;
var Mileage = document.getElementById("number3").value;
var error = document.getElementById("myError");
if (GasPrice == "" || Distance == "" || Mileage == "") {
error.style.display = "block";
return false;
}
else {
error.style.display = "none";
return true;
}
}

Categories