I'm sure there must be a really simple answer to this, but at the risk of sounding stupid- I can't get this switch statement to work. The input var, 'status' can be either 'public' or 'draft', and I can assure you it is only holding one of those two values as I have alerted it out at various stages, and anyway, the if statement here works. Take a look:
function switch_status(status){
if (status == 'public'){
return false;
} if (status == 'draft') {
return true;
}
^This works, but replacing the 'if' with this 'switch' statement below doesn't work.
switch(status){
case 'public':
return false;
case 'draft':
return true;
}
}
The first one to provide me with the inevitable embarrassingly simple answer wins my accolade!
EDIT: Here is my full code-
$('.status').live('click',
function(){
fullClass = $(this).attr('class');
id = fullClass.split(' ').slice(-1);
status = fullClass.split(' ').slice(-2,-1);
var newStatus = switch_status(status);
alert(newStatus);
});
function switch_status(status){
// if (status == 'public'){
// return false;
// } if (status == 'draft') {
// return true;
// }
switch(status){
case 'public':
return false;
case 'draft':
return true;
}
}
You're passing status as an array of one string (the result of slice) rather than as just a string.
When you check equality between your array and your string, it appears that coercion is causing the equality check to work. But coercion doesn't happen in a switch statement.
If I change
status = fullClass.split(' ').slice(-2,-1);
to
status = fullClass.split(' ').slice(-2,-1)[0];
then it works fine.
I suspect this problem is occuring due to type conversion.
Javascipt is generally a loosely typed language. The if statement you used earlier used a loose == comparison. This worked just fine.
However, switch statements are a different matter. For the case to be a match, the data types must match. In other words, the status must be converted to a string before it is passed to the switch statement.
I used a .each in a jquery loop and compared value to 'this'; I could clearly see that 'this' had the correct value if I used console.log. It worked in the if/else logic but failed in the switch/case logic.
The solution is:
var obj = this.toString();
switch(obj){
case 'one': ...
case 'two': ...
}
By forcing the 'this' to a string type, the logic in the switch now works.
Related
I have two arrays.
First one:
const triggerWord = ["what", "how", "where", "who", "can"];
Second one:
const myArray = query.split(" "); - it is created after splitting the user input in this case called query.
One is a fixed number of strings, that will not change as they are the trigger words. The other array is an input string that has been split into an array, separated by a space.
I am trying to build some sort of control flow that if any of the triggerWords are present within the myArray then it should call a specific function call the questionFunction(). However the else is that is should call the statement function. Here are the functions I have attempted:
#1: Switch Case:
switch (lowercaseMyArray.includes()) {
case triggerWord[0].toString():
questionFunction(lowercaseMyArray);
break;
case triggerWord[1].toString():
questionFunction(lowercaseMyArray);
break;
case triggerWord[2].toString():
questionFunction(lowercaseMyArray);
break;
case triggerWord[3].toString():
questionFunction(lowercaseMyArray);
break;
default:
statementFunction(lowercaseMyArray);
#2: If statement
if (lowercaseMyArray.includes(triggerWord[0] || triggerWord[1] || triggerWord[2] || triggerWord[3], 2)) {
//alert("This is a question");
questionFunction(lowercaseMyArray);
//passe onto questionFunction
} else {
statementFunction(lowercaseMyArray);
//alert(myArray);
}
#3: Bool and If Statment
var lowercaseMyArrayBool = lowercaseMyArray.includes(triggerWord);
if (lowercaseMyArrayBool === true) {
questionFunction(lowercaseMyArray);
} else {
statementFunction(lowercaseMyArray);
}
The idea being that if it contains a trigger word then the input must be a question and therefore treated as such. However if it doesn't contain the trigger words then the input is a statement and must be treated as that.
Any help or pointers will be greatly appreciated.
Resolved this with the following code:
const intersection = triggerWord.filter(element => lowercaseMyArray.includes(element)).length;
const intersectionBool = Boolean(intersection);
I just needed to cast the filtered array length as a Boolean, to get an accurate true or false result.
I am having some trouble with this current lesson on control flow with JavaScript...
The question states:
In this exercise, you will be given a variable, it will be called value.
You will also be given another variable, it will be called greaterThanFive.
Using an 'if statement' check to see if the value is greater than 5. If it is, re-assign the boolean true.
code with stars next to it is the code I was given.
**let greaterThan5 = false;**
if (value > 5 ) {
console.log("That is true");
}
**return greaterThanFive;**
I have tried a number of different ways on how to write the correct code but it obviously is not right.
I tried assigning var value = 10;and then finishing the code as above but it says value has already been assigned. I have tried changing the boolean to let greaterThanFive = true;
The hint only tells me that "should return boolean value equal to 10" and "expected true to be false"
Please help, I have been working on this simple code it may seem for a week and do not want to move on to the next lesson without fully understanding this question.
Thank You!
You have two different variables; greaterThan5 and greaterThanFive.You also have a return statement, which will only work inside of a function.
I believe what you're looking for is something like the following, which passes a value into the function, then checks whether the value is greater than five or not, setting the variable to true inside of the if conditional if it is. The function then returns the greaterThan5 variable's truthiness:
function greater(value) {
let greaterThan5 = false;
if (value > 5) {
greaterThan5 = true;
}
return greaterThan5;
}
console.log(greater(10));
console.log(greater(3));
Which can be further simplified to a simple one-line return statement:
function greater(value) {
return value > 5;
}
console.log(greater(10));
console.log(greater(3));
So, the first clue in the code is the return statement. That means you are likely being asked to write a function that, given some value, checks to see if that value is greater than 5.
Let's define it using your existing code:
function isGreaterThan5(value) {
let greaterThan5 = false;
if (value > 5 ) {
console.log("That is true");
}
return greaterThan5;
}
So right now, we're always going to return false. All you need to do is reassign the value of greaterThanFive if value > 5. So, you can simply do that in your if-statement:
function isGreaterThan5(value) {
let greaterThan5 = false;
if (value > 5 ) {
greaterThan5 = true;
}
return greaterThan5;
}
You can now test your code by calling the function with various values:
isGreaterThan5(1); // returns false
isGreaterThan5(5); // returns false
isGreaterThan5(6); // returns true
And we're done!
I'm wondering if what confused you was the use of let. You might want to read more about var, let, and const.
if (value > 5) {greaterThanFive = true;}
I want to exit from the below if block in Javascript. if I return, then it does not check for the next if condition. How do I do that?
if ($('#id1').length > 0) {
if(yester_energy == "NaN" || yester_energy == 0){
//break from #id1
}
else{
//something
}
$("#abc").html(somthing)
}
if ($('#id2').length > 0) {
if(yester_energy == "NaN" || yester_energy == 0){
//break from #id2
}
else{
//something
}
}
Super late to the party, but for folks from search, you can use something called labeling. It's not good practice, but in rare cases that can be applied. Basically you can assign a name to the if statement that you want to break from. And anywhere in statement call break from specified name.
Code example:
my_if: if (condition) {
// do stuff
break my_if;
// not do stuff
}
in your particular case:
id1: if ($('#id1').length > 0) {
if(yester_energy == "NaN" || yester_energy == 0){
break id1;
}else{
//something
}
$("#abc").html(somthing)
}
More about labeling can be found here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label#Syntax
Even later to the party... Typically in such situations, I use a combination of if and do...while as follows...
if ( condition ) do {
// processing
if ( exit_condition ) break;
// more processing...
} while ( false );
Thus, when the break is encountered, it applies to the do...while loop, and processing continues after the while, effectively breaking out of the outer if statement...
All your code after if(isNaN(yester_energy) || yester_energy == 0) is in else block, so it'll not be executed if your data matches this if. And you just don't need anything else.
Also, if you want to check if variable got NaN value, then use isNaN() function. You can't just compare it.
Use switch statment,
switch(n)
{
case 1:
execute code block 1
break;
case 2:
execute code block 2
break;
default:
code to be executed if n is different from case 1 and 2
}
you can use function and pass command
function iff(condition){
if(condition ==0) return;
console.log("other commands")
}
iff(0);
iff(1)
Don't Use Labeling
You can do labeling as the other answer suggests, but it smells odds and it will definitely come up in code review. It will confuse readers of your code and increase the maintenance burden of your codebase.
Answer
Best is to refactor (extract out) the code inside the if-statement into a separate function that you can then return from. In addition to allowing you to exit from the code block early, it also makes your code more modular and readable.
Example (based on OP)
if ($('#id1').length > 0) {
ifInner(yester_energy)
$("#abc").html(somthing) // [sic]
}
if ($('#id2').length > 0) {
ifInner(yester_energy)
}
// Rename to something more descriptive.
function ifInner(yester_energy) {
if (yester_energy == "NaN" || yester_energy == 0){
// Break out.
return;
}
else {
// something
}
}
Adding another answer to the pool, in many cases using a try catch makes perfect sense:
if(something is allowed) {
try {
if(missing requirements) throw 'missing requirements'
//do your stuff;
}
catch {
//you may do logging and issue warning here
}
}
$(document).ready(function(){
createForm("text,password",".content");
});
function createForm(types,object){
typ = types.split(',');
//var source = "";
$.each(typ,function(){
switch(this) {
case "text":
console.log('text');
break;
default:
console.log('default');
break;
}
});
//$(object).html(source);
}
I have this code an in console it return 2xdefaults. Why?
I try to return a input for each type as text or password but my switch does not recognize the "typ"
The reason you're seeing this behavior is that this within the each call is a String object instance, not a string primitive. JavaScript has both. In a switch statement, the comparison with the cases is via ===, and a string instance is not === to a string primitive.
Three ways to fix it:
If you change your switch to:
switch (String(this)) {
...that will turn it back into a primitive, whereupon your switch works.
As VisioN points out in the comments below, use the arguments that $.each passes (each string — as a primitive — will be provided as the second argument):
$.each(typ, function(index, value) {
switch (value) {
// ...
}
});
Use any of the alternatives discussed in this other answer (one of which is a nice simple for loop).
Side note: You're falling prey to The Horror of Implicit Globals by not declaring your typ variable.
jQuery is overkill here, for a correct way to do it with jQuery anyway have a look at T.J. Crowders answer.
I recommend a method that is way simpler by using a standard for-loop. It works fine:
var types = "text,password".split(",");
for (var i = 0; i < types.length; i++) {
switch(types[i]){
case "text":
console.log('text');
break;
default:
console.log('default');
break;
}
}
You use the $.each function wrongly. It should look like this:
$.each( typ, function( key, value ) {
switch(value){
case "text":
console.log('text');break;
default:
console.log('default');break;
}
});
Try using switch(String(this)) instead of switch(this). And of course, initialize your variables.
Don't be frightened, its a very basic code.
Just wanted to check with you guys if you know any methods to make it faster ? (still learning)
It looks so ugly :)
Or, if you notice anything which could be made differently... Thanks!
function pic_form_function(form, nr, val) {
document.getElementById("image_to_delete").value=0;
var re = /\..+$/;
var extension = val.match(re);
if (extension==".jpg" || extension==".jpeg" || extension==".gif" || extension==".png" || extension==".bmp") {
if (nr==1){
var ID_file1 = document.getElementById("pic_id_nr1").value;
window.parent.document.getElementById("pic1_filename").value=ID_file1+extension;
window.parent.document.getElementById("annonsera_nr_pics").value=1;
window.parent.document.getElementById("iframe_upload_pic").style.height="180px";
document.getElementById("pic_target").style.height="160px";
document.getElementById("pic_target").style.display="block";
document.getElementById("remove_pic").value=0;
document.getElementById("extra_pic_checkbox").style.display="inline";
document.getElementById("extra_pic_fnt").style.display="inline";
}
else if (nr==2){
var ID_file2 = document.getElementById("pic_id_nr2").value;
window.parent.document.getElementById("pic2_filename").value=ID_file2+extension; //Passing fileInputName to parent window...
window.parent.document.getElementById("annonsera_nr_pics").value=2;
document.getElementById("extrapic").value=2;
document.getElementById("pic_file3").disabled=false;
}
else if (nr==3){
var ID_file3 = document.getElementById("pic_id_nr3").value;
window.parent.document.getElementById("annonsera_nr_pics").value=3;
window.parent.document.getElementById("pic3_filename").value=ID_file3+extension;
document.getElementById("extrapic").value=3;
document.getElementById("pic_file4").disabled=false;
}
else if (nr==4){
var ID_file4 = document.getElementById("pic_id_nr4").value;
window.parent.document.getElementById("annonsera_nr_pics").value=4;
window.parent.document.getElementById("pic4_filename").value=ID_file4+extension;
document.getElementById("extrapic").value=4;
document.getElementById("pic_file5").disabled=false;
}
else if (nr==5){
var ID_file5 = document.getElementById("pic_id_nr5").value;
window.parent.document.getElementById("annonsera_nr_pics").value=5;
window.parent.document.getElementById("pic5_filename").value=ID_file5+extension;
document.getElementById("extrapic").value=5;
}
}
if (extension!=".jpg" && extension!=".jpeg" && extension!=".gif" && extension!=".png" && extension!=".bmp") {
window.parent.document.getElementById("annonsera_imagenotvalid_error").style.display="block";
}
else {
window.parent.document.getElementById("annonsera_imagenotvalid_error").style.display="none";
form.submit();
}
}
If me, I will define following on the top.
$=function(x){return document.getElementById(x);}
will replace all the document.getElementById to $ first.
or better user jQuery.
About performance:
To extract the file extension you can use the String.substring method instead of a RegExp, the performance improvement would be negligible but I think it gains readability:
var extension = val.substring(val.lastIndexOf('.'));
About the code:
You could have only one ID_file variable declared at the top of your function, and use it in the if blocks.
The else if blocks where nr==2, 3, and 4 are really similar, and you could do the same for those three cases:
//..
else if (nr >= 2 && nr <= 4){
ID_file = document.getElementById("pic_id_nr"+nr).value; // point #1 assumed
window.parent.document.getElementById("pic"+nr+"_filename").value=ID_file+extension;
window.parent.document.getElementById("annonsera_nr_pics").value = nr;
document.getElementById("extrapic").value = nr;
document.getElementById("pic_file"+(+nr+1)).disabled=false;
}
About readability:
You could define shorthands to common and verbose function calls at the beginning as S.Mark also suggests:
var el = document.getElementById,
parentEl = window.parent.document.getElementById;
Continuing what CMS did with code repetition, you can refactor the common code outside the sequence of else if blocks.
The switch statement was made to replace a sequence of ifs.
Instead of the above two suggestions, you could define functions do to the same tasks for a more readable implementation.
If you continue to use regexps (I personally find them very readable), remember that match returns an array.
Also, the .+ will greedily match all characters after the first period. Better to only match non-periods with [^.]+.
Instead of the long sequence of string comparisons, you can use objects as associative arrays:
var imageExtensions = {'.jpg': 1, '.jpeg': 1, '.gif': 1, '.png': 1, '.bmp': 1};
if (imageExtensions[extension]) {
The last if ... else ... is unnecessary, considering that the condition checks for the negation of the condition in the first if. Just move the else block to the end of the first if and turn the last if (...) to an else.
Personally, I find short error handling code more readable when placed next to the if statement that detected the error, rather than after a long block handling the non-error case. After the previous refactor, let's swap the if block with the else block and negate the conditional.
Taking all the above together, we get:
function pic_form_function(form, nr, val) {
document.getElementById("image_to_delete").value=0;
var extension = val.match(/\.[^.]+$/);
if (extension) {
extension = extension[0];
}
var imageExtensions = {'.jpg': 1, '.jpeg': 1, '.gif': 1, '.png': 1, '.bmp': 1};
if (! imageExtensions[extension]) {
window.parent.document.getElementById("annonsera_imagenotvalid_error").style.display="block";
} else {
var ID_file = document.getElementById("pic_id_nr" + nr).value;
window.parent.document.getElementById("pic"+nr+"_filename").value=ID_file+extension;
window.parent.document.getElementById("annonsera_nr_pics").value=nr;
switch (nr) {
case 1:
window.parent.document.getElementById("iframe_upload_pic").style.height="180px";
document.getElementById("pic_target").style.height="160px";
document.getElementById("pic_target").style.display="block";
document.getElementById("remove_pic").value=0;
document.getElementById("extra_pic_checkbox").style.display="inline";
document.getElementById("extra_pic_fnt").style.display="inline";
break;
case 2: // FALLTHRU
case 3: // FALLTHRU
case 4:
document.getElementById("pic_file"+nr).disabled=false;
// FALLTHRU
case 5:
document.getElementById("extrapic").value=nr;
break;
}
window.parent.document.getElementById("annonsera_imagenotvalid_error").style.display="none";
form.submit();
}
}
which is shorter, but could be more readable.
Note that if the $ wrapper is defined in 'window.parent', you should be able to call it as window.parent.$ in the child:
window.parent.$("annonsera_imagenotvalid_error").style.display="none";
There isn't any special computation being done beside traversing elements and assigning their attributes some values. So the code is not performing much to try to improve its performance.
On the other hand, you should use a library like jQuery for the kind of work you are doing. You might be able to cut short many traversals because you can have jQuery reuse the object it found and continue further from this point to look for other objects...
You should cache your dom lookups e.g.
var pic_target = document.getElementById("pic_target");
You can then use this variable to to apply the style and it only does the dom lookup once. I think this is a key thing to speeding up the js