conditional statement, if else if - javascript

I am trying to write a if, else if condition, with some luck.
after trying for some time I have some of it working but not fully functional.
simple script to change div style for simple image gallery.
I have the first and third divs working but the second is not showing up.
I seem to understand the concept but in reverse and suspect the problem is in the else if part of the code.
I am not looking for someone to do it for me but to explain where I am reversing things.
Here is what I have working so far, but as I said something is reversed.
any thoughts or better yet explanations would be most appreciated.
function scroll()
{
if (document.getElementById('thumbs1').style.visibility=='hidden' && document.getElementById('thumbs2').style.visibility=='visible' && document.getElementById('thumbs3').style.visibility=='visible' )
{
document.getElementById('thumbs1').style.visibility='visible';
document.getElementById('thumbs2').style.visibility='hidden';
document.getElementById('thumbs3').style.visibility='hidden';
}
else if (document.getElementById('thumbs2').style.visibility=='hidden' && document.getElementById('thumbs1').style.visibility=='visible' && document.getElementById('thumbs3').style.visibility=='visible' )
{
document.getElementById('thumbs1').style.visibility='hidden';
document.getElementById('thumbs2').style.visibility='visible';
document.getElementById('thumbs3').style.visibility='hidden';
}
else
{
document.getElementById('thumbs1').style.visibility='hidden' ;
document.getElementById('thumbs2').style.visibility='visible' ;
document.getElementById('thumbs3').style.visibility='visible';
}
}

the second is not showing up
That's because your code never enters the block that shows it. Your condition for that is that thumbs2 is hidden while thumbs1 and thumbs3 are visible, which is a combination that is not apparent in any of the assignments. Seems like you have confused 1 and 3 somewhere.
Tip for spotting such mistakes easier: Create variables for the style objects and reuse them instead of executing the code to access them every time. That's not only faster, but also makes the code shorter and more readable. Or even better, an array:
var styles = [];
for (var i=0; i<3; i++)
styles[i] = document.getElementById("thumbs"+(i+1)).style;
if (styles[0].visibility=='hidden' && styles[1]=='visible' && styles[2].visibility=='visible') {
styles[0].visibility='visible';
styles[1].visibility='hidden';
styles[2].visibility='hidden';
} else if (styles[0].visibility=='visible' && styles[1].visibility=='hidden' && styles[2].visibility=='visible') {
styles[0].visibility='hidden';
styles[1].visibility='visible';
styles[2].visibility='hidden';
} else {
styles[0].visibility='hidden' ;
styles[1].visibility='visible' ;
styles[2].visibility='visible';
}
If your pattern had been more predictable (like rotating the visibility), a programmatical approach would be possible as well now.

Hard to tell what you're trying to do, but if you want to just reverse all 3:
function scroll()
{
var t1 = document.getElementById('thumbs1'),
t2 = document.getElementById('thumbs2'),
t3 = document.getElementById('thumbs3');
t1.visibility = t1.visibility === "hidden" ? "visible" : "hidden"
t2.visibility = t2.visibility === "hidden" ? "visible" : "hidden"
t2.visibility = t3.visibility === "hidden" ? "visible" : "hidden"
}
or more succinctly
function scroll()
{
var thumbs = [document.getElementById('thumbs1'),
document.getElementById('thumbs2'),
document.getElementById('thumbs3')];
for(var i=0; i<thumbs.length; i++) {
thumbs[i].visibility = thumbs[i].visibility === "hidden" ? "visible" : "hidden";
}
}

First, thanks for the thoughts. I found much understanding in the serious thoughts posted here, and i now am beginning to see the appeal of working with arrays.
The answer was simple and obvious, too many conditions. I used the ideas on variables and used a logical approach. Here is what I came up with.
function scroll()
{
var t1=document.getElementById('thumbs1'),
t2=document.getElementById('thumbs2'),
t3=document.getElementById('thumbs3');
if (t1.style.visibility=='visible' )
{
t2.style.visibility='visible';
t1.style.visibility='hidden';
t3.style.visibility='hidden';
}
else if (t2.style.visibility=='visible' )
{
t1.style.visibility='hidden';
t3.style.visibility='visible';
t2.style.visibility='hidden';
}
else
{
t1.style.visibility= 'visible';
t2.style.visibility='hidden' ;
t3.style.visibility='hidden';
}
}
Simple, huh?
Thanks again.
P.S.
would of posted the solution sooner but had to wait 8 hours to answer my own question.

Related

Image shows if condition is met

I am making a cookie clicker-esque game and i am making an upgrade bar. One icon starts off invisible and once you have 1 cursor it becomes visible. The problem is it isn't.
I have looked thoroughly and still can't find the bug.
This is in JSFiddle.
Here it is-https://jsfiddle.net/wizviper/mq0qwnvr/
Main Code-
document.getElementById("reinforcedFingerShop").addEventListener(cursorAmount >= 1, function() {
if (reinforcedFingerActive = 0) {
$(this).show();
}
});
addEventListener listens to events but you are assigning a condition to it "cursorAmount >= 1".
I guess you probably want to know when (cursorAmount >= 1) and also (reinforcedFingerActive == 0), please provide the related part of your code, so that we will be able to help you better
UPDATE
You are changing cursorAmount inside "cursorShop" function so the best place to check "reinforcedFingerActive == 0" condition is there.
document.getElementById("cursorShop").onclick = function() {
if (cookies >= cursorPrice) {
cookies = cookies - cursorPrice;
cursorPrice = cursorPrice * 1.15;
cps = cps + 0.1;
updateValue();
cursorAmount = cursorAmount + 1;
if (reinforcedFingerActive == 0) {
$(this).show();
}
}
}
I have not tested but it should work.
I think the problem come from :
if (reinforcedFingerActive = 0) {
Maybe did you forgot the second = ?
Read official MDN addEventListener documentation on how to use this function. First argument is type
A string representing the event type to listen for.
in your code your first argument is cursorAmount >= 1

Ternary operator in Javascript and grouped sentences

I have the following ternary operator condition. Is there a way of the second if statement to be included somehow in line 1, so I don't need to make another if statement? The first condition, if true, should prepare the display status change and also the checkbox change.
function change_properties(display){
var display_r = ( display === 1) ? 'block' : 'none';
/*THIS LINE - can it be integrated in the ternary if-else condition above? */
if(display) jQuery("#checkbox").prop('checked',false);
jQuery("#field").css("display", display_r);
}
Please write it like this, assuming it is ok to have display truthy rather than ===1
function change_properties(display){
$("#checkbox").prop('checked',!display);
$("#field").toggle(display);
}
or if you ONLY want to uncheck when display is 1 (truthy):
function change_properties(display){
if (display) $("#checkbox").prop('checked',false);
$("#field").toggle(display);
}
Wow, if you're willing to write really hard to read code then yes, it's technically possible:
var display_r = ( display === 1) ? jQuery("#checkbox").prop('checked',false), 'block' : 'none';
You could use && instead of the , operator... exploiting the fact that the string 'block' is truthy.
For that matter, why have the next line of code in its own line?
jQuery("#field").css("display", ( display === 1) ? jQuery("#checkbox").prop('checked',false), 'block' : 'none');
In short, lines of code are not the enemy...
EDIT: Fixed the order around the ,, which I don't know off the top of my head since I literally never do this.
But okay. Let's just write something sensible, without using the ternary operator for fun:
var display_r;
if (display === 1) {
display_r = 'block';
jQuery("#checkbox").prop('checked',false);
}
else {
display_r = 'none';
}
jQuery("field").css("display", display_r);
IMO better if you could write clear and easy to read code like following :
function change_properties(display){
if(display){
jQuery("#field").css("display","block");
jQuery("#checkbox").prop('checked',false);
}else
jQuery("#field").css("display","none");
}
Or you could use show()/hide() :
function change_properties(display){
if(display){
jQuery("#field").show();
jQuery("#checkbox").prop('checked',false);
}else
jQuery("#field").hide();
}
Hope this helps.
Is there a way of the second if statement to be included somehow in line 1, so I don't need to make another if statement?
It's possible, but that doesn't make it a good idea.
function change_properties(display){
jQuery("#field").css("display", display === 1 && jQuery("#checkbox").prop('checked',false)
? 'block'
: 'none');
}
To be clear, I really think you ought to go for the second function from mplungjan's answer:
function change_properties(display){
if (display) $("#checkbox").prop('checked',false);
$("#field").toggle(display);
}

What is the best way to set a variable with an if, else if, else statement

There has to be a better way to set the variable $callLinkContainer in the following code block:
var $callLinkContainer;
if ( $callLink.closest('class1-tel').length > 0 ) {
$callLinkContainer = $('body').find('.class1-container');
} else if ( $callLink.closest('.class2').length > 0 ) {
$callLinkContainer = $('body').find('.class2-container');
} else {
$callLinkContainer = $callLink.closest('.class3');
}
Previously, I had used a ternary operator to set the variable, but I'm pretty sure the third condition makes that impossible. I'd like to make this code more concise if it's possible to do so.
You can use several ternary operators with indentation
var $callLinkContainer = $callLink.closest('class1-tel').length > 0
? $('body').find('.class1-container')
: $callLink.closest('.class2').length > 0
? $('body').find('.class2-container')
: $callLink.closest('.class3');
The priority of the operators is so that you don't need to add parenthesis like in
a ? b : (c ? d : e)
You might want to add them for extra clarity, though.
You can nest conditional operators. The code is shorter, and with appropriate line breaks and indentation it's as readable as the if statements.
$callLinkContainer = $callLink.closest('class1-tel').length ?
$('.class1-container') :
($callLink.closest('.class2').length ?
$('.class2-container') :
$callLink.closest('.class3'));
I'd like to do the next suggestion
Encapsulate the code in several functions
function isCallLinkClosest(var callLinkSelector){
return $callLink.closest(callLinkSelector).length > 0;
}
function getCallLinkContainer(var containerSelector){
return $('body').find(containerSelector);
}
function getDataAttributeByClass(){
if ( isCallLinkClosest('class1-tel')) {
return getCallLinkContainer('.class1-container');
} else if ( isCallLinkClosest('.class2')) {
return getCallLinkContainer('.class2-container');
} else {
return $callLink.closest('.class3');
}
}
This is the best suggestion that I can do with the given information :)
Do .class1-tel, .class2 or .class3 exist at the same time?
If not, then you could possibly do something like this:
var $callLinkContainer = ($callLink.closest('.class1-tel, .class2').length
? $('body').find('.class1-container, .class2-container')
: $callLink.closest('.class3'));
If you could be more specific about class names and dom structure, the code could be even easier.

Seeing if input matches array if not alert

var tagAllowed = true;
var allowedTags =["Person","People","Dance","Word"];
if(tagAllowed === true) {
for(var i=0;i<allowedTags.length;i++){
var aTags = allowedTags[i];
if(input.val().toLowerCase() === aTags.toLowerCase()) {
tagged.append('<span unselectable="on" class="tagged '+colorize+'" title="Click To Delete">'+inputVal.trim()+'</span>');
tagSize = $('.tagged').length;
var ele = $('.tagged').last(),
subtract = parseInt(ele.outerWidth(true),10);
input.width(input.width() - subtract);
tagged.width(tagged.width() + subtract);
input.css('marginLeft','5px');
input.val("");
input.css('color','#000');
} else {
errorMess.children('span').remove();
errorMess.prepend('<span>'+errorProcess+'<span>');
errorMess.slideDown();
}
}
The following code works in a way, if the input.val() does not match it will show the custom alert errorMess and well even if the word matches it still shows the custom alert. I am wondering if maybe I am doing something wrong in my conditional. As I don't need the custom alert to appear if the words match.
If any suggestions please post. I know this isn't the best example with just a code, but I hope all of you get what I am trying to say. I just don't want the custom alert to appear if the two words match together.
You have the if-statement inside the for-loop. The input value will never equal more than one of the tags in the array. You could use a for-loop to set a boolean. Then the if-statement could follow the for-loop.
boolean isAllowedTag = false;
for(var i=0;i<allowedTags.length;i++){
var aTags = allowedTags[i];
if(input.val().toLowerCase() === aTags.toLowerCase()) {
isAllowedTag = true;
break;
}
}
if (isAllowedTag) {
// ...
} else {
errorMess.children('span').remove();
errorMess.prepend('<span>'+errorProcess+'<span>');
errorMess.slideDown();
}
}
add a break; after your input.css('color, '#000'); line. also, you should really change those last 3 lines to: input.val("").css({marginLeft:'5px', color:'#000'});. Making calls to .css() is slow, so it's better to do as much as you can in one call.

Finding in a predefined set of text options

Say, I want to see if a DOM element is a block. I can write it in three ways, depending on my mood:
// first way
if (el.currentStyle.display == "block" || el.currentStyle.display == "inline-block" || el.currentStyle.display == "table-cell")
// second way
var blocks = {"block": 1, "inline-block": 1, "table-cell": 1};
if (el.currentStyle.display in blocks)//
// third way
if (el.currentStyle.display.match(/block|inline-block|table-cell/))
I have mixed feeling about all of them. First is too verbose once I have more than one option. Second contains those arbitrary values in the object (where I put 1s this time). Third looks like overkill. (What exactly is bad about overkilling?)
Do you know another, better way? If no, any cons I am missing about these three ways?
Javascript only, please.
I like the third way; I don't think it looks like overkill at all. If you need an even shorter way then this works too:
el.currentStyle.display.match(/(e-)?(block|cell)/)
But that's not very readable...
It might be worth abstracting it all away by extending the String prototype:
String.prototype.matches = function(what) {
return (',' + what + ',').indexOf(',' + this + ',') > -1;
};
// Using it:
el.currentStyle.display.matches('block,inline-block,table-cell');
If we're primarily aiming for readability, and if this is happening more than once -- perhaps even if it is just once -- I'd move the test to a function. Then define that function whichever way you like -- probably option 1, for max simplicity there.
Overkill? Possibly. But a gift to the programmer who wants to scan and understand the code 6 months from now. Probably you :-)
function isBlock(el) {
return (el.currentStyle.display == "block" ||
el.currentStyle.display == "inline-block" ||
el.currentStyle.display == "table-cell");
}
// ...
if (isBlock(el)) {
// do something
}
Can't you use the 2nd way but check if it's undefined and then skip the ": 1" part. I haven't tested though.
It looks like you need an inArray function, here is one from the top search result:
Array.prototype.inArray = function (value) {
var i;
for (i=0; i < this.length; i++) {
if (this[i] === value) {
return true;
}
}
return false;
};
Then the forth way would look like this:
if (['block','inline-block','table-cell'].inArray(el.currentStyle.display))
Or in a more readable manner:
var isBlock = ['block','inline-block','table-cell'].inArray(el.currentStyle.display);
My prefered solution for this is:
'block||inline-block||table-cell'.indexOf( el.currentStyle.display ) >= 0
I think that this will use native code of the string and be way more efficient than the array & iteration method.

Categories

Resources