my freefriday

what i did today was make a calculator but it is an advance one

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>Advanced Calculator</title>
  <style>
    * { box-sizing: border-box; font-family: system-ui, sans-serif; }
    body {
      background: #111827;
      color: #e5e7eb;
      display: flex;
      justify-content: center;
      align-items: center;
      min-height: 100vh;
      margin: 0;
    }
    .calc {
      background: #020617;
      padding: 1rem;
      border-radius: 1rem;
      box-shadow: 0 20px 40px rgba(0,0,0,0.5);
      width: 360px;
      max-width: 100%;
    }
    .display {
      background: #020617;
      border-radius: 0.75rem;
      padding: 0.75rem 0.9rem;
      border: 1px solid #1f2937;
      margin-bottom: 0.75rem;
    }
    .expression {
      font-size: 0.85rem;
      color: #9ca3af;
      min-height: 1.2em;
      word-wrap: break-word;
    }
    .result {
      font-size: 1.6rem;
      text-align: right;
      margin-top: 0.25rem;
      word-wrap: break-word;
    }
    .row {
      display: grid;
      grid-template-columns: repeat(4, 1fr);
      gap: 0.4rem;
      margin-bottom: 0.4rem;
    }
    button {
      border: none;
      border-radius: 0.6rem;
      padding: 0.7rem 0.4rem;
      font-size: 0.95rem;
      cursor: pointer;
      background: #111827;
      color: #e5e7eb;
      transition: background 0.1s, transform 0.05s;
    }
    button:active {
      transform: translateY(1px);
      background: #0f172a;
    }
    .btn-op { color: #38bdf8; }
    .btn-fn { color: #a855f7; font-size: 0.8rem; }
    .btn-eq {
      background: #22c55e;
      color: #022c22;
      font-weight: 600;
    }
    .btn-eq:active { background: #16a34a; }
    .btn-ac { color: #f97373; }
    .row-wide {
      display: grid;
      grid-template-columns: 2fr 1fr 1fr;
      gap: 0.4rem;
      margin-bottom: 0.4rem;
    }
    .history {
      margin-top: 0.5rem;
      max-height: 120px;
      overflow-y: auto;
      font-size: 0.8rem;
      border-top: 1px solid #1f2937;
      padding-top: 0.4rem;
    }
    .history-item {
      display: flex;
      justify-content: space-between;
      gap: 0.5rem;
      padding: 0.15rem 0;
      cursor: pointer;
    }
    .history-exp { color: #9ca3af; }
    .history-res { color: #e5e7eb; }
  </style>
</head>
<body>
  <div class="calc">
    <div class="display">
      <div class="expression" id="expression"></div>
      <div class="result" id="result">0</div>
    </div>

    <div class="row">
      <button class="btn-ac" data-action="clear">AC</button>
      <button data-action="backspace">⌫</button>
      <button class="btn-op" data-value="(">(</button>
      <button class="btn-op" data-value=")">)</button>
    </div>

    <div class="row">
      <button class="btn-fn" data-fn="sin">sin</button>
      <button class="btn-fn" data-fn="cos">cos</button>
      <button class="btn-fn" data-fn="tan">tan</button>
      <button class="btn-op" data-value="/">÷</button>
    </div>

    <div class="row">
      <button class="btn-fn" data-fn="log">log</button>
      <button class="btn-fn" data-fn="ln">ln</button>
      <button class="btn-fn" data-fn="sqrt">√</button>
      <button class="btn-op" data-value="*">×</button>
    </div>

    <div class="row">
      <button data-value="7">7</button>
      <button data-value="8">8</button>
      <button data-value="9">9</button>
      <button class="btn-op" data-value="-">−</button>
    </div>

    <div class="row">
      <button data-value="4">4</button>
      <button data-value="5">5</button>
      <button data-value="6">6</button>
      <button class="btn-op" data-value="+">+</button>
    </div>

    <div class="row">
      <button data-value="1">1</button>
      <button data-value="2">2</button>
      <button data-value="3">3</button>
      <button class="btn-op" data-value="^">xʸ</button>
    </div>

    <div class="row-wide">
      <button data-value="0">0</button>
      <button data-value=".">.</button>
      <button class="btn-eq" data-action="equals">=</button>
    </div>

    <div class="history" id="history"></div>
  </div>

  <script>
    const exprEl = document.getElementById('expression');
    const resultEl = document.getElementById('result');
    const historyEl = document.getElementById('history');

    let expression = '';
    let lastResult = null;
    const history = [];

    function updateDisplay() {
      exprEl.textContent = expression;
      if (!expression) resultEl.textContent = lastResult !== null ? lastResult : '0';
    }

    function addToHistory(exp, res) {
      history.unshift({ exp, res });
      if (history.length > 20) history.pop();
      renderHistory();
    }

    function renderHistory() {
      historyEl.innerHTML = '';
      history.forEach((item, index) => {
        const div = document.createElement('div');
        div.className = 'history-item';
        div.innerHTML = `
          <span class="history-exp">${item.exp}</span>
          <span class="history-res">${item.res}</span>
        `;
        div.addEventListener('click', () => {
          expression = item.exp;
          lastResult = item.res;
          updateDisplay();
        });
        historyEl.appendChild(div);
      });
    }

    function insertValue(val) {
      expression += val;
      updateDisplay();
    }

    function insertFunction(fn) {
      // functions are in radians
      expression += fn + '(';
      updateDisplay();
    }

    function clearAll() {
      expression = '';
      lastResult = null;
      updateDisplay();
    }

    function backspace() {
      expression = expression.slice(0, -1);
      updateDisplay();
    }

    function toSafeExpression(exp) {
      // Replace ^ with ** and map functions to Math.*
      return exp
        .replace(/π/g, 'Math.PI')
        .replace(/e/g, 'Math.E')
        .replace(/\^/g, '**')
        .replace(/\bsin\(/g, 'Math.sin(')
        .replace(/\bcos\(/g, 'Math.cos(')
        .replace(/\btan\(/g, 'Math.tan(')
        .replace(/\blog\(/g, 'Math.log10(')
        .replace(/\bln\(/g, 'Math.log(')
        .replace(/\bsqrt\(/g, 'Math.sqrt(');
    }

    function evaluateExpression() {
      if (!expression) return;
      try {
        const safe = toSafeExpression(expression);
        // eslint-disable-next-line no-new-func
        const fn = new Function('return ' + safe);
        let res = fn();
        if (typeof res === 'number' && !Number.isNaN(res) && Number.isFinite(res)) {
          // round to avoid floating noise
          res = Math.round((res + Number.EPSILON) * 1e12) / 1e12;
          lastResult = res;
          resultEl.textContent = res;
          addToHistory(expression, res);
        } else {
          resultEl.textContent = 'Error';
        }
      } catch (e) {
        resultEl.textContent = 'Error';
      }
    }

    document.addEventListener('click', (e) => {
      const btn = e.target.closest('button');
      if (!btn) return;

      const val = btn.getAttribute('data-value');
      const action = btn.getAttribute('data-action');
      const fn = btn.getAttribute('data-fn');

      if (val !== null) {
        insertValue(val);
      } else if (fn) {
        insertFunction(fn);
      } else if (action === 'clear') {
        clearAll();
      } else if (action === 'backspace') {
        backspace();
      } else if (action === 'equals') {
        evaluateExpression();
      }
    });

    // Basic keyboard support
    document.addEventListener('keydown', (e) => {
      const key = e.key;

      if ((key >= '0' && key <= '9') || key === '.' || key === '(' || key === ')') {
        insertValue(key);
      } else if (['+', '-', '*', '/'].includes(key)) {
        insertValue(key);
      } else if (key === '^') {
        insertValue('^');
      } else if (key === 'Backspace') {
        backspace();
      } else if (key === 'Enter' || key === '=') {
        e.preventDefault();
        evaluateExpression();
      } else if (key === 'Escape') {
        clearAll();
      }
    });

    updateDisplay();
  </script>
</body>
</html>

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *