2
\$\begingroup\$

I have made this app to get a bit more familiar with JavaScript and CSS.

I functionality seem to work as expected. Although I've noticed problems with the flexbox-layout in Firefox. Currently no good idea what causes that issue.

Any tips how to improve the app appreciated.

var sc = {};

sc.btns = document.querySelectorAll('.btn');
sc.from = document.querySelectorAll('.from');
sc.to = document.querySelectorAll('.to');
sc.nums = document.querySelectorAll('.num');
sc.delete = document.querySelector('.del'); 
sc.display = document.querySelector('.display');

sc.currentSystem = 'dec';
sc.targetSystemInt;
sc.targetSystemString;

sc.btns = Array.prototype.slice.call(sc.btns);
sc.from = Array.prototype.slice.call(sc.from);
sc.to = Array.prototype.slice.call(sc.to);
sc.nums = Array.prototype.slice.call(sc.nums);

sc.changeClasses = function (element, toRemove, toAdd) {
  element.classList.remove(toRemove);
  element.classList.add(toAdd);
}

sc.setSystem = function(setSystem) {

  sc.nums.forEach(function(num) {
    if (num.classList.contains(setSystem)) {
      sc.changeClasses(num, 'not-selectable', 'selectable');
    } else {
      sc.changeClasses(num, 'selectable', 'not-selectable');
    }
  });

  sc.setState = function(setOfElements, addOrRemove, cssClass) {
    setOfElements.forEach(function(element) {

      if (addOrRemove === 'add') {
        element.classList.add(cssClass);
      }

      if (addOrRemove === 'remove') {
        element.classList.remove(cssClass);
      }
    });
  }    

  sc.from.forEach(function(btn) {

    if (btn.classList.contains(setSystem)) {
      btn.classList.add('selected');
    } else {
      btn.classList.remove('selected');
    }
  });

  sc.to.forEach(function(btn) {
    var btnSystem = btn.getAttribute('data-system-string');

    if (btnSystem === sc.currentSystem) {
      btn.classList.add('not-selectable');
    } else {
      btn.classList.remove('not-selectable');
    }

  });
}

sc.from.forEach(function(element) {

  element.addEventListener('click', function(e) {
    sc.currentSystem =
      e.currentTarget.getAttribute('data-system-string');
    sc.setSystem(sc.currentSystem);
  });
});

sc.to.forEach(function(element) {

  element.addEventListener('click', function(e) {
    var toConvert = sc.display.textContent;
    var parsed;

    sc.targetSystemInt =
      e.currentTarget.getAttribute('data-system-number');

    sc.targetSystemString =
      e.currentTarget.getAttribute('data-system-string');

    switch (sc.currentSystem) {
      case 'bin':
        parsed = parseInt(toConvert, 2);
        break;
      case 'dec':
        parsed = parseInt(toConvert, 10);
        break;
      case 'hex':
        parsed = parseInt(toConvert, 16);
        break;
      default:
        console.log('Something has gone wrong.');
    }

    sc.btns.forEach(function(btn) {
      if (!btn.classList.contains('del') && !btn.classList.contains('not-selectable')) {
        btn.classList.add('not-selectable');
      }
    });

    sc.display.innerHTML =
      '<strong>' + toConvert + '</strong> <i>' +
      sc.currentSystem + '</i> => <strong>' +
      parsed.toString(+sc.targetSystemInt) +
      '</strong> <i>' + sc.targetSystemString + '</i>';
  });
});

sc.nums.forEach(function(btn) {
  btn.addEventListener('click', function() {
    var tmp = sc.display.textContent;

    sc.setState(sc.from, 'add', 'not-selectable');
    tmp = tmp.replace(/^0/, '');
    tmp += this.getAttribute('data-number-value');
    sc.display.textContent = tmp;
  });

});

sc.delete.addEventListener('click', function() {
  sc.display.textContent = 0;
  sc.setSystem('dec');
  sc.setState(sc.from, 'remove', 'not-selectable');
});

sc.setSystem('dec');
.wrap {
  max-width: 480px;
  margin: 20px auto;
  font-family: helvetica, arial, sans-serif;
}

.calculator {
  background-color: #cdcdcd;
  padding: 10px 20px;
  border-radius: 16px;
  border: 1px solid #000;
  border-right: 2px solid #000;
  border-bottom: 2px solid #000;
}

.display {
  width: 100%;
  text-align: right;
  background: #efefef;
  background: linear-gradient(to right, #c5c5c5, #f4f4f4);
  padding: 10px 15px;
  border-radius: 6px;
  border: 1px solid #000;
  border-top: 2px solid #000;
  border-left: 2px solid #000;
  font-family: "courier new", sans-serif;
  font-size: 1.5em;
}

.row {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.description {
  font-size: 1.5em;
  padding-right: 2.0833%;
  min-width: 12.4998%;
}

.btn {
  border-radius: 12px;
  border: 1px solid #000;
  width: 4.16666%;
  height: 4.16666%;
  text-align: center;
  line-height: 20px;
  padding: 2.0833333%;
  margin: 1.0416%;
  border-right: 2px solid #000;
  border-bottom: 2px solid #000;
  position: relative;
  text-shadow: 1px 1px 1px #323232;
}

label {
  text-shadow: 2px 2px 2px #969696;
}

.system {
  width: 25%;
  background-color: #898989;
  color: white;
  font-weight: bold;
  font-size: 2em;
}

.num {
  background-color: #efefef;
}

.btn:hover {
  opacity: 0.5;
}

.btn:active {
  top: 2px;
  border-right: 2px solid transparent;
  border-bottom: 2px solid transparent;
}

.del {
  color: orange;
  font-size: 1.5em;
}

.not-selectable {
  opacity: 0.2;
  pointer-events: none;
}

.selected, .reset:active {
  border-top: 2px solid #000;
  border-left: 2px solid #000;
  border-right: 1px solid #000;
  border-bottom: 1px solid #000;
  color: #898989;
  background-color: white;
}

.message-board {
  font-weight: bold;
  font-family: georgia;
  font-size: 2em;
  text-align: center;
}

@media only screen and (max-width: 600px) {
  .message-board, .system, .description {
    font-size: 1em;
  }

  .display {
    font-size: 1em;
    padding: 10px 7px;
  }

  .btn {
    padding: 1.0416%;
  }
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.1/css/font-awesome.min.css" rel="stylesheet"/>
<div class="wrap">
  <div class="message-board">
    <p>Binary-Decimal-Hexadecimal Converter</p>
  </div>
  <div class="calculator">
    <div class="row">
      <div class="display">0</div>
    </div>

    <div class="row">
      <div class="description" title="Convert from which number-system? "><label>From</label></div>
      <div title="Convert FROM binary number-system ..." class="system from btn bin"
           data-system-string="bin" data-system-number="2">Bin</div>
      <div title="Convert FROM decimal number-system ..." class="system from btn dec"
           data-system-string="dec" data-system-number="10">Dec</div>
      <div title="Convert FROM hexadecimal number-system ..." class="system from btn hex"
           data-system-string="hex" data-system-number="16">Hex</div>
      <div class="system btn del reset" title="Reset converter-app">
        <i class="fa fa-refresh" aria-hidden="true"></i></div>
    </div>

    <div class="numbers">
      <div class="row">
        <div class="num btn bin dec hex" data-number-value="0">0</div>
        <div class="num btn bin dec hex" data-number-value="1">1</div>
        <div class="num btn dec hex" data-number-value="2">2</div>
        <div class="num btn dec hex" data-number-value="3">3</div>
        <div class="num btn dec hex" data-number-value="4">4</div>
        <div class="num btn dec hex" data-number-value="5">5</div>
        <div class="num btn dec hex" data-number-value="6">6</div>
        <div class="num btn dec hex" data-number-value="7">7</div>
      </div>
      <div class="row">
        <div class="num btn dec hex" data-number-value="8">8</div>
        <div class="num btn dec hex" data-number-value="9">9</div>
        <div class="num btn hex" data-number-value="A">A</div>
        <div class="num btn hex" data-number-value="B">B</div>
        <div class="num btn hex" data-number-value="C">C</div>
        <div class="num btn hex" data-number-value="D">D</div>
        <div class="num btn hex" data-number-value="E">E</div>
        <div class="num btn hex" data-number-value="F">F</div>
      </div>
    </div>        

    <div class="row">
      <div class="description" title="Convert to which number-system? "><label>To</label></div>
      <div class="system to btn bin" title="... convert TO binary number-system."
           data-system-string="bin" data-system-number="2">Bin</div>
      <div class="system to btn dec" title="... convert TO decimal number-system."
           data-system-string="dec" data-system-number="10">Dec</div>
      <div class="system to btn hex" title="... convert TO hexadecimal number-system."
           data-system-string="hex" data-system-number="16">Hex</div>
    </div>

  </div>
</div>

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

When working in global scope it's a good practice to check if a variable hasn't been declared already:

var sc = sc || {};

Also, "delete" is a reserved word in JavaScript, which means as an object property name it should be declared and accessed with bracket notation:

sc["delete"] = ... 
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.