4lackof
4lackof

Reputation: 1390

JS - Using multi-criteria cases in switch statement

I am using "multi-criteria cases" in my switch statement in order to handle the different values I am getting.

One of the things I am running into is this (dummy code from snippet below):

case '2':
  // Don't mind the inline styling, its' only for this example
  document.getElementById('output').lastChild.style.color = 'red';
case '2.5':
  document.getElementById('output').lastChild.style.color = 'white';
  document.getElementById('output').lastChild.style.backgroundColor = 'blue';
  break;

What I am attempting to do here is to set either 2 or 2.5's background color to be blue, but still set the text color uniquely based on the value.

Only that, like the code was meant to do, it overrides the text color of 2 with the text color of 2.5.


There are two solutions I have worked out so far.

The first is:

case '2':
  document.getElementById('output').lastChild.style.color = 'red';
  document.getElementById('output').lastChild.style.backgroundColor = 'blue';
  break;
case '2.5':
  document.getElementById('output').lastChild.style.color = 'white';
  document.getElementById('output').lastChild.style.backgroundColor = 'blue';
  break;

The second is:

case '2':
  document.getElementById('output').lastChild.style.color = 'red';
case '2.5':
  if (e.target.textContent === '2.5') {
    document.getElementById('output').lastChild.style.color = 'white';
  }
  document.getElementById('output').lastChild.style.backgroundColor = 'blue';
  break;

The only real problem now is that I am a big fan of the "DRY" theory. The above two solutions are, to some degree, "WET."

Thus I am trying to figure out a better way to write this code, potentially something which looks like this:

case '2':
  document.getElementById('output').lastChild.style.color = 'red';
case '2.5':
  document.getElementById('output').lastChild.style.color = 'white';
case '2':  
case '2.5':
  document.getElementById('output').lastChild.style.backgroundColor = 'blue';
  break;

(Even this is a bit "DRY")

I understand that to some degree my code will be a bit "DRY" and I am willing to have that if necessary, I am just at the stage of lessening the code I do have for performance and want to see if I can cut the code down in any way possible.

Here's a snippet with my dummy code in action:

document.addEventListener('click', function(e) {
  if (e.target.nodeName === 'BUTTON') {
    document.getElementById('output').innerHTML += '<div>' + e.target.textContent + '</div>';
    switch(e.target.textContent) {
      case '1':
        // Don't mind the inline styling for this example pls
        document.getElementById('output').lastChild.style.backgroundColor = 'green';
        break;
      case '2':
        document.getElementById('output').lastChild.style.color = 'red';
      case '2.5':
        document.getElementById('output').lastChild.style.color = 'white';
        document.getElementById('output').lastChild.style.backgroundColor = 'blue';
        break;
      case '3':
        document.getElementById('output').lastChild.style.color = 'lime';
      case '3.5':
        if (e.target.textContent === '3.5') {
          document.getElementById('output').lastChild.style.color = 'cyan';
        }
        document.getElementById('output').lastChild.style.backgroundColor = 'red';
        break;
    }
  }
});
<button id="b1">1</button>
<button id="b2">2</button>
<button id="b2-5">2.5</button>
<button id="b3">3</button>
<button id="b3-5">3.5</button>
<div id="output"></div>

UPDATE

Going on, I figured there was another way to do this, which looks like this:

switch(e.target.textContent) {
  case '2':
  case '2.5':
    switch(e.target.textContent) {
      case '2':
        document.getElementById('output').lastChild.style.color = 'red';
        break;
      case '2.5':
        document.getElementById('output').lastChild.style.color = 'white';
        break;
    }
    document.getElementById('output').lastChild.style.backgroundColor = 'blue';
    break;
}

However, that basically is two of the same switch statements nested in one another.

I am not trying to write all the wrong ways to do things (I know it looks like that), I am trying to figure out the right way to do it, maybe by testing all the wrong ways to do it.

If anyone can help me with the right way to do this, that would be much appreciated.

Upvotes: 1

Views: 64

Answers (2)

Dice Kusaba
Dice Kusaba

Reputation: 198

You could do something like:

var config = {
  "1" : {
    "bgColor": "green"
  },
  "2" : {
    "bgColor": "red"
  },
  "2.5" : {
    "color": "white",
    "bgColor": "blue"
  },
  "3" : {
    "color": "lime"
  },
  "3.5" : {
    "color": "cyan",
    "bgColor": "red"
  }
};

document.addEventListener('click', function(e) {
  if (e.target.nodeName === 'BUTTON') {
    var output = document.getElementById('output');
    output.innerHTML += '<div>' + e.target.textContent + '</div>';
    for(var key in config) {
      if(e.target.textContent == key) {
        var obj = config[key];  
        if(obj['color']) {
          output.lastChild.style.color = obj['color'];
        }
        if(obj['bgColor']) {
          output.lastChild.style.backgroundColor = obj['bgColor'];
        }
      }
    }
  }
});

This way you can just edit the data layer (JSON) when you need to add more options. You also won't need to touch the click event.

Upvotes: 0

Hayden Braxton
Hayden Braxton

Reputation: 1161

This might be a slightly simplified solution. Is this what you're looking for?

document.addEventListener('click', function(e) {
  if (e.target.nodeName === 'BUTTON') {
    var elem = document.getElementById('output');
    elem.innerHTML += '<div>' + e.target.textContent + '</div>';
    
    var txColor = '',
        bgColor = '',
        elemStyle = elem.lastChild.style;
    
    switch(e.target.textContent) {
      case '1':
	bgColor = 'green';
        break;
      case '2':
      	txColor = 'red';
      case '2.5':
      	txColor = 'white';
        bgColor = 'blue';
        break;
     default:
        bgColor = 'red';
        txColor = (e.target.textContent === '3.5') ? 'cyan':'lime';
    }
    
    elemStyle.color = txColor;    
    elemStyle.backgroundColor = bgColor;
    
  }
});
<button id="b1">1</button>
<button id="b2">2</button>
<button id="b2-5">2.5</button>
<button id="b3">3</button>
<button id="b3-5">3.5</button>
<div id="output"></div>

Upvotes: 2

Related Questions