Switch Statement and jQuery hasClass function - javascript

I am trying to use a switch statement to check if the current page has a specific body class. This is kind of what I am looking for:
var bodyClass = $('body').hasClass('className')
switch(bodyClass) {
case 'homepage':
// console.log("This is the homepage");
break;
case 'residential-page':
// console.log("This is the residential page");
break;
default:
// console.log("default code block ran");
}
I do understand that the jQuery hasClass function returns true of false and is used like $('body').hasClass('someClassName') and this will return true or false. Also, my body typically has about 7-10 different class names for a given page.

This is not the use case for a switch in my opinion, but a simple set of branches
var body = $('body');
if(body.hasClass('abc')) {
}
else if(body.hasClass('def')) {
}
else {
/* default case */
}
/* etc */

I agree with the other answer that you're better suited to just use if, else if statements here, but an alternative would be to rip the classes off the body tag and check them against your strings:
var bodyClasses = ($('body').attr('class') || '').split(' ');
for (var i = 0, len = bodyClasses.length; i < len; i++) {
switch(bodyClasses[i]) {
case 'homepage':
// console.log("This is the homepage");
break;
case 'residential-page':
// console.log("This is the residential page");
break;
default:
// console.log("default code block ran");
}
}

I know this is an old thread, but it may help someone else.
If you are able to ensure the classes for the element are declared in a specific order, you could ensure the class you are checking for is first / last in the list, and use something similar to this:
var bodyClass = $('body').attr('class');
var firstClass = bodyClass.slice(0, bodyClass.indexOf(' '));
switch(firstClass) {
case 'homepage':
// Some code here
break;
case 'residential-page':
// Other code here
break;
default:
// More code here
}

Related

Changing style through JavaScript doesn't work with variables

I want to do is change the left margin of a DOM element based on a variable in JavaScript. This function works:
function updateTabs(i) {
console.log('Switching to tab ' + i)
switch(i) {
case 0:
document.querySelector('#About-content1').style.marginLeft = "0";
break;
case 1:
document.querySelector('#About-content1').style.marginLeft = "-100%";
break;
case 2:
document.querySelector('#About-content1').style.marginLeft = "-199%";
break;
default:
break;
}
}
This successfully sets the margin-left property like I want it to. However, I don't want to call document.querySelector every time I call the updateTabs function. I tried this:
var contentDiv1 = document.querySelector('#About-content1');
function updateTabs(i) {
console.log('Switching to tab ' + i)
switch(i) {
case 0:
contentDiv1.style.marginLeft = "0";
break;
case 1:
contentDiv1.style.marginLeft = "-100%";
break;
case 2:
contentDiv1.style.marginLeft = "-199%";
break;
default:
break;
}
}
However, this only works the first time I call the function. After that, it prints "Switching to tab" but doesn't actually modify the style. Is there any way I could change the style without having to call document.querySelector every time?
I think the reason is that the second time around it doesn't know what contentDiv1 is how about you put that inside the function like this:
function updateTabs(i) {
var contentDiv1 = document.querySelector('#About-content1');
console.log('Switching to tab ' + i)
switch(i) {
case 0:
contentDiv1.style.marginLeft = "0";
break;
case 1:
contentDiv1.style.marginLeft = "-100%";
break;
case 2:
contentDiv1.style.marginLeft = "-199%";
break;
default:
break;
}
}
So now everytime the function runs it knows what contentDiv1 is. So now you still call document.querySelector only once but the function know what you want.
The question is missing some context, but if Hadi Pawar's answer isn't correct, my guess is that the element is being destroyed and recreated. This should validate that:
var contentDiv1 = document.querySelector('#About-content1');
contentDiv1.myResize = function(i) {
console.log('Switching to tab ' + i)
var offsets = [0, -100, -199];
if( i > offsets.length ) return;
this.style.marginLeft = offsets[i] + '%';
}
[...]
contentDiv1.myResize( n );
Now, when you call resize, you will get a hard error if 'contentDiv1' loses scope. Otherwise, the logic is contained within the element itself.
Turns out that the problem was that I had a Vue.js element connected to the same element, so the element was changed. I moved the Vue.js declaration to before the const contentDiv1 = document.querySelector('#About-content1'), and it fixed the problem.

Javascript switch case that runs code when any case is true?

I have a standard switch case block:
switch(variable) {
case "option1":
alert("Option 1");
break;
case "option2":
alert("Option 2");
break;
}
And I would like to run this code:
alert("Any Option");
Is there a simple way to run this code when either of the cases match, without adding the code to every case, and without rechecking "variable" (i.e. not using an if statement after the switch)?
There are a bunch of really hacky ways to do what you are suggesting (named do loops with break/continue, recursive functions with switch statements, etc.) but the cleanest would be to use a function, like so:
var variable = "option1";
function checkValue (val) {
switch (variable) {
case "option1":
alert("Option 1");
return true;
case "option2":
alert("Option 2");
return true;
default:
return false;
}
}
if (checkValue(variable)) {
// run common code
alert("Any option");
}
A labeled block allows you to break out of it at any time. If you break in the default case, you can run some code following the switch statement when either of the cases match and without rechecking the variable, as requested:
let variable = prompt("option1 or option2?");
select: {
switch(variable) {
case "option1":
alert("Option 1");
break;
case "option2":
alert("Option 2");
break;
default:
break select;
}
alert("Both Options");
}
However, I don't recommend this! Labels make the code execution path less clear. Above code is not readable. Rechecking the variable is a better approach.
Not directly with a switch statement. See The Switch Statement, ECMAScript 2016 standard.
In particular:
Runtime Semantics: Switch Evaluation
Runtime Semantics: CaseBlockExpression
The language spec does not contain the feature that you are looking for.
Why not making a function called by both cases?
switch(variable) {
case "option1":
dualAlert("Option 1");
break;
case "option2":
dualAlert("Option 2");
break;
}
function dualAlert(text){
alert(text);
alert('Common Alert');
}
I don't think i would ever use the pattern you described, nonetheless something like this could suit your needs.
/**
* Use this method to simulate a "finally" statement in a
* method that resembles a switch
*
* #param {*} value - The value to compare
* #param {Array<*, boolean, function>} options - The collection of switch statements
* First value is the value to compare against the original value
* Second value specifies if this statement should behave like a break at its end
* Third value is the action to take when the value matches
* #param {function} finallyFn - The method which is run if any statement was executed
*/
function switchWithFinally(value, options, finallyFn) {
var matched = false,
breakSwitch = true;
for(var i = 0; i < options.length; i++) {
if(!breakSwitch || value === options[i][0]) {
options[i][2]();
matched = true;
breakSwitch = options[i][1];
}
}
if(matched) finallyFn();
}
/**
* Example call, should return
* Option 2
* Option 3
* Any option
*/
switchWithFinally(
'option2',
[
['option1', true, function() {
console.log('Option 1');
}],
['option2', false, function() {
console.log('Option 2');
}],
['option3', true, function() {
console.log('Option 3');
}]
],
function() {
console.log('Any option');
}
);

add a wildcard to a JavaScript switch statement

is there a way i can create a switch statement with a wildcard with the logic of:
case: '/jobs/'+WILDCARD and ending in +'-jobs' :
this is for the window.location.pathname, which could be '/jobs/design-jobs', or '/jobs/engineer-jobs' etc
but, there are other pages which start with '/jobs' I don't want this to apply to, e.g '/jobs/post'
or any suggestions on a better way?
No there are not wildcards for switch statements, but you could e.g. use RegExp and test against it:
if( path.match(/^\/jobs\/(.*)-jobs$/) !== null ) {
//jobs url
} else {
switch( path ) {
case '/jobs/post':
//something else
break;
}
}
One trick you can use in some cases could be to use a function to normalize the input of your switch, to turn variable inputs into the specific cases:
Instead of:
switch(input) {
case 'something': // something
case 'otherthing': // another
case '/jobs/'+WILDCARD: // special
}
You could do:
function transformInput (input) {
if (input.match(/jobs.*-jobs/) return 'JOBS';
return input;
}
switch(transformInput(input)) {
case 'something': // something
case 'otherthing': // another
case 'JOBS': // special
}
You can do something like this:
var categories = {
design: function(){ console.log('design'); },
engineer: function(){ console.log('engineer'); }
};
for(var category in categories)
if(window.location.pathname === '/jobs/' + category + '-jobs')
categories[category]();

Trying to make an on/off/auto button

I am new to javascript and am trying to make a button that cycles through on/off/auto each click. Each state also has to run code in the if statement and code in the switch as well. I currently cannot seam to get it to run right. Later Once I get this working I want the "if statement" function to be in its own .js file so I can reference it for other on/off/auto buttons. While the switch will be apart of the main code. What am I doing wrong?
function cycle()
{
var onoffB = ();
if (document.getElementById("button1").value="On")
{
onoffB=1;
document.getElementById("button1").value="Off";
}
else if (document.getElementById("button1").value="Off")
{
onoffB=2;
document.getElementById("button1").value="Auto"
}
else
{
onoffB=0;
document.getElementById("button1").value="On"
}
switch(onoffB)
{
case 0:
//running code;
break;
case 1:
//running code;
break;
case 2:
//running code;
break;
}
}
</script>
</head>
<body>
<input type="button" id="button1" value="On" onclick="cycle()">
</body>
</html>
Well, there are two big problems I see right off the bat. First of all, the following syntax is invalid JavaScript:
var onoffB = ();
I think what you mean there is to have an undefined state for onoffB, which your'e better off doing with:
var onoffB = null;
Secondly, you're using assignment (=) instead of comparison (== or ===). (As a rule of thumb, you should always prefer === over == unless you have a very good reason and know what you're doing.) Consider the following:
var x = 3; // *sets* the value of x to 3
var x == 3; // invalid syntax
var x === 3; // invalid syntax
if( x = 2 ) { print 'x is 2'; } // will *always* print 'x is 2', no matter what
// the value of x is; x now has the value 2
// PROBABLY NOT WHAT YOU WANT
if( x = 0 ) { print 'x is 0'; } // will *never* print 'x is 0', no matter what
// the value of x is; x now has the value 0
// PROBABLY NOT WHAT YOU WANT
if( x === 5 ) { print 'x is 5'; } // will only print 'x is 5' if the value of x
// is 5; value of x
if( x === 0 ) { print 'x is 0'; } // will only print 'x is 0' if the value of x
// is 0; value of x unchanged
There are a lot of stylistic things I would change about this too. Your code's really difficult to read because of your formatting choices. Furthermore, there's a lot of unnecessarily repeated code. If I were writing this, I would shorten it to the following:
switch( document.getElementById("button1").value ) {
case 'On':
// do stuff
break;
case 'Off':
// do stuff
break;
case 'Auto':
// do stuff
break;
default:
// probably an error condition; show message, maybe?
break;
}
If you really need the value of the on/off/auto button, you can set it inside the case bodies.
On this line:
var onoffB = ();
You need to either remove the initializer or replace the parentheses with something else.
In each of your if statements:
if (document.getElementById("button1").value="On")
You're setting the value, making it always true. You probably want to compare using == rather than assigning with = here.
While it's not really a problem but rather a possible improvement, I'd recommend putting the result of document.getElementById in a variable so you don't have to keep calling it. It should be rather quick on its own, but doing it once will probably be faster.
Here's the complete working and running code:
<html>
<head>
<script type="text/javascript">
function cycle()
{
var onoffB = null;
if (document.getElementById("button1").value == "On")
{
onoffB = 1;
document.getElementById("button1").value = "Off";
}
else if (document.getElementById("button1").value == "Off")
{
onoffB = 2;
document.getElementById("button1").value = "Auto";
}
else if (document.getElementById("button1").value == "Auto")
{
onoffB = 0;
document.getElementById("button1").value = "On";
}
switch(onoffB)
{
case 0:
//running code;
break;
case 1:
//running code;
break;
case 2:
//running code;
break;
}
}
</script>
</head>
<body>
<input type="button" id="button1" value="On" onclick="cycle();">
</body>
</html>
As you can see, the main problems were:
You set var onoffB = (); while it should have been null.
You should have used the "==" instead of "=".
Another 'else if' was missing for when the value is 'Auto'.
I hope I've helped :-)
Try something like this:
var doc = document, bod = doc.body;
function E(e){
return doc.getElementById(e);
}
var state = 'On';
function onOffAuto(element){
var e = element;
switch(state){
case 'On':
e.value = state = 'Off';
return;
case 'Off':
e.value = state = 'Auto';
return;
case 'Auto':
e.value = state = 'On';
return;
}
}
E('button1').onclick = function(){
onOffAuto(this);
}

javascript switch(true)

Hi i am trying to handle an ajax json response
here is my code
success: function (j) {
switch(true)
{
case (j.choice1):
alert("choice2");
break;
case (j.choice2):
alert("choice2");
break;
default:
alert("default");
break;
}
}
based on what j is return i do my action BUT i keep getting the default.
I have alert the j values and come correct.Some how case (j.choice1) case (j.choice2) is not working.
I tried case (j.choice1!="") (j.choice2!="") But in this scenario i keep getting the first choice.
What am i missing
It works for me:
var a = 0, b = true;
switch(true) {
case a:
console.log('a');
break;
case b:
console.log('b');
break;
}
However, the case labels must be equal to true, not just implicitly true.
Also, only the first case that evaluates to true will execute.
SOLVED
Based on SLaks answer i modify the code as below
if(j.choice1){ var choice1=true;} else { var choice1=false;}
if(j.choice2){ var choice2=true;} else { var choice2=false;}
switch(true)
{
case choice1:
alert("choice1");
break;
case choice2:
alert("choice2");
break;
default:
alert("default");
break;
}
For all asking why switch and not if.
Switch will execute only 1 statement, but if can execute more than 1 if any mistake come form response (for example if set choice1 and choice 2 the if will alert both but switch will alert only choice1).
The response expecting as choice has to do with credit card charge to bank so i want to ensure that only 1 action will exetute
Thank to all
You need to read up on the switch statement. You should not be switching on a constant value.
It appears that you need to use if statements, as you don't really want to be switching on your j value:
success: function (j) {
if (j.choice1)
{
alert("choice1");
break;
}
if (j.choice2)
{
alert("choice2");
break;
}
alert("default");
}
}
In a case like this, a better way to do this is probably something like:
success: function (j) {
if(j.choice1 || j.choice2) {
alert("choice2");
} else {
alert("default");
}
}
Why not use an object literal instead of a switch(true) ?
const j= {
choice1: false,
choice2: true
};
const map = {
true: 'default',
...(j.choice1 ? {[`${j.choice1}`]: 'choice1'} :{}),
...(j.choice2 ? {[`${j.choice2}`]: 'choice2'} :{})
}['true']
console.log(map) // 'choice2'

Categories

Resources