javascripthtmlmathematical-expressions

How do i check if the p elements in my div are a valid mathematical expression


I wanted to check if the <p> elements inside my <div> with id screen are a valid mathematical expression,doing the validation inside my operationLogic() then return the result of whatever was the mathematical expression on my <div> with id screen again, but I'm having a hard time into finding out how to do that

let screen = document.getElementById('screen');

function getButtonValue() {
  var element = event.target.innerHTML
  var insert = document.createElement("p");
  if (element == '=') {
    insert.innerHTML = `${operationLogic()}`;
  } else {
    insert.innerHTML = `${element}`;
  }
  screen.appendChild(insert);
};

function operationLogic() {
  let p = screen.querySelectorAll('p');
  let number = ''
  p.forEach(element => {
    let number = +element.innerHTML;
    return Number(number)
  })
}
<div id="calculator">
  <div id=screen></div>
  <div id="operationMain">
    <ul>
      <li class="operatorColor" onclick="getButtonValue()">{</li>
      <li class="operatorColor" onclick="getButtonValue()">}</li>
      <li class="operatorColor" onclick="getButtonValue()">(</li>
      <li class="operatorColor" onclick="getButtonValue()">)</li>
      <li class="blue" onclick="getButtonValue()">=</li>
      <li class="operatorColor" onclick="getButtonValue()">+</li>
      <li class="operatorColor" onclick="getButtonValue()">-</li>
      <li class="operatorColor" onclick="getButtonValue()">x</li>
      <li class="operatorColor" onclick="getButtonValue()">÷</li>
      <li class="operatorColor" onclick="getButtonValue()">%</li>
      <li class="operatorColor" onclick="getButtonValue()">.</li>
      <li onclick="getButtonValue()">0</li>
      <li onclick="getButtonValue()">1</li>
      <li onclick="getButtonValue()">2</li>
      <li onclick="getButtonValue()">3</li>
      <li onclick="getButtonValue()">4</li>
      <li onclick="getButtonValue()">5</li>
      <li onclick="getButtonValue()">6</li>
      <li onclick="getButtonValue()">7</li>
      <li onclick="getButtonValue()">8</li>
      <li onclick="getButtonValue()">9</li>
      <li onclick="getButtonValue()">00</li>
    </ul>
  </div>
</div>


Solution

  • It is much easier if you delegate.

    It is quite complex to validate and you would need a parser for that

    Here is a possible way - extended version here

    I had to change x and ÷ to * and /. You can keep them but then we need data-attributes on the LIs instead of textcontent

    const screen = document.getElementById('screen');
    const ul = document.getElementById('operationMain');
    
    const operationLogic = () => {
      const statement = Array.from(screen.querySelectorAll('p'))
        .map(element => element.textContent.trim())
        .join(' ');
      console.log(statement);
      return statement
    };
    
    ul.addEventListener('click', (event) => {
      const tgt = event.target.closest('li');
      if (!tgt) return;
      let element = tgt.textContent.trim();
    
      if (element === '=') {
        const expression = operationLogic();
        try {
          const result = math.evaluate(expression);
          console.log('Result:', result);
        } catch (error) {
          console.error('Invalid Expression:', error.message);
        }
      }
    
      const insert = document.createElement('p');
      insert.textContent = (element === '=') ? `${operationLogic()}` : `${element}`;
      screen.appendChild(insert);
    });
    <script src="https://unpkg.com/mathjs/lib/browser/math.js"></script>
    
    <div id="calculator">
      <div id=screen></div>
      <div>
        <ul id="operationMain">
          <li class="operatorColor">{</li>
          <li class="operatorColor">}</li>
          <li class="operatorColor">(</li>
          <li class="operatorColor">)</li>
          <li class="blue">=</li>
          <li class="operatorColor">+</li>
          <li class="operatorColor">-</li>
          <li class="operatorColor">*</li>
          <li class="operatorColor">/</li>
          <li class="operatorColor">%</li>
          <li class="operatorColor">.</li>
          <li>0</li>
          <li>1</li>
          <li>2</li>
          <li>3</li>
          <li>4</li>
          <li>5</li>
          <li>6</li>
          <li>7</li>
          <li>8</li>
          <li>9</li>
          <li>00</li>
        </ul>
      </div>
    </div>