Bitwise operators part 10 – The UI!

This is the last part of my bitwise operators series! I hope it could be useful to you, and help you understand an underrated operator. It can be useful, if well used, and the proposed UI will help you test and expose to other devs your “point of view” about how to get rid of complex “ifs and elses” /”switches”.

As this post is about the operators, not about the UI, here is the HTML!

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, shrink-to-fit=no"
    />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <link
      rel="stylesheet"
      href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
      integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T"
      crossorigin="anonymous"
    />
    <link href="./css/style.css" rel="stylesheet" />
    <title>Bitwise Example</title>
  </head>
  <body>
    <div class="container">
      <h3>Open the terminal to see the logs!</h3>
      <p>(press F12 on your keyboard to open it)</p>
      <div class="row">
        <div class="col border border-secondary rounded">
          <h1 class=" mt-2">State/Rule Simulator</h1>
          <hr />
          <p>
            Test if an action, which has rules, is allowed given a state.<br />
            <b>Example:</b> to <b>approve</b> a document, the document state
            should be <i>'submited'</i>. If the document is with the state
            <i>'draft'</i> or <i>'pending'</i>, the test should return
            <b>false</b>.
          </p>
          <h3>Instructions</h3>
          <ol>
            <li>Add a State</li>
            <ol>
              <li>Name a State;</li>
              <li>Click ADD State.</li>
            </ol>
            <li>To create a rule</li>
            <ol>
              <li>
                Select one or more states wich will represent the condition to
                be tested (will return true);
              </li>
              <li>Name a rule;</li>
              <li>click ADD Rule.</li>
            </ol>
            <li>To test a state and the rule</li>
            <ol>
              <li>Select one state;</li>
              <li>Click on 'Set State';</li>
              <li>Select one Rule;</li>
            </ol>
          </ol>
          <hr />
          <div class="container">
            <div class="row">
              <!-- States Column -->
              <div class="col-sm">
                <h3>Possible states</h3>
                <div class="form-group">
                  <!-- Input + Button Group -->
                  <div class="input-group mb-3">
                    <input
                      id="newState"
                      type="text"
                      class="form-control"
                      placeholder="Add new state"
                      aria-label="Add new state"
                      aria-describedby="addStateButton"
                    />
                    <div class="input-group-append">
                      <span class="input-group-text" id="addStateButton"
                        >ADD State</span
                      >
                    </div>
                  </div>
                  <label>Multiple select to create a rule</label>
                  <div style="height: 100px">
                    <select
                      id="possibleStatesItems"
                      class="form-control"
                      multiple
                    >
                    </select>
                  </div>
                  <div class="mt-2">
                    <label>
                      Select ONE state and click 'Set State'
                    </label>
                  </div>
                  <button
                    id="setStateButton"
                    type="button"
                    class="btn btn-primary mt-2"
                  >
                    Set State
                  </button>
                </div>
              </div>

              <!-- Rules Column -->
              <div class="col-sm">
                <h3>Possible rules</h3>
                <div class="form-group">
                  <!-- Input + Button Group -->
                  <div class="input-group mb-3">
                    <input
                      id="newRule"
                      type="text"
                      class="form-control"
                      placeholder="Add new rule"
                      aria-label="Add new rule"
                      aria-describedby="addRuleButton"
                    />
                    <div class="input-group-append">
                      <span class="input-group-text" id="addRuleButton"
                        >ADD Rule</span
                      >
                    </div>
                  </div>
                  <label>Available rules</label>
                  <div style="height: 100px">
                    <select id="possibleRulesItems" class="form-control" single>
                      <option value="">There are no rules available</option>
                    </select>
                  </div>
                  <div class="mt-2">
                    <label>
                      Once a state is active, select ONE rule and click 'Check
                      Rule' to test it.
                    </label>
                  </div>
                  <button
                    id="checkRuleButton"
                    type="button"
                    class="btn btn-primary mt-2"
                  >
                    Check Rule
                  </button>
                </div>
              </div>
            </div>
            <div class="row">
              <div class="col">
                <h2 class="text-center">
                  <span id="dialog" class="badge"></span>
                </h2>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <script
      src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
      integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
      crossorigin="anonymous"
    ></script>
    <script
      src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
      integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
      crossorigin="anonymous"
    ></script>
    <script
      src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
      integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
      crossorigin="anonymous"
    ></script>
    <script type="module" src="./viewModels/index.js"></script>
  </body>
</html>

Now, it’s time to change our index viewmodel. Delete everything and let’s start!

This is the final code:

import { StateManager } from '../businessLogic/stateManager.js';

const sm = new StateManager();
let selectedRule = '';

function writeOnDialog(message, classToAdd) {
  let badge = $('#dialog');
  badge.removeClass(
    'badge-danger badge-warning badge-success badge-secondary badge-dark',
  );
  badge.addClass(`badge-${classToAdd}`);
  badge.text(message);
}

function addState() {
  try {
    const newState = document.getElementById('newState').value;
    sm.createState(newState.toUpperCase());
    document.getElementById('newState').value = '';
    const states = sm.getStates();
    states.sort((a, b) => a.value - b.value);
    console.log(states);
    const element = $('#possibleStatesItems');
    element
      .find('option')
      .remove()
      .end();
    states.forEach(state => {
      element.append(new Option(state.state, state.state));
    });
  } catch (error) {
    console.log(`Ignoring`, error.message);
  }
}

function setState() {
  const selectedState = $('#possibleStatesItems').val();
  if (selectedState.length > 1) {
    return writeOnDialog('Select only ONE state to set!', 'danger');
  }
  sm.currentState = selectedState[0];
  writeOnDialog(`The current state is ${sm.currentState.stateName}`, 'primary');
}

function addRule() {
  try {
    const newRule = $('#newRule').val();
    const stateArray = $('#possibleStatesItems').val();

    if (stateArray.length === 0) {
      return writeOnDialog(
        'Select at least one or more states to create a rule.',
        'danger',
      );
    }
    console.log(`The rule ${newRule} will test these states: ${stateArray}`);
    sm.createBitwiseOrRule(newRule.toUpperCase(), stateArray);
    document.getElementById('newRule').value = '';
    const rules = sm.getRules();
    rules.sort((a, b) => a.value - b.value);
    console.log(rules);
    const element = $('#possibleRulesItems');
    element
      .find('option')
      .remove()
      .end();

    element.append(new Option('Select a rule...', ''));
    rules.forEach(rule => {
      element.append(new Option(rule.state, rule.state));
    });
  } catch (error) {
    console.log(`Ignoring`, error.message);
  }
}

function checkRule() {
  const result = Boolean(sm.checkRule(selectedRule));
  const msg = `When checking the status ${sm.currentState.stateName} and the rule ${selectedRule.stateName} the result was ${result}`;
  if (result) {
    return writeOnDialog(msg, 'primary');
  }
  return writeOnDialog(msg, 'danger');
}

$(function() {
  sm.clearAllData();

  $('[data-toggle="tooltip"]').tooltip();

  writeOnDialog('Waiting...', 'warning');

  // STATE
  $('#addStateButton').mouseover(function() {
    $(this).css('cursor', 'pointer');
  });

  $('#newState').on('keyup', function(event) {
    if (event.keyCode === 13) {
      event.preventDefault();
      $('#addStateButton').click();
    }
  });

  $('#addStateButton').click(function() {
    addState();
  });

  $('#setStateButton').click(function() {
    setState();
  });

  // RULE
  $('#addRuleButton').mouseover(function() {
    $(this).css('cursor', 'pointer');
  });

  $('#newRule').on('keyup', function(event) {
    if (event.keyCode === 13) {
      event.preventDefault();
      $('#addRuleButton').click();
    }
  });

  $('#addRuleButton').click(function() {
    addRule();
  });

  $('#possibleRulesItems').change(function() {
    selectedRule = $(this).val();
    return writeOnDialog(
      `The current state is ${sm.currentState.stateName} and the rule you'll check is ${selectedRule}`,
    );
  });

  $('#checkRuleButton').click(function() {
    checkRule();
  });
});

Now, to test the project, the easier way is: download the plugin Live Server ( https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer ) open the index.html and click on Go Live

See it in action!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s