Vanilla JavaScript if clause executes when false - javascript

This is my first post and I am thankful in advance for all the support.
Short background:
I am part of a script team developing a script to make our tasks easier. We are using a MySQL DB to allow the team choose which features we create each wants to use. The DB is working fine, as well as the data retrieval.
Issue:
Even though the cookies we create are set to hold the boolean value False, a function is always executing the if clause it holds.
function tkAlwaysViewAll(snippet) {
console.log('Viewall: ' + snippet);
if (snippet) {
var ticketURL = window.location.href;
var showAllURL, x;
x = ticketURL.indexOf('block=');
// if the string 'block=' does not exist in the URL, it adds the parameter and
// reloads the ticket to the correct 'view all' URL
if (x == -1) {
showAllURL = ticketURL + '&block=15:.a';
window.location.href = showAllURL;
} else {
console.log('Viewall function executed');
}
}
}
The code above should execute only when the value of snippet is set to True. However, it is being executed always, ignoring the value of snippet. Below you see the output of the console.log() which has been included for the debugging only.
The first console.log() displays the value of the snippet variable.
The second console.log() will be displayed only after the page has been reloaded (or when directly using the link with the 'block' parameter, but we are aware of this and not using it).
When snippet is True:
Viewall: true
Viewall function executed
And when the snippet is False (function should not be executed):
Viewall: false
Viewall function executed
The function is not using any global variables nor being altered by any other events.
What am I doing wrong in this function?
Best regards

The reason is that you pass a String "false" to your function (cookies always store Strings). Putting that in an if() condition internally converts that String to a Boolean value. Non-empty strings are converted to true in that mechanism.
Here's what Javascript does with non-Boolean values when converting:
// converts val to Boolean and returns it
function truthy(val) {
return Boolean(val)
}
console.log(truthy("true")) // true
console.log(truthy("false")) // true
console.log(truthy("")) // false
console.log(truthy(1)) // true
console.log(truthy(0)) // false
console.log(truthy([])) // true
console.log(truthy([].length)) // false
console.log(truthy({})) // true

Related

How to fix "Function returned undefined, expected Promise or value" error when function loops

I have an android application I developed, that allows the sign up of users. I wrote a firebase cloud function that triggers when a User is created, to generate a 5-digit random integer value for the user who just signed up and it stores the generated code in firebase real time database in the following structure.
MainProject
|
|-Codes
|-UniqueUID_1
|-code:72834
|-UniqueUID_2
|-code:23784
The function that I deployed in order to make sure that the code generation is in the backend, is as seen below. There is a value "checker" which is initialised as 0. I use this value to determine when to exit the while loop. Basically I want the function to generate a 5-digit random value, then check the real time database if that generated value exists in all entries under "Codes", then if it does not exist, append it to the Codes under the relevant UID. If it exists, checker remains zero and the loop continues.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
var checker = 0;
exports.createUserCode = functions.auth.user().onCreate(event => {
while (checker == 0){
var newRand = getUserCode(89999,10000);
var userObject = {
uCode : newRand
};
//run a db query to strategically check value generated
return admin.database().ref("Codes/").orderByChild("uCode").equalTo(newRand).once("value",snapshot => {
if (!snapshot.exists()){
checker = 1;
//add uCode into respective uid slot under Codes
console.log(""+newRand+" : "+event.uid);
return admin.database().ref('Codes/' + event.uid).set(userObject);
}else{
checker = 0;
console.log("uCode "+newRand+" exists");
console.log("uCode generation failed for: "+event.uid);
}
});
}
});
function getUserCode(size, add){
return Math.floor(Math.random()*size+add);
}
I tested it and it worked fine. I thought the problem was solved. However, on the 7th to 11th trial, it gave me a Function returned undefined, expected Promise or value error. I tried it again after a while, and it generated the code fine. Some one else tested it and it brought the same error.
How can I fix this issue to ensure it always works? Thanks in advance.
It's really not clear to me what this function is supposed to do, and the top-level while loop doesn't make sense to me. However, I can see there are a few things wrong with what this code is doing.
First of all, it's depending on the global state checker too heavily. This value will not be the consistent for all function invocations, because they all won't be running on the same server instance. Each running server instance will see a different value of checker. Please watch this video series for more information about how Cloud Functions runs code.
Second of all, when checker has a value of 1 when the function starts, the function will do exactly what the error message says - it will return undefined. It should be pretty easy to see how this happens by reading the code.
To fix this, I suggest first coming up with a clear description of what this function is supposed to do when invoked. Also, I would strongly suggest eliminating dependency on global variables, unless you are absolutely certain you understand what you're doing and the effect they have.
I had the same problem a while ago. ESLint won't allow the function to complete because it evaluates whether every part of your code returns a promise.
From what i can see the first part of the if does return something. Try returning a boolean in the else block.
if (!snapshot.exists()){
checker = 1;
//add uCode into respective uid slot under Codes
console.log(""+newRand+" : "+event.uid);
return admin.database().ref('Codes/' + event.uid).set(userObject);
}else{
checker = 0;
console.log("uCode "+newRand+" exists");
console.log("uCode generation failed for: "+event.uid);
return false;
}

Is there a way to hijack what is in the DOM?

When I console.log a value, I get immediate response. But, the html takes time.
I know what the issue is and it has nothing to do with async or anything.
Is there a way to get what you are console.logging without doing a return?
Possibly saving it in localStorage.
"status" comes from third party API where it's boolean.The value changes from true to false based on user input. Which is correct. But, HTML takes time for it to change in timely manner
public elementEvent($event) {
this.isValid = $event.status;
console.log($event.status);
}
//output: true
<div>{{isValid}}</div>
//output: false
So here is what I had to do:
public elementEvent($event) {
this.isValid = $event.status;
this.ref.detectChanges();
}

How would one set the initial value of an editable div?

So, I've got a notepad extension for Google Chrome that syncs and displays stored notes from a user. Currently my problem is as follows.
When the extension is run for the first time after download, the word 'undefined' is displayed in the editable div (id = edit_notepad). I want it to just be blank instead of displaying anything. Obviously, I know its undefined because the user hasn't been able to add any text yet.
Picture of what's displayed on initial run:
From my content script, here are my chrome.storage get and set functions (which do work):
document.body.onload = function() {
chrome.storage.sync.get("edit_notepad", function(items) {
if (!chrome.runtime.error) {
console.log(items);
document.getElementById("edit_notepad").innerHTML = items.edit_notepad;
}
});
}
document.getElementById("edit_notepad").onkeyup = function() {
var d = document.getElementById("edit_notepad").innerHTML;
chrome.storage.sync.set({ "edit_notepad" : d }, function() {
if (chrome.runtime.error) {
console.log("Runtime error.");
}
});
}
I presume I'm going to need some sort of if statement, but after hours of playing around, I'm lost as to what exactly it'd contain. The issue I've kept running into is that whatever I set the initial value of edit_notepad to, it always reverts back to "undefined" even when a user has written some notes! e.g. "This is a notes test" would revert back to "undefined" when the notepad is closed and reopened.
Well, an easy way to do this would be to specify a default value in your chrome.storage.sync.get(). Doing so would apply the default value when the key does not exist in the storage. However, given that you are replacing any contents which might already exist, the better solution would be not to set the contents when you have no value, or an invalid value, stored. The only valid value will be a string. This will prevent you from overwriting any default value supplied by the webpage when you have no value stored. Thus, an if statement something like the following should work (alternately, you could test for !== 'undefined':
document.body.onload = function() {
chrome.storage.sync.get("edit_notepad", function(items) {
if (!chrome.runtime.error) {
console.log(items);
if(typeof items.edit_notepad === 'string') {
document.getElementById("edit_notepad").innerHTML = items.edit_notepad;
}
}
});
}
Note: Storing the contents of the editable <div> on every key will result in many users running into both the MAX_WRITE_OPERATIONS_PER_MINUTE and MAX_WRITE_OPERATIONS_PER_HOUR quotas. You will need to have some other criteria for writing to storage.sync. Perhaps you could temporarily store the value in storage.local and only to storage.sync every couple of minutes.

Why isn't my cookie updating?

I am making a dark mode for a site using a button toggle. To keep the dark mode saved when changing pages, I am using cookies. When pressing the toggle again, the dark mode is disabled but is not saving and I am not sure why.
Ps. I am new at javascript so this may be a dumb mistake.
if ($.cookie('darkModeOn')){
$('html').toggleClass('dark-mode');
$('#dark-toggle').click(function(){
$.cookie('darkModeOn', false, { expires: 7 });
$('html').toggleClass('dark-mode');
});
}
else
{
$('#dark-toggle').click(function(){
$.cookie('darkModeOn', true, { expires: 7 });
$('html').toggleClass('dark-mode');
});
}
When you press the toggle button you also want to toggle the True/False value of the cookie. Now you always either set it to True or to False depending on the first state.
Use ! $.cookie('darkModeOn') as value to store into the cookie to automatically toggle the boolean value.
EDIT
It was indeed not working, and I found out that it was not working because of the boolean values.
The boolean values are stored as string ("false" and "true") since if ( "false") gives boolean true, the if is always executed. When you use integers instead of booleans this would work, but you can also change the if to:
if ($.cookie('darkModeOn')=="true") //...
If you use integers it also works:
https://jsfiddle.net/6m2ydrh2/12/
$('#dark-toggle').click(function(){
//this gets executed each click so we need to toggle the boolean value.
if ($.cookie('darkModeOn')==0){
$.cookie('darkModeOn', 1, { expires: 7 });
}else{
$.cookie('darkModeOn', 0, { expires: 7 });
}
console.log( "cookie:"+$.cookie('darkModeOn')) ;
$('#test').toggleClass('dark-mode');
});
if ($.cookie('darkModeOn')){
//this is only executed on load
$('#test').toggleClass('dark-mode');
}
See also this post: jquery cookie set value to boolean true.
The boolean values are stored as string and therefor causing problems.

Debugging script Netsuite suitescript in Chrome exception

So I am trying to add a button to the Sales Order form in netsuite that validates certain fields based on what you entered in previous fields. I am having trouble testing and debugging this in google chrome in netsuite. First, here is my code: I am adding the button that calls this function within the client script record.
function vsoeValidate(){
var calc = nlapiGetFieldValue('custbody_cv_vsoe_calculation');
calc = nlapiGetFieldValue('custbody_cv_renewal_rev_amount') - (nlapiGetFieldValue('custbody_cv_vsoe_cola') * nlapiGetFieldValue(1-'custbody_cv_vsoe_partner_disc')) - (nlapiGetFieldValue('custbody_cv_vsoe_bts_fees') * (1-nlapiGetFieldValue('custbody_cv_vsoe_partner_disc'))) /
(nlapiGetFieldValue('custbody_cv_vsoe_software_amt') * (1- nlapiGetFieldValue('custbody_cv_vsoe_multiyear_disc')));
nlapiSetFieldValue('custbody_cv_vsoe_calculation', calc);
var display = nlapiGetFieldValue('custbody_cv_vsoe_calculation_disp');
var bucket = nlapiGetFieldValue('custbody_cv_vsoe_bucket');
if(bucket === 'X'){
return false;
}
if(calc > (nlapiGetFieldValue('custbody_cv_vsoe_bucket.custrecord_cv_vsoe_maintenance_rate') *1.15) || calc < ('custbody_cv_vsoe_bucket.custrecord_cv_vsoe_maintenance_rate'*0.85)){
display = '<div style="; background-color:red; color:white;font-weight:bold;text-align:center">Out of bounds</div>';
return true;
}
else{
display = '<div style="; background-color:green; color:white;font-weight:bold;text-align:center">In bounds</div>';
return true;
}
}
when I click the button I get the error TypeError undefined is not a function.
I am really not sure where to go from here, is it because the logic inside vsoeValidate is not right or am I using the wrong type of function? Any help would be great thank you!
Update: here is the screenshot of my script record!
Try passing the function name as string i.e.
form.addButton('custpage_validatevsoe', 'Validate VSOE', 'vsoeValidate');
You mentioned that you set vsoeValidate as a validateField function. Do you want this function to run when users click the button or when NetSuite's valdiateField event is fired (upon field change, before the value is stored)?
If you want this to run on NetSuite's validateField event, then the function must return true or false; it cannot return void. Right now in your logic, you have:
if (bucket = 'x') {
return;
}
if (bucket = 'x') is an assignment operation, not an equality check. This assignment operation will return 'x', which is a truthy value, so your code will enter that if-block. You then return void (undefined), so my guess is that NetSuite is trying to do something with the result returned by your function but cannot because it returned undefined.
The validateField function also gets passed a parameter that provides the ID of the field being validated.
You will also want to inject some console logging at various points so you can figure out where your script is failing instead of just trying to guess at reading syntax.
Can you provide us with a screenshot of your Script record setup?
Also since you are using a client side script, you don't need to use the pageInit event for adding a custom button.
There is a 'Buttons' subtab, under the 'Scripts' tab when you create the Script record in NetSuite. This subtab is next to the 'Libraries' subtab.
There are two columns here, 'Label' and 'Function'.
So in your case, you can just put 'Validate VSOE' in the Label field and vsoeValidate in the Function field.
Please note that if you do it this way, the button will only be shown when you are creating or editing a record.

Categories