Switch combining cases string regex and number - javascript

Is there a way to create multiple cases in a single Javascript switch statement?
In my code I receive the value of a field via jQuery.
Is it possible that one case checks for string regex and another for number of the same variable?
I am thinking along the lines of:
var field = $(this).val();
var msg;
switch (field)
{
case field.test('Yes'):
msg = "FOO\n";
break;
case 10:
msg = "BAR\n";
break;
}
Although I saw here: Switch statement for string matching in JavaScript
That the way to use switch on strings is by sending the switch statement a "true" value.
What would be the most concise (and correct!) way to achieve this?

OK, compiling both answers above my code that worked and was most elegant IMO is:
var fieldVal = $(this).val();
var msg;
switch (true)
{
case /Yes/.test(fieldVal):
msg = "FOO";
break;
case fieldVal > 10 :
msg = "BAR";
break;
}
this works as separate if statements since we are evaluating whether or not the case returns true but in a clearer and more concise way that could give us the option to add totally disparate test statements in one switch.
the reason it works is probably that the case expression evaluated is interpreted as a true or false value and then checked against the main -
switch(true)

You can't the case need to single value, that's compared to switch expression, but you can put multiple cases to execute the same code:
switch (field) {
case 'Yes':
case 'yes':
case 'YES':
msg = "FOO\n";
break;
case 10:
msg = "BAR\n";
break;
}
but in order to use test as case you can pass true to switch (I found that trick in some open source project):
switch (true) {
case field.test('Yes'):
msg = "FOO\n";
break;
case field == 10:
msg = "BAR\n";
break;
}
but this is the same as if/else

Note: you're using test() incorrectly, it's a method of a regex object, so you need /Yes/.test(field) rather than field.test('Yes'). Anyway...
If you've only got two cases as shown then I'd use an if/else/else if structure:
var field = $(this).val();
var msg;
if(/Yes/.test(field)) {
msg = "FOO\n";
} else if (field === 10) {
msg = "BAR\n";
}
If you need to add additional cases I'd just add extra if else {} branches on the end.
If you have several specific numeric cases you might consider putting them in a switch with the regex tests in a default at the end:
switch (field) {
case 10:
msg = "BAR\n";
break;
case 30:
msg = "whatever\n";
break;
case 50:
msg = "hi\n";
break;
default:
if (/Yes/.test(field)) {
msg = "FOO\n";
else if (/No|N|False|/i.test(field)) {
msg = "blah\n";
}
break;
}
The switch (true) option you alluded to in the question is really just a messier version of an if/else/else if, so it doesn't really make sense unless you have some fall-through cases:
switch(true)
case /Yes/.test(field):
case /Y/.text(field):
case /Whatever/.text(field):
msg = "FOO\n";
break;
case field == 10:
msg = "BAR\n";
break;
}
...and even then an if with multiple conditions joined by || arguably just as tidy with appropriate newlines, and combining multiple regexes into a single one is probably a lot neater.

Related

What is empty switch case in javascript [duplicate]

I need multiple cases in switch statement in JavaScript, Something like:
switch (varName)
{
case "afshin", "saeed", "larry":
alert('Hey');
break;
default:
alert('Default case');
break;
}
How can I do that? If there's no way to do something like that in JavaScript, I want to know an alternative solution that also follows the DRY concept.
Use the fall-through feature of the switch statement. A matched case will run until a break (or the end of the switch statement) is found, so you could write it like:
switch (varName)
{
case "afshin":
case "saeed":
case "larry":
alert('Hey');
break;
default:
alert('Default case');
}
This works in regular JavaScript:
function theTest(val) {
var answer = "";
switch( val ) {
case 1: case 2: case 3:
answer = "Low";
break;
case 4: case 5: case 6:
answer = "Mid";
break;
case 7: case 8: case 9:
answer = "High";
break;
default:
answer = "Massive or Tiny?";
}
return answer;
}
theTest(9);
Here's different approach avoiding the switch statement altogether:
var cases = {
afshin: function() { alert('hey'); },
_default: function() { alert('default'); }
};
cases.larry = cases.saeed = cases.afshin;
cases[ varName ] ? cases[ varName ]() : cases._default();
In Javascript to assign multiple cases in a switch, we have to define different case without break inbetween like given below:
<script>
function checkHere(varName){
switch (varName)
{
case "saeed":
case "larry":
case "afshin":
alert('Hey');
break;
case "ss":
alert('ss');
break;
default:
alert('Default case');
break;
}
}
</script>
Please see example click on link
I like this for clarity and a DRY syntax.
varName = "larry";
switch (true)
{
case ["afshin", "saeed", "larry"].includes(varName) :
alert('Hey');
break;
default:
alert('Default case');
}
If you're using ES6, you can do this:
if (['afshin', 'saeed', 'larry'].includes(varName)) {
alert('Hey');
} else {
alert('Default case');
}
Or for earlier versions of JavaScript, you can do this:
if (['afshin', 'saeed', 'larry'].indexOf(varName) !== -1) {
alert('Hey');
} else {
alert('Default case');
}
Note that includes won't work in some browser including older IE versions, but you could patch things up fairly easily. See the question determine if string is in list in javascript for more information.
My situation was something akin to:
switch (text) {
case SOME_CONSTANT || ANOTHER_CONSTANT:
console.log('Case 1 entered');
break;
case THIRD_CONSTANT || FINAL_CONSTANT:
console.log('Case 2 entered');
break;
default:
console.log('Default entered');
}
The default case always entered. If you're running into a similar multi-case switch statement issue, you're looking for this:
switch (text) {
case SOME_CONSTANT:
case ANOTHER_CONSTANT:
console.log('Case 1 entered');
break;
case THIRD_CONSTANT:
case FINAL_CONSTANT:
console.log('Case 2 entered');
break;
default:
console.log('Default entered');
}
Adding and clarifying Stefano's answer, you can use expressions to dynamically set the values for the conditions in switch, e.g.:
var i = 3
switch (i) {
case ((i>=0 && i<=5) ? i : -1):
console.log('0-5');
break;
case 6: console.log('6');
}
So in your problem, you could do something like:
var varName = "afshin"
switch (varName) {
case (["afshin", "saeed", "larry"].indexOf(varName)+1 && varName):
console.log("hey");
break;
default:
console.log('Default case');
}
Although it is so much DRY...
In Node.js it appears that you are allowed to do this:
data = "10";
switch(data){
case "1": case "2": case "3": // Put multiple cases on the same
// line to save vertical space.
console.log("small");
break;
case "10": case "11": case "12":
console.log("large");
break;
default:
console.log("strange");
break;
}
This makes for much more compact code in some cases.
I use it like this:
switch (true){
case /Pressure/.test(sensor):
{
console.log('Its pressure!');
break;
}
case /Temperature/.test(sensor):
{
console.log('Its temperature!');
break;
}
}
Some interesting methods. For me the best way to solve is using .find.
You can give an indication of what the multiple cases are by using a suitable name inside your find function.
switch (varName)
{
case ["afshin", "saeed", "larry"].find(firstName => firstName === varName):
alert('Hey');
break;
default:
alert('Default case');
break;
}
Other answers are more suitable for the given example but if you have multiple cases to me this is the best way.
It depends. Switch evaluates once and only once. Upon a match, all subsequent case statements until 'break' fire no matter what the case says.
var onlyMen = true;
var onlyWomen = false;
var onlyAdults = false;
(function(){
switch (true){
case onlyMen:
console.log ('onlymen');
case onlyWomen:
console.log ('onlyWomen');
case onlyAdults:
console.log ('onlyAdults');
break;
default:
console.log('default');
}
})(); // returns onlymen onlywomen onlyadults
<script src="https://getfirebug.com/firebug-lite-debug.js"></script>
You can use the 'in' operator...
It relies on the object/hash invocation, so it's as fast as JavaScript can be.
// Assuming you have defined functions f(), g(a) and h(a,b)
// somewhere in your code,
// you can define them inside the object, but...
// the code becomes hard to read. I prefer it this way.
o = { f1:f, f2:g, f3:h };
// If you use "STATIC" code can do:
o['f3']( p1, p2 )
// If your code is someway "DYNAMIC", to prevent false invocations
// m brings the function/method to be invoked (f1, f2, f3)
// and you can rely on arguments[] to solve any parameter problems.
if ( m in o ) o[m]()
You can do this:
alert([
"afshin",
"saeed",
"larry",
"sasha",
"boby",
"jhon",
"anna",
// ...
].includes(varName)? 'Hey' : 'Default case')
or just a single line of code:
alert(["afshin", "saeed", "larry",...].includes(varName)? 'Hey' : 'Default case')
a little improvement from ErikE's answer
I can see there are lots of good answers here, but what happens if we need to check more than 10 cases? Here is my own approach:
function isAccessible(varName){
let accessDenied = ['Liam', 'Noah', 'William', 'James', 'Logan', 'Benjamin',
'Mason', 'Elijah', 'Oliver', 'Jacob', 'Daniel', 'Lucas'];
switch (varName) {
case (accessDenied.includes(varName) ? varName : null):
return 'Access Denied!';
default:
return 'Access Allowed.';
}
}
console.log(isAccessible('Liam'));
The problem with the above approaches, is that you have to repeat the several cases every time you call the function which has the switch. A more robust solution is to have a map or a dictionary.
Here is an example:
// The Map, divided by concepts
var dictionary = {
timePeriod: {
'month': [1, 'monthly', 'mensal', 'mês'],
'twoMonths': [2, 'two months', '2 months', 'bimestral', 'bimestre'],
'trimester': [3, 'trimesterly', 'quarterly', 'trimestral'],
'semester': [4, 'semesterly', 'semestral', 'halfyearly'],
'year': [5, 'yearly', 'annual', 'ano']
},
distance: {
'km': [1, 'kms', 'kilometre', 'kilometers', 'kilometres'],
'mile': [2, 'mi', 'miles'],
'nordicMile': [3, 'Nordic mile', 'mil (10 km)', 'Scandinavian mile']
},
fuelAmount: {
'ltr': [1, 'l', 'litre', 'Litre', 'liter', 'Liter'],
'gal (imp)': [2, 'imp gallon', 'imperial gal', 'gal (UK)'],
'gal (US)': [3, 'US gallon', 'US gal'],
'kWh': [4, 'KWH']
}
};
// This function maps every input to a certain defined value
function mapUnit (concept, value) {
for (var key in dictionary[concept]) {
if (key === value ||
dictionary[concept][key].indexOf(value) !== -1) {
return key
}
}
throw Error('Uknown "'+value+'" for "'+concept+'"')
}
// You would use it simply like this
mapUnit("fuelAmount", "ltr") // => ltr
mapUnit("fuelAmount", "US gal") // => gal (US)
mapUnit("fuelAmount", 3) // => gal (US)
mapUnit("distance", "kilometre") // => km
// Now you can use the switch statement safely without the need
// to repeat the combinations every time you call the switch
var foo = 'monthly'
switch (mapUnit ('timePeriod', foo)) {
case 'month':
console.log('month')
break
case 'twoMonths':
console.log('twoMonths')
break
case 'trimester':
console.log('trimester')
break
case 'semester':
console.log('semester')
break
case 'year':
console.log('year')
break
default:
throw Error('error')
}
One of the possible solutions is:
const names = {
afshin: 'afshin',
saeed: 'saeed',
larry: 'larry'
};
switch (varName) {
case names[varName]: {
alert('Hey');
break;
}
default: {
alert('Default case');
break;
}
}
If your case conditions are complex, many case value matches, or dynamic value match required, then it may be best to move that case matching logic to handler child functions.
In your case, if say you had thousands of usernames to match against for a security permissions check for example, this method is cleaner option, more extensible, exposing the high level multi-way branch logic without getting swamped in a long list of case statements.
switch (varName)
{
case checkPatternAdministrator(varName):
alert('Hey');
break;
case checkPatternUserTypeA(varName):
alert('Hey2');
break;
case checkPatternUserTypeB(varName):
alert('Hey3');
break;
default:
alert('Default case');
break;
}
function checkPatternAdministrator(varName) {
// Logic to check Names against list, account permissions etc.
// return the varName if a match is found, or blank string if not
var matchedAdministratorName = varName;
return matchedAdministratorName;
}
Here is one more easy-to-use switch case statement. which can fulfill your requirement. We can use the find method in the switch statement to get the desire output.
switch(varname){
case["afshin","saeed","larry"].find(name => name === varname):
alert("Hey")
break;
default:
alert('Default case');
break;
}
The switch statement is used to select one of many code blocks to execute based on a condition
the value in the switch expression is compared to the different values provided
if there is a match the code block related to it will be executed
if there is no match the default block is executed
syntax:
switch(expression) {
case x:
// code block
break;
case y:
// code block
break;
default:
// code block
}
NOTE:
It must be noted that if the break statement is omitted then the next block will be executed as well even if they does not match with switch expression. So don't forget to add the break statement at the end of each code block if you don't want to get the specified behaviour
A practical example:
the following code returns the current day of the week in strings based on an integer (provided by 'new Date().getDay()')
switch (new Date().getDay()) {
case 0:
day = "Sunday";
break;
case 1:
day = "Monday";
break;
case 2:
day = "Tuesday";
break;
case 3:
day = "Wednesday";
break;
case 4:
day = "Thursday";
break;
case 5:
day = "Friday";
break;
case 6:
day = "Saturday";
}
the code samples were taken from W3Schools
Another way of doing multiple cases in a switch statement, when inside a function:
function name(varName){
switch (varName) {
case 'afshin':
case 'saeed':
case 'larry':
return 'Hey';
default:
return 'Default case';
}
}
console.log(name('afshin')); // Hey
Cleaner way to handle that
if (["triangle", "circle", "rectangle"].indexOf(base.type) > -1)
{
//Do something
}else if (["areaMap", "irregular", "oval"].indexOf(base.type) > -1)
{
//Do another thing
}
You can do that for multiple values with the same result
Just change the switch condition approach:
switch (true) {
case (function(){ return true; })():
alert('true');
break;
case (function(){ return false; })():
alert('false');
break;
default:
alert('default');
}
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Example1</title>
<link rel="stylesheet" href="css/style.css" >
<script src="js/jquery-1.11.3.min.js" type="text/javascript"></script>
<script>
function display_case(){
var num = document.getElementById('number').value;
switch(num){
case (num = "1"):
document.getElementById("result").innerHTML = "You select day Sunday";
break;
case (num = "2"):
document.getElementById("result").innerHTML = "You select day Monday";
break;
case (num = "3"):
document.getElementById("result").innerHTML = "You select day Tuesday";
break;
case (num = "4"):
document.getElementById("result").innerHTML = "You select day Wednesday";
break;
case (num = "5"):
document.getElementById("result").innerHTML = "You select day Thusday";
break;
case (num = "6"):
document.getElementById("result").innerHTML = "You select day Friday";
break;
case (num = "7"):
document.getElementById("result").innerHTML = "You select day Saturday";
break;
default:
document.getElementById("result").innerHTML = "You select day Invalid Weekday";
break
}
}
</script>
</head>
<body>
<center>
<div id="error"></div>
<center>
<h2> Switch Case Example </h2>
<p>Enter a Number Between 1 to 7</p>
<input type="text" id="number" />
<button onclick="display_case();">Check</button><br />
<div id="result"><b></b></div>
</center>
</center>
</body>
You could write it like this:
switch (varName)
{
case "afshin":
case "saeed":
case "larry":
alert('Hey');
break;
default:
alert('Default case');
break;
}
For me this is the simplest way:
switch (["afshin","saeed","larry"].includes(varName) ? 1 : 2) {
case 1:
alert('Hey');
break;
default:
alert('Default case');
break;
}

Switch case match with string

function getFieldType(value){
var type = "";
switch(value){
case "TEXT_BOX":
type=FieldTypeEnum.TEXT_BOX;
break;
case "PASSWORD":
type=FieldTypeEnum.PASSWORD;
break;
case "CHECK_BOX":
type=FieldTypeEnum.CHECK_BOX;
break;
case "RADIO_BUTTON":
type=FieldTypeEnum.RADIO_BUTTON;
break;
case "DROP_DOWN":
type=FieldTypeEnum.DROP_DOWN;
break;
case "SEARCH_CARD_BOX":
type=FieldTypeEnum.SEARCH_CARD_BOX;
break;
case "STATE_DROP_DOWN":
type=FieldTypeEnum.STATE_DROP_DOWN;
break;
case "ID_DROP_DOWN":
type=FieldTypeEnum.ID_DROP_DOWN;
break;
case "GENDER_DROP_DOWN":
type = FieldTypeEnum.GENDER_DROP_DOWN;
break;
default:
type = "";
}
return type;
}
I want to combined three drop down box (STATE_DROP_DOWN, ID_DROP_DOWN, GENDER_DROP_DOWN)into one .
Means I want something like below :
case String.endwith("_DROP_DOWN"):
type=FieldTypeEnum.ID_DROP_DOWN;
break;
Is it possible in JavaScript? If yes then how?
It is possible, in a javascript switch/case statement you can compare for string equality (which evaluates to true or false) or more complex statements which just as when testing for string equality, also evaluate to true or false (e.g. String.endwith("_DROP_DOWN")). However personally I would prefer the following:
STATE_DROP_DOWN:
// intentional fall through
ID_DROP_DOWN:
// intentional fall through
GENDER_DROP_DOWN:
//.. do your stuff
break;
I believe this way it is more clearly through which switch case you are falling in a certain situation.
You can put a ternary operator in the case, and test if it ends with "DROP_DOWN" return value otherwise blank string.
switch(value){
case value.endsWith("_DROP_DOWN") ? value : '' {
type=FieldTypeEnum.ID_DROP_DOWN;
break;
}
}

How To Use JavaScript Switch Case in Filed Validation

I am trying a simple input validation at This Demo and as you can see I am using some nested if statements (which can be more for applying more validation rules). Now my question is if you can help me to use JavaScript Switch Statement instead of theses if statement
the reason which I got confused is the (expression) and default: part of the statement which I am totally confused how to use them in my case?
switch(expression) {
case n:
code block
break;
case n:
code block
break;
default:
default code block
}
and here is my code:
$(function () {
$("#pro").on("click", function (e) {
inputData = $.trim($('input[type="text"]').val());
if (inputData == ""){
alert("Field Can not be Empty");
}
else if (inputData.length<3){
alert("Field Can Be Less Than 4");
}
else
{
alert($('input[type="text"]').val());
}
e.preventDefault();
});
});
Thanks
That's not the way, how switch statement works. You can not write different expressions in the case of a switch. It can only compare the expression to a single value defined in a case statement.
See another explanation at: Expression inside switch case statement
An example of how to use switch() statement would be like this:
var expression = "1";
switch(expression) {
case "1":
//this will be executed
break;
case "2":
//wont be executed
break;
default:
//wont be executed, since a match was found
}
It is better to use one switch instead of using 2-3 if/then/else statements.
You can find more examples here: http://www.w3schools.com/js/js_switch.asp
Although not a good way to use switches you ca proceed like this:
switch(true){
case (inputData == "") :
// your code
break;
case (inputData.length<3) :
//your code
break;
default:
//your code
break;
}
If else statement is suit here. It is difficult to use switch here.
Let us look the switch
$(function () {
$("#pro").on("click", function (e) {
inputData = $.trim($('input[type="text"]').val());
var len = inputData.length;
switch(len)
{
case 0:
alert("Field Can not be Empty");
break;
case 1:
alert("Field Can't Be Less Than 4");
break;
case 2:
alert("Field Can't Be Less Than 4");
break;
case 3:
alert("Field Can't Be Less Than 4");
break;
default:
alert($('input[type="text"]').val());
}
e.preventDefault();
});
});
The code looks lengthy and become make problem for more condition. So the if else is the better solution here.
switch demo
You can write expressions in case clauses but you have to return the value for comparison.
$(function () {
var $input = $('input[type="text"]');
$('button').on('click', validateInput)
function validateInput(e) {
e.preventDefault();
var alertMsg = "";
var inputData = $.trim($input.val());
switch(inputData) {
case "":
alertMsg = "Field Can not be Empty";
break;
case (inputData.length < 4 && inputData):
alertMsg = "Field Can't Be Less Than 4";
break;
default:
alertMsg = inputData;
}
alert(alertMsg);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text"><button>Click here</button>
In my case I used switch as an exercise to a form in Bootstrap. Due so I let the break between the cases as the program keeps tracking for more fields, so it doesn't need to check every variant on it and jumps to the next field. I made and object with the conditions that the switch should look for. Pls, do remember that this is a schoolar exercise and my boundaries were quite clear: no if/else allowed. Here is the code
//taking input value field
let mailLine = inputEmail.value;
//obj mail
let mailObj = {
case1 : (mailLine == ""),
case2 : (!checkValidity(mailLine)),
//function check, no need to place it here!
}
//if the cases are true
switch (true) {
case mailObj.case1:
inputEmail.classList.add("is-invalid");//bootstrap div
document.getElementById("errorEmail").textContent = "No empty field allowed";
counter ++; //for more stuff in the code
break; //left it on purpose. No itineration. So it goes to password, city...
case mailObj.case2:
inputEmail.classList.add("is-invalid");
document.getElementById("errorEmail").textContent = "Not right mail format";
counter ++;
break;
default:
inputEmail.classList.remove("is-invalid");
inputEmail.classList.add("is-valid");
document.getElementById("okEmail").textContent = "Right mail format";
break;
}

Replace with the regular expression

What regular expression I need to use to correct
if (text.indexOf("+") != -1) {
action = "+";
} else if (text.indexOf("-") != -1) {
action = "-";
} else if (text.indexOf("*") != -1) {
action = "*";
} else if (text.indexOf("/") != -1) {
action = "/";
}
this code
?
EDIT:
and how can I improve this code:
switch (action) {
case "+":
result = parseInt(array[0]) + parseInt(array[1]);
break;
case "-":
result = parseInt(array[0]) - parseInt(array[1]);
break;
case "*":
result = parseInt(array[0]) * parseInt(array[1]);
break;
case "/":
result = parseInt(array[0]) / parseInt(array[1]);
break;
default:
break;
}
Sorry for dull questions I am new in js.
You can use either of these:
var action = text.replace(/.*([+*/-]).*/,'$1');
var match = /[*+/-]/.exec(text);
var action = match && match[0];
If there's the possibility of newlines in your text then change the first to:
var action = text.replace(/[\d\D]*([+*/-])[\d\D]*/,'$1');
Edit: You can improve your switch statement by using, e.g.
// allow floating point values, and also
// don't accidentally interpret "011" as octal
array[0]*1 + array[1]*1;
For more details on why parseInt is probably bad, see this answer.
You can also remove the superfluous default section of your case statement. However, I suspect that your desired "improvement" was making fewer lines. Given that =-*/ are operators in JavaScript (and not methods), I cannot think of any way to avoid having four calculations (i.e. a switch or if/else if).
Whereas in Ruby you could, for example, use array[0].send(action,array[1]) to cover all four cases ;)

trouble with SWITCH javascript always executing default case

well i have this trouble and ive been dealing with but i just cant get it to work
i have this function
function getDirections(dir)
{
var img;
switch(dir)
{
case 0:
img+='N.png';
break;
case 1:
img+='NE.png';
break;
case 2:
img+='E.png';
break;
case 3:
img+='SE.png';
break;
case 4:
img+='S.png';
break;
case 5:
img+='SO.png';
break;
case 6:
img+='O.png';
break;
case 7:
img+='NO.png';
break;
default:
alert('enetered default but direction='+dir);
}
return img;
}
quite simple right? now i have this interval set to 5000 ms to call getDirections(variable), the function works well the first time its called but after that , it always enter in the default clause and it also alerts the 'entered default but direction=dirvalue' , i mean even if dir is a value between 0-7 it will always enter to default: but it would alert the value so it was supossed to enter to one of the cases.
i made the same using else if and it worked so i dont know what its wrong with SWITCH
if(dir==0){img+='N.png';}
else if(dir==1){img+='NE.png';}
else if(dir==2){img+='E.png';}
else if(dir==3){img+='SE.png';}
else if(dir==4){img+='S.png';}
else if(dir==5){img+='SO.png';}
else if(dir==6){img+='O.png';}
else if(dir==7){img+='NO.png';}
That is weird... try to make sure that dir is an int, do this before the switch:
dir = parseInt(dir);
If the alert shows the value correctly it should enter the switch, but still it can "look" correct but be of a different data type. Do the conversion manually to ensure it's an int
I know I'm a bit late to the party, but I thought it might be important for anyone who doesn't understand why the "ifs" worked and the switch didn't. It's likely no one will read this answer, but I found it while searching for something else, so perhaps someone will find this helpful anyway:
Your switch is this:
function getDirections(dir) {
var img;
switch(dir) {
case 0:
img+='N.png';
break;
case 1:
img+='NE.png';
break;
case 2:
img+='E.png';
break;
case 3:
img+='SE.png';
break;
case 4:
img+='S.png';
break;
case 5:
img+='SO.png';
break;
case 6:
img+='O.png';
break;
case 7:
img+='NO.png';
break;
default:
alert('enetered default but direction='+dir);
}
return img;
}
This is not the same as a series of double equals (==) but a series of triple equals (===). It would be equivalent to:
if (dir === 0) {
img+='N.png';
} else if (dir === 1) {
img+='NE.png';
} else if (dir === 2) {
img+='E.png';
} else if (dir === 3) {
img+='SE.png';
} else if (dir === 4) {
img+='S.png';
} else if (dir === 5) {
img+='SO.png';
} else if (dir === 6) {
img+='O.png';
} else if (dir === 7) {
img+='NO.png';
} else {
alert('enetered default but direction='+dir);
}
In the world of "==", the integer 2 IS the same as the string "2", but not in the land of "===".
I'd guess that for some reason dir is being passed in as a string. Try changing case 1: to case '1':
Using an array instead of a chain of if/else blocks or a giant switch statement will be faster, more flexible and less error-prone. Also, you wouldn't have to worry if dir is a number or a string. Instead of:
if(dir==0){img+='N.png';}
else if(dir==1){img+='NE.png';}
else if(dir==2){img+='E.png';}
else if(dir==3){img+='SE.png';}
else if(dir==4){img+='S.png';}
else if(dir==5){img+='SO.png';}
else if(dir==6){img+='O.png';}
else if(dir==7){img+='NO.png';}
you can store the file names in an array:
var images = [
'N.png', 'NE.png', 'E.png', 'SE.png', 'S.png', 'SO.png', 'O.png', 'NO.png'
];
or arguably more readable:
var images = "N.png NE.png E.png SE.png S.png SO.png O.png NO.png".split(' ');
and then use just:
img = images[dir];
Full implementation of getDirections using an array would be:
var images = "N.png NE.png E.png SE.png S.png SO.png O.png NO.png".split(' ');
function getDirections(dir) {
var img = images[dir];
if (!img) {
alert("something");
}
return img;
}
Does it work for you?
If images is used only in that one function then you may want to store it as a property of the function to avoid your namespace pollution like this:
function getDirections(dir) {
var img = getDirections.images[dir];
if (!img) {
alert("something");
}
return img;
}
getDirections.images =
"N.png NE.png E.png SE.png S.png SO.png O.png NO.png".split(' ');
or use a closure.
Hard to explain why, but the default: case also need a break; statement after it like all the other cases.
I just ran the code in FireFox/FireBug and called the function this way
getDirections(0);
getDirections('1');
getDirections("2");
The first one does it correctly and the next two enter default.
They are strings and not integer which is what the cases are looking for.
I added
case "2":
img+='NO2.png';
break;
and then only the middle one entered the default. Obviously there is an issue with the way you are calling the function. It is likely passing a string.
I also used your if-else block (added an else{alert(dir);} and that returned the correct value for each call.
Javascript can do on the fly conversion (I think there's a better word for that) between strings and ints (and others). This is occuring when you do the comparrison using ==. If you change the comparison in the ifs to === you get the same behavior as with the switch block.
I pasted your code into an HTML file and ran it with the following buttons:
<button onclick="alert(getDirections(2))">Switch / Int</button>
<button onclick="alert(getDirections('2'))">Switch / String</button>
<button onclick="alert(getDirections2(2))">If-Else / Int</button>
<button onclick="alert(getDirections2('2'))">If-Else / String</button>
When calling the switch-version with a plain 2, it works as expected. Calling it with '2' makes it drop through to the default line. The if-else version works as expected in both cases. So the issue is probably that switch doesn't do an implicit conversion and == does.

Categories

Resources