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);
}
Related
Using pure vanilla JavaScript can you make this smaller? Or even more efficient?
It's a "copy" of Jquery's '$' function. Though this works different, here is the code:
function $(id,from = document) {
if(!'#.<'.includes(id.charAt(0))) id = '#' + id;
if (id.charAt(0) == '<') id = id.charAt(id.length-1) == '>' ? id.substring(1,id.length-1) : id.substring(1,id.length);
return from.querySelectorAll(id).length == 1 ? from.querySelectorAll(id)[0] : from.querySelectorAll(id).length == 0 ? false : from.querySelectorAll(id);
}
At least you can extract the result of from.querySelectorAll(id) into a variable instead of evaluating it multiple times.
And in another, just as Barmar suggested, cache the result of this function invocation somewhere out of it and keep this function simple and stupid(KISS).
Is there a possibility to write this "If" more efficient?
if((text.val(“Hello“) == false)&& (text.val(“This“) == true)&&(text.val(“Is“) == false)&&(text).val(“Me“) == false))
{
text = "This"
}
This “if“ should check, whether a value is set true or not. It should display only the “true“ one. If I make it in this way, I have to make a lot of If’s in order to have all possibilities. Is there a way to make it more efficient and better? In database all values are boolean.
To test for one of multiple conditions you could use:
var txt = text.val();
switch(txt){
case "Hello":
case "This":
case "Is":
case "Me":
case "Whatever Else":
text.val("This");
break;
}
This will allow you to test very simply for multiple conditions and respond accordingly. In this case it will return true is any of these conditions are true. To require all would be:
if (txt=="This" && txt=="Hello" && txt=="Is" && txt=="Me"){...}
This is the only way to test that all conditions are true, unless you want to use arrays and a true-false marker.
I think you might be confused as to how .val() works. If the parameter is left empty, it returns the value. If it has a parameter, it sets the value. (jQuery API Documentation) If I read your if statement correctly, it will only execute if the value of the text is equal to "This". This could be simplified by the following:
if(text.val() == “This“) {
text.val("This");
}
In case you wanted your statement rewritten, here is how it might look:
if((text.val() != “Hello“) && (text.val() == “This“) && (text.val() != “Is“) && (text).val() != “Me“))
{
text.val("This");
}
I would also recommend looking through the documentation in link above and even looking through W3Schools.com
This is an efficient way without jQuery or other library:
var text = "Hello This Is Me";
var textSplit = text.split(' ');
var count = textSplit.length;
for(i=0;i<=count;i++){
if(textSplit[i] == 'This'){
text = 'This';
alert(text);
break;
}
}
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.
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.
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.