LightningChart JS crashes with WebGL errors in React 18 (screen turns black)

I’m using LightningChart JS (@lightningchart/lcjs version ^6.1.1) in a React 18 project, and after running the chart component continuously for about 3 days, it eventually crashes with WebGL-related errors and the chart area turns completely black.

Environment:

  • React: 18
  • LightningChart JS: ^6.1.1
  • Chrome: 132.0.6834.83
  • OS: Ubuntu 2.24

Errors in console:

  1. Uncaught TypeError: Failed to execute ‘clientWaitSync’ on ‘WebGL2RenderingContext’: parameter 1 is not of type ‘WebGLSync’ – lcjs.mjs:10
  2. Uncaught r: EngineError: Couldn’t reserve Framebuffer – lcjs.mjs:10
  3. Uncaught TypeError: Cannot read properties of undefined (reading ‘x0’) – lcjs.mjs:10

These errors don’t happen immediately—they occur after the chart has been rendering continuously for around 72 hours. After that, the chart becomes unresponsive, and the screen goes black.

Browser Console:
enter image description here

Has anyone encountered this issue before with long-running LightningChart JS apps? Could this be related to WebGL resource leaks or memory limits? Any tips on preventing this or detecting it earlier?

Happy to provide a reproducible example if needed.

Thanks in advance!

I’ve followed the official documentation for chart setup and rendering. No custom WebGL code is involved.

Open Tailwind modal manually?

I’m using Preline UI together with Tailwind CSS for modals:

https://preline.co/docs/modal.html

Preline UI uses these HTML attributes to auto-open the modal on tap:

aria-haspopup="dialog"
aria-expanded="false"
aria-controls="hs-basic-modal"
data-hs-overlay="#hs-basic-modal"

I’d like to be able to open the modal programmatically through js.

How would I do that?

Here’s an example Preline UI provides for a basic modal:

<button type="button" class="py-3 px-4 inline-flex items-center gap-x-2 text-sm font-medium rounded-lg border border-transparent bg-blue-600 text-white hover:bg-blue-700 focus:outline-hidden focus:bg-blue-700 disabled:opacity-50 disabled:pointer-events-none" aria-haspopup="dialog" aria-expanded="false" aria-controls="hs-basic-modal" data-hs-overlay="#hs-basic-modal">
  Open modal
</button>

<div id="hs-basic-modal" class="hs-overlay hs-overlay-open:opacity-100 hs-overlay-open:duration-500 hidden size-full fixed top-0 start-0 z-80 opacity-0 overflow-x-hidden transition-all overflow-y-auto pointer-events-none" role="dialog" tabindex="-1" aria-labelledby="hs-basic-modal-label">
  <div class="sm:max-w-lg sm:w-full m-3 sm:mx-auto">
    <div class="flex flex-col bg-white border border-gray-200 shadow-2xs rounded-xl pointer-events-auto">
      <div class="flex justify-between items-center py-3 px-4 border-b border-gray-200">
        <h3 id="hs-basic-modal-label" class="font-bold text-gray-800">
          Modal title
        </h3>
        <button type="button" class="size-8 inline-flex justify-center items-center gap-x-2 rounded-full border border-transparent bg-gray-100 text-gray-800 hover:bg-gray-200 focus:outline-hidden focus:bg-gray-200 disabled:opacity-50 disabled:pointer-events-none" aria-label="Close" data-hs-overlay="#hs-basic-modal">
          <span class="sr-only">Close</span>
          <svg class="shrink-0 size-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
            <path d="M18 6 6 18"></path>
            <path d="m6 6 12 12"></path>
          </svg>
        </button>
      </div>
      <div class="p-4 overflow-y-auto">
        <p class="mt-1 text-gray-800">
          This is a wider card with supporting text below as a natural lead-in to additional content.
        </p>
      </div>
      <div class="flex justify-end items-center gap-x-2 py-3 px-4 border-t border-gray-200">
        <button type="button" class="py-2 px-3 inline-flex items-center gap-x-2 text-sm font-medium rounded-lg border border-gray-200 bg-white text-gray-800 shadow-2xs hover:bg-gray-50 focus:outline-hidden focus:bg-gray-50 disabled:opacity-50 disabled:pointer-events-none" data-hs-overlay="#hs-basic-modal">
          Close
        </button>
        <button type="button" class="py-2 px-3 inline-flex items-center gap-x-2 text-sm font-medium rounded-lg border border-transparent bg-blue-600 text-white hover:bg-blue-700 focus:outline-hidden focus:bg-blue-700 disabled:opacity-50 disabled:pointer-events-none">
          Save changes
        </button>
      </div>
    </div>
  </div>
</div>

How to display a fallback value while waiting for API data?

I’m building a dashboard in React, and I want to greet the user like
“Hi, {firstName}!” But the data is fetched from an API, and sometimes it’s not immediately available.

<h2 className="mb-4">Hi, {user?.firstName || '{name}'}!</h2>

I tried using optional chaining (user?.firstName) and fallback values (|| ‘{name}’), but I’m not sure if this is the best way.
Is there a better or cleaner approach for this?

Why does useEffect run twice on initial render even with an empty dependency array? [duplicate]

I’m working on a small React project and using useEffect to fetch data from an API when the component loads. I used an empty dependency array to make it run only once, but it seems to be firing twice on initial render in development.

Here’s my simplified code:

import { useEffect, useState } from "react";

function Users() {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    console.log("Fetching users...");
    fetch("https://jsonplaceholder.typicode.com/users")
      .then((res) => res.json())
      .then((data) => setUsers(data));
  }, []);

  return (
    <div>
      <h2>User List</h2>
      <ul>
        {users.map((user) => (
          <li key={user.id}>{user.name}</li>
        ))}
      </ul>
    </div>
  );
}

Outlook EWS Exchange Html Body

For some reason trying to use

const { ExchangeService, ExchangeVersion, Uri, EmailMessage, MessageBody } = require('ews-javascript-api');

with

      const message = new EmailMessage(this.ews);
      message.Subject = params.subject;
      message.Body = new MessageBody(`<html>
                  <head>
                  </head>
                  <body>
                    <b>HTML BODY</b><br>
                  </body>
                </html>`);

Doesn’t allow html body to used with ewa-javascript-api , is this module text supported only because i get “The request failed schema validation” anytime i try to send HTML body with the Outlook EWS api

JS slideshow that displays caption in two different places in the HTML

I’m trying to create a slideshow gallery using Javascript that displays the caption in two different places in the html – above and below the slideshow. The reason for the redundancy is to incorporate it into a Bootstrap that displays the top caption and hides the lower caption when in mobile view, and vice versa when displayed on larger devices.

I’ve tried multiple ways to have both captions display simultaneously but the script breaks down when improvising the role of “slide_caption” Id element with function ‘showSlides’. How do I apply different Id elements or class element to the demo caption so that it works off the same function?

Here’s the complete slideshow: https://codepen.io/canQuackattack/full/RNPaLrV

JS

let slideIndex = 1;
showSlides(slideIndex);

function plusSlides(n) {
  showSlides(slideIndex += n);
}

function currentSlide(n) {
  showSlides(slideIndex = n);
}

function showSlides(n) {
  let i;
  let slides = document.getElementsByClassName("mySlides");
  let dots = document.getElementsByClassName("demo");
  let captionText = document.getElementById("slide_caption");
  if (n > slides.length) {slideIndex = 1}
  if (n < 1) {slideIndex = slides.length}
  for (i = 0; i < slides.length; i++) {
    slides[i].style.display = "none";
  }
  for (i = 0; i < dots.length; i++) {
    dots[i].className = dots[i].className.replace(" active", "");
  }
  slides[slideIndex-1].style.display = "block";
  dots[slideIndex-1].className += " active";
  captionText.innerHTML = dots[slideIndex-1].alt;
}

CSS

/* Position the image container (needed to position the left and right arrows) */
.container {
  position: relative;
}

/* Hide the images by default */
.mySlides {
  display: none;
}

/* Add a pointer when hovering over the thumbnail images */
.cursor {
  cursor: pointer;
}

/* Next & previous buttons */
.prev,
.next {
  cursor: pointer;
  position: absolute;
  top: 40%;
  width: auto;
  padding: 16px;
  margin-top: -50px;
  color: white;
  font-weight: bold;
  font-size: 20px;
  border-radius: 0 3px 3px 0;
  user-select: none;
  -webkit-user-select: none;
}

/* Position the "next button" to the right */
.next {
  right: 0;
  border-radius: 3px 0 0 3px;
}

/* On hover, add a black background color with a little bit see-through */
.prev:hover,
.next:hover {
  background-color: rgba(0, 0, 0, 0.8);
}

/* Number text (1/3 etc) */
.numbertext {
  color: #f2f2f2;
  font-size: 12px;
  padding: 8px 12px;
  position: absolute;
  top: 0;
}

/* Container for image text */
.caption-container {
  text-align: center;
  background-color: #222;
  padding: 2px 16px;
  color: white;
}

.row:after {
  content: "";
  display: table;
  clear: both;
}

/* columns side by side */
.column {
  float: left;
  width: 16.66%;
}

/* Add a transparency effect for thumnbail images */
.demo {
  opacity: 0.6;
}

.active,
.demo:hover {
  opacity: 1;
}

HTML

<body>
  
<h2 style="text-align:center">Slideshow Gallery</h2>
  
   <div>  
      <a class="prev" onclick="plusSlides(-1)">❮</a>
      <a class="next" onclick="plusSlides(1)">❯</a>
   </div>
   <div class="caption-container">
    <p id="slide_caption"></p>
  </div> 
  
<div class="container">
  <div class="mySlides">
    <div class="numbertext">1 / 3</div>
    <img class="myImages" src="https://www.w3schools.com/howto/img_woods_wide.jpg" alt="The Woods 1" style="width:100%">
  </div>

  <div class="mySlides">
    <div class="numbertext">2 / 3</div>
    <img class="myImages" src="https://www.w3schools.com/howto/img_5terre_wide.jpg" alt="Cinque Terre 1" style="width:100%">
  </div>

  <div class="mySlides">
    <div class="numbertext">3 / 3</div>
    <img class="myImages" src="https://www.w3schools.com/howto/img_mountains_wide.jpg" alt="Mountains and fjords 1" style="width:100%">
  </div>

  <div>  
      <a class="prev" onclick="plusSlides(-1)">❮</a>
      <a class="next" onclick="plusSlides(1)">❯</a>
   </div>
   <div class="caption-container">
    <p id="slide_caption"></p>
  </div>

  <div class="row">
    <div class="column">
      <img class="demo cursor" src="https://www.w3schools.com/howto/img_woods_wide.jpg" style="width:100%" onclick="currentSlide(1)" alt="The Woods">
    </div>
    <div class="column">
      <img class="demo cursor" src="https://www.w3schools.com/howto/img_5terre_wide.jpg" style="width:100%" onclick="currentSlide(2)" alt="Cinque Terre">
    </div>
    <div class="column">
      <img class="demo cursor" src="https://www.w3schools.com/howto/img_mountains_wide.jpg" style="width:100%" onclick="currentSlide(3)" alt="Mountains and fjords">
    </div>

  </div>
</div>

Javascript created SVG text shows up in the DOM but doesn’t display

The following code creates a slider with left, middle and right handles. Clicking on the middle handle pops up a rectangle, intended to be a menu. The code iterates through two arrays to populate the menu. Using F12 (On Firefox 138.0 – 64bit) I can see in the inspector tab that the text elements have been created with the correct content but nothing appears and selecting a row in the inspector normally shows the bounding box for the selected line. Nothing for these text elements which at first glance seem to have the same syntax as other text that does display.

<!DOCTYPE html>
<html lang="en">
  
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content=
        "width=device-width, initial-scale=1.0" />
        <link rel="preconnect" href="https://fonts.googleapis.com">
        <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
        <!--link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:ital,wght@0,100..700;1,100..700&display=swap" rel="stylesheet"-->
        <link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans" rel="stylesheet">
    <title>Programmatic SVG</title>
    <style>
        .ibm-plex-sans-labelText {
            font-family: "IBM Plex Sans", sans-serif;
            fill: #000000;
            font-size: 18px;
            font-optical-sizing: auto;
            font-weight: 600;
            font-style: normal;
            font-variation-settings: "wdth" 100;
        }
        .ibm-plex-sans-timestampText{
            font-family: "IBM Plex Sans", sans-serif;
            fill: #000000;
            font-size: 10px;
            font-optical-sizing: auto;
            font-weight: 400;
            font-style: italic;
            font-variation-settings: "wdth" 100; 
        }

        .ibm-plex-sans-menuitem{
            font-family: "IBM Plex Sans", sans-serif;
            fill: #000000;
            font-size: 10px;
            font-optical-sizing: auto;
            font-weight: 400;
            font-style: normal;
            font-variation-settings: "wdth" 100;             
        }

        .static {
            cursor: not-allowed;
        }
        .draggable {
            cursor: move;
        }
        .menuRect {
            stroke: #00aeff;
            fill:rgb(253, 253, 201);
            fill-opacity: 100%;
            stroke-width: 1px;
            filter: drop-shadow(4px 5px 2px rgb(0 0 0 / 0.4));
        }

    </style>

</head>



<body>
    <div id="Test" style="position: absolute; visibility: hidden; height: auto; width: auto; white-space: nowrap;">
        hidden div for measuring pixel length of text strings in a particular font/size
    </div>

    <script  id="svgScript" type="text/javascript">

        //https://github.com/amitonline/true-ruler/blob/main/js/true-ruler.js
        var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");

        const control_W = 550; //width of slider
        const control_H = 350; //Height of slider
        const left_padding = 75;
        const right_padding = 75;
        const top_padding = 25;
        const bottom_padding = 25;
        const pillRad = 10;
        const pillOpacity = 50;
        const diamondSide = Math.sqrt(2*(Math.pow(pillRad, 2))); //make the diamond the same height as the circle handles (pythagorus)
        const labelOffset = 75;
        const PDDheight = 120;
        const PDDwidth = 75;
        const PDDrad = 2; 

        svg.setAttribute("id","sliderControl");
        svg.setAttribute("overflow", "visible");
        svg.setAttribute("viewBox","0 0 " + control_W + " " + control_H);
        svg.setAttribute("width", control_W);
        svg.setAttribute("height", control_H);
        svg.setAttribute("onload", "makeDraggable(evt)");
        
        var svgNS = svg.namespaceURI;

        var slider = document.createElementNS(svgNS, 'path');
        slider.setAttributeNS(null, "d", "M " + left_padding + "," +  (top_padding + (control_H/2)) + " H " + (control_W - right_padding));
        slider.setAttribute("id", "slider");
        slider.setAttribute("stroke", "silver");
        slider.setAttribute("stroke-width", "5");
        slider.setAttribute("opacity", "1");
        slider.setAttribute("fill", "none");
        svg.appendChild(slider);

        const startPill = document.createElementNS(svgNS, "circle");
        startPill.setAttribute("class", "draggable");
        startPill.setAttribute("id", "startPill");
        startPill.setAttribute("cx", left_padding);
        startPill.setAttribute("cy", (top_padding + (control_H/2)));
        startPill.setAttribute("r", pillRad);
        startPill.setAttribute("fill", "#55aaff");
        startPill.setAttribute("opacity",pillOpacity+"%");
        //startPill.setAttribute("cursor", "move");
        svg.appendChild(startPill);

        const periodPill = document.createElementNS(svgNS, "rect");
        periodPill.setAttribute("class", "draggable");
        periodPill.setAttribute("id", "period");
        periodPill.setAttribute("x", -diamondSide/2);
        periodPill.setAttribute("y", -diamondSide/2);
        periodPill.setAttribute("width", diamondSide);
        periodPill.setAttribute("height", diamondSide);
        periodPill.setAttribute("transform", "translate(" + (control_W/2) + ", " + (top_padding + (control_H/2)) + ") rotate(45)");
        periodPill.setAttribute("fill", "#55aaff");
        periodPill.setAttribute("opacity",pillOpacity+"%");
        periodPill.addEventListener("click", function(){ //don't keep recreating the menu if one already exists
            if (document.getElementById("periodDD") == null){
                var menu = createPeriodDD();
            }
        });
        svg.appendChild(periodPill);

        const endPill = document.createElementNS(svgNS, "circle");
        endPill.setAttribute("class", "draggable");
        endPill.setAttribute("id", "endPill");
        endPill.setAttribute("cx", (control_W - right_padding));
        endPill.setAttribute("cy", (top_padding + (control_H/2)));
        endPill.setAttribute("r", pillRad);
        endPill.setAttribute("fill", "#55aaff");
        endPill.setAttribute("opacity",pillOpacity+"%");
        //endPill.setAttribute("cursor", "move");
        svg.appendChild(endPill);

        const startLabel = document.createElementNS(svgNS, "text");
        startLabel.setAttribute("class", "ibm-plex-sans-labelText");
        startLabel.setAttribute("y", labelOffset);
        startLabel.setAttribute("text-anchor", "left");
        startLabel.textContent = "Start time";
        startLabel.setAttribute("x", left_padding  - (measureTextWidth(startLabel.textContent))/2);
        svg.appendChild(startLabel);
        
        const periodLabel = document.createElementNS(svgNS, "text");
        periodLabel.setAttribute("class", "ibm-plex-sans-labelText");
        periodLabel.setAttribute("y", labelOffset);
        periodLabel.setAttribute("text-anchor", "center");
        periodLabel.textContent = "Period";
        periodLabel.setAttribute("x", (control_W/2) - (measureTextWidth(periodLabel.textContent))/2);
        svg.appendChild(periodLabel);

        const endLabel = document.createElementNS(svgNS, "text");
        endLabel.setAttribute("class", "ibm-plex-sans-labelText");
        endLabel.setAttribute("y", labelOffset);
        endLabel.setAttribute("text-anchor", "right");
        endLabel.textContent = "End time";
        endLabel.setAttribute("x", (control_W - right_padding)  - (measureTextWidth(endLabel.textContent))/2 );
        svg.appendChild(endLabel); 

        function measureTextWidth(text) {
            const testDiv = document.getElementById("Test");
            testDiv.innerText = text; // Set the text to measure
            
            // Measure width after rendering
            const width = testDiv.clientWidth;
            return width;
        }

        function createPeriodDD(){
            const P = [100,1,1,1,1,7]; //enumerated values
            const U = ["ms","sec","min","hour","day","days"]; //units for values
            const periodDD = document.createElementNS(svgNS, "rect");
            periodDD.setAttribute("class", "menuRect");
            periodDD.setAttribute("id", "periodDD");
            periodDD.setAttribute("x", ((control_W/2) - (PDDwidth/2)));
            periodDD.setAttribute("y", (top_padding + (control_H/2) + bottom_padding));
            periodDD.setAttribute("width", PDDwidth);
            periodDD.setAttribute("height", PDDheight);
            periodDD.setAttribute("rx", PDDrad);
            periodDD.setAttribute("ry", PDDrad);
            var i = 0;
            var menuitem = [];
            P.forEach(element => {
                menuitem[i] = document.createElementNS(svgNS, "text");
                menuitem[i].setAttribute("class", "ibm-plex-sans-menuitem");
                menuitem[i].setAttribute("text-anchor", "left");
                menuitem[i].setAttribute("y", i*10);
                menuitem[i].textContent = P[i] + " " + U[i];
                menuitem[i].setAttribute("x", "10");
                periodDD.appendChild(menuitem[i]);
                i+=1;
            });
            svg.appendChild(periodDD);
        }

        function makeDraggable(evt) {
            var obj = evt.target;
            obj.addEventListener('contextmenu', contextMenu);
            obj.addEventListener('menu', menu);
            obj.addEventListener('mousedown', startDrag);
            obj.addEventListener('mousemove', drag);
            obj.addEventListener('mouseup', endDrag);
            obj.addEventListener('mouseleave', endDrag);

            var selectedElement, offset, transform;

            function contextMenu(evt){
                alert("context menu");
            }

            function menu(evt){
                alert("menu");
            }

            function startDrag(evt) {
                if (evt.target.classList.contains('draggable')) {
                    selectedElement = evt.target;
                    console.log(selectedElement.id)
                }
            }

            function drag(evt) { //NB for this appliocation no dragging happens - the start or end time (or both) change at a rate that fits with the period but the pills remain static
                if (selectedElement) {
                    console.log(selectedElement.id);
                    evt.preventDefault();
                    var x = parseFloat(selectedElement.getAttributeNS(null, "x"));
                    selectedElement.setAttributeNS(null, "x", x + 0.1);
                }
            }

            function endDrag(evt) {
                selectedElement = null;
            }
        }

        document.body.appendChild(svg);
    </script>

</body>

</html>

Javacript form submitting with e.preventdefault() on

I have written Javascript for an HTML form that uses e.preventdefault to stop the form from submitting unless the requirements are met. However, for some reason, my form is submitting even though I’ve used e.preventdefault.

Can you please help? HTML and Javascript below –

HTML –

 <form class="tg-form" id="tg-form" novalidate>
        <div>Upload Avatar</div>
        <div class="upload-container upload-hover" id="hover-box">
          <label for="input-file" id="drop-area" class="upload-hover">
            <input type="file" accept="image/*" id="input-file" hidden />
            <div class="inner-label-container">
              <div id="img-view" class="hidden"></div>
              <div id="upload-icon">
                <img src="assets/images/icon-upload.svg" />
              </div>
              <div id="photo-error"></div>
              <div id="upload-text">Drag and drop or click to upload</div>
            </div>
            <div class="upload-remove-btns hidden" id="change-btns">
              <button class="remove-btns" id="remove-btn">Remove image</button>
              <button class="remove-btns" id="change-btn">Change image</button>
            </div>
          </label>
        </div>
        <div class="photo-container">
          <div><img src="assets/images/icon-info.svg" /></div>
          <div>
            <p class="upload-font">
              Upload your photo (JPG or PNG, max size: 500KB).
            </p>
          </div>
        </div>

        <div class="input-header">Full Name</div>
        <input type="text" id="fname" class="input" name="fname" />
        <div id="error"></div>

        <div class="input-header">Email Address</div>
        <input
          class="input"
          type="email"
          id="email"
          name="email"
          placeholder="[email protected]"
        />
        <div id="email-error"></div>
        <div class="input-header">GitHub Username</div>
        <input
          class="input"
          type="text"
          id="username"
          name="username"
          placeholder="@yourusername"
        />

        <div><button class="generate-btn">Generate My Ticket</button></div>
      </form>

JS –

form.addEventListener("submit", (e) => {
  e.preventDefault();
  const isEmail = /^.+@.+$/.test(emailAddress.value);

  let messages = [];
  let messagesTwo = [];

  if ((firstName.value === "") | (firstName.value == null)) {
    messages.push("name is required");
  }

  if (messages.length > 0) {
    errorElement.innerText = messages.join(" , ");
  }

  if (!isEmail) {
    messagesTwo.push("Email is formatted incorrectly.");
  }

  if (messagesTwo.length > 0) {
    errorElementEmail.innerText = messagesTwo;
  }

  document.getElementById("tg-form").submit();
});

I’ve tried removing the submit function at the bottom, but my form doesn’t submit at all. My error messages are appearing if I leave the corresponding input fields empty, but the form is still submitting, which shouldn’t be happening, and I have no idea what I’m doing wrong.

Thanks.

How to round the result up to the nearest 500?

I have not brushed up on Javascript for a while and am having difficulty completing the task I am working so I wondered if someone could help me to fix my code or give me some insight please?

I have made a calculator where you put in 2 numbers, it multiplies them together (this part works already), but then the result needs to be divided by 3 and shown separately and rounded up or down to the nearest 500 but never less than 1000, even if the result of dividing by 3 is < 1000

I have called the first answer result and the second answer is result2 which should be result/3

function multiplyBy() {
        num1 = document.getElementById(
            "firstNumber").value;
        num2 = document.getElementById(
            "secondNumber").value;
        document.getElementById(
            "result").innerHTML = num1 * num2;
        document.getElementById(
            "result2").innerHTML = ( num1 * num2 ) / 3;

    }
<form style="font-family: 'Helvetica';">
  <p> Value 1</p> <input style="padding: 10px; width: 70%"  type="text" id="firstNumber" /><br>
  <p> Value 2</p> <input style="padding: 10px; width: 70%" type="text" id="secondNumber" /><br>
  <input style="background-color: #236478; color: #fff; border: none; margin-top:14px; width: 70%;" type="button" onClick="multiplyBy()" Value="Calculate" /> <br>
</form>

<p style="font-family: helvetica; font-weight: 700; font-size: 21px;">Two numbers multiplied:<br></p>
<span style="font-family: helvetica; font-weight: 700; font-size: 21px; color: #236478; padding-top:14px;" id="result"></span>

<p style="font-family: helvetica; font-weight: 700; font-size: 21px;">The Result divided by 3 but never less than 1000<br></p>

<span style="font-family: helvetica; font-weight: 700; font-size: 21px; color: #236478; padding-top:14px;" id="result2"></span>

Javascript Function Division – Rounding Result Up To The Nearest 500

I have not brushed up on Javascript for a while and am having difficulty completing the task I am working so I wondered if someone could help me to fix my code or give me some insight please?

I have made a calculator where you put in 2 numbers, it multiplies them together (this part works already), but then the result needs to be divided by 3 and shown separately and rounded up or down to the nearest 500 but never less than 1000, even if the result of dividing by 3 is < 1000

I have called the first answer result and the second answer is result2 which should be result/3

Here is my html

   <form style="font-family: 'Helvetica';">
  <p>   Value 1</p> <input style="padding: 10px; width: 70%"  type="text" id="firstNumber" /><br>
  <p> Value 2</p> <input style="padding: 10px; width: 70%" type="text" id="secondNumber" /><br>
   
    <input style="background-color: #236478; color: #fff; border: none; margin-top:14px; width: 70%;" type="button" onClick="multiplyBy()" Value="Calculate" /> <br>
</form>

<p style="font-family: helvetica; font-weight: 700; font-size: 21px;">Two numbers multiplied:<br></p>
    <span style="font-family: helvetica; font-weight: 700; font-size: 21px; color: #236478; padding-top:14px;" id="result"></span>

The Result divided by 3 but never less than 1000

Here is my Javascript

function multiplyBy() {
        num1 = document.getElementById(
            "firstNumber").value;
        num2 = document.getElementById(
            "secondNumber").value;
        document.getElementById(
            "result").innerHTML = num1 * num2;

    };
     function Mathfloor() {
        num1 = document.getElementById(
            "firstNumber").value;
        num2 = document.getElementById(
            "secondNumber").value;
        document.getElementById(
            "result").innerHTML = num1 * num2;
      document.getElementById(
            "result2").innerHTML = ( num1 * num2 ) / 3;

    }

NuxtUI stepper error : expose() should be called only once per setup()

I’ve tried to use the stepper component to create a stepper into my nuxt app.

The stepper is correctly loaded, but there is an error in the console : expose() should be called only once per setup(). But I haven’t used any expose() function.

By removing the UStepper component, everything works.

Here is my code :

<template>
  <div class="w-screen bg-slate-100 dark:bg-slate-900">
    <div class="container mx-auto py-12 mt-20">
      <h2 id="working" class="text-center mb-20">How it works</h2>

      
    </div>
  </div>
</template>

<script setup lang="ts">
  import type { StepperItem } from '@nuxt/ui';

  const items = ref<StepperItem[]>([
    {
      title: 'Address',
      description: 'Add your address here',
      icon: 'i-lucide-house',
    },
    {
      title: 'Shipping',
      description: 'Set your preferred shipping method',
      icon: 'i-lucide-truck',
    },
    {
      title: 'Checkout',
      description: 'Confirm your order',
    },
  ]);
</script>

Here is the entire error :

 WARN  [Vue warn]: expose() should be called only once per setup(). 
  at <StepperRoot orientation="horizontal" linear=true modelValue=0  ... > 
  at <Stepper items= [ { title: 'Address', description: 'Add your address here', icon: 'i-lucide-house' },
  { title: 'Shipping',
    description: 'Set your preferred shipping method',
    icon: 'i-lucide-truck' },
  { title: 'Checkout', description: 'Confirm your order' } ] class="w-full" > 
  at <LandingPageWorking> 
  at <Index onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< undefined > > 
  at <RouteProvider vnode= { __v_isVNode: true,
  __v_skip: true,
  type:
   { __name: 'index',
     setup: [Function (anonymous)],
     ssrRender: [Function: _sfc_ssrRender],
     __file:
      '/Users/josselinarnaud/Documents/personnel/dev/personnel/url-shortener-frontend/App/pages/index.vue' },
  props:
   { onVnodeUnmounted: [Function: onVnodeUnmounted],
     ref:
      RefImpl {
        dep: [Dep],
        __v_isRef: true,
        __v_isShallow: false,
        _rawValue: undefined,
        _value: undefined } },
  key: null,
  ref:
   { i:
      { uid: 8,
        vnode: [Object],
        type: [Object],
        parent: [Object],
        appContext: [Object],
        root: [Object],
        next: null,
        subTree: [Object],
        effect: null,
        update: null,
        job: null,
        scope: [EffectScope],
        render: [Function (anonymous)],
        proxy: [Object],
        exposed: null,
        exposeProxy: null,
        withProxy: null,
        provides: [Object <Complex prototype>],
        ids: [Array],
        accessCache: [Object: null prototype] {},
        renderCache: [],
        components: null,
        directives: null,
        propsOptions: [Array],
        emitsOptions: null,
        emit: [Function: bound emit],
        emitted: null,
        propsDefaults: [Object: null prototype] {},
        inheritAttrs: false,
        ctx: [Object],
        data: {},
        props: [Object],
        attrs: {},
        slots: [Object],
        refs: {},
        setupState: {},
        setupContext: [Object],
        suspense: null,
        suspenseId: 0,
        asyncDep: null,
        asyncResolved: false,
        isMounted: false,
        isUnmounted: false,
        isDeactivated: false,
        bc: null,
        c: null,
        bm: null,
        m: null,
        bu: null,
        u: null,
        um: null,
        bum: null,
        da: null,
        a: null,
        rtg: null,
        rtc: null,
        ec: null,
        sp: null },
     r:
      RefImpl {
        dep: [Dep],
        __v_isRef: true,
        __v_isShallow: false,
        _rawValue: undefined,
        _value: undefined },
     k: undefined,
     f: false },
  scopeId: null,
  slotScopeIds: null,
  children: null,
  component: null,
  suspense: null,
  ssContent: null,
  ssFallback: null,
  dirs: null,
  transition: null,
  el: null,
  anchor: null,
  target: null,
  targetStart: null,
  targetAnchor: null,
  staticCount: 0,
  shapeFlag: 4,
  patchFlag: 0,
  dynamicProps: null,
  dynamicChildren: null,
  appContext: null,
  ctx:
   <ref *1> {
     uid: 8,
     vnode:
      { __v_isVNode: true,
        __v_skip: true,
        type: [Object],
        props: [Object],
        key: null,
        ref: null,
        scopeId: null,
        slotScopeIds: null,
        children: [Object],
        component: [Circular *1],
        suspense: null,
        ssContent: null,
        ssFallback: null,
        dirs: null,
        transition: null,
        el: null,
        anchor: null,
        target: null,
        targetStart: null,
        targetAnchor: null,
        staticCount: 0,
        shapeFlag: 36,
        patchFlag: 0,
        dynamicProps: null,
        dynamicChildren: null,
        appContext: null,
        ctx: [Object] },
     type:
      { name: 'RouterView',
        inheritAttrs: false,
        props: [Object],
        compatConfig: [Object],
        setup: [Function: setup] },
     parent:
      { uid: 7,
        vnode: [Object],
        type: [Object],
        parent: [Object],
        appContext: [Object],
        root: [Object],
        next: null,
        subTree: [Object],
        effect: null,
        update: null,
        job: null,
        scope: [EffectScope],
        render: [Function (anonymous)],
        proxy: [Object],
        exposed: [Object],
        exposeProxy: null,
        withProxy: null,
        provides: [Object <Complex prototype>],
        ids: [Array],
        accessCache: [Object: null prototype] {},
        renderCache: [],
        components: null,
        directives: null,
        propsOptions: [Array],
        emitsOptions: null,
        emit: [Function: bound emit],
        emitted: null,
        propsDefaults: [Object: null prototype] {},
        inheritAttrs: false,
        ctx: [Object],
        data: {},
        props: [Object],
        attrs: {},
        slots: {},
        refs: {},
        setupState: {},
        setupContext: [Object],
        suspense: null,
        suspenseId: 0,
        asyncDep: null,
        asyncResolved: false,
        isMounted: false,
        isUnmounted: false,
        isDeactivated: false,
        bc: null,
        c: null,
        bm: null,
        m: null,
        bu: null,
        u: null,
        um: null,
        bum: null,
        da: null,
        a: null,
        rtg: null,
        rtc: null,
        ec: null,
        sp: null },
     appContext:
      { app: [Object],
        config: [Object],
        mixins: [],
        components: [Object],
        directives: {},
        provides: [Object: null prototype],
        optionsCache: [WeakMap],
        propsCache: [WeakMap],
        emitsCache: [WeakMap] },
     root:
      <ref *2> {
        uid: 0,
        vnode: [Object],
        type: [Object],
        parent: null,
        appContext: [Object],
        root: [Circular *2],
        next: null,
        subTree: null,
        effect: null,
        update: null,
        job: null,
        scope: [EffectScope],
        render: [Function: NOOP],
        proxy: {},
        exposed: {},
        exposeProxy: null,
        withProxy: null,
        provides: [Object <Complex prototype>],
        ids: [Array],
        accessCache: [Object: null prototype] {},
        renderCache: [],
        components: null,
        directives: null,
        propsOptions: [],
        emitsOptions: null,
        emit: [Function: bound emit],
        emitted: null,
        propsDefaults: [Object: null prototype] {},
        inheritAttrs: undefined,
        ctx: {},
        data: {},
        props: {},
        attrs: {},
        slots: {},
        refs: {},
        setupState: [Object],
        setupContext: [Object],
        suspense: null,
        suspenseId: 0,
        asyncDep: null,
        asyncResolved: false,
        isMounted: false,
        isUnmounted: false,
        isDeactivated: false,
        bc: null,
        c: null,
        bm: null,
        m: null,
        bu: null,
        u: null,
        um: null,
        bum: null,
        da: null,
        a: null,
        rtg: null,
        rtc: null,
        ec: [Array],
        sp: null,
        devtoolsRawSetupState: [Object] },
     next: null,
     subTree:
      { __v_isVNode: true,
        __v_skip: true,
        type: [Object],
        props: [Object],
        key: null,
        ref: null,
        scopeId: null,
        slotScopeIds: null,
        children: [Object],
        component: null,
        suspense: null,
        ssContent: [Object],
        ssFallback: [Object],
        dirs: null,
        transition: null,
        el: null,
        anchor: null,
        target: null,
        targetStart: null,
        targetAnchor: null,
        staticCount: 0,
        shapeFlag: 160,
        patchFlag: 0,
        dynamicProps: null,
        dynamicChildren: null,
        appContext: null,
        ctx: [Object] },
     effect: null,
     update: null,
     job: null,
     scope:
      EffectScope {
        detached: true,
        _active: true,
        _on: 0,
        effects: [],
        cleanups: [],
        _isPaused: false,
        parent: undefined,
        prevScope: undefined },
     render: [Function (anonymous)],
     proxy: { name: [Getter/Setter], route: [Getter/Setter] },
     exposed: null,
     exposeProxy: null,
     withProxy: null,
     provides:
      Object <Object <Complex prototype>> {
        [Symbol(router view depth)]: [ComputedRefImpl],
        [Symbol(router view location matched)]: [ComputedRefImpl],
        [Symbol(router view location)]: [ComputedRefImpl] },
     ids: [ '0-', 2, 2 ],
     accessCache: [Object: null prototype] {},
     renderCache: [],
     components: null,
     directives: null,
     propsOptions: [ [Object], [Array] ],
     emitsOptions: null,
     emit: [Function: bound emit],
     emitted: null,
     propsDefaults: [Object: null prototype] {},
     inheritAttrs: false,
     ctx: { name: [Getter/Setter], route: [Getter/Setter] },
     data: {},
     props: { route: undefined, name: 'default' },
     attrs: {},
     slots: { default: [Function] },
     refs: {},
     setupState: {},
     setupContext: { attrs: [Getter], slots: [Getter], emit: [Getter], expose: [Function: expose] },
     suspense: null,
     suspenseId: 0,
     asyncDep: null,
     asyncResolved: false,
     isMounted: false,
     isUnmounted: false,
     isDeactivated: false,
     bc: null,
     c: null,
     bm: null,
     m: null,
     bu: null,
     u: null,
     um: null,
     bum: null,
     da: null,
     a: null,
     rtg: null,
     rtc: null,
     ec: null,
     sp: null } } route= { fullPath: '/',
  hash: '',
  query: {},
  name: 'index',
  path: '/',
  params: {},
  matched:
   [ { path: '/',
       redirect: undefined,
       name: 'index',
       meta: {},
       aliasOf: undefined,
       beforeEnter: undefined,
       props: [Object],
       children: [],
       instances: {},
       leaveGuards: Set(0) {},
       updateGuards: Set(0) {},
       enterCallbacks: {},
       components: [Object] } ],
  meta: {},
  redirectedFrom: undefined,
  href: '/' } vnodeRef=Ref< undefined > > 
  at <RouterView name=undefined route=undefined > 
  at <NuxtPage> 
  at <Default ref=Ref< undefined > > 
  at <AsyncComponentWrapper ref=Ref< undefined > > 
  at <LayoutLoader key="default" layoutProps= { ref:
   RefImpl {
     dep:
      Dep {
        computed: undefined,
        version: 0,
        activeLink: undefined,
        subs: undefined,
        map: undefined,
        key: undefined,
        sc: 0,
        subsHead: undefined },
     __v_isRef: true,
     __v_isShallow: true,
     _rawValue: undefined,
     _value: undefined } } name="default" > 
  at <NuxtLayoutProvider layoutProps= { ref:
   RefImpl {
     dep:
      Dep {
        computed: undefined,
        version: 0,
        activeLink: undefined,
        subs: undefined,
        map: undefined,
        key: undefined,
        sc: 0,
        subsHead: undefined },
     __v_isRef: true,
     __v_isShallow: true,
     _rawValue: undefined,
     _value: undefined } } key="default" name="default"  ... > 
  at <NuxtLayout > 
  at <App> 
  at <NuxtRoot>


 WARN  [nuxt] Failed to stringify dev server logs. Received DevalueError: Cannot stringify a function. You can define your own reducer/reviver for rich types following the instructions in https://nuxt.com/docs/api/composables/use-nuxt-app#payload.```

How to implement Scheme float, ceil, and round that work on exact rationals in JavaScript?

I just found about those two expressions in Scheme:

(quotient (expt 1000 999) 998001)
(floor (/ (expt 1000 999) 998001))

They return bigInt that looks like this 100200300 ... 999 (with all numbers except 998).

The problem I have is that in my Scheme interpreter in JavaScript, I’ve got +inf.0, because it creates float (inexact number).

This is the implementation of my quotient:

(define (quotient a b)
  "(quotient a b)

   Return quotient from division as integer."
  (typecheck "quotient" a "number")
  (typecheck "quotient" b "number")
  (if (zero? b 0)
     (throw (new Error "quotient: division by zero"))
     (let ((quotient (/ a b)))
       (if (integer? quotient)
           quotient
           (if (> quotient 0)
               (floor quotient)
               (ceiling quotient))))))

And this is implementation of floor, ceil, and round:

['floor', 'ceil', 'round'].forEach(fn => {
    LNumber.prototype[fn] = function() {
        if (this.float || LNumber.isFloat(this.__value__)) {
            return LNumber(Math[fn](this.__value__));
        } else {
            return LNumber(Math[fn](this.valueOf()));
        }
    };
});

(function() {
    var map = { ceil: 'ceiling' };
    ['floor', 'round', 'ceil'].forEach(fn => {
        var name = map[fn] ? map[fn] : fn;
        global_env.set(name, doc(name, function(value) {
            typecheck(name, value, 'number');
            if (value instanceof LNumber) {
                return value[fn]();
            }
        }, `(${name} number)

            Function that calculates the ${name} of a number.`));
    });
})();

As you can see, it just use Math.floor and convert the number to float (this.valueOf() on rationals return a float/inexact value).

How the floor, ceil, and round functions should look like to create BigInt number when the argument is exact? What algorithm should I use?

HTML Javascript, render title based on SQL Query method

I am currently making a template for my school things.

The app can now display 3 sections, and while I am mostly happy with it I want to simplify the title part a bit.

Currently you need to hover over an element to assign a title, but is there a method to pre render all the titles with an SQL query?

Here is the code so far – I am sending the project, so if you have any other suggestion outside of my original request, I am happy to receive them -.

Thanks in advance.

Backend (Server.JS):

const express = require('express');
const mysql = require('mysql');

const app = express();
app.use(express.static("public"));

const db = mysql.createConnection({
    host: 'localhost',
    user: 'root',
    password: '',
    database: ''
});

app.get('/api/table1', (req, res) => {
    db.query('SELECT * FROM table1', (err, results) => {
        if (err) return res.status(500).json({ error: err });
        res.json(results);
    });
});

app.get('/api/table2', (req, res) => {
    db.query('SELECT * FROM table2', (err, results) => {
        if (err) return res.status(500).json({ error: err });
        res.json(results);
    });
});

app.get('/api/select-options', (req, res) => {
    db.query('SELECT selectoption FROM table1', (err, results) => {
        if (err) return res.status(500).json({ error: err });
        res.json(results);
    });
});

app.get('/api/filter', (req, res) => {
    const value = req.query.value;
    db.query('SELECT * FROM table1 t1 JOIN table2 t2 ON t1.attribute = t2.attribute WHERE t2.attribute = ?', [value], (err, results) => {
        if (err) return res.status(500).json({ error: err });
        res.json(results);
    });
});

app.get('/api/title-info', (req, res) => {
    const id = req.query.id;
    db.query('SELECT * FROM table1 WHERE x = ?', [id], (err, results) => {
        if (err) return res.status(500).json({ error: err });
        if (results.length === 0) return res.json({ info: 'No data' });

        const info = results[0].RESULTFIELD;
        res.json({ info });
    });
});

app.listen(3000, () => console.log('Server running on port 3000'));

Frontend: (Index.HTML and Index.JS):

function showSection(id)
{
    ['section1', 'section2', 'section3'].forEach(sid =>
    {
        document.getElementById(sid).style.display = 'none';
    });
    document.getElementById(id).style.display = 'block';
}

function loadTable1()
{
    fetch('/api/table1')
        .then(res => res.json())
        .then(data =>
        {
            const container = document.getElementById('table1');
            container.innerHTML = '';

            if (!data.length) return;

            const table = document.createElement('table');
            const headers = Object.keys(data[0]);

            const headerRow = document.createElement('tr');
            headers.forEach(h =>
            {
                const th = document.createElement('th');
                th.textContent = h;
                headerRow.appendChild(th);
                th.addEventListener('click', () =>
                {
                    const sortedData = data.sort((a, b) =>
                    {
                        if (a[h] < b[h]) return -1;
                        if (a[h] > b[h]) return 1;
                        return 0;
                    });
                    renderTable('table1', sortedData);
                });
            });
            table.appendChild(headerRow);

            data.forEach(row =>
            {
                const tr = document.createElement('tr');
                headers.forEach(h =>
                {
                    const td = document.createElement('td');
                    td.textContent = row[h];
                    tr.appendChild(td);
                });
                table.appendChild(tr);
            });

            container.appendChild(table);
        });
}


function loadTable2()
{
    fetch('/api/table2')
        .then(res => res.json())
        .then(data =>
        {
            const container = document.getElementById('table2');
            container.innerHTML = '';

            if (!data.length) return;

            const table = document.createElement('table');
            const headers = Object.keys(data[0]);

            const headerRow = document.createElement('tr');
            headers.forEach(h =>
            {
                const th = document.createElement('th');
                th.textContent = h;
                headerRow.appendChild(th);
            });
            table.appendChild(headerRow);
            data.forEach(row =>
            {
                const tr = document.createElement('tr');
                headers.forEach(h =>
                {
                    const td = document.createElement('td');
                    td.textContent = row[h];
                    tr.appendChild(td);
                });

                tr.addEventListener('mouseover', () =>
                {
                    fetch(`/api/title-info?id=${ row.id }`)
                        .then(res => res.json())
                        .then(info =>
                        {
                            tr.title = info.info || 'No data';
                        })
                        .catch(() =>
                        {
                            tr.title = 'Error occured';
                        });
                });

                table.appendChild(tr);
            });

            container.appendChild(table);
        });
}



async function loadDropdown()
{
    const dropdown = document.getElementById('dropdown');
    dropdown.innerHTML = '<option value="">Kérem válasszon!</option>';

    try
    {
        const res = await fetch('/api/select-options');
        const data = await res.json();

        data.forEach(row =>
        {
            const key = Object.values(row)[0];
            dropdown.innerHTML += `<option value="${ key }">${ key }</option>`;
        });

        loadFiltered();
    } catch (err)
    {
        console.error('Failed to load dropdown options:', err);
    }
}


async function loadFiltered()
{
    const value = document.getElementById('dropdown').value;

    if (value !== '')
    {
        try
        {
            const res = await fetch(`/api/filter?value=${ (value) }`);
            const data = await res.json();
            renderTable('filtered', data);
        } catch (err)
        {
            console.error('Failed to load filtered data:', err);
        }
    } else
    {
        document.getElementById('filtered').innerHTML = '';
    }
}

function renderTable(id, data)
{
    const container = document.getElementById(id);
    container.innerHTML = '';

    if (!data.length) return;

    const table = document.createElement('table');
    const headers = Object.keys(data[0]);

    const headerRow = document.createElement('tr');
    headers.forEach(h =>
    {
        const th = document.createElement('th');
        th.textContent = h;
        headerRow.appendChild(th);
        th.addEventListener('click', () =>
        {
            const sortedData = data.sort((a, b) =>
            {
                if (a[h] < b[h]) return -1;
                if (a[h] > b[h]) return 1;
                return 0;
            });
            renderTable('table1', sortedData);
        });
    });
    table.appendChild(headerRow);

    data.forEach(row =>
    {
        const tr = document.createElement('tr');
        headers.forEach(h =>
        {
            const td = document.createElement('td');
            td.textContent = row[h];
            tr.appendChild(td);
        });
        table.appendChild(tr);
    });

    container.appendChild(table);
}

loadTable1();
loadTable2();
loadDropdown();
showSection('section1');


<!DOCTYPE html>
<html>
<head>
  <title>API Page</title>
</head>
<body>
  <nav>
    <a onclick="showSection('section1')">Section 1</a>
    <a onclick="showSection('section2')">Section 2</a>
    <a onclick="showSection('section3')">Section 3</a>
  </nav>

  <div id="section1">
    <h2>table1</h2>
    <div id="table1"></div>
  </div>

  <div id="section2">
    <h2>table2</h2>
    <div id="table2"></div>
  </div>

  <div id="section3">
    <h2>selector</h2>
    <select id="dropdown" onchange="loadFiltered()"></select>
    <div id="filtered"></div>
  </div>

  <script src="index.js"></script>
</body>
</html>

And here is the part that I mainly need help with:

tr.addEventListener('mouseover', () =>
                {
                    fetch(`/api/title-info?id=${ row.id }`)
                        .then(res => res.json())
                        .then(info =>
                        {
                            tr.title = info.info || 'No data';
                        })
                        .catch(() =>
                        {
                            tr.title = 'Error occured';
                        });
                });

Is it possible to pre-render the titles for each row respectively?

Tracking Qgiv embedded form via GTM on my website

I need a little help, I’m stuck.

I’m trying to track my Qgiv Donation Form via GTM on my website. The form is embedded using an iframe. The default GTM variables I imported into my GTM container seem to work within the form’s own container, but they don’t work in the main website’s container.

So, I tried creating a separate trigger and tag for iframe tracking using a script, which works. However, to track form submission, I want to place the tracker on the submission or thank-you page, which I’ve been unable to do.

I checked the console behaviour during submission and noticed:

  • There is no URL change inside the iframe.
  • No event is triggered.
  • The only thing that happens is HTML injection.

That means once the donation is submitted and the thank-you message appears, I can see the HTML of that thank-you state in the console, but it’s not treated as a new page or event.

I’m running out of ideas. To make it more challenging, Qgiv doesn’t allow injecting custom JavaScript into the form. I had hoped to create a script that would send a submission event from within the iframe to the parent website, but that doesn’t seem possible either. Please let me know if I need to share anything to help answer my question.

iFrame related HTML:

<iframe id="qgiv-embed" class="qgiv-embed-form qgiv-embed" frameborder="0" allowtransparency="true" style="display: block; float: none; width: 100%; border: 0px; overflow: hidden; height: 1444.4px;" scrolling="no" data-embed-position="206.6750030517578" title="Collaborative Research Foundation" src="https://secure.qgiv.com/for/collaborativeresearchfoundation/embed"></iframe>

HTML that’s visible after submission:

</svg><input type="hidden" name="form-type" id="form-type" value="Donation Forms"> <input type="hidden" name="isStandardDonationForm" id="isStandardDonationForm" value="1"><div class="main"><div id="injection-container"></div><style id="custom-css"></style><div id="app-container"><div id="top-content" class=""></div><div class="donation-form-app" id="app"><div class="donation-form-container"><div class="donation-form-embed"><div class="qg-vendor-form-container donation-form-embed-container"><main class="qg-vendor-page__content donation-form-content__embed-view"><section class="page"><div class="page__content receipt"><div class="donation-form__header--login -margin-bottom--30 -text--right"><div class="qgiv-vender-login login"><a class="-type--small -color--theme-primary login__account-link ignore-typography ignore-auto-focus" href="/account/2280020/embed/?org=452968&amp;formId=1029461" target="_blank" rel="noreferrer"><strong><span class="icon -type--regular -margin-right--10 -vertical-align--text-bottom align-text-bottom"><svg role="img" aria-hidden="true"><title id="title-50054">user-circle-regular</title><use href="#FontAwesome__user-circle-regular"></use></svg></span>My Account</strong></a><span class="icon login__dot -margin--5 -vertical-align--middle"><svg role="img" aria-hidden="true"><title id="title-95279">circle-solid</title><use href="#FontAwesome__circle-solid"></use></svg></span><button class="qg-vendor-text-button text-button -type--small -color--theme-primary ignore-auto-focus" type="button"><strong>Sign Out</strong></button></div></div><div class="qg-vendor-controls-container qg-vendor-controls-container-confirmation-page controls-container"><div class="qg-vendor-receipt-header receipt-header -padding-bottom--30"><div class="col col--12 -text--center"><span class="icon qg-vendor-receipt-header-icon receipt-header__confirmation-icon -color--theme-primary -vertical-align--text-bottom align-text-bottom"><svg role="img" aria-hidden="true"><title id="title-98617">qgiv-confirmation</title><use href="#Custom__qgiv-confirmation"></use></svg></span></div><div class="qg-vendor-receipt-header-heading col col--12 -text--center -padding-top--20"><h1>Thank you, Daniel!</h1></div><div class="qg-vendor-receipt-header-subheading col col--12 -text--center -padding-top--5"><span class="-type--xlarge"><span>Your gift of <span class="-color--theme-primary">$1.05</span> will make a difference</span></span></div></div><div id="qg-vendor-receipt-summary receipt-summary"><div class="accordion"><div class="panel accordion__panel"><button type="button" aria-expanded="true" class="panel__heading panel__heading--large -cursor--pointer"><span class="icon panel__heading__icon -vertical-align--text-bottom align-text-bottom"><svg role="img" aria-hidden="true"><title id="title-42933">minus-circle-regular</title><use href="#FontAwesome__minus-circle-regular"></use></svg></span><div class="accordion-header-receipt-content"><div class="grid"><div class="col col--8 col--no-top-gutter"><strong class="-type--regular -color--theme-primary">Your Receipt</strong><br><small class="-color--system-medium-dark -margin-top--5">A copy will be emailed shortly.</small></div><div class="col col--4 col--no-top-gutter -text--right"><p><a class="print-link ignore-typography" tabindex="0" role="link"><span class="icon -type--regular -margin-right--10 -vertical-align--text-bottom align-text-bottom"><svg role="img" aria-hidden="true"><title id="title-8646">print-regular</title><use href="#FontAwesome__print-regular"></use></svg></span><strong>Print</strong></a></p></div></div></div></button><div><div class="-padding-bottom--20"><div class="grid"><div class="col col--12"><h3>Summary</h3><p>Transaction #30934130<br>Placed on 05/31/2025 at 05:58 AM</p></div></div><div class="grid"><div class="qg-vendor-receipt-summary-details col col--12"><div class="grid"><div class="col col--12 col--no-top-gutter"><div><div class="grid"><div class="col col--6 -padding-top--10"><p>Other</p></div><div class="col col--6 -text--right -padding-top--10"><p>$1</p></div></div><div class="qg-vendor-divider divider "><hr class="divider__hr divider__hr--dashed"> </div></div><div><div class="grid"><div class="col col--6 -padding-top--10"><p>Processing Fee<br><small>Thanks for giving a little extra!</small></p></div><div class="col col--6 -text--right -padding-top--10"><p>$0.05</p></div></div><div class="qg-vendor-divider divider "><hr class="divider__hr divider__hr--dashed"> </div></div></div><div class="col col--12 col--no-top-gutter"><div class="grid"><div class="col col-6 "><h3>Total Gift</h3></div><div class="col col-6 -text--right"><p><strong class="-color--system-dark -padding-left--5 -type--large">$1.05</strong></p></div></div></div></div></div></div><div class="grid"><div class="col col--12 col--sm-6 -margin-top--15"><section><h3>Personal Details</h3><p class="-type--small -margin-top--15"> Daniel Truesdale <br><a class="-color--theme-primary" href="mailto:[email protected]"><strong class="receipt-details__email">[email protected]</strong></a><br>Block N, North Nazimabad<br>karachi, Sindh 74700<br>PK<br></p></section></div><div class="col col--12 col--sm-5 -margin-top--15"><section><h3>Payment Details</h3><p class="-type--small -margin-top--15">MasterCard ending in<strong>··</strong>24<br>Daniel Truesdale<br>5023 North Capitol Street, NE<br>Washington, District of Columbia 20011<br>US</p></section></div><div class="col col--12"><div class="-callout"><p><span class="icon -margin-right--10 -vertical-align--text-bottom align-text-bottom"><svg role="img" aria-hidden="true"><title id="title-23982">bell-solid</title><use href="#FontAwesome__bell-solid"></use></svg></span> You opted-in for news and updates.</p></div></div></div></div></div></div></div></div></div><div class="qg-vendor-controls-container qg-vendor-controls-container-confirmation-page controls-container"><div class="grid"><div class="col col--12"><div class="donor-account__content -padding--30 -text--center"><div class="grid"><div class="my-account -padding--30"><div class="grid"><div class="col col--12 -padding-top--0 -text--center"><h2>Go to <a href="/account/2280020/embed/?org=452968&amp;formId=1029461" class="-color--theme-primary" target="_blank"><strong>my account</strong></a></h2></div><div class="col col--12 -padding-top--0 -text--center"><p>You're signed in as <strong>Daniel</strong> <strong>Truesdale</strong></p></div></div></div></div></div></div></div><div class="qg-vendor-widget-social widget-sharing grid"><div class="col col--12"><div class="qg-vendor-page__callout -callout -padding--30"><div class="grid grid--justify-content-center"><div class="col col--12 -padding-top--0 -text--center"><h2>Share With Friends</h2></div><div class="col col--12 -padding-top--5 -margin-bottom--15 -text--center"><p>Your gift can inspire generosity</p></div><div class="col col--10 col--no-top-gutter -text--center"><div class="grid grid--tight-gutters grid--justify-content-center"><div class="col col--6 col--sm-4 col--no-top-gutter"><button aria-label="Share on Facebook" class="qg-vendor-button button button--primary button--large -background-color--facebook" role="link" type="button"><span class="button__content"><span class="icon -vertical-align--text-bottom align-text-bottom"><svg role="img" aria-hidden="true"><title id="title-11525">facebook-brands</title><use href="#FontAwesome__facebook-brands"></use></svg></span></span></button></div><div class="col col--6 col--sm-4 col--no-top-gutter"><button aria-label="Share on X" class="qg-vendor-button button button--primary button--large -background-color--twitter" role="link" type="button"><span class="button__content"><span class="icon -vertical-align--text-bottom align-text-bottom"><svg role="img" aria-hidden="true"><title id="title-83435">x-twitter-brands</title><use href="#FontAwesome__x-twitter-brands"></use></svg></span></span></button></div></div></div></div></div></div></div></div><div class="qg-vendor-form-footer form-footer"><div class="form-footer__col -text--center"><span class="icon form-footer__powered-by-qgiv qg-vendor-powered-by-qgiv-logo powered-by-qgiv-logo powered-by-qgiv-logo--dark -vertical-align--text-bottom align-text-bottom"><svg role="img" aria-hidden="true"><title id="title-47610">logo-powered-by-qgiv</title><use href="#Custom__logo-powered-by-qgiv"></use></svg></span></div></div></div></section></main></div></div></div></div><div id="bottom-content" class=""></div></div></div><input type="hidden" value="wifvWZ7rpiq5" name="csrfToken" id="csrfToken"><script>window.QGIV = {};

Why does adding an event handler during a handler appear to work differently from removing one?

I’m writing an event driver for a project I’m working on and I’m using the standard browser event system as a model, which has made me look at it in more detail. I’m testing things in Edge and Firefox.

Consider this:

document.documentElement.addEventListener("click", () =>
{
    console.log("Handler 1");
    document.documentElement.addEventListener("click", () => console.log("Handler 2"));

    return;
});

When the document element is clicked for the first time, the output in the console is:

Handler 1

From this, it would seem that, even though the end result are two events bound in order (Handler 1 and Handler 2), a handler added inside another event handler is not added to the currently processed queue.

Now consider this:

const handler2 = () => console.log("Handler 2");

document.documentElement.addEventListener("click", () =>
{
    console.log("Handler 1");
    document.documentElement.removeEventListener("click", handler2);

    return;
});
document.documentElement.addEventListener("click", handler2);

When the document element is clicked, the output in the console is also:

Handler 1

In this second case, the two handlers are initially bound in order, and I would presume the event queue contains both when Handler 1 is initially run, but removing an event handler is enough to also remove it from the currently processed queue.

Is there a rationale behind this apparent difference? I don’t understand why removing the listener would impact the event queue. If the browser doesn’t update the queue when an event is added for performance reasons, then surely those reasons apply when removing too. I would also think the logical thing would be to have the two operations behave consistently.