javascript - if statement excecutes both if and else blocks - javascript

This is my code:
var counter = 0;
function showAddButton() {
var cnt = document.getElementsByClassName('img-cntnr').length;
counter++; // for detecting double excecution in debugger
if (cnt < 4) {
$('#div-add').show();
} else {
$('#div-add').hide();
}
}
//someweher in my code
showAddButton();
when I call function in my code, JavaScript executes both $('#div-add').show(); and $('#div-add').hide(); lines.
I've defined a variable (counter) and watched that in debugger for detecting parallel twice call. but there is not any parallel execution and in first call if-statement executes both blocks!
how can I fix that?
Thank You.

Your issue is most likely your if statement is not the logic you want perhaps your < should be a >, because even if you were hitting it multiple times that shouldn't really effect the results of the problem because the only way for the else to hit would be if you count was actually greater than what you expected.
So either something else is hiding the div, something is modifying the class count, or your logic is not what you expected it to be.
However you can try this line of code which will get rid of all the excess logic you have
$('#div-add').toggle($('.img-cntnr').length < 4)
you can use a boolean in the toggle fuction to set the display
you can see the toggle documentation here

Here look at this jsFiddle
I cannot see any duplicate calls, nor that both blocks of if/else are executed in one call.
showAddButton always shows element because it depends on:
document.getElementsByClassName('img-cntnr').length;
which gets length of how many elements matched img-cntnr class. So, unless you are adding elements with that class to the DOM, that count will always be the same.
If you can show us jsFiddle that prints both show and hide we will have something to go by.

There is definitely something else that is causing the code to run again. What I would do is add a killer to your js and modify the else statement to look like this:
var counter = 0;
var killer = false;
function showAddButton() {
var cnt = document.getElementsByClassName('img-cntnr').length;
counter++; // for detecting double excecution in debugger
if (cnt < 4) {
$('#div-add').show();
killer = true
} else if(killer === false) {
$('#div-add').hide();
}
}
//someweher in my code
showAddButton();

Related

How do I get my if/else statement to run a bunch of functions if my IF statement is false?

So what I am trying to do is make a website that can convert the percentages of each letters average frequency in the english language to the amount of times they should appear in a given message length, and here is the part of my code that isn't working.
var Messagelength = prompt("What is the length of a single passage from the broken-up cryptogram? Write down as the numbers appear, or else you will need to refresh this page and try again.");
if (0 >= Messagelength)(true){
confirm("No negative numbers or 0 are accepted")};
if (0 >= Messagelength)(false){
var MessagelengthA = function(number) {
var PercentageA = number * 0.08167;
confirm(PercentageA);
};
};
What I want it to do is run the rest of my script like normal, but only if the number that is given from a prompt asked in the unseen part of the code is greater than 0.
So after a few attempts with what people have told me to do, I've ended up deciding this is my best stepping stone towards my goal. The problem remains though, it doesn't work. If I were to remove the second if statement, the first plays regardless, and if I remove the first one or just leave the second if statement, then nothing happens, not even the initial prompt deciding what the value of Messagelength is. So to recap, my question is, how do I get the page to run a script of 26 different functions, but only if the number the user puts in the prompt is greater than 0, and NOT run those 26 functions if it is NOT greater than 0?
EDIT: I was able to find my error and correct it. I had a semicolon at the end of my if statement, and it shouldn't have been there. The script is finally working the way I had wanted it too. Thanks!
You said it in your question title. This is an if/else statement, so put the rest of the code in the else block.
var MessagelengthA = function(number) {
var PercentageA = number * 0.08167;
confirm(PercentageA);
};
if (MessageLength <= 0) {
alert("No negative numbers or 0 are accepted");
} else {
MessageLengthA(MessageLength);
// rest of code here
}
Remove continue. That's for restarting loop bodies.
An if statement merely provides a way of running code if a given condition is true. If it is, that block of code run. Regardless of if it does or not, the following block runs.
if (true) {
console.log('The condition is true so I run');
}
console.log('I run just because I come next in the script');
if (false) {
console.log('I will never run');
}
console.log('Again, I will run');
So your code will automatically run after your if statement. What it sounds like you want is a way to prevent the following code to run under some circumstances. The simplest way is to use an else.
if (true) {
console.log('true condition, I run');
} else {
console.log('I do not since the preceding `if` block did');
}
if (false) {
console.log('I will not run');
} else {
console.log('since the condition failed, I will run');
}

Why does this code create an infinite loop?

I have a JavaScript problem. I have a function that runs when I hit a button, the variables are changed via JavaScript. Everything in the function runs properly but this one last part:
else if (upgrade == "upgMiner4") {
var cost="500";
var qty="1";
var readCash=parseInt(document.getElementById("cash").innerHTML);
while (readCash >= cost) {
document.getElementById("cash").innerHTML += "-"+cost;
document.getElementById("cash").innerHTML = eval(document.getElementById("cash").innerHTML);
document.getElementById("gpt").innerHTML += "+"+qty;
document.getElementById("gpt").innerHTML = eval(document.getElementById("gpt").innerHTML);
}
}
When I run this code, it freezes and creates an infinite loop. I don't see the problem here, so I would like to know if you guys could help me, thanks!
-Zachucks
Your code inside the while loop does nothing to update readCash or cost, so if the condition (readCash >= cost) is true, this will never change, and the while loop will never exit.
I should add that a reader cannot tell what the evals are evaluating--so it's hard to be sure what is going on. However, notice you assign to readCash and cost exactly one time and that you never do this again. So why would it change?
Because you set readCash value only once and don't update it together with innerHTML with your div. That's why your loop doesn't end.
Working code:
while (readCash >= cost) {
document.getElementById("cash").innerHTML += "-"+cost;
document.getElementById("cash").innerHTML = eval(document.getElementById("cash").innerHTML);
document.getElementById("gpt").innerHTML += "+"+qty;
document.getElementById("gpt").innerHTML = eval(document.getElementById("gpt").innerHTML);
readCash = document.getElementById("cash").innerHTML;
}
neither readCash or cost variable are changing in the last while loop. That's why you're facing a loop. Probably you have to increment/decrement readCash or cost vars with a logic you're missing. Or maybe you don't actually need a while statement, but simply an if

Not able to get my if else statement logic to work

I've been working on making a basic little image carousel in jQuery.
Currently at the moment I am stuck on the if else logic inside of my changeImage function.
When the user clicks on the "next" link then the next image in line should fade in. Luckily when I comment out the if else statement I'm able to achieve the images fading out but this is not what I am after. So we know it's a logic issue.
I'm just not sure how to implement the correct syntax with combining conditions within my if else statement and I'm sure this logic could also be much cleaner.
Please review
function changeImage (newIndex) {
var i = newIndex;
var current = i;
// `if` user clicks on next then slide image "right"
// something wrong here with my logic..
if ((newIndex === 'next') && i === (current < lengthOfImages - 1)) {
return current + 1;
}
else {
return 0;
}
// fadeout
listOfImages.fadeOut(transitionSpeed).
eq(i).fadeIn(transitionSpeed);
}
// click function on the next link
$('.next').on('click',function() {
changeImage('next');
});
Some feed back on how to fix this with a few hints towards a solution would be greatly appreciated.
JSFiddle
http://jsfiddle.net/kapena/v82pvq7x/1/
Return statement will exit the function. Anything after it will NOT run. If you want to actually return the number, you need to do it at the end.
I think you actually want to set current and not to return. Also your logic really does not make any sense. Most people would do the check like this:
current++;
if (current >= lengthOfImages) {
current = 0;
}
When 'Next' is clicked, the following is happening:
changeImage is fired, passing in 'next' as its parameter.
Within this function, a variable of i is declared and set as 'next'.
A variable of current is also being set to i, which is currently set to 'next'.
Your if statement checks to see if newIndex(the passed in parameter) is equal to 'next' as well as if i is equal to a boolean of current < lengthOfImages - 1. This is evaluating to a boolean, and i is not a boolean. This is why your function is not firing appropriately.
Your return statements in your conditionals are causing your function to complete, making it so your fadeOut and fadeIn transitions never get a chance to execute.
This part
if ((newIndex === 'next') && i === (current < lengthOfImages - 1))
is always false:
i = 'next'
current = 'next'
(current < lengthOfImages - 1) is a boolean
therefore the === is always false, and flow goes to the return clause.

Unchecking and simulating a click on checkboxes in Javascript

I am admittedly a super newbie to programming in general. I am trying to design a quick piece of javascript to inject on a website for a class that will both uncheck and simulate a click on a series of checkboxes. This is nothing malicious, the web form we use to download data for use in this class presents way more variables than necessary, and it would be a lot more convenient if we could 'uncheck' all and only check the ones we want. However, simply unchecking the boxes via javascript injection doesn't yield the desired result. A mouse click must be simulated on each box. I have been trying to use the .click() function to no avail. Any help is greatly appreciated. My code below fails with an error of:
"TypeError: Cannot read property 'click' of null"
CODE:
var getInputs = document.getElementsByTagName("input");
for (var i = 0, max = getInputs.length; i < max; i++){
if (getInputs[i].type === 'checkbox')
getInputs[i].checked = false;
document.getElementById('shr_SUBJECT=VC' + i).click();
}
--------EDIT#1--------------
FYI, this is the website that I am trying to use this on:
http://factfinder2.census.gov/faces/nav/jsf/pages/searchresults.xhtml
if you search for and open up any of these tables they are huge. It would be awesome if I could easily pare down the variables by 'unchecking' and 'clicking' them all at once via javascript.
The code at the bottom ALMOST works.
The problem I am running into now is that it throws an error after the first or second run through the for loop:
"TypeError: document.getElementById(...) is null"
I understand that this is because the value it's trying to find doesn't exist? Sometimes on these tables the checkboxes are greyed out/don't exist or are otherwise 'unclickable'. My theory as to why I am getting this error is because in the table/form the 'available' ID's will start around:
shr_SUBJECT=VC03 or sh_SUBJECT=VC04
and it may then skip to:
shr_SUBJECT=VC06 then skip to shr_SUBJECT=VC09 and so on...
So if the for loop hits an ID that isn't available such as 05 or 07, it returns a null error :(
I did some reading and learned that javascript is able to 'catch' errors that are 'thrown' at it? My question now is that I'm wondering if there is an easy way to simply iterate to the next ID in line if this error is thrown.
Again, any and all help is appreciated, you guys are awesome.
OLD DRAFT OF SCRIPT
var getInputs = document.getElementsByTagName("input");
for (var i = 3, max = getInputs.length; i < max; i++){
if (getInputs[i].type === 'checkbox' && i < 10){
var count = i;
var endid = count.toString();
var begid = "shr_SUBJECT=VC0";
var fullid = begid.concat(endid);
document.getElementById(fullid).click();
}
else if(getInputs[i].type === 'checkbox' && i >= 10){
var count = i ;
var endid = count.toString();
var begid = "shr_SUBJECT=VC";
var fullid = begid.concat(endid);
document.getElementById(fullid).click();
}
}
--------EDIT#2----------
An example of a table that I am trying to manipulate can be found at this URL:
http://factfinder2.census.gov/faces/tableservices/jsf/pages/productview.xhtml?pid=ACS_12_5YR_DP02&prodType=table#
If you click on the 'Modify Table' button, you are able to select/deselect specific variables via the checkboxes. If you right-click on a couple of 'active' checkboxes and inspect the elements, and it looks something like this:
<input id="shr_SUBJECT=VC03" checked="" alt="hide SUBJECT=VC03" name="" value="" onclick="javascript:hiderow('SUBJECT=VC03');" type="checkbox">
<input id="shr_SUBJECT=VC25" checked="" alt="hide SUBJECT=VC25" name="" value="" onclick="javascript:hiderow('SUBJECT=VC25');" type="checkbox">
Thank you so much #Jonathan Steinbeck for the tip about the ternary operator, it really cleaned up my code.
The script works properly, but the problem I am running into now is that it doesn't iterate enough times after the try, catch statement. If there is a gap in the id #'s; say it jumps from shr_SUBJECT=VC19 to shr_SUBJECT=VC=24 the script will stop running. Is there a way to make it keep retrying the try/catch until it gets a valid ID # or one that exists/is an active checkbox?
CURRENT DRAFT OF SCRIPT :
var getInputs = document.getElementsByTagName("input");
for (var i = 3, max = getInputs.length; i < max; i += 1) {
try {
if (getInputs[i].type === 'checkbox'){
document.getElementById("shr_SUBJECT=VC" + (i < 10 ? "0" : "") + i).click();
}
}
catch (err) {
i+=1;
if (getInputs[i].type === 'checkbox'){
if (getInputs[i].type === 'checkbox'){
document.getElementById("shr_SUBJECT=VC" + (i < 10 ? "0" : "") + i).click();
}
}
}
}
When you call document.getElementById() with a non-existing ID, null is returned. Therefore this error means that you're trying to call the .click() method on null, which can't work.
So you should check what the correct ID naming scheme for the elements you want is. Maybe the elements' count starts with 1 instead of 0?
Also, the .click() doesn't work for all elements like you would expect as far as I know. So depending on the kind of element you are trying to retrieve you might have to create and dispatch your own event as suggested by RobG's comment.
EDIT in response to your recent edit:
You can wrap code that throws errors in a try-catch like this:
for (var i = 3, max = getInputs.length; i < max; i += 1) {
try {
document.getElementById("the_ID").click();
}
catch (error) {
console.error(error);
// continue stops the current execution of the loop body and continues
// with the next iteration step
continue;
}
// any code here will only be executed if there's not been an error thrown
// in the try block because of the continue in the catch block
}
Also, what are you doing with the 'i' variable? It doesn't make sense to assign it to so many variables. This does the same:
document.getElementById("shr_SUBJECT=VC" + (i < 10 ? "0" : "") + i).click();
The ... ? ... : ... is an operator (called the 'ternary operator') that works like this: evaluate the expression before the "?" - if it results in a truthy value, the expression between "?" and ":" is evaluated and becomes the result of using the operator; if the condition results to false, the part after the ":" is evaluated as the value of the operator instead. So while "if" is a statement in JavaScript (and statements usually don't result in a value), the ternary operator can be used as an expression because it results in a value.
By concatenating a string with something else, you are forcing the 'something else' to be converted to string. So an expression like this will usually result in a string:
"" + someNonStringVar
Also, it doesn't make sense to define variables in a loop body in JavaScript. JavaScript variables have function scope, not block scope. What this means is that any variables defined in the loop body exist inside the whole function as well. Therefore it is recommended to write all of the "var"s at the top of your function to make it clear what their scope is. This behaviour of JavaScript is called 'hoisting', by the way.
I've furthermore taken a look at the URL you've given in your recent edit but I fail to find the kind of naming scheme for IDs you describe. In which table did you find those?
Edit in response to your second edit:
You shouldn't mess with the 'i' variable inside the body of a for loop. It makes your code much harder to reason about and is probably not what you want to do anyway. You don't need to handle the next step of the iteration in the catch block. The 'i' variable is incremented even if there's an error during fetching the element from the DOM. That's why you use catch in the first place.

Javascript Function Stops Safari from Any Other Actions

I am using a Javascript function to animate counting a number up. Whenever that function runs Safari doesn't allow any other Javascript to run on the page, including actions associated with the navigation.
Here is the code:
function animateCountUp(containerSpan){
//We pull the max number from the data-number attribute on the container span.
var maxNumber = containerSpan.attr('data-number');
maxNumber = Number(maxNumber);
//Add active class at start and remove at the end. This way we don't run it again while it's already running.
//This was required for IE7 and IE8.
containerSpan.addClass('active');
var currentNumber = 0;
var i = setInterval(function(){
if(currentNumber <= maxNumber){
containerSpan.text(currentNumber);
currentNumber++;
}
else{
clearInterval();
containerSpan.removeClass('active');
}
}, 1);
}
Any feedback would be much appreciated. Thanks.
I see multiple issues:
Is containerSpan a jQuery object?
You are never stopping the interval because you aren't passing the interval ID to clearInterval like clearInterval(i).
Your interval time is set to 1ms. That's basically going to use max CPU and go way faster than can visually be seen.
If containerSpan is a jQuery object, I would try this:
function animateCountUp(containerSpan){
//We pull the max number from the data-number attribute on the container span.
var maxNumber = containerSpan.data('number');
//Add active class at start and remove at the end. This way we don't run it again while it's already running.
//This was required for IE7 and IE8.
containerSpan.addClass('active');
var currentNumber = 0;
var timer = setInterval(function(){
if(currentNumber <= maxNumber){
containerSpan.text(currentNumber);
currentNumber++;
} else {
clearInterval(timer);
containerSpan.removeClass('active');
}
}, 50);
}
Beyond this, you need to check your error console or debug console to see what javascript errors are being reported. That should always be the very first thing you look at when scripts aren't running as expected.
is containerSpan a jquery object( i.e. $('nameOf the object')) because it looks like you're using jquery methods but i dont see any jquery objects for them to be used on
try right clicking and using inspect element to see if there are any errors in your console log

Categories