Javascript multiple decisions in switch case - javascript

I have difficulty with running a code which checks two criteria in switch case as this code prints 'unknown' since in javascript
['police',false]!=['police',false]
Is there any way to implement this code using switch-case rather than nested ifs?
var option='police';
var urgent=false;
switch([option,urgent])
{
case ['police',true]:
console.log('police,true');
call_police_urgent();
break;
case ['police',false]:
console.log('police,false');
call_police();
break;
case ['hospital',true]:
console.log('hospital,true');
call_hospital_urgent();
break;
case ['hospital',false]:
console.log('hospital,false');
call_hospital();
break;
case ['firestation',true]:
console.log('firestation,true');
call_firestation_urgent();
break;
case ['firestation',false]:
console.log('firestation,false');
call_firestation();
break;
default:
console.log('unknown');
}

Your code doesn't work because one array literal is never equal to another even if they look the same. There are many ways to solve that, but most of them boil down to converting arrays to something one can compare, e.g. strings:
let str = (...args) => JSON.stringify(args);
switch (str(option, urgent)) {
case str('police', false):
console.log('police,false');
break;
case str('hospital', true):
console.log('hospital,true');
break;
default:
console.log('unknown');
}
This works for your simple case, but not in general, because not everything can be stringified.

You can convert an array of options to string:
var option='police';
var urgent=false;
switch([option,urgent].join())
{
case 'police,true':
console.log('police,true');
break;
case 'police,false':
console.log('police,false');
break;
case 'hospital,true':
console.log('hospital,true');
break;
case 'hospital,false':
console.log('hospital,false');
break;
case 'firestation,true':
console.log('firestation,true');
break;
case 'firestation,false':
console.log('firestation,false');
break;
default:
console.log('unknown');
}

i don't know what you are trying to do, but your above code javascript engines and runtime environments with yell at you.
and secondly [] literal can and will never be equal to another [] literal
choose in between this two
var option='police';
var urgent=false;
function first_switch(option,urgent) {
switch(option) {
case "police":
if ( urgent )
console.log('police,true');
else
console.log('police,false');
break;
case "hospital":
if ( urgent )
console.log('hospital,true');
else
console.log('hospital,false');
break;
case "firestation":
if ( urgent )
console.log('firestation,true');
else
console.log('firestation,false');
break;
default:
console.log('unknown');
}
}
function second_switch(option,urgent) {
if ( urgent ) {
switch(option) {
case "police":
case "hospital":
case "firestation":
console.log(`${option}`, "true");
break;
default:
console.log('unknown');
}
return ;
}
switch(option) {
case "police":
case "hospital":
case "firestation":
console.log(`${option}`, "false");
break;
default:
console.log('unknown');
}
}
first_switch(option,urgent);
first_switch(option, true);
second_switch(option, urgent);
second_switch(option, true);

We can create the same funtionality without using switch cases. We could create a lookup table like:
var emergencyLookupTable = {
police: [{
case: true,
fn: call_police_urgent
},
{
case: false,
fn: call_police
}
],
hospital: [{
case: true,
fn: call_hospital_urgent
},
{
case: false,
fn: call_firestation_urgent
}
],
firestation: [{
case: true,
fn: call_firestation_urgent
},
{
case: false,
fn: call_firestation
}
]
}
And pass this object into emergency which is looking for the correct cases.
function emergency(lookup, option, urgent) {
if (lookup[option]) {
lookup[option]
.filter(function(obj) {
return obj.case === urgent
})
.forEach(function(obj) {
obj.fn()
})
} else {
console.log('unknown')
}
}
emergency(emergencyLookupTable, 'police', true)
Working Example
var emergencyLookupTable = {
police: [{
case: true,
fn: call_police_urgent
},
{
case: true,
fn: call_police_urgent2
},
{
case: false,
fn: call_police
}
],
hospital: [],
firestation: []
}
function emergency(lookup, option, urgent) {
if (lookup[option]) {
lookup[option]
.filter(function(obj) {
return obj.case === urgent
})
.forEach(function(obj) {
obj.fn()
})
} else {
console.log('unknown')
}
}
function call_police_urgent() {
console.log('call the police!')
}
function call_police_urgent2() {
console.log('call the police again!')
}
function call_police() {
console.log('call the police..')
}
emergency(emergencyLookupTable, 'police', true)
emergency(emergencyLookupTable, 'police', false)

Related

Reduce the number of switch - case with Object Literals

I'm studying javascript, and I've already seen that there's a way to reduce the number of switch - case with Object Literals. I'm trying to change this method, but I am not able to reduce the number of switches
static darkerColors(value: string, theme: ThemeMode) {
const test = theme === ThemeMode.LIGHT
switch (value) {
case Colors.BLUE: {
return test ? '#253F82' : '#BED1FF'
}
case Colors.CYAN: {
return test ? '#066262' : '#A2EAEA'
}
case Colors.PURPLE: {
return test ? '#4727B0' : '#D3C6FD'
}
case Colors.ORANGE: {
return test ? '#9C2100' : '#FF9377'
}
case Colors.YELLOW: {
return test ? '#6C5200' : '#F9E298'
}
default:
return test ? '#32363B' : '#C9CED4'
}
}
you can use an object to handle the configuration
like this
const config = {
light: {
blue: '#253F82',
default: '#32363B'
},
default: {
blue: '#BED1FF',
default: '#C9CED4'
}
}
function darkerColors(value, theme) {
const fallback = 'default'
const colors = config[theme] || config[fallback]
return colors[value] || colors[fallback]
}
console.log(darkerColors('blue', 'light'))
console.log(darkerColors('red', 'light'))
console.log(darkerColors('blue', 'dark'))
console.log(darkerColors('red', 'dark'))

Is it possible to insert a switch/case statement inside a JavaScript class?

I'm want to insert a switch/case statement inside a JavaScript class. In various cases, I'm trying to create a class that shows a specific step of a guided tour made with a library. So I asked myself if it is possible to insert this kind of statement inside a JavaScript class to execute depending on the PHP route name. Is it possible?
class TourUtils {
constructor(routeName) {
switch (routeName) {
case "host":
$(document).ready(function () {
document
.querySelector(".dashboard__tour")
.addEventListener("click", () => {
window.TOUR.start();
});
});
break;
case "Nuovo annuncio":
$(document).ready(function () {
window.TOUR.show("new-ad-page-intro-step");
});
break;
case "Modifica annuncio":
$(document).ready(function () {
window.TOUR.show("new-ad-page-nineth-step");
});
break;
case "Casa annuncio":
$(document).ready(function () {
if ($("#save").is(":visible"))
window.TOUR.show("mod-house-page-intro-step");
});
break;
case "Nuova casa":
$(document).ready(function () {
window.TOUR.show("mod-house-page-second-step");
});
break;
case "Modifica casa":
$(document).ready(function () {
window.TOUR.show("mod-price-page-intro-step");
});
break;
case "Calendario":
$(document).ready(function () {
if ($(".update-btn").is(":visible"))
window.TOUR.show("final-step");
else if (!$(".update-btn").is(":visible")) {
window.TOUR.show("mod-price-page-second-step");
}
});
break;
case "Aggiungi date":
$(document).ready(function () {
window.TOUR.show("add-date-page-intro-step");
});
break;
}
}
}
I don't see why not.
In general, before asking on a forum if some code works, there's a super easy thing you can do: try it. You can try it in a js file and run it with node or in your browser's console. Make a super minimal test and run it, you'll get your answer.
For the question "Is it possible to use switch case in a JS class constructor" here's the minimal test I would make
class A {
constructor(a) {
switch (a) {
case 1:
this.a = 'one';
break;
case 2:
this.a = 'two';
break;
default:
this.a = 'something else';
break;
}
}
}
let first = new A(1);
let second = new A(2);
let third = new A(93);
console.log({
test1: first.a,
test2: second.a,
test3: third.a
});
And make sure it shows
{
test1: 'one',
test2: 'two',
test3: 'something else'
}
You could simplify your code to the following. Maybe that helps finding the problem of your code.
class TourUtils {
constructor(routeName) {
var routes = {
"host": function () {
document
.querySelector(".dashboard__tour")
.addEventListener("click", () => {
window.TOUR.start();
});
},
"Nuovo annuncio": "new-ad-page-intro-step",
"Modifica annuncio": "new-ad-page-nineth-step",
"Casa annuncio": function () {
if ($("#save").is(":visible"))
window.TOUR.show("mod-house-page-intro-step");
},
"Nuova casa": "mod-house-page-second-step",
"Modifica casa": "mod-price-page-intro-step",
"Calendario": function () {
if ($(".update-btn").is(":visible")) window.TOUR.show("final-step");
else if (!$(".update-btn").is(":visible")) {
window.TOUR.show("mod-price-page-second-step");
}
},
"Aggiungi date": "add-date-page-intro-step"
};
$(document).ready(function () {
var route = routes[routeName];
if (typeof route === 'function') {
route();
} else {
window.TOUR.show(route);
}
}
}
}

What is the best practice to handle if true then run?

function handleOrder(data) {
if (data.payment_type === 'VISA') {
handleVisaPayment()
}
if (data.payment_type === 'VISA') {
handleMastercardPayment()
}
if (data.payment_type === 'PayPal') {
handlePayPalPayment()
}
if (data.shipping === 'Express') {
handleExpressShipping()
}
if (data.shipping === 'Standard') {
handleStandardShipping()
}
}
Is there a better way to write this function especially by following best practices?
You can create an array data structure that will hold the value you want to compare and the function that you want to execute in that case. That will simplify your code and keep it manageable:
let allowedValues = [{
"value": "VISA",
"handler": handleVisaPayment
},
{
"value": "PayPal",
"handler": handlePayPalPayment
},
{
"value": "Express",
"handler": handleExpressShipping
},
{
"value": "Standard",
"handler": handleStandardShipping
}
]
function handleOrder(data) {
let matchedOrder = allowedValues.find(({
value
}) => value === data.payment_type);
if (matchedOrder) {
matchedOrder.handler();
}
}
You can even create a object mapping for those values and operations:
let allowedValues = {
"VISA": handleVisaPayment,
"PayPal": handlePayPalPayment,
"Express": handleExpressShipping,
"Standard": handleStandardShipping
}
function handleOrder(data) {
if (allowedValues[data.payment_type]) {
allowedValues[data.payment_type]();
}
}
First of all, you are executing the same IF statement twice in a row.
if (data.payment_type === 'VISA') {
handleVisaPayment
}
if (data.payment_type === 'VISA') {
handleMastercardPayment
}
I imagine it would be more logical if your second IF statement was like this:
if (data.payment_type === 'Mastercard') {
handleMastercardPayment
}
This looks like a simple copy-paste mistake, but I think it's worth pointing out.
Secondly, you might want to reorganize your code using a switch statement.
Ex:
switch (data.payment_type) {
case 'VISA':
handleVisaPayment
break;
case 'Mastercard':
handleMastercardPayment
break;
case 'PayPal':
handlePayPalPayment
break;
}
switch (data.shipping) {
case 'Express':
handleExpressShipping
break;
case 'Standard':
handleStandardShipping
break;
}
This should make your code easier to read/maintain/add new features in the future.
Again, I know it was specified to avoid using switch, but it does look like the most simple solution here.
I think this will give some building blocks to go further, as others have mentioned use mapping to resolve the functions you need.
const data = {
shipping: 'Standard',
payment_type: 'VISA',
}
const handleVisaPayment = () => console.log('handling visa payment')
const handleStandardShipping = () => console.log('handling standard shipping')
const orderHandlingMap = {
'Standard': handleStandardShipping,
'VISA': handleVisaPayment,
}
const handleOrder = data =>
Object.values(data)
.filter(element => orderHandlingMap[element])
.map(handlerName => orderHandlingMap[handlerName]())
handleOrder(data)

how to make the if else code better, React js

I want to make the if else code I become reusable or use a switch, how do I use the switch?
this my code :
handleChange = (selectedkey) => {
this.setState({ activeKey: selectedkey })
if (selectedkey === '1') {
this.updateTabNotPay();
} else if (selectedkey === '2') {
this.updateTabNotSent();
} else if (selectedkey === '3') {
this.updateTabInDelivery();
} else if (selectedkey === '4') {
this.updateTabFinish();
} else if (selectedkey === '5') {
this.updateTabCancel();
}
};
I'd avoid switch, and instead use an object indexed by selectedkey, whose values are the associated function names:
const keyFnNames = {
'1': 'updateTabNotPay',
'2': 'updateTabNotSent',
'3': 'updateTabInDelivery',
'4': 'updateTabFinish',
'5': 'updateTabCancel'
};
// ...
handleChange = (selectedkey) => {
this.setState({ activeKey: selectedkey })
const fnName = keyFnNames[selectedKey];
if (fnName) {
this[fnName]();
}
};
If you know that selectedKey will always have a corresponding function, then you can levae out the if (fnName) check.
Using switch instead would be unnecessarily verbose and more error-prone, IMO.
i suppose something like this could work ?
handleChange = (selectkey) => {
this.state({ activeKey: selectedkey })
switch(selectedkey){
case 1:
this.updateTabNotPay();
break;
case 2:
this.updateTabNotSent();
break;
case 3:
this.updateTabInDelivery();
break;
case 4:
this.updateTabFinish();
break;
case 5:
this.updateTabCancel();
break;
default:
console.log("error");
}
}
strong text

change node icon using fancytree.js

I am using fancytree.js for treeview and I have a callback on the tree:
$("#tree").fancytree({
source: {url: "/" + appPath + "/pathosadmin?treepages=true"},
postProcess: function (event, data) {
data.result = convertData(data.response, true);
},
init: function (event, data) {
var root = $("#tree").fancytree("getRootNode");
root.sortChildren(function (a, b) {
return treeSort(a, b);
}, true);
},
icon: function (event, data) {
switch (data.node.data.NODE_TYPE) {
case 1: //page
if (data.node.data.STARTPAGE == 0) {
return "fancytree_page_icon";
} else if (data.node.data.STARTPAGE == 1) {
_this.startPageNode = data.node;
return "fancytree_startpage_icon";
}
case 2: //group
return "fancytree_group_icon";
case 3: //level
if (data.node.data.LEVELID) {
switch (data.node.data.LEVELID) {
case 1:
return "fancytree_level_1_icon";
case 2:
return "fancytree_level_2_icon";
case 3:
return "fancytree_level_3_icon";
case 4:
return "fancytree_level_4_icon";
case 5:
return "fancytree_level_5_icon";
}
} else {
return "fancytree_location_icon";
}
}
},
extensions:
Now I want to also change the icons on runtime. Sadly
if (_this.startPageNode) {
_this.startPageNode.icon = "fancytree_page_icon";
_this.startPageNode.renderTitle();
}
activeNode.icon = "fancytree_startpage_icon";
activeNode.render();
_this.startPageNode = activeNode;
doesnt work. Any hints on how to tackle that problem. The node.icon attribute is always undefined and even if i set it (+render the node) it doesnt show.
renderTitle() calls icon function, so only way I found to change icon dynamically is to put some attribute on node
activeNode.state = 'clicked';
activeNode.renderTitle();
and then put extra handling login in icon function on tree:
var state = data.node.state;
if (state) {
switch (state) {
case "clicked": return "glyphicon glyphicon-ban-circle"
return;
case "completed": return "glyphicon glyphicon-ok-circle"
return;
case "removed": return "glyphicon glyphicon-remove-circle"
return;
default:
return "glyphicon glyphicon-remove-circle"
break;
}
}

Categories