KGRKJGETMRETU895U-589TY5MIGM5JGB5SDFESFREWTGR54TY
Server : Apache/2.4.62
System : FreeBSD fbsdweb2.web.rcn.net 14.1-RELEASE FreeBSD 14.1-RELEASE releng/14.1-n267679-10e31f0946d8 GENERIC amd64
User : www ( 80)
PHP Version : 8.3.8
Disable Function : NONE
Directory :  /domains/drsuper/CalculusMechanics/images/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /domains/drsuper/CalculusMechanics/images/calc-popup.js
/* calc-popup-original-plus-move.js */
/* Based on your original JS, with only one behavior added:
   - drag the calculator by the header
   It still opens in the same top-right place as before.
*/

document.addEventListener("DOMContentLoaded", () => {
  if (document.getElementById("calcFab") || document.getElementById("calcOverlay")) return;

  const wrapper = document.createElement("div");
  wrapper.innerHTML = `
    <button id="calcFab" type="button" aria-label="Open calculator">🧮</button>

    <div id="calcOverlay" class="calc-overlay" role="dialog" aria-modal="true" aria-labelledby="calcTitle">
      <div class="calc-modal" role="document">
        <div class="calc-header">
          <div>
            <div id="calcTitle" class="calc-title">Calculator</div>
            <div class="calc-sub">Esc to close • Enter to =</div>
          </div>
          <button id="calcClose" type="button" class="calc-x" aria-label="Close">✕</button>
        </div>

        <input id="calcDisplay" class="calc-display" inputmode="decimal" autocomplete="off"
               placeholder="Type: (3+2)*5  or  sin(0.5)" />

        <div class="calc-grid" aria-label="Calculator buttons">
          <button class="cb" type="button" data-a="7">7</button>
          <button class="cb" type="button" data-a="8">8</button>
          <button class="cb" type="button" data-a="9">9</button>
          <button class="cb op" type="button" data-a="/">÷</button>
          <button class="cb fn" type="button" data-a="(">(</button>
          <button class="cb fn" type="button" data-a=")">)</button>

          <button class="cb" type="button" data-a="4">4</button>
          <button class="cb" type="button" data-a="5">5</button>
          <button class="cb" type="button" data-a="6">6</button>
          <button class="cb op" type="button" data-a="*">×</button>
          <button class="cb fn" type="button" data-a="^">^</button>
          <button class="cb fn" type="button" data-a="pi">Ï€</button>

          <button class="cb" type="button" data-a="1">1</button>
          <button class="cb" type="button" data-a="2">2</button>
          <button class="cb" type="button" data-a="3">3</button>
          <button class="cb op" type="button" data-a="-">−</button>
          <button class="cb fn" type="button" data-a="sqrt(">√</button>
          <button class="cb fn" type="button" data-a="abs(">abs</button>

          <button class="cb" type="button" data-a="0">0</button>
          <button class="cb" type="button" data-a=".">.</button>
          <button class="cb fn" type="button" data-a="%">%</button>
          <button class="cb op" type="button" data-a="+">+</button>
          <button class="cb danger" type="button" data-a="back">⌫</button>
          <button class="cb danger" type="button" data-a="clear">C</button>

          <button class="cb fn" type="button" data-a="sin(">sin</button>
          <button class="cb fn" type="button" data-a="cos(">cos</button>
          <button class="cb fn" type="button" data-a="tan(">tan</button>
          <button class="cb fn" type="button" data-a="ln(">ln</button>
          <button class="cb fn" type="button" data-a="log10(">log</button>
          <button class="cb eq" type="button" data-a="=">=</button>
        </div>

        <div class="calc-footer">
          <button id="calcCopy" type="button" class="calc-copy">Copy result</button>
          <span id="calcMsg" class="calc-msg" aria-live="polite"></span>
        </div>
      </div>
    </div>
  `;
  document.body.appendChild(wrapper);

  const fab = document.getElementById("calcFab");
  const overlay = document.getElementById("calcOverlay");
  const modal = overlay.querySelector(".calc-modal");
  const header = overlay.querySelector(".calc-header");
  const closeBtn = document.getElementById("calcClose");
  const display = document.getElementById("calcDisplay");
  const copyBtn = document.getElementById("calcCopy");
  const msg = document.getElementById("calcMsg");

  const showMsg = (t) => { msg.textContent = t; setTimeout(() => (msg.textContent = ""), 1400); };

  function resetToDefaultOpenSpot(){
    modal.style.position = "";
    modal.style.left = "";
    modal.style.top = "";
    modal.style.marginTop = "52px";
    modal.style.marginRight = "8px";
  }

  const setOpen = (open) => {
    overlay.classList.toggle("is-open", !!open);
    if (open) {
      resetToDefaultOpenSpot();
      setTimeout(() => display.focus(), 0);
    }
  };
  const toggleOpen = () => setOpen(!overlay.classList.contains("is-open"));

  function evaluateExpr(input){
    let s = (input || "").trim();
    if (!s) return "";

    s = s.replaceAll("×","*").replaceAll("÷","/").replaceAll("−","-");

    if (!/^[0-9+\-*/().,^% \tA-Za-z]+$/.test(s)) {
      throw new Error("Invalid characters");
    }

    s = s
      .replace(/\bpi\b/gi, "Math.PI")
      .replace(/\be\b/g, "Math.E")
      .replace(/\^/g, "**")
      .replace(/\babs\s*\(/gi, "Math.abs(")
      .replace(/\bsqrt\s*\(/gi, "Math.sqrt(")
      .replace(/\bsin\s*\(/gi, "Math.sin(")
      .replace(/\bcos\s*\(/gi, "Math.cos(")
      .replace(/\btan\s*\(/gi, "Math.tan(")
      .replace(/\bln\s*\(/gi, "Math.log(")
      .replace(/\blog10\s*\(/gi, "Math.log10(");

    s = s.replace(/(\d+(?:\.\d+)?)\s*%/g, "($1/100)");

    const f = new Function(`"use strict"; return (${s});`);
    const result = f();
    if (typeof result !== "number" || !isFinite(result)) throw new Error("Bad result");
    return result;
  }

  function doEquals(){
    try{
      const r = evaluateExpr(display.value);
      if (r === "") return;
      display.value = String(r);
      showMsg("OK");
    } catch (e){
      showMsg("Error");
    }
  }

  fab.addEventListener("click", toggleOpen);
  closeBtn.addEventListener("click", () => setOpen(false));

  document.addEventListener("keydown", (e) => {
    if (!overlay.classList.contains("is-open")) return;
    if (e.key === "Escape") setOpen(false);
    if (e.key === "Enter") { e.preventDefault(); doEquals(); }
  });

  document.querySelectorAll(".cb").forEach(btn => {
    btn.addEventListener("click", () => {
      const a = btn.getAttribute("data-a");
      if (a === "clear") { display.value = ""; display.focus(); return; }
      if (a === "back")  { display.value = display.value.slice(0, -1); display.focus(); return; }
      if (a === "=")     { doEquals(); return; }
      if (a === "pi")    { display.value += "pi"; display.focus(); return; }
      display.value += a;
      display.focus();
    });
  });

  copyBtn.addEventListener("click", async () => {
    try{
      await navigator.clipboard.writeText(display.value || "");
      showMsg("Copied");
    } catch(e){
      showMsg("Copy failed");
    }
  });

  /* --- Dragging: only by header, and starts from the same open spot --- */
  let dragging = false;
  let startX = 0;
  let startY = 0;
  let originLeft = 0;
  let originTop = 0;

  function startDrag(clientX, clientY){
    const rect = modal.getBoundingClientRect();
    modal.style.position = "fixed";
    modal.style.left = rect.left + "px";
    modal.style.top = rect.top + "px";
    modal.style.marginTop = "0";
    modal.style.marginRight = "0";

    startX = clientX;
    startY = clientY;
    originLeft = rect.left;
    originTop = rect.top;
    dragging = true;
  }

  header.addEventListener("mousedown", (e) => {
    if (e.target === closeBtn) return;
    e.preventDefault();
    startDrag(e.clientX, e.clientY);
  });

  document.addEventListener("mousemove", (e) => {
    if (!dragging) return;
    const dx = e.clientX - startX;
    const dy = e.clientY - startY;
    modal.style.left = (originLeft + dx) + "px";
    modal.style.top = (originTop + dy) + "px";
  });

  document.addEventListener("mouseup", () => {
    dragging = false;
  });

  header.addEventListener("touchstart", (e) => {
    if (e.target === closeBtn) return;
    const t = e.touches[0];
    if (!t) return;
    startDrag(t.clientX, t.clientY);
  }, {passive: true});

  document.addEventListener("touchmove", (e) => {
    if (!dragging) return;
    const t = e.touches[0];
    if (!t) return;
    const dx = t.clientX - startX;
    const dy = t.clientY - startY;
    modal.style.left = (originLeft + dx) + "px";
    modal.style.top = (originTop + dy) + "px";
  }, {passive: true});

  document.addEventListener("touchend", () => {
    dragging = false;
  });

  setOpen(false);
});

Anon7 - 2021