Using different array's with switch statements - javascript

I am creating a recycling app and am attempting to use a switch statement to provide the user with instructions on what to do with the item upon entering into an input field. I'm a little turned around on how to call it (I am very new to switch). Eventually I want to have a few different arrays according to material. How would I place the item's within an array in the a switch? Would I be better off with if else statements? Any advice would be much appreciated!
const plasticItem = ["Milk Jug , Shampoo, Deodarant, Soda Bottle"];
function recycleItem(plasticItem) {
let instructions = "";
switch (true) {
case plasticItem:
instructions = "Put in recycling";
break;
}
}

I made this code which should work:
function recycleItem(){
const x = document.querySelector("input").value;
switch(x) {
case "Milk Jug":
console.log("Milk");
break;
case "Shampoo":
// code block
console.log("Shampoo");
break;
case "Deodarant":
console.log("Deodarant");
break
case "Soda Bottle":
console.log("Soda Bottle");
break
default:
// code block
}
}

Related

Is there a way to compare the strings in two arrays to see if one of them is present within the other

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.

Goto somewhere based on a variable, JavaScript

Ok so I'm a kinda new to the whole JavaScript thing but I was just trying something Some kind of yes/no quiz thingy and I want to skip certain questions and stuff I came up with the following but the whole "continue Q + question_nr;" doesn't work like I hoped it would. How am I supposed to do this? :)
var question_nr = 1;
Q1:
function q1() {
var a1 = prompt("Wanna skip the next question?", "y/n");
switch(a1) {
case "y":
alert("k");
question_nr = question_nr + 2;
continue Q + question_nr;
break;
case "n":
alert("oki");
question_nr = question_nr + 1;
break;
default:
alert("please enter y or n.");
break;
}
}
Q2:
alert("test2");
//<insert question 2>
break;
Q3:
alert("test3");
//<insert question 3>
break;
<button onclick="q1()">test</button>
p.s. any good sites to help me learn JS are appreciated so I don't have to ask (probably really stupid) questions like this one in the future
I don't want to teach you, go to the code academy, but if you at least "don't know" how to implement something that works as you want, I can tell you how to do something that works somehow near how goto worked. Listen:
You can declare execution of your questions (let's call that "goto targets") as:
const QUESTIONS = {
Q1: function () {
someLogicThere();
},
Q2: function () {
someLogicThere();
}
};
And execute it in some way like this (this will throw an error if you don't define any of required questions):
switch(lastPrompt) {
case "y":
alert("k");
question_nr = question_nr + 2;
QUESTIONS["Q" + question_nr]();
break;
case "n":
alert("oki");
question_nr = question_nr + 1;
break;
default:
alert("please enter y or n.");
break;
}
}
But I assume that a bad code. You should wrap everything inside IIFE/module and use more html/angular/react to keep this organised.
I understand that you are still learning, but you should not use labels to do this. The following is a more simple way to accomplish this goal.
(function () {
var questions = [
'How much wood can a wood chuck chuck?',
'How many fish in the sea?',
'How does this JavaScript work?'
];
var index = -1;
window.askQuestion = function () {
var answer = prompt("Wanna skip the next question?", "y/n");
if(answer === 'y' || answer === 'n') {
index = (index + 1) + (answer === 'y');
if(questions[index]) {
alert(questions[index]);
} else {
alert("No more questions to ask.");
index = -1;
}
} else {
alert("please enter y or n.");
}
};
}());
A few things to note. The function above wraps its code in what is called a self-executing anonymous function. This makes it so that the variables declared inside it are within a private scope. Next, we store questions inside of an array while keeping in mind that the array index always begins at 0. This is why when we declare the variable for index that it begins at -1. If the answer given by the user is y or n, then we add one to the index plus true or false whether or not the answer is y. This conditionally increments index by 1 if n or 2 if y. Then check whether or not a question exists at the calculated index. If it does, trigger the alert for the question, or if not alert that there are no more questions and reset the index to -1.

Switch is not properly working in javascript

I have a switch statement which has several cases. These cases compare values and assign a text to a variable. But when I try to execute this switch, it always executes the default case. But my condition is true.. Why?
Here is my value
Apartment
Here is my code
var rental_cat = $('#rentals_type').val();
alert(rental_cat);
var rental_type = "";
switch (rental_cat) {
case (rental_cat == "Apartment"):
rental_type='daily';
alert(rental_type);
break;
case (rental_cat == "Office"):
rental_type='work_daily';
alert(rental_type);
break;
default:
rental_type='other';
alert(rental_type);
break;
}
When I execute this switch, it always gives me "other"
Remove the conditional expression inside the "case" clause.
Try this:
var rental_cat = $('#rentals_type').val();
alert(rental_cat);
var rental_type = "";
switch (rental_cat) {
case "Apartment":
rental_type='daily';
alert(rental_type);
break;
case "Office":
rental_type='work_daily';
alert(rental_type);
break;
default:
rental_type='other';
alert(rental_type);
break;
}
switch (rental_cat) {
case (rental_cat == "Apartment"):
is equivalent to
switch (rental_cat) {
case true:
which in turn is equivalent to
if (rental_cat === true)
You don't put a condition in the case, the condition is created as an equality check between the switch and the cases, so it should be like this instead:
switch (rental_cat) {
case "Apartment":
a switch is not the right structure to deal with this problem. Here I'd recommend a map:
var rentalTypesByCat = {
DEFAULT: "other",
"Apartement": "daily",
"Office": "work_daily",
}
var rental_cat = $('#rentals_type').val();
console.log("rental_cat:", rental_cat);
var rental_type = rentalTypesByCat[rental_cat] || rentalTypesByCat.DEFAULT;
console.log("rental_type:", rental_type);
or if you need it a bit more explicit (for example because some of your mapped values may be falsy themselves):
var rental_type = rentalTypesByCat[rental_cat in rentalTypesByCat? rental_cat: "DEFAULT"];
console.log("rental_type:", rental_type);

Switch case as string

$(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.

Ways to improve performance of this javascript code?

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

Categories