Using switch case in javascript - javascript

This is the variable i am having right now
[
{
"_id":"63773059c3160f782c087e33",
"nfrid":"637328ebf5c4b2558b064809",
"nfrname":"azuread",
"fileName":"package.json",
"isImport":false,
"isConst":false,
"isComponent":false,
"isNewFile":false,
"landmark":"\"react\"",
"isAfter":false,
"fileContent":"\"#azure/msal-react\": \"^1.4.9\",",
"filePath":"package.json",
"isPackage":true,
"isIndexHtml":false,
"projecttypeid":"6372366d1b568e00d8af2e44",
"projecttypetitle":"PWA React",
"nfrGitIo":[
{
"_id":"637328ebf5c4b2558b064809",
"iconpath":"https://cdnerapidxdevportal.azureedge.net/webdesignerimages/azure-active-directory-aad-icon-488x512-3d71nrtk.png",
"title":"Azure AD",
"description":"Azure Active Directory (Azure AD), part of Microsoft Entra, is an enterprise identity service that provides single sign-on, multifactor authentication, and conditional access to guard against 99.9 percent of cybersecurity attacks."
}
]
},
{
"_id":"63773144c3160f782c087e35",
"nfrid":"637328ebf5c4b2558b064809",
"nfrname":"azuread",
"fileName":"index.js",
"isImport":true,
"isConst":false,
"isComponent":false,
"isNewFile":false,
"isPackage":false,
"landmark":null,
"isAfter":null,
"fileContent":"import { MsalProvider } from '#azure/msal-react';import { msalConfig } from './authConfig';import {PublicClientApplication } from '#azure/msal-browser';",
"filePath":"src/index.js",
"isIndexHtml":false,
"projecttypeid":"6372366d1b568e00d8af2e44",
"projecttypetitle":"PWA React",
"nfrGitIo":[
{
"_id":"637328ebf5c4b2558b064809",
"iconpath":"https://cdnerapidxdevportal.azureedge.net/webdesignerimages/azure-active-directory-aad-icon-488x512-3d71nrtk.png",
"title":"Azure AD",
"description":"Azure Active Directory (Azure AD), part of Microsoft Entra, is an enterprise identity service that provides single sign-on, multifactor authentication, and conditional access to guard against 99.9 percent of cybersecurity attacks."
}
]
},
]
I am having many flags like isImport, isPackage, isIndexHtml like that. I am trying to put those flags in a switch case and call individual function when each flag is true.Something like this,
for (let i = 0; i < cosmos.length; i++) {
console.log(cosmos[0].isPackage);
switch (cosmos[i]) {
case `${cosmos[i].isImport === true}`:
const statusImport = common.updateImport(cosmos[i]);
console.log(statusImport);
break;
// case `${cosmos[i].isConst === true}`:
// console.log("I own a dog");
// break;
case `${cosmos[i].isPackage === true}`:
const statusPackage = common.updatePackage(cosmos[i]);
console.log(statusPackage);
break;
case `${cosmos[i].isIndexHtml === true}`:
const statusIndexHtml = common.updateIndexHTML(cosmos[i]);
console.log(statusIndexHtml);
break;
// case `${cosmos[i].isNewFile === true}`:
// const statusNewFile = common.addNewFile(cosmos[i]);
// console.log(statusNewFile);
// break;
default:
console.log("Nothing to add/update");
break;
}
}
But when I run this i am always getting the default console log. I dont know what i am missing
This is my first switch case implementation. Can someone point me in the right direction?

Don't convert them to strings and in switch condition add just true:
for (let i = 0; i < cosmos.length; i++) {
console.log(cosmos[0].isPackage);
switch (true) {
case cosmos[i].isImport:
const statusImport = common.updateImport(cosmos[i]);
console.log(statusImport);
break;
case cosmos[i].isPackage:
const statusPackage = common.updatePackage(cosmos[i]);
console.log(statusPackage);
break;
case cosmos[i].isIndexHtml:
const statusIndexHtml = common.updateIndexHTML(cosmos[i]);
console.log(statusIndexHtml);
break;
default:
console.log("Nothing to add/update");
break;
}
}

switch is not the right construct to use in this case.
Simply use if/else here.

Since you're testing several different values from cosmos[i], not testing a single value against multiple possible matches, switch isn't the right tool here. (You can use it, just like you can use a wrench to bang in a nail, but it's not the right tool.) Instead, use an if/else if/else chain:
for (let i = 0; i < cosmos.length; i++) {
if (cosmos[i].isImport) {
const statusImport = common.updateImport(cosmos[i]);
console.log(statusImport);
} else if (cosmos[i].isPackage) {
const statusPackage = common.updatePackage(cosmos[i]);
console.log(statusPackage);
} else if (cosmos[i].isIndexHtml) {
const statusIndexHtml = common.updateIndexHTML(cosmos[i]);
console.log(statusIndexHtml);
} else {
console.log("Nothing to add/update");
}
}
Separately, in new code, I'd suggest using a for-of instead of a for when you don't need the index:
for (const entry of cosmos) {
if (entry.isImport) {
const statusImport = common.updateImport(entry);
console.log(statusImport);
} else if (entry.isPackage) {
const statusPackage = common.updatePackage(entry);
console.log(statusPackage);
} else if (entry.isIndexHtml) {
const statusIndexHtml = common.updateIndexHTML(entry);
console.log(statusIndexHtml);
} else {
console.log("Nothing to add/update");
}
}

A switch statement can only interrogate one variable. In your case the correct solution is an if statement for each member variable. Replace the switch statement with this snippet:
if (cosmos[i].isImport === true) {
const statusImport = common.updateImport(cosmos[i]);
console.log(statusImport);
}
if (cosmos[i].isPackage === true) {
const statusPackage = common.updatePackage(cosmos[i]);
console.log(statusPackage);
}
if (cosmos[i].isIndexHtml === true) {
const statusIndexHtml = common.updateIndexHTML(cosmos[i]);
console.log(statusIndexHtml);
}
I note that your data structure does not mutually exclude the isImport isPackage and isIndexHtml - so in principle any combination of them could be true and my proposed code would execute accordingly.

Related

Better way of searching specific keywords in strings in JavaScript

I am working with an array of urls and for each url i wanna find a image corresponding to the site domain. my first attempt was
const url = new URL(props.url);
const platform = url.hostname.split(".")[1];
console.log(platform)
const platform_logos = {
"codechef": "images/chef.png",
"withgoogle": "images/google.png",
.
.
.
"codeforces": "images/codeforces.png",
}
let platform_logo = platform_logos[platform];
but it doesnt work with url of type 'https://momo2022fr.hackerearth.com' so i had to resort to
let platform_logo = "images/code.png"
if (url.includes("hackerearth")) {
platform_logo = "images/hackerearth.png"
}
else if (url.includes("hackerrank")) {
platform_logo = "images/hackerrank.png"
}
else if (url.includes("codeforces")) {
platform_logo = "images/codeforces.png"
}
else if (url.includes("codechef")) {
platform_logo = "images/chef.png"
}
else if (url.includes("atcoder")) {
platform_logo = "images/atcoder.png"
}
else if (url.includes("leetcode")) {
platform_logo = "images/leetcode.png"
}
else if (props.url.includes("withgoogle")) {
platform_logo = "images/google.png"
}
Is there any better way of writing the code below, it just feels like it violates DRY
You could change how you're reading the url to only get the root domain.
location.hostname.split('.').reverse().splice(0,2).reverse().join('.').split('.')[0]
This code would give hackerearth for https://momo2022fr.hackerearth.com/.
So there are several ways of achieving this.
These are just two from the top of my head.
Parsing the url and using a switch() to determine the outcome, with fallback if none is found.
const url = new URL("https://www.withgoogle.com/search?q=test");
const sites = [
"hackerearth",
"hackerrank",
"codeforces",
"codechef",
"atcoder",
"leetcode",
"withgoogle",
];
console.info(url.hostname);
const site = url.hostname.match(new RegExp(`${sites.join("|")}`));
let logo = "";
switch (site[0]) {
case "hackerearth":
logo = "images/hackerearth.png";
break;
case "hackerrank":
logo = "images/hackerrank.png";
break;
case "codeforces":
logo = "images/codeforces.png";
break;
case "codechef":
logo = "images/chef.png";
break;
case "atcoder":
logo = "images/atcoder.png";
break;
case "leetcode":
logo = "images/leetcode.png";
break;
case "withgoogle":
logo = "images/google.png";
break;
default:
logo = "images/code.png";
break;
}
console.info(logo);
Then there is the modern way, with less code and programming the fallback.
// const url = new URL("https://eee.com/test");
const url = new URL("https://www.withgoogle.com/search?q=test");
const sites = {
hackerearth: "images/hackerearth.png",
hackerrank: "images/hackerrank.png",
codeforces: "images/codeforces.png",
codechef: "images/chef.png",
atcoder: "images/atcoder.png",
leetcode: "images/leetcode.png",
withgoogle: "images/google.png",
default: "images/code.png",
};
let site = url.hostname.match(new RegExp(`${Object.keys(sites).join("|")}`));
if (site === null) {
site = "default";
}
console.info(site, sites[site]);
You could just do the same thing as in your first solution and store the mapping from the substring to the image path in an ocject:
const platform_logos = {
"hackerearth": "images/hackerearth.png",
"hackerrank": "images/hackerrank.png",
"codeforces": "images/codeforces.png",
"codechef": "images/chef.png",
"atcoder": "images/atcoder.png",
"leetcode": "images/leetcode.png",
"withgoogle": "images/google.png"
};
Then you could iterate over the key-value pairs in your object to find the key that is part of the URL and return it once it matches:
function getLogo(url) {
for(const [key, value] of Object.entries(platform_logos)) {
if(url.contains(key)) {
return value;
}
}
}
let platform_logo = getLogo(url);
You can iterate over the images and check URL:
const url = "https://example.com/codechef/asdasd/...";
const platform_logos = {
"codechef": "images/chef.png",
"withgoogle": "images/google.png",
"codeforces": "images/codeforces.png",
}
let img = "default.png";
for (const [key, value] of Object.entries(platform_logos)) {
if (url.includes(key)) {
img = value;
break;
}
}
console.log(img);

javascript retrieve value from a map

I am trying to develop a google script app.
Here is one function to create an array map.
function getOffices(){
var result=AdminDirectory.Groups.list({domain:"example.com"})
result=result.groups.filter(function(group){
var str=group.email;
return str.search("-office#example.com")>=0;
})
result=result.map(function(group){ return {name:group.name,email:group.email}})
return result;
}
I have created a logic piece, that I want to execute certain actions based on the results, that looks like this:
var getOrgUnitPath = (accountOffice, accountType) => {
if (accountType === 'facilitator') {
return 'Limited Accounts/Gmail Plus Calendar';
} else {
switch (accountOffice) {
case accountOffice.includes('Boston'):
return "/Standard-Access/Boston";
break;
case accountOffice.includes('New York'):
return '/Standard-Access/New York';
break;
case accountOffice.includes('Lincoln'):
return '/Standard-Access/Lincoln';
break;
default:
return '/Standard-Access';
break;
}
}
};
Lastly, I try to set the organizational unit -- which is ultimately what i am trying to do, but can't seem to get the syntax right, I have tried everything I can think of. I have hardcoded the "accountType" and it worked, so I know the formObject.accountType is functioning properly.
orgUnitPath: getOrgUnitPath(accountType, formObject.accountType),
Thanks in advance!
This is a wrong usage of switch case.
if accountOffice's would be just New York, Boston, Lincoln. Remove the complex condition and replace with
switch (accountOffice) {
case "Boston":
return "/Standard-Access/Boston";
break;
case "New York":
return "/Standard-Access/New York";
break;
case "Lincoln":
return "/Standard-Access/Lincoln";
break;
default:
return "/Standard-Access";
break;
}
If not, use if-else if you have complex condition to check rather than simple match cases
if (accountOffice.includes("Boston")) {
return "/Standard-Access/Boston";
} else if (accountOffice.includes("New York")) {
return "/Standard-Access/New York";
} else if (accountOffice.includes("Lincoln")) {
return "/Standard-Access/Lincoln";
} else {
return "/Standard-Access";
}
I rewrote the code so I could get a better understanding of it. From what I can tell, getOffices lists all offices and getOrgUnitPath returns a path including the first office that matches the ordered list of offices ['Boston', 'NY', 'Lincoln']. If that's the case, what's missing is that the first argument to getOrgUnitPath should be getOffices(), right? (Notice it is the execution of the function getOffices.)
Here's the code "simplified" to my liking. I hope it helps:
const getOffices = () => {
const bigList = x.y.list({ domain: 'example.com' }) // ?
return bigList
.filter(cur => ~cur.email.search('abc'))
.map(cur => ({
name: cur.name,
email: cur.email
}))
}
const getPath = (accOffice, accType) => {
if (accType === 'xyz')
return 'foobar'
const city = ['Boston', 'NY', 'Lincoln']
.find(cur => accOffice.includes(cur))
return `yadayada/${city}`
}
const theFinalObj = {
orgUnitPath: getPath(getOffices(), 'rightHardcodedType')
}

Convert ternary to if/else in mapped array function

I have a ternary within a map function, that currently only switches based on one option. I need to be able to pull the "home" option and set it to "/" if the user clicks that option
const buttons = ['Home', 'Docs', 'About-Us'];
const buttonSlugs = buttons.map(button => button === 'About-Us' ? 'aboutus' : button.toLowerCase());
How can I modify the ternary to an if/else, so that the home button can be set to "/"?
You can use a conditional like:
const buttons = ['Home', 'Docs', 'About-Us'];
const buttonSlugs = buttons.map(button => {
if (button === 'About-Us') {
return 'aboutus';
}
else if (button === 'Home') {
return '/';
}
else {
return button.toLowerCase();
}
});
console.log(buttonSlugs);
But this sort of approach can get ugly if you have many mappings or if you expect to add more. Another approach is to use an object of functions, each of which performs the transformation you wish for a given button:
const buttons = ['Home', 'Docs', 'About-Us'];
const transformations = {
'About-Us': () => 'aboutus',
Home: () => '/',
Docs: button => button.toLowerCase(),
};
const buttonSlugs = buttons.map(btn => transformations[btn](btn));
console.log(buttonSlugs);
This is easily extensible and keeps the transformation logic out of the map.
If you want a default action or the ability to handle missing buttons, you can check for an empty key in the transformations object before calling the retrieved function and proceed accordingly.
Are you just asking for:
buttons.map(button => {
if(button === 'Home'){
do something
} else if (button === 'About-us') {
do something else
} else if (button === 'Docs') {
do something elser
}
}
might be better to use a switch though and a forEach since map returns something, forEach doesnt:
buttons.forEach(button => {
switch(button){
case 'Home':
do something
break
case 'About-us':
do something
break
case 'Docs':
do something
break
default:
break
}
}
You could use a switch statement rather than if
const buttonSlugs = buttons.map(button => {
switch (button) {
case 'About-Us':
button = 'aboutus';
break;
case 'Docs':
button = 'docs';
break;
case 'Home':
button = '/';
break;
}
})
I think this is what you wanted to do.
const buttons = ['Home', 'Docs', 'About-Us'];
const buttonSlugs = buttons.map((button)=>{
if(button==='About-Us'){
return 'aboutus';
}
else if(button==='Home'){
return '/';
}
else{
return button.toLowerCase();
}
});
console.log(buttonSlugs); // for result
const buttons = ['Home', 'Docs', 'About-Us'];
const buttonSlugs = buttons.map(button => {
let slug;
switch (button) {
case 'About-Us':
slug = 'aboutus';
break;
case 'Home':
slug = '/';
break;
default:
slug = button.toLocaleLowerCase();
break;
}
return slug;
});

const scoping issue within a switch statement

I have the following code in my reducer. In both cases, findFile() returns a result, however, only in the first occurrence (setImageRotation) will "origFile" get set. Changing the name of the second occurrence of "origFile" will allow it to get set. I'm wondering why this is case, as const has a block level scope.
function handler(stateArg, action) {
const state = stateArg || {};
let nextState;
switch (action.type) {
case actions.types.setImageRotation: {
const origFile = findFile(action.fileUid, state.files);
const newfile = Object.assign({}, origFile, { rotation: action.rotation });
nextState = updateStateFile(state, newfile);
break;
}
case actions.types.setImageRegionOfInterest: {
const origFile = findFile(action.fileUid, state.files);
const newfile = Object.assign({}, origFile, { roi: action.roi });
nextState = updateStateFile(state, newfile);
break;
}
}
return nextState || state;
}
Notes:
origFile is not defined anywhere else in my solution.
there are no console errors
Transpiled Code:
case actions.types.setImageRegionOfInterest:{
var origFile = findFile(action.fileUid, state.files);
var newfile = (0, _assign2.default)({}, origFile, { roi: action.roi });
nextState = updateStateFile(state, newfile);
break;
}
case actions.types.setImageRotation:{
var _origFile = findFile(action.fileUid, state.files);
var _newfile = (0, _assign2.default)({}, _origFile, { rotation: action.rotation });
nextState = updateStateFile(state, _newfile);
break;
}
As people stated in the discussion, this code works. What I ran into was a bug with Google Chromes debugger & source mapping. When I turned source mapping off and debugged the transpiled code, I got the correct value for "origfile".

Simple JavaScript Selector

Using pure JavaScript without any library like jQuery, how could I detect if a variable holds a DOM Class or ID?
For example if I pass into a function a value that could be...
var mySelector = ".class-name";
or
var mySelector = "#id-name";
Then based on if mySelector holds a Class or ID I would run
document.getElementsByClassName
or
document.getElementsById
What would be the best way to do this without the use of a library like jQuery or another library?
Take a look at document.querySelector or document.querySelectorAll, instead. Both of those can find elements by ID or class (as well as other selectors). querySelector will return 1 element, querySelectorAll will return all elements.
var mySelector = ".class-name", // "#id-name" will also work fine.
elements = document.querySelectorAll(mySelector);
Note that this doesn't work in IE < 8 (see http://caniuse.com/#search=querySelectorAll). A polyfill would be the best way to handle it to add IE7 support.
You can use this simple if/else statement to differentiate. This would also allow you to run other code based on whether it's a class or an ID you are referencing.
var mySelector = ".class-name";
if(mySelector.charAt(0) == ".")
{
document.getElementsByClassName(mySelector.substring(1));
}
else if(mySelector.charAt(0) == "#")
{
document.getElementsById(mySelector.substring(1));
}
The first way I think is check a first symbol of stroke.
Something like:
var $ = function( string ) {
var result;
switch (string.substr(0,1)) {
case '.': result = document.getElementsByClassName(string); break;
case '#': result = document.getElementById(string); break;
default: result = document.getElementsByTagName(string); break;
}
return result;
}
var mySelector = ".class-name";
console.log( $(mySelector) );
Just because you only want a selector and not the entire jQuery library, doesn't mean you have to roll your own own. jQuery uses the Sizzle selector engine, and you could just as easily use it yourself without the overhead of full jQuery:
http://sizzlejs.com/
I'm not an advanced user, but some time ago I created this little script:
https://gist.github.com/caiotarifa/cc7d486292f39157d763
var __;
__ = function(selector, filter) {
'use strict';
var response;
function filtering(selectors, filter) {
switch (filter) {
case "first":
return selectors[0];
break;
case "last":
return selectors[selectors.length - 1];
break;
default:
return selectors[filter];
break;
}
}
selector = selector.trim();
if (typeof filter === "string") { filter = filter.trim(); }
if (selector.indexOf(' ') < 0 && selector.indexOf('.', 1) < 0 && selector.indexOf('#', 1) < 0) {
switch (selector.substr(0, 1)) {
case '.':
response = document.getElementsByClassName(selector.substr(1));
if (response.length === 1) { filter = "first"; }
if (typeof filter !== "undefined") { response = filtering(response, filter) }
break;
case '#':
response = document.getElementById(selector.substr(1));
break;
default:
response = document.getElementsByTagName(selector);
if (response.length === 1) { filter = "first"; }
if (typeof filter !== "undefined") { response = filtering(response, filter) }
break;
}
} else {
if (typeof filter !== "undefined") {
switch (filter) {
case "first":
response = document.querySelector(selector);
break;
case "last":
response = document.querySelectorAll(selector);
response = response[response.length - 1];
break;
default:
response = document.querySelectorAll(selector);
response = response[filter];
break;
}
} else {
response = document.querySelectorAll(selector);
if (response.length === 1) { response = response[0]; }
else if (response.length < 1) { response = false; }
}
}
return response;
};
It's simple to use it:
__("div")
Or passing some filter like:
__("div", "first")
I didn't make a benchmark test with it. I hope it can help you.

Categories

Resources