Switch case as string - javascript

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

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.

Using different array's with switch statements

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
}
}

Javascript: change test() method name

Okay, I am making a text based game and I have been using the switch command like so
switch(true){
case /run/.test(g1):
prompt("run");
break;
}
the question I have is can I can I change the name of the test() method like so
switch(true){
case /run/.act(g1):
prompt("run");
break;
}
I thought if I created a function like so it would work
function act(str){
test(str);
return;
}
but it didn't... any help would be nice.
edit: fixed switch statements
So /run/ is a regex object. It has a method called test. It doesn't have a method act, so hence you can't call act() on it.
You'll need to use prototypes:
switch{
case /run/.act(g1):
prompt("run");
break;
}
RegExp.prototype.act = function (str) {
return this.test(str);
}
Here's an explanation of Prototypes.
If you really need to do this (please see What is the XY problem?) then you can add a prototype to the RegExp object.
var regex = /fo+/;
var str = 'fooooooooooooooo';
regex.test(str); //true
RegExp.prototype.act = function(str) {
if (str == 'fooooooo' && this.test(str)) {
return true;
} else {
return false;
}
}
regex.act(str); //false (str is not 'fooooooo')
Likewise, you can make an alias (but please, don't - it works fine as it is) by simply returning this.test():
RegExp.prototype.act = function(str) {
return this.test(str);
}

Javascript switch statement- very simple, what am I doing wrong?

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.

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