Code review - if else function - javascript

I cannot for the life of me understand why I am getting the error:
"Type error: eCurVar is undefined". Please review the code below.
var aBBTemplates = document.getElementsByClassName ("cBBTemplates");
var i = 2;
while (i < aBBTemplates.length)
{
var eCurVar = aBBTemplates[i];
if (eCurVar === e.target)
{
eCurVar.style.zIndex = 3;
// type error: eCurVar is undefined on the following line.
} else if (eCurVar.style.zIndex === 3) {
console.log (eCurVar);
eCurVar.style.zIndex = 3-1;
} else
{
console.log (eCurVar)
eCurVar.style.zIndex = i;
}
i--;
}

After each iteration i is decremented of one unit... and after three iterations it becomes negative; so you read aBBTemplates[-1] you get undefined.
When you can't understand what's going on with few console.logs, your best bet is to add a debugger; instruction, and open your devtool (usually by pressing F12).
As for your problem you could fix it by adding a check on i:
while (i < aBBTemplates.length && i >= 0) {
}

In the second case aBBTemplates[i] probably returns null

You start with i equal to 2. Lets assume that aBBTemplates[2] returns something meaningful. You do someting with it and them decrement i. Lets assume aBBTemplates[1] in meaningful.
Keep going, and sooner or lates i becomes -1, which will definately not be meaningful when reading aBBTemplates[-1]

Into if function check if also eCurrVar is not a null
if (eCurVar != null && eCurVar === e.target){
// your code
} else {
// if ecurvar == null or ecurvar != e.targer
}
Also in while check if your i is possitive number, because array do not contains items with negative indexes:
while(i >= 0 && i < aBBTemplates.length)

Related

Specific case of "cannot return length of undefined"

So I'm making this program that loops through an array and returns each character in each element of the array. The elements in the array are lines of regular english. Here's my current code:
(I'm using javascript btw)
let array = ["this", "does", "not", "work"]
var current_pos_in_line = -1
var current_line = 0
var current_char
function advance() {
current_pos_in_line += 1
if (current_pos_in_line < array[current_line].length) {
current_char = array[current_line][current_pos_in_line]
return current_char
} else {
current_char = null
newline()
}
}
function newline() {
current_line += 1
current_pos_in_line = -1
advance()
}
for (some_condition) {
advance()
}
So you get the basic idea. The advance function loops through the current_line, and when it gets to the end, it increments current_line by 1. However, the problem is at the first if...else statement. There is an error returned when I try to do array[current_line]. It's undefined!
I have no clue why this is the case, as array[1] is most definitely defined, and current_line is within the bounds of the length of array
Please help
Change newline function as follows:
function newline() {
if (current_line < array.length - 1) {
current_line += 1
current_pos_in_line = -1
advance()
}
}
That will prevent the error, though you should really check the some_condition that drives the advance function forward.

Are there instances where "!undefined" ends up being falsey? How can I work around this?

I was always under the impression that the value 'undefined' was one of the so-called 'falsey' values, and that thus negating it with '!' would cause it to become truthy. However, I have a piece of code that is meant to return a message. However, if the message ends up undefined, it's supposed to return 'false' instead (for rendering purposes). The code snippet is as follows:
if (!decodedMessage) {
return !!decodedMessage;
}
return decodedMessage;
I reason that, if decodedMessage is an actual string, then "!decodedMessage" will evaluate to false, thus skipping that conditional statement right to the final return. However, if decodedMessage is undefined, then "!decodedMessage" will evaluate to true to enter the conditional statement and return "!!decodedMessage" which I figured would be false. Needless to say, this is not working out this way at all, hence the console log statement. However, the console log confuses me the most here, as it logs undefined false to the console, which I am interpreting to mean "decodedMessage = undefined" and "!decodedMessage = false". Is there something I am overlooking? What would be a better way to handle undefined like this?
Edit: The full code for the function is as follows:
function polybiusDecode(input) {
let decodedMessage = "";
for (let i = 0; i < input.length; i += 2) {
let charCodeProxy = input[i].toLowerCase().charCodeAt(0);
while (
charCodeProxy < 47 ||
(charCodeProxy > 57 && charCodeProxy < 97) ||
charCodeProxy > 122
) {
decodedMessage += input[i];
i++;
if (i >= input.length) break;
else charCodeProxy = input[i].toLowerCase().charCodeAt(0);
}
if (i >= input.length) break;
if (input[i] === "/") {
decodedMessage += input[i + 1];
continue;
}
decodedMessage += polybiusTable[input[i] - 1][input[i + 1] - 1];
}
console.log(decodedMessage, !decodedMessage);
if (!decodedMessage) {
return !!decodedMessage;
}
return decodedMessage;
}
It could be that the string is composed of the characters 'undefined'.
const decodedMessage = 'undefined';
console.log(Boolean(decodedMessage));
If this is the case, consider fixing the code that creates decodedMessage by having undefined become an actual undefined value, rather than a string.
A workaround would be to check against 'undefined' explicitly, but that's a bit of an X/Y approach. (decodedMessage === 'undefined')

JavaScript throws TypeError saying that my variable is undefined

I don't have much experience in JavaScript, so far I have this:
function loop() {
var authorDivs = document.getElementById('ctl00_MainContent_MCPObjectInfo_dvCreatorView').getElementsByTagName("div");
for (var i = 0; i < authorDivs.length; i++) {
var divOfDiv = authorDivs[i].getElementsByTagName("div");
if (typeof divOfDiv.item(i) === 'undefined' || divOfDiv.item(i) === null) {
console.log("This is undefined or null");
}
else {
var realDivs = divOfDiv.item(i);
realDivs.item(i).textContent = "please work plz";
}
}
}
I get the following error from the console in FireFox: TypeError: realDivs is undefined on this line: realDivs.item(i).innerHTML = "please work plz";
Essentially what I have (in my mind) is a loop that goes through authorDivs and gets all of the divs within those divs and saves them in divOfDiv. I then check to see if the divs in divOfDiv are undefined or null, if they are not then those divs get saved in a variable realDivs which I then use to edit the innerHTML. That's what I'd ideally like to see happen, what is causing the error? What am I doing wrong?
Note: I do not have access to jQuery but only JavaScript.
Edit: I've added the changes suggested below and its fixed that -- thanks! But I'm now getting the following error: TypeError: realDivs.item is not a function
What is causing that? And on another note how do I know when I'm dealing with an array and when I'm dealing with an HTMLCollection? Do you just assume? I've never used a loosely typed language before so its new to me.
Well, you'll need to move that code inside the conditional block that is supposed to prevent it! Also, || "null" is not going to work as you expect, you'll need to check for || divOfDiv.item(i) === null explicitly.
So try
for (var i = 0; i < authorDivs.length; i++) {
var divOfDiv = authorDivs[i].getElementsByTagName("div");
if (divOfDiv.item(i) == null) {
console.log("This is undefined or null");
} else {
var realDivs = divOfDiv.item(i)
realDivs.item(i).innerHTML = "please work plz";
console.log(divOfDiv.item(i));
}
}
However, that still doesn't really work for two reasons:
The i index you use to access the i-th divOfDiv comes from the iteration over authorDivs - hardly what you want. Instead, use a second loop over all divOfDivs.
Your realDivs variable does hold a single <div>, which does not have an .item method. You'd just directly access its .innerHTML property.
So you should use
var authorDivs = document.getElementById('authorView').getElementsByTagName("div");
for (var i=0; i<authorDivs.length; i++) {
var divsOfDiv = authorDivs.item(i).getElementsByTagName("div");
for (var j=0; j<divsOfDiv.length; j++) {
var realDiv = divsOfDiv.item(j);
realDiv.innerHTML = "please work plz";
console.log(realDiv);
}
}
it will happen in case when your if (typeof divOfDiv.item(i) === 'undefined' || 'null') returns true. Then you never initialize realDivs (what would happen if condition was falsy). Later you try to call item function on that unitialized object
There are two problems in the code.
comparing DOM object with 'undefined' and null. If div tag is not available in authorDivs[i], it will return empty DOM array. So, comparision of empty DOM array with undefined and null is not good approach. We can use array length property for doing validation.
divOfDiv = authorDivs[i].getElementsByTagName("div");
if(divOfDiv.length > 0) { console statement}
As item(i) is already return single DOM element, item(i) of "realDivs" variable is not proper approach. In addition to this, innerHTML method needs to be used after validating whether realDivs contains DOM element. Please update the code as below.
var realDivs = divOfDiv.item(i);
realDivs ? (realDivs.innerHTML = "please work plz"): null;
Note : item(i) will return null if DOM is not available.

Javascript for loop behaving as though 2=21

I've found a lot of discussion about javascript validation functions for forms but can't find anyone running into this particular problem.
In the code below, even though there are 21 values in the array 'fields[]', the for loop ends after 2 iterations. The last alert it pops reads "1 < 21" - it's as though it thinks 2 is not less than 21.
I thought it might be a data type error but can't figure it out. Thanks to anyone who can see it.
var fields = new Array;
var fields = [
document.forms["survey"]["Q1Age"].value,
document.forms["survey"]["Q2Gender"].value,
document.forms["survey"]["Q3Education"].value,
document.forms["survey"]["Q4Field"].value,
document.forms["survey"]["Q6Other"].value,
document.forms["survey"]["Q7Edited"].value,
document.forms["survey"]["UserAccount"].value,
document.forms["survey"]["Whole"].value,
document.forms["survey"]["Sections"].value,
document.forms["survey"]["Images"].value,
document.forms["survey"]["Keywords"].value,
document.forms["survey"]["writing"].value,
document.forms["survey"]["trustworthy"].value,
document.forms["survey"]["accuracy"].value,
document.forms["survey"]["bias"].value,
document.forms["survey"]["info"].value,
document.forms["survey"]["Viz1"].value,
document.forms["survey"]["Viz2"].value,
document.forms["survey"]["VizDescription"].value,
document.forms["survey"]["VizOver"].value,
document.forms["survey"]["submit2"].value
];
var err = 0;
//Start Validation Loop
for(var i = 0; i < fields.length; i++) {
alert(i + " < " + fields.length); //test how many iterations
//Check Fields in Array to Make Sure they are not Empty
if(fields[i].value == "" || fields[i].value == "Select One") {
err++;
}
}
if(err === 0) {
//Submit Form
//document.survey.submit();
return true;
} else {
//If there are errors, return false and alert the user
alert("Please fill out all of the fields.");
return false;
}
}
Since you are getting the input's value when you are creating the array your array elements are already strings, so in your if statement you are trying to get property value from a string, which is probably causing the script to end cause it is trying to access an undefined property
Your if statement should be this.
if(fields[i] == "" || fields[i] == "Select One") {
err++;
}

Javascript function to compare two versions

Im writting a function to compare 2 versions, and return true if the second is bigger then first version.
but my algorithm have a "hole", and I cant figure out how fix.
function compareversion(version1,version2){
var result=false;
if(typeof version1!=='object'){ version1=version1.toString().split('.'); }
if(typeof version2!=='object'){ version2=version2.toString().split('.'); }
for(var i=0;i<(Math.max(version1.length,version2.length));i++){
if(version1[i]==undefined){ version1[i]=0; }
if(version2[i]==undefined){ version2[i]=0; }
if(version1[i]<version2[i]){
result=true;
break;
}
}
return(result);
}
this exemples return as expected
compareversion('1','1') //false
compareversion('1','1.0.0') //false
compareversion('2.0','1.0.0') //false
compareversion('1.1','1.2') //true
compareversion('1','1.0.0.1') //true
but this
compareversion('1.1.0','1.0.1') //return true but should be false
This should work:
function compareversion(version1,version2){
var result=false;
if(typeof version1!=='object'){ version1=version1.toString().split('.'); }
if(typeof version2!=='object'){ version2=version2.toString().split('.'); }
for(var i=0;i<(Math.max(version1.length,version2.length));i++){
if(version1[i]==undefined){ version1[i]=0; }
if(version2[i]==undefined){ version2[i]=0; }
if(Number(version1[i])<Number(version2[i])){
result=true;
break;
}
if(version1[i]!=version2[i]){
break;
}
}
return(result);
}
The reason compareversion('1.1.0','1.0.1') fails is that your code first compares 1 to 1, then 1 to 0 (it does not break here since it only breaks if version1[i] < version2[i]) and then 0 to 1.
Since 0 < 1, it returns false.
If version1 is at that index bigger, you know it should return false. You only need to continue if they are equal.
if(version1[i]<version2[i]){
result=true;
break;
}
if(version1[i]>version2[i]){
result=false;
break;
}
// Will only get here if both are equal, in all other
// cases you broke out of the loop. So only continue
// checking the next index when this one was equal.
Your problem is that if you have 1.1.0 and 1.0.1,
the function does not reach the break when you need it to
if(version1[i]<version2[i]){
result=true;
break;
}
it keeps comparing the numbers until the end.
you get 1<1 == false, the if does not run
then you get 1<0 == false, the if does not run
and then 0<1 == true, if makes result = true.
you would need:
if(version1[i]<version2[i]){
return true;
}else
if(version1[i]>version2[i]){
return false;
}
None of these answers is optimal for the following reasons:
your parameters being passed in can be strings. later on you convert them to an array. this is expensive and goes against good coding practice. NEVER change the type of a variable after it has been initialised! Create a new variable to hold the array.
The function continues through the loop even after it has enough info to return with a result.
You basically want to start at the major version and work down to the minor version. As soon as you find one that is not equal, you want to return. It is standard when doing a greater than, less than operation in function(a,b) that the return value of the function should be :
1 = a > b
-1 = a < b
0 = a===b
Otherwise, anyone calling this function would not know what it returns true for unless they look at the internals of it. If minified and obfuscated, this could be a waste of time.
I have rewritten and improved the function with this in mind.
function (versionA, versionB) {
var arrA,
arrB;
arrA = typeof versionA !== 'object' ? versionA.toString().split('.') : versionA;
arrB = typeof versionB !== 'object' ? versionB.toString().split('.') : versionB;
for (var i = 0; i < (Math.max(arrA.length, arrB.length)); i++) {
arrA[i] = typeof arrA[i] === 'undefined' ? 0 : Number(arrA[i]);
arrB[i] = typeof arrB[i] === 'undefined' ? 0 : Number(arrB[i]);
if (arrA[i] > arrB[i]) {
return 1;
}
if (arrA[i] < arrB[i]) {
return -1;
}
}
return 0;
};
version1 = version1.toString();
version2 = version2.toString();
var matchFound = false;
if(version1.length != version2.length){
//Different Versions
}else{
//They are the same length so compare each element
FIND:
for(var i = 0; i < version1.length; i++){
var match = version[i].match(version2[i]){
if(match == ""){
//Match found
matchFound = true;
break FIND;
}
}
return matchFound;
Using localeCompare works pretty well.
The below link have my solution used in comparing version number
https://stackoverflow.com/a/73749865/13970597

Categories

Resources