Drawing HTML range/slider through Javascript renders incorrectly

Following this tutorial I created a double range slider. I have slightly adapted it to look like this:

<div class="range_container">
  <div class="form_control">
    <div class="form_control_container">
      <input class="form_control_container__time__input" type="number" id="fromInput" value="-150" min="-150" max="0"/>
    </div>
    <div class="form_control_container">
      <div>RSSI</div>
    </div>
    <div class="form_control_container">
      <input class="form_control_container__time__input" type="number" id="toInput" value="0" min="-150" max="0"/>
    </div>
  </div>
  <div class="sliders_control">
    <input id="fromSlider" type="range" value="-150" min="-150" max="0"/>
    <input id="toSlider" type="range" value="0" min="-150" max="0"/>
  </div>
</div>

The result is OK:

enter image description here

However, if I generate the same through JS, I get the following formatting:

enter image description here

The problem is that no matter what I tried, the “fromSlider” always has its slider/thumb below the range. I’ve played with z-index but so far no avail. Does anyone have a suggestion how I can resolve this issue?

The code I used to generate this:

  const quantitiesConfig = {
    "rssi": { "nice": "RSSI", "absMin": -150, "relMin": -120, "relMax": -70, "absMax":  0, "unit": "dBm", "decimals": 1, "step": 1 }
  };

  const container = document.getElementById('filter-container');

  Object.entries(quantitiesConfig).forEach(([atrb, cfg]) => {
    // Inject slider markup
    container.innerHTML += `
      <div class="range_container" id="range_container-${atrb}">
        <div class="form_control">
          <div class="form_control_container">
            <input class="form_control_container__time__input" type="number" id="fromInput-${atrb}" 
              value="${cfg.absMin}" min="${cfg.absMin}" max="${cfg.absMax}" step="${cfg.step}" />
          </div>
          <div class="form_control_container">
            <div>${cfg.nice}</div>
          </div>
          <div class="form_control_container">
            <input class="form_control_container__time__input" type="number" id="toInput-${atrb}" 
              value="${cfg.absMax}" min="${cfg.absMin}" max="${cfg.absMax}" step="${cfg.step}" />
          </div>
        </div>
        <div class="sliders_control">
          <input id="fromSlider-${atrb}" type="range" value="${cfg.absMin}" min="${cfg.absMin}" max="${cfg.absMax}" step="${cfg.step}" />
          <input id="toSlider-${atrb}" type="range" value="${cfg.absMax}" min="${cfg.absMin}" max="${cfg.absMax}" step="${cfg.step}" />
        </div>
      </div>
    `;

    // Select elements
    const fromSlider = document.getElementById(`fromSlider-${atrb}`);
    const toSlider = document.getElementById(`toSlider-${atrb}`);
    const fromInput = document.getElementById(`fromInput-${atrb}`);
    const toInput = document.getElementById(`toInput-${atrb}`);

    // Ensure sliders are properly drawn initially
    fillSlider(fromSlider, toSlider, '#C6C6C6', '#0074D9', toSlider);
    setToggleAccessible(toSlider);

    // Attach event listeners
    fromSlider.addEventListener('input', () => controlFromSlider(fromSlider, toSlider, fromInput));
    toSlider.addEventListener('input', () => controlToSlider(fromSlider, toSlider, toInput));
    fromInput.addEventListener('input', () => controlFromInput(fromSlider, fromInput, toInput, toSlider));
    toInput.addEventListener('input', () => controlToInput(toSlider, fromInput, toInput, toSlider));
  });

The latter functions are as defined from the tutorial except a changed colour and slightly modified function

  function setToggleAccessible(currentTarget) {
    const toSlider = document.querySelector('#toSlider');
    if (Number(currentTarget.value) <= currentTarget.min ) {
      toSlider.style.zIndex = 2;
    } else {
      toSlider.style.zIndex = 0;
    }
  }

Is using class based approach in Grafana K6 test scripts a bad practice?

I’m working on performance testing with Grafana K6 and trying to structure my test scripts to avoid redundancy. So I’ve implemented a class-based approach. Here’s a sample code:

const metrics = new MetricsBuilder();

const k6Runner = new K6Runner();

export const setup = () => k6Runner.doSetup();
export const options = k6Runner.getOptions();
export default () => k6Runner.run();

The MetricsBuilder class is designed to hold various metrics (including custom ones) and make them reusable across multiple test scripts. I want to keep the codebase clean, as there will be multiple test scripts and need to avoid redundancy.

However, I have a few concerns:

# Init Context and SharedArray Behavior

According to the documentation, the init context runs once per Virtual User (VU), while a SharedArray is only initialized once and shared across all VUs. I’ve noticed that the MetricsBuilder class gets initialized for every VU in the init context, but I don’t see any significant difference in the reports. Does K6 handle it appropriately?

# Is it a bad practice to use a class like MetricsBuilder in this context?

Does initializing the same object multiple times in the init context (one per VU) have any negative impact on performance or results?

# Initialization of Classes in the Init Context

I’ve noticed that initializing a class like K6Runner in the init context (e.g., const k6Runner = new K6Runner();) results in the same number of instances being created as the number of VUs.

# Is this approach considered a bad practice?

Would this lead to any issues, such as resource overuse or unexpected side effects?

# Constructor Approach with SharedArray

If we pass multiple datasets from different SharedArray instances to a constructor in the K6Runner, are there any known issues or limitations? I haven’t encountered any problems so far, but I want to ensure this is a safe practice in K6.

# Best Practices for Class-Based K6 Scripts

Are there any best practices for using a class-based approach in K6 scripts for managing metrics and modularizing test execution logic?

Would appreciate any insights or recommendations for structuring large-scale k6 test scripts in a way that avoids redundancy while maintaining performance and accuracy. Thanks in advance.

nextjs middleware not running

I am building a dashboard in nextjs, using supabase for user auth. I am trying to protect my /dashboard route if a user is not signed in. the supabase boilerplate has checks for if the user is not signed in, but i can still access /dashboard by typing it in the url even if a user is not signed in. In my middleware.ts and /utils/supabase/middleware.ts, i am logging just to see if the middleware is being hit, but nothing is being logged. Below is my project structure, my middleware.ts, and my /utils/supabase/middleware.ts.

project structure

// src/app/utils/supabase/middleware.ts

import { createServerClient } from '@supabase/ssr'
import { NextResponse, type NextRequest } from 'next/server'
import { redirect } from 'next/navigation'

export async function updateSession(request: NextRequest) {
  console.log("Middleware running for:", request.nextUrl.pathname);
  let supabaseResponse = NextResponse.next({
    request,
  })

  const supabase = createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        getAll() {
          return request.cookies.getAll()
        },
        setAll(cookiesToSet) {
          cookiesToSet.forEach(({ name, value, options }) => request.cookies.set(name, value))
          supabaseResponse = NextResponse.next({
            request,
          })
          cookiesToSet.forEach(({ name, value, options }) =>
            supabaseResponse.cookies.set(name, value, options)
          )
        },
      },
    }
  )

  // Do not run code between createServerClient and
  // supabase.auth.getUser(). A simple mistake could make it very hard to debug
  // issues with users being randomly logged out.

  // IMPORTANT: DO NOT REMOVE auth.getUser()

  const {
    data: { user },
  } = await supabase.auth.getUser()

  **if (
    !user &&
    !request.nextUrl.pathname.startsWith('/login') &&
    !request.nextUrl.pathname.startsWith('/dashboard')
  ) {
    // no user, potentially respond by redirecting the user to the login page
    const url = request.nextUrl.clone()
    url.pathname = '/login'
    return NextResponse.redirect(url)
  }**

  // IMPORTANT: You *must* return the supabaseResponse object as it is.
  // If you're creating a new response object with NextResponse.next() make sure to:
  // 1. Pass the request in it, like so:
  //    const myNewResponse = NextResponse.next({ request })
  // 2. Copy over the cookies, like so:
  //    myNewResponse.cookies.setAll(supabaseResponse.cookies.getAll())
  // 3. Change the myNewResponse object to fit your needs, but avoid changing
  //    the cookies!
  // 4. Finally:
  //    return myNewResponse
  // If this is not done, you may be causing the browser and server to go out
  // of sync and terminate the user's session prematurely!

  

  return supabaseResponse
}
//src/app/middleware.ts

import { type NextRequest } from 'next/server'
import { updateSession } from "./utils/supabase/middleware";

export async function middleware(request: NextRequest) {
  console.log("middleware is running")
  return await updateSession(request)
}

export const config = {
  matcher: [
    /*
     * Match all request paths except for the ones starting with:
     * - _next/static (static files)
     * - _next/image (image optimization files)
     * - favicon.ico (favicon file)
     * Feel free to modify this pattern to include more paths.
     */
    '/((?!_next/static|_next/image|favicon.ico|.*\.(?:svg|png|jpg|jpeg|gif|webp)$).*)',
  ],
}

Nashorn: Execute script with anonymous root-level function and subfunctions

I’m attempting to put together a basic test framework for a number of JS scripts that I’ve been provided. These all run on nashorn (JDK 11) without issue in their original habitat. I’m attempting to load and run the scripts myself, and execute tests by comparing input and output.

The issue I’m having is with the format of the scripts. While I know they can be run via Nashorn, I don’t have access to the source code that does it, and I’m having a problem grabbing references to all of the functions/methods I need. The source files follow this pattern:

(function () {
    "use strict";

    print("Canary: Here I am inside the root level function");

    function writeLogEntry(message) {
        echo(message);
    }

    return function main(data) {
        print("Canary: Here I am inside main");
        writeLogEntry(data.someVitalStat());
        return true;
    };
})();

I do not have the option to change the source files – I have to use them as-is. The issue has been with getting a reference to functions other than main. I was able to get a ref for main in the following way, which required two passes:

String scriptTextRaw = new String(Files.readAllBytes(Paths.get(location)), StandardCharsets.UTF_8);
var ee = new ScriptEngineManager().getEngineByName("Nashorn");
scriptTextRaw = "var mainfunc = " + scriptTextRaw;
ee.eval(scriptTextRaw);
Object mainRef = ee.get("mainfunc");
// Second eval pass
ee.eval(mainRef.toString());
var mainInvocable = (ScriptObjectMirror)ee.get("main");

// Invoke main function
Object mainResult = mainInvocable.call(myDataObject);

I’m open to better ways to get that main reference. However, the bigger problem is that the anonymous functions encapsulated in the script aren’t accessible. Running the above code, I get:

Exception in thread "main" <eval>:3 ReferenceError: "writeLogEntry" is not defined. 

I’ve tried a few things, e.g.:

Object writeLogEntryRef = (ScriptObjectMirror)ee.get("writeLogEntry"); 

(Both after the first and second eval pass)

But this is unsuccessful. I’ve also paused the program in the debugger after each eval pass to examine the returned object, but I don’t find any references to the other methods.

Can anyone suggest an approach to parsing and running a script formatted like this one? All input is appreciated.

Fixing Header with JavaScript After Scrolling Past 100vh Header:

I am trying to make a header that stays fixed when I scroll down, but it only goes until the end of the header, which is set to 100vh. Does anyone have any idea how I can solve this without stopping using min-height?

I tried using JS to replace the class with fixed so that it only fixes after scrolling past the header, but without success.

document.addEventListener('DOMContentLoaded', function() {
  const nav = document.getElementById('mainNav'); // Certifique-se de que o ID está correto
  const header = document.querySelector('.header');

  function handleScroll() {
    const headerHeight = header.offsetHeight;
    const scrollPosition = window.scrollY;

    if (scrollPosition > headerHeight) {
      nav.classList.add('fixed');
    } else {
      nav.classList.remove('fixed');
    }
  }

  window.addEventListener('scroll', handleScroll);
});
.header {
  min-height: 100vh;
  width: 100%;
  background-image: linear-gradient(rgba(4, 9, 30, 0.7), rgba(4, 9, 30, 0.7)), url('img/background-main.jpg');
  background-position: center;
  background-size: cover;
  text-align: center;
  color: #fff;
  position: relative;
}

nav {
  display: flex;
  padding: 2% 6%;
  justify-content: space-between;
  align-items: center;

  z-index: 1000;
}

nav.fixed {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 1001;
}

nav img {
  width: 200px;
}

.nav-links {
  flex: 1;
  text-align: right;
}

.nav-links ul li {
  list-style: none;
  display: inline-block;
  padding: 8px 12px;
  position: relative;

}

.nav-links ul li a {
  color: #fff;
  text-decoration: none;
  font-size: 16px;
  font-weight: bold;
}

.nav-links ul li::after {
  content: '';
  width: 0%;
  height: 2px;
  background: #1b99ca;
  display: block;
  margin: auto;
  transition: 0.5s;
}

.nav-links ul li:hover::after {
  width: 100%;
}

.nav-links ul li:hover>ul.dropdown {
  display: block;
}

ul li ul.dropdown {
  position: absolute;
  top: 100%;
  left: 0;
  background-color: rgba(41, 145, 255, 0.425);
  z-index: 999;
  display: none;
  min-width: 130px;
  border-radius: 5px;
  box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.2);
}

ul li ul.dropdown li {
  display: block;
  padding: 10px;
}

ul li ul.dropdown li a {
  color: #fff;
  text-decoration: none;
  display: block;
  font-size: 14px;
  font-weight: 600;
  transition: 0.3s;
  text-align: left;
}

ul li ul.dropdown li:hover {
  background: #003580;
}

.text-box {
  width: 90%;
  color: #fff;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  text-align: center;
}

.text-box h1 {
  font-size: 62px;
}

text-box p {
  margin: 10px 0 40px;
  font-size: 14px;
  color: #fff;
}

.hero-btn {
  display: inline-block;
  text-decoration: none;
  color: #fff;
  border: 1px solid #fff;
  padding: 12px 34px;
  font-size: 13px;
  background: transparent;
  position: relative;
  cursor: pointer;
  transition: 0.6s;
  margin-top: 15px;
  border-radius: 5px;
}

.hero-btn:hover {
  background-color: #1b99ca;
  border: 1px solid #1b99ca;
  transition: 1s;
}

nav .fa {
  display: none;
}

nav .fa-bars {
  font-size: 25px;
}
<link href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="index.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css" integrity="sha512-Evv84Mr4kqVGRNSgIGL/F/aIDqQb7xQ2vcrdIwxfjThSH8CSR7PBEakCr51Ck+w+/U6swU2Im1vVX0SVk9ABhg==" crossorigin="anonymous" referrerpolicy="no-referrer">

<section class="header">
  <nav id="mainNav" class="mainNav">
    <div class="logo">
      <a href="index.html"> <img src="img/logo-padrao.png" alt="logo da JL Marine"></a>
    </div>
    <div class="nav-links" id="navLinks">
      <i class="fa fa-times" onclick="hideMenu()"></i>
      <ul class="ul">
        <li><a href="index.html">Início</a></li>
        <li>
          <a href="#">Sobre</a>
          <ul class="dropdown">
            <li><a href="sobre.html">A Empresa</a></li>
            <li><a href="equipe.html">Equipe</a></li>
          </ul>
        </li>
        <li>
          <a href="services/services.html">Serviços</a>
          <ul class="dropdown">
            <li><a href="services/marine.html">Marine</a></li>
            <li><a href="services/log.html">Logística</a></li>
            <li><a href="services/desp-adua.html">Despacho Aduaneiro</a></li>
            <li><a href="services/comex.html">Comex</a></li>
            <li><a href="services/outros.html">Outros</a></li>
          </ul>
        </li>
        <li><a href="contacts.html">Contato</a></li>
      </ul>
    </div>
    <i class="fa fa-bars" onclick="showMenu()"></i>
  </nav>
  <div class="text-box">
    <h1>Conheça a JL Marine!</h1>
    <p>Confiabilidade & Excelência</p>
    <a href="sobre.html" class="hero-btn">Saiba Mais</a>
  </div>
</section>

What’s the difference between setting object properties recursively and Object.assign? [duplicate]

So I wrote up this helper function when I first started my project to help update objects that I would get from an API.

export const setValRecursive = (currObj: any, newObj: any) => {
  Object.keys(newObj).forEach((k: any) => {
    if (typeof newObj[k] == "object" && currObj[k] != null) {
      setValRecursive(newObj[k], currObj[k]);
    } else {
      currObj[k] = newObj[k];
    }
  });
  return currObj;
};

Recently, I forgot about that helper function and found and started using Object.assign in other components to help merge together different objects that stored CSS variables.

Now that’s I’ve re-looked at an old component and saw it again, I was curious to know what the difference between the two functions, is there performance issues, are there reference issues, should I switch to using Object.assign or is there no problem using either?

Export toast doesn’t exist in target module – using heroui/toast

Background:

I am trying to add Toast notifications to my nextjs application. I followed the official documentation here: https://www.heroui.com/docs/components/toast

providers.jsx:

import {NextUIProvider} from '@nextui-org/react'
import {useRouter} from "next/navigation";
import {ThemeProvider as NextThemesProvider} from "next-themes";
import {HeroUIProvider} from "@heroui/react";
import {ToastProvider} from "@heroui/toast";

export function Providers({children}) {

    const router = useRouter()

    return (
        <NextUIProvider navigate={router.push}>
            <NextThemesProvider attribute="class" defaultTheme="dark">
                <HeroUIProvider>
                    <ToastProvider toastProps={{
                        radius: "full",
                        color: "primary",
                        variant: "bordered",
                        timeout: 1500,
                        hideIcon: true,
                        classNames: {
                            closeButton: "opacity-100 absolute right-4 top-1/2 -translate-y-1/2",
                        },
                    }} />
                    {children}
                </HeroUIProvider>
            </NextThemesProvider>
        </NextUIProvider>
    )
}

layout.js:

export default function RootLayout({children}) {
    return (
        <html lang="en" suppressHydrationWarning>
        <head title="Hydra Server">
            <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
            <title>Hydra Server</title>
        </head>
        <body
            className={`${geistSans.variable} ${geistMono.variable} antialiased`}
        >
        <Providers>
            <main className="bg-gradient-to-br from-black via-gray-700 to-green-900">
                {children}
            </main>
        </Providers>
        </body>
        </html>
    );
}

Example of adding a Toast:

import {addToast} from "@heroui/toast";

...

    function onError(error) {
        addToast({
            title: "Error",
            description: error.statusText
        });
        setIsLoading(false)
    }

The problem:

When the page is compiled (I’m currently using npm run dev for testing), I get the following errors:

 ⨯ ./node_modules/@heroui/toast/dist/chunk-A3E4DQTR.mjs:5:1
Export toast doesn't exist in target module
  3 | // src/use-toast.ts
  4 | import { mapPropsVariants, useProviderContext } from "@heroui/system";
> 5 | import { toast as toastTheme } from "@heroui/theme";
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  6 | import { useDOMRef } from "@heroui/react-utils";
  7 | import { clsx, dataAttr, isEmpty, objectToDeps } from "@heroui/shared-utils";
  8 | import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";

The export toast was not found in module [project]/node_modules/@heroui/theme/dist/index.mjs [app-client] (ecmascript) <exports>.
Did you mean to import tabs?
All exports of the module are statically known (It doesn't have dynamic exports). So it's known statically that the requested export doesn't exist.


./node_modules/@heroui/toast/dist/chunk-RJHHOZ5N.mjs:11:1
Export toastRegion doesn't exist in target module
   9 | import { useHover } from "@react-aria/interactions";
  10 | import { mergeProps } from "@react-aria/utils";
> 11 | import { toastRegion } from "@heroui/theme";
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  12 | import { jsx } from "react/jsx-runtime";
  13 | function ToastRegion({
  14 |   toastQueue,

The export toastRegion was not found in module [project]/node_modules/@heroui/theme/dist/index.mjs [app-client] (ecmascript) <exports>.
Did you mean to import listboxSection?
All exports of the module are statically known (It doesn't have dynamic exports). So it's known statically that the requested export doesn't exist.

Is this a bug or a problem with my setup?

Image is getting cropped using html-to-image library

I am making a dashboard website where I have a canvas having a pie chart as in image below.

screenshot of dashboard

I am exporting image of canvas using html-to-image library and as pdf using jspdf library using the following code.

useEffect(() => {
    if (pageSettings.callForDownload) {
      const input = document.getElementById(
        "GraphAreaToDownload"
      ) as HTMLElement;

      const d = new Date();
      const id = `${tabTileProps.selectedTabName}_${d.getDate()}${d.getMonth() + 1
        }${d.getFullYear()}:${d.getHours()}${d.getMinutes()}${d.getSeconds()}`;
      if (pageSettings.downloadType === "pdf") {
           // exporting for pdf
        html2canvas(input).then((canvas) => {
          const imageData = canvas.toDataURL("image/png");

          const pdf = new jsPDF(
            pageSettings.SelectedOrientation,
            "px",
            pageSettings.selectedFormat
          );
          var width = pdf.internal.pageSize.getWidth();
          var height = pdf.internal.pageSize.getHeight();
          const heightAndWidth = getHeightAndWidth(height, width);
          pdf.addImage(
            imageData,
            "JPEG",
            pageSettings.left_margin,
            pageSettings.top_margin,
            heightAndWidth.width,
            heightAndWidth.height
          );
          pdf.save(`${id}`);
          resetPageSettings();
        });
      } else {
           //exporting for image
        toPng(input, { cacheBust: true })
          .then((dataUrl: any) => {
            const link = document.createElement("a");
            link.download = `${id}`;
            link.href = dataUrl;
            link.click();
            resetPageSettings();
          })
          .catch((err: any) => {
            Logger("error", "", err);
          });
      }
    }
  }, [pageSettings.callForDownload]);

Exporting as pdf works fine whereas pie chart is getting cropped in exporting as image.
Below are the exported outcomes.

exported as image

exported as pdf

I tried tinkering with padding and margin but the image was still cropped. I expect the export as an image to show full pie chart similar to export as pdf.

Why does throwing an error in a not-yet-awaited async function call terminate node.js?

async function delay(ms) {
    return new Promise(r=>setTimeout(r,ms))
}
async function fail(ms){
    await delay(ms)
    throw new Error("kek");
}
async function ok(ms){
    await delay(ms)
    return 1;
}
async function start() {
    try{

        let fail_p = fail(500);
        let ok_p = ok(1000);
        console.log(await ok_p)
        console.log(await fail_p)
    }
    catch(e){
        console.log("ERR")
    }
}
start().then(()=>console.log("Finish"))

In the browser I get what I expected.

1
ERR
Finish

But in nodejs the application just crashes with the error “kek”

/path/test.js:6
    throw new Error("kek");
          ^

Error: kek
    at fail (/path/test.js:6:11)

Node.js v22.14.0

Is this a nodejs bug?
And how can I achieve the same behavior with nodejs?

Why does this code behave differently in node.js and browser?

async function delay(ms) {
    return new Promise(r=>setTimeout(r,ms))
}
async function fail(ms){
    await delay(ms)
    throw new Error("kek");
}
async function ok(ms){
    await delay(ms)
    return 1;
}
async function start() {
    try{

        let fail_p = fail(500);
        let ok_p = ok(1000);
        console.log(await ok_p)
        console.log(await fail_p)
    }
    catch(e){
        console.log("ERR")
    }
}
start().then(()=>console.log("Finish"))

In the browser I get what I expected.

1
ERR
Finish

But in nodejs the application just crashes with the error “kek”

/path/test.js:6
    throw new Error("kek");
          ^

Error: kek
    at fail (/path/test.js:6:11)

Node.js v22.14.0

Is this a nodejs bug?
And how can I achieve the same behavior with nodejs?

Konva.js – how to make only Konva objects interactive instead of the entire layer

I’m using Konva.js to draw interactive shapes on top of an existing HTML element on the page, like this:

<div id="mainContainer">
    <div id="otherStuff"></div>
    <div id="konvaContainer"></div>
</div>

where both inner divs are set to position: absolute; so they fill the container and overlap each other.

I’m then initializing Konva and drawing a shape like this:

const stage = new Konva.Stage({
    container: konvaContainer,
    width: konvaContainer.clientWidth,
    height: konvaContainer.clientHeight,
});

const layer = new Konva.Layer();
stage.add(layer);

const circle = new Konva.Circle({
    radius: 50,
    fill: 'red',
    draggable: true,
    x: stage.width() / 2,
    y: stage.height() / 2,
});
layer.add(circle);

The behavior I’m looking for is for the circle I’ve drawn to respond to mouse interactions (click, drag, etc.), but everywhere else on the stage (where there are no shapes) should be “transparent” to the mouse. In other words: the events should pass through and hit the underlying otherStuff div.

Is this possible?

when adding script as a ajax resonse all kinds of erorrs [closed]

I have 2 pages html and php. where a table is selected based on which option then a table and a script for that table is loaded. When adding the script in an php echo response. I get( Undefined variable $btn in) only after adding the 3rd section im assuming it has something to do with the response or the ways its inserted. Can anyone tell me what wrong? or guide me? chatgpt dont know, ur my last hope…

Why does the code stop working and error out after adding the 3rd section of code?
Once the code is working i will secure it with pdo and prepared statements lets focus on the question

// This function is user to insert data in database
    $('#btnSaveAction').on('click', function () {
        params = ''
        $('td[contentEditable="true"]').each(function () {
            if ($(this).text() != '') {
                if (params != '') {
                    params += '&';
                }
                params += $(this).data('id') + '=' + $(this).text();
            }
        });
        if (params != '') {
             alert(params);// santize data
            $.ajax({
                url: 'function.php',
                type: 'POST',
                data: params,
                success: function (response) {
                    $('#ajax-response').append(response);
                    $('td[contentEditable="true"]').text('');
                }
            });
            return false;
        }
    });
    

    // This function is used for edit the row to make it editable
    $('#tbl').on('click', '.edit', function () {
        $('#tbl').find('.save, .cancel').hide();
        $('#tbl').find('.edit').show();
        $(this).hide().siblings('.save, .cancel').show();

        $(this).closest('td').siblings().each(
            function () {
                var inp = $(this).find('input');
                if (inp.length) {
                    $(this).text(inp.val());
                } else {
                    var t = $(this).text();
                    $(this).attr('contentEditable', 'true');
                }
            });
    });

    // This function is used for edit the row to make it editable
    $('#tbl').on('click', '.cancel', function () {
        $('#tbl').find('.save, .cancel').hide();
        $(this).hide().siblings('.edit').show();
        $(this).closest('td').siblings().each(
            function () {
                $(this).attr('contentEditable', 'false');
                location.reload();
            });
    });

   

and once u add this its starts to error but it all looks correct

// This function is used for saving the edit data in database
$('#tbl').on('click', '.save', function () {
    var $btn = $(this);
    $('#tbl').find('.save, .cancel').hide();
    $btn.hide().siblings('.edit').show();
    params = '';
    var id = $btn.data('id');
    $(this).closest('td').siblings().each(function () {
        $(this).attr('contentEditable', 'false');
        if (params != '') {
            params += '&';
        }
        params += $(this).data('id') + '=' + $(this).text();
    });
    params += '&id' + '=' + id;
       alert(params);// santize data
    if (params != '') {
        $.ajax({
            url: 'function.php',
            type: 'POST',
            data: params,
            success: function (response) {
                $('#ajax-response').append(response);
                // $('td[contentEditable='true']').text('');
            }
        });
        return false;
    }
});
   
// this ajax is using for deleting the row 
$('#tbl').on('click', '.del', function () {
    var el = this;

    var deleteid = $(this).data('id');

    console.log(deleteid);

    var confirmalert = confirm('Are you sure?');
    if (confirmalert == true) {
        $.ajax({
            url: 'function.php',
            type: 'POST',
            data: {
                id: deleteid,
                action: 'del'
            },
            success: function (response) {

                if (response == 1) {
                    // Remove row from HTML Table
                    $(el).closest('tr').css('background', 'tomato');
                    $(el).closest('tr').fadeOut(800, function () {
                        $(this).remove();
                    });
                } else {
                    alert('Invalid ID.');
                }

            }
        });
    }

});


 

i have tried these

// using this
$("#ajax-response").append(response);

//but can also use this
var maincontent = document.getElementById("ajax-response");
maincontent.innerHTML = response;
//or this
$.getScript('asset/custom.js'); // Execute the JavaScript file

this dont work either ,neither does placing it before or after the html

$('script', response).each(function() {
            var script = document.createElement('script');
            script.type = 'text/javascript';
            script.text = this.innerHTML;
            document.body.appendChild(script);

html

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Manager combined Console</title>
    <link rel="stylesheet" href="asset/style11.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">

    <style>
        #btnSaveAction {
            display: inline-block;
            color: #444;
            border: 1px solid #CCC;
            background: #DDD;
            box-shadow: 0 0 5px -1px rgba(0, 0, 0, 0.2);
            cursor: pointer;
            vertical-align: middle;
            max-width: 100px;
            padding: 5px;
            text-align: center;
        }
    </style>

    <script src="https://code.jquery.com/jquery-1.10.2.js"></script>
    <script>
        // Load table data when a table is selected
        $(document).on('change', '#tableSelect', function() {
            var table = $(this).val();
            if (table) {
                $.ajax({
                    url: 'function77.php',
                    type: 'GET',
                    data: { table: table },
                    success: function(response) {
                        // Replace the current content with the new response
                        $("#tableData").html(response);
                        
                        
                        $('script', response).each(function() {
            var script = document.createElement('script');
            script.type = 'text/javascript';
            script.text = this.innerHTML;
            document.body.appendChild(script);
        });
                        
                        
                    }
                });
            } else {
                $('#tableData').html('');
            }
        });

    </script>
</head>

<body>

    <h1>Business Console</h1>

    <!-- Dropdown to select table -->
    <select id="tableSelect">
        <option value="">Select Business</option>
        <option value="maploc">Business Manager</option>
        <option value="reviews">1-Location1</option>
        <option value="table3">2-Location2</option>
        <option value="table4">3-Location3</option>
        <option value="table5">4-Location4</option>
        <option value="table6">5-Location5</option>
        <option value="table7">6-Location6</option>
        <option value="table8">7-Location7</option>
        <option value="table9">8-Location8</option>
        <option value="table10">9-Location9</option>
        <option value="table11">10-Location10</option>
    </select>

    <div id="tableData">
        <!-- Table data will be inserted here dynamically -->
    </div>
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
</body>

</html>

and the function77.php

<?php
require_once "dbcontroller555.php";

// Initialize DBController instance
$db_handle = new DBController();

// Function to validate and clean input data
function cleanInput($data) {
    // Trim whitespaces and sanitize input to prevent XSS
    return htmlspecialchars(trim($data));
}

// Check if table is selected via GET request
if (isset($_GET['table'])) {
    $table = $_GET['table'];

    try {
        
    
        // Fetch rows from the selected table
        $sql = "SELECT * FROM $table ORDER BY CAST(id AS UNSIGNED) DESC";
        $stmt = $db_handle->getConnection()->prepare($sql);
        $stmt->execute();
        $productResult = $stmt->fetchAll(PDO::FETCH_ASSOC);





        // Check if any rows are returned
       if (!empty($productResult)) {
    echo "
    

<script>


// This function is user to insert data in database
    $('#btnSaveAction').on('click', function () {
        params = ''
        $('td[contentEditable="true"]').each(function () {
            if ($(this).text() != '') {
                if (params != '') {
                    params += '&';
                }
                params += $(this).data('id') + '=' + $(this).text();
            }
        });
        if (params != '') {
             alert(params);// santize data
            $.ajax({
                url: 'function.php',
                type: 'POST',
                data: params,
                success: function (response) {
                    $('#ajax-response').append(response);
                    $('td[contentEditable="true"]').text('');
                }
            });
            return false;
        }
    });
    

    // This function is used for edit the row to make it editable
    $('#tbl').on('click', '.edit', function () {
        $('#tbl').find('.save, .cancel').hide();
        $('#tbl').find('.edit').show();
        $(this).hide().siblings('.save, .cancel').show();

        $(this).closest('td').siblings().each(
            function () {
                var inp = $(this).find('input');
                if (inp.length) {
                    $(this).text(inp.val());
                } else {
                    var t = $(this).text();
                    $(this).attr('contentEditable', 'true');
                }
            });
    });

    // This function is used for edit the row to make it editable
    $('#tbl').on('click', '.cancel', function () {
        $('#tbl').find('.save, .cancel').hide();
        $(this).hide().siblings('.edit').show();
        $(this).closest('td').siblings().each(
            function () {
                $(this).attr('contentEditable', 'false');
                location.reload();
            });
    });

    // This function is used for saving the edit data in database
    $('#tbl').on('click', '.save', function () {
        var $btn = $(this);
        $('#tbl').find('.save, .cancel').hide();
        $btn.hide().siblings('.edit').show();
        params = '';
        var id = $btn.data('id');
        $(this).closest('td').siblings().each(function () {
            $(this).attr('contentEditable', 'false');
            if (params != '') {
                params += '&';
            }
            params += $(this).data('id') + '=' + $(this).text();
        });
        params += '&id' + '=' + id;
           alert(params);// santize data
        if (params != '') {
            $.ajax({
                url: 'function.php',
                type: 'POST',
                data: params,
                success: function (response) {
                    $('#ajax-response').append(response);
                    // $('td[contentEditable='true']').text('');
                }
            });
            return false;
        }
    });
   
    // this ajax is using for deleting the row 
    $('#tbl').on('click', '.del', function () {
        var el = this;

        var deleteid = $(this).data('id');

        console.log(deleteid);

        var confirmalert = confirm('Are you sure?');
        if (confirmalert == true) {
            $.ajax({
                url: 'function.php',
                type: 'POST',
                data: {
                    id: deleteid,
                    action: 'del'
                },
                success: function (response) {

                    if (response == 1) {
                        // Remove row from HTML Table
                        $(el).closest('tr').css('background', 'tomato');
                        $(el).closest('tr').fadeOut(800, function () {
                            $(this).remove();
                        });
                    } else {
                        alert('Invalid ID.');
                    }

                }
            });
        }

    });



</script>

<script src='https://code.jquery.com/jquery-1.10.2.js'></script>

    <div class='container'>
        <div id='add-product'>
            <div class='txt-heading'>Add Location</div>
            <p id='statusMessage' style='color: green; display: none;'></p>

            <table cellpadding='10' cellspacing='1' border='1'>
                <tbody>
                    <tr>
                        <th><strong>Name</strong></th>
                        <th><strong>Manager</strong></th>
                        <th><strong>Address</strong></th>
                        <th><strong>Phone</strong></th>
                        <th><strong>Fax</strong></th>
                        <th><strong>Hours</strong></th>
                    </tr>
                    <tr>
                        <td contentEditable='true' data-id='Name'></td>
                        <td contentEditable='true' data-id='Manager'></td>
                        <td contentEditable='true' data-id='Address'></td>
                        <td contentEditable='true' data-id='Telephone' style='text-align:right;'></td>
                        <td contentEditable='true' data-id='Fax'></td>
                        <td contentEditable='true' data-id='Hours' style='text-align:right;'></td>
                    </tr>
                </tbody>
            </table>
            <br>
            <div id='btnSaveAction'>Insert</div>
        </div>
        <br>
        <div id='list-product'>
            <div class='txt-heading'>Products</div>
            <table id='tbl' cellpadding='10' cellspacing='1' border='1'>
                <tbody id='ajax-response'>
                    <tr>
                        <th><strong>Name</strong></th>
                        <th><strong>Manager</strong></th>
                        <th><strong>Address</strong></th>
                        <th><strong>Phone</strong></th>
                        <th><strong>Fax</strong></th>
                        <th><strong>Hours</strong></th>
                        <th><strong>Actions</strong></th>
                    </tr>
    ";

    foreach ($productResult as $row) { 
        echo "<tr>
                <td data-id='Name'>" . htmlspecialchars($row['Name']) . "</td>
                <td data-id='Manager'>" . htmlspecialchars($row['Manager']) . "</td>
                <td data-id='Address'>" . htmlspecialchars($row['Address']) . "</td>
                <td data-id='Telephone'>" . htmlspecialchars($row['Telephone']) . "</td>
                <td data-id='Fax'>" . htmlspecialchars($row['Fax']) . "</td>
                <td data-id='Hours'>" . htmlspecialchars($row['Hours']) . "</td>
                <td>
                
      
<button class='edit btn btn-success'><i class='fa fa-pencil' aria-hidden='true'></i></button>

<button type='button' id='edit' class='save btn btn-success' data-id='" . htmlspecialchars($row['id']) . "'
    style='display: none'><i class='fa fa-check' aria-hidden='true'></i></button>

<button type='button' id='edit' class='cancel btn btn-danger' style='display: none'><i class='fa fa-times'
        aria-hidden='true'></i></button>

<button class='del btn btn-warning' data-id='" . htmlspecialchars($row['id']) . "'><i class='fa fa-trash'
        aria-hidden='true'></i></button>
                
                
                
                
        
                    
                    
                    
                </td>
            </tr>";
    }

    echo "
                </tbody>
            </table>
        </div>
    </div>
    ";
} else {
    echo "No data found in this table.";
}

        


    } catch (PDOException $e) {
        echo "Error fetching data: " . $e->getMessage();
    }
    
    
    
    
    
    if (isset($_POST['Name'])) {

    
   $id = "";
    $Name = "";
    $Manager = "";
    $Address = "";
    $Telephone = "";
    $Fax = "";
    $Hours = "";


     if (!empty($_POST["id"])) {
        $id = $db_handle->cleanData($_POST["id"]);
    }
 
    if (!empty($_POST["Name"])) {
        $Name = $db_handle->cleanData($_POST["Name"]);
    }
    if (!empty($_POST["Manager"])) {
        $Manager = $db_handle->cleanData($_POST["Manager"]);
    }
    if (!empty($_POST["Address"])) {
        $Address = $db_handle->cleanData($_POST["Address"]);
    }
    if (!empty($_POST["Telephone"])) {
        $Telephone = $db_handle->cleanData($_POST["Telephone"]);
    }
  if (!empty($_POST["Fax"])) {
        $Fax = $db_handle->cleanData($_POST["Fax"]);
    }
      if (!empty($_POST["Hours"])) {
        $Hours = $db_handle->cleanData($_POST["Hours"]);
    }
    if (isset($_POST['id'])) {
        $sql = "UPDATE
        maploc
    SET
        Name = '$Name',
        Manager = '$Manager',
        Address = '$Address',
        Telephone = '$Telephone',
        Fax = '$Fax',
        Hours = '$Hours'
    WHERE
        maploc.id = $id";

    } else {
        $sql = "INSERT INTO
    maploc (Name,Manager,Address,Telephone,Fax,Hours)
          VALUES ('" . $Name . "','" . $Manager . "','" . $Address . "','" . $Telephone . "','" . $Fax . "','" . $Hours . "')";
    }
    
    

    $id = $db_handle->executeInsert($sql);

    if (!empty($id)) {
        
  $sql = "SELECT * FROM maploc ORDER BY CAST(id AS UNSIGNED) DESC";
        $productResult = $db_handle->readData($sql);
        
    }
    ?>
    
    
    
<?php
if (!empty($productResult)) {
    
?>




<tr>
    <td data-id="Name"><?php echo $productResult[0]["Name"]; ?></td>
    <td data-id="Manager"><?php echo $productResult[0]["Manager"]; ?></td>
      <td data-id="Address"><?php echo $productResult[0]["Address"]; ?></td>
    <td data-id="Telephone"><?php echo $productResult[0]["Telephone"]; ?></td>
     <td data-id="Fax"><?php echo $productResult[0]["Fax"]; ?></td>
         <td data-id="Hours"><?php echo $productResult[0]["Hours"]; ?></td>
    <td>
        <button class="edit btn btn-success"><i class="fa fa-pencil" aria-hidden="true"></i></button>

        <button type="button" id="edit" class="save btn btn-success" data-id="<?php echo $productResult[0]["id"]; ?>"
            style="display: none"><i class="fa fa-check" aria-hidden="true"></i></button>

        <button type="button" id="edit" class="cancel btn btn-danger" style="display: none"><i class="fa fa-times"
                aria-hidden="true"></i></button>

        <button class="del btn btn-warning" data-id="<?php echo $productResult[0]["id"]; ?>"><i class="fa fa-trash"
                aria-hidden="true"></i></button>
    </td>
</tr>

<?php
}
}
//echo '<script>';
//echo 'console.log("it ran");';
//echo '</script>';



?>


<?php  
$id = 0;
if (isset($_POST['action']) == 'del') {
    $id = $db_handle->cleanData($_POST["id"]);
}
if ($id > 0) {




    // Check record exists
    $sql = "SELECT * from maploc WHERE id = '$id' ";
    $productResult = $db_handle->readData($sql);

    if ($productResult > 0) {
        // Delete record
        $query = "DELETE FROM maploc WHERE id=" . $productResult[0]['id'];
        $db_handle->executeInsert($query);
        echo 1;
        exit;
    } else {
        echo 0;
        exit;
    }
}
  
}//isset(GET['table']

//if ($_SERVER['REQUEST_METHOD'] === 'POST') {

?>

List is not being fully displayed [closed]

when I click run on my program the list is sorted correctly but when it tries to display the filtered version of the list it cycles through all of the items in the list and lands on the last one.
The code that I have

I’ve tried using n but I can never figure that out as when I use it without quotes it gives an error and when I use it with quotes it just displays it with the text. When the code is ran it should filter the lists and then display all the items in the filtered version of the list.

Error while loading remote module in angular module federation. TypeError: Cannot read properties of undefined (reading ‘ɵmod’)

This query is regarding loading remote module in host (shell) application.
I am using Angular 16.2.12.

Code to load remote module is as below:

 const routes: Routes = [

    { 
    path: 'cat', 
   
    loadChildren: () => {
      return loadRemoteModule( {
        
        remoteEntry: REMOTE_MODULE,
        remoteName: "CatModule",
        exposedModule: "./CatModule"
      }).then( m=> m.CatModule).catch( err => console.log(err))
    }
  }];

however currently getting error while loading module in host app (shell), here are error details

ERROR Error: Uncaught (in promise): TypeError: Cannot read properties of undefined (reading ‘ɵmod’)

TypeError: Cannot read properties of undefined (reading 'ɵmod')
    at getNgModuleDef (core.mjs:2055:29)
    at new NgModuleRef (core.mjs:22683:29)
    at NgModuleFactory.create (core.mjs:22721:16)
    at router.mjs:4160:40
    at map.js:7:37
    at OperatorSubscriber._next (OperatorSubscriber.js:13:21)
    at OperatorSubscriber.next (Subscriber.js:31:18)
    at subscribe.innerComplete (mergeInternals.js:25:28)
    at OperatorSubscriber._next (OperatorSubscriber.js:13:21)
    at OperatorSubscriber.next (Subscriber.js:31:18)
    at getNgModuleDef (core.mjs:2055:29)
    at new NgModuleRef (core.mjs:22683:29)
    at NgModuleFactory.create (core.mjs:22721:16)
    at router.mjs:4160:40
    at map.js:7:37
    at OperatorSubscriber._next (OperatorSubscriber.js:13:21)
    at OperatorSubscriber.next (Subscriber.js:31:18)
    at subscribe.innerComplete (mergeInternals.js:25:28)
    at OperatorSubscriber._next (OperatorSubscriber.js:13:21)
    at OperatorSubscriber.next (Subscriber.js:31:18)
    at resolvePromise (zone.js:1193:31)
    at resolvePromise (zone.js:1147:17)
    at zone.js:1260:17
    at _ZoneDelegate.invokeTask (zone.js:402:31)
    at core.mjs:10757:55
    at AsyncStackTaggingZoneSpec.onInvokeTask (core.mjs:10757:36)
    at _ZoneDelegate.invokeTask (zone.js:401:60)
    at Object.onInvokeTask (core.mjs:11070:33)
    at _ZoneDelegate.invokeTask (zone.js:401:60)
    at Zone.runTask (zone.js:173:47)

Help is appreciated. Thanks.

Issue with Rebuilding Hidden Inputs After Drag‐and‐Drop Sorting Mixed “Links” and “Embeds” Using Sortable.js

I’m experiencing an issue on my dashboard where users can reorder a mixed list of items—some of which are “links” and others “embeds”—using Sortable.js. After reordering, I update the data-index attributes for each item and then rebuild the hidden input fields used for form submission. However, after saving the page, I sometimes find that one of the items (often a link) appears empty (its values are missing).

I suspect the problem lies in the way I re-index and rebuild the hidden inputs for the mixed content. In my implementation, I update the indexes for links and embeds separately but then rebuild the hidden fields using a unified loop over all .link-item elements. This may lead to an index mismatch between the rebuilt hidden fields and the actual order of items.

Below are the relevant parts of my code:

Javascript:

if (linksContainerEl) {
  new Sortable(linksContainerEl, {
    handle: '.drag-handle',
    animation: 400,
    onEnd: function () {
      // Update each item's data-index based on type
      let linkIndex = 0;
      let embedIndex = 0;
      $('#links-container .link-item').each(function () {
        const type = $(this).data('type');
        if (type === 'link') {
          $(this).attr('data-index', linkIndex);
          linkIndex++;
        } else if (type === 'embed') {
          $(this).attr('data-index', embedIndex);
          embedIndex++;
        }
      });

      // Rebuild hidden fields with the correct indexes
      $('#links-container .link-item').each(function (i) {
        const $item = $(this);
        const itemType = $item.data('type');

        if (itemType === 'link') {
          const iconClass    = $item.find('input[name^="links[icon_class]"]').val()     || '';
          const linkText     = $item.find('input[name^="links[link_text]"]').val()      || '';
          const linkUrl      = $item.find('input[name^="links[link_url]"]').val()       || '';
          const isPopup      = $item.find('input[name^="links[is_popup]"]').val()       || '0';
          const popupContent = $item.find('input[name^="links[popup_content]"]').val()  || '';
          const isEnabled    = $item.find('input[name^="links[enabledHidden]"]').val()  || '1';

          // Remove old link inputs
          $item.find('input[name^="links["]').remove();

          // Recreate them with the new index
          $item.append(`
            <input type="hidden" name="links[icon_class][${i}]" value="${iconClass}">
            <input type="hidden" name="links[link_text][${i}]" value="${linkText}">
            <input type="hidden" name="links[link_url][${i}]" value="${linkUrl}">
            <input type="hidden" name="links[is_popup][${i}]" value="${isPopup}">
            <input type="hidden" name="links[popup_content][${i}]" value="${popupContent.replace(/"/g, '&quot;')}">
            <input type="hidden" name="links[enabledHidden][${i}]" value="${isEnabled}">
          `);
        } 
        else if (itemType === 'embed') {
          const embedType    = $item.find('input[name^="embeds[embed_type]"]').val()    || '';
          const embedUrl     = $item.find('input[name^="embeds[embed_url]"]').val()     || '';
          const embedEnabled = $item.find('input[name^="embeds[enabledHidden]"]').val() || '1';

          // Remove old embed inputs
          $item.find('input[name^="embeds["]').remove();

          // Recreate them with the new index
          $item.append(`
            <input type="hidden" name="embeds[embed_type][${i}]" value="${embedType}">
            <input type="hidden" name="embeds[embed_url][${i}]" value="${embedUrl}">
            <input type="hidden" name="embeds[enabledHidden][${i}]" value="${embedEnabled}">
          `);
        }
      });

      // Rebuild items_order field
      const newOrder = [];
      $('#links-container .link-item').each(function () {
        const t = $(this).data('type');
        const i = $(this).data('index');
        newOrder.push(`${t}-${i}`);
      });
      $('#items_order').val(newOrder.join(','));
    },
  });
}

HTML Structure:

<div class="card mt-4">
  <div class="card-header d-flex justify-content-between align-items-center">
    <h2>
      <i class="fas fa-window-minimize fa-xs"></i> Buttons and Media
      <span class="tooltip-icon">
        <i class="fas fa-info-circle fa-sm"></i>
        <div class="custom-tooltip">
          <h6>Add links to your page as buttons with an icon and link name.</h6>
        </div>
      </span>
    </h2>
  </div>

  <div class="card-body">
    <div id="links-container">
      <?php foreach ($combined_items as $i => $item): ?>
        <?php if ($item['item_type'] === 'link'): ?>
          <div class="link-item mb-3 d-flex align-items-center" data-index="<?= $i; ?>" data-type="link" style="opacity: <?= ($item['is_enabled'] == 1) ? '1' : '0.5'; ?>;">
            <i class="fas fa-grip-lines ms-2 drag-handle"></i>
            <div class="link-content flex-grow-1 me-2">
              <div class="link-text"><?= htmlspecialchars($item['link_text']); ?></div>
              <div class="link-url"><?= htmlspecialchars($item['link_url']); ?></div>
            </div>
            <div class="link-icon">
              <i class="<?= htmlspecialchars($item['icon_class']); ?> fa-2x"></i>
            </div>
            <!-- Hidden fields for POST -->
            <input type="hidden" name="links[icon_class][]" value="<?= htmlspecialchars($item['icon_class']); ?>">
            <input type="hidden" name="links[link_text][]" value="<?= htmlspecialchars($item['link_text']); ?>">
            <input type="hidden" name="links[link_url][]" value="<?= htmlspecialchars($item['link_url']); ?>">
            <input type="hidden" name="links[enabledHidden][]" value="<?= $item['is_enabled']; ?>">
            <input type="hidden" name="links[is_popup][]" value="<?= $item['is_popup']; ?>">
            <input type="hidden" name="links[popup_content][]" value="<?= htmlspecialchars($item['popup_content']); ?>">
          </div>
        <?php elseif ($item['item_type'] === 'embed'): ?>
          <div class="link-item mb-3 d-flex align-items-center" data-index="<?= $i; ?>" data-type="embed" style="opacity: <?= ($item['is_enabled'] == 1) ? '1' : '0.5'; ?>;">
            <i class="fas fa-grip-lines ms-2 drag-handle"></i>
            <div class="link-content flex-grow-1 me-2">
              <div class="link-text"><?= htmlspecialchars($item['embed_type']); ?></div>
              <div class="link-url"><?= htmlspecialchars($item['embed_url']); ?></div>
            </div>
            <div class="link-icon">
              <i class="fas fa-play-circle fa-2x"></i>
            </div>
            <!-- Hidden fields for POST -->
            <input type="hidden" name="embeds[embed_type][<?= $i ?>]" value="<?= htmlspecialchars($item['embed_type']); ?>">
            <input type="hidden" name="embeds[embed_url][<?= $i ?>]" value="<?= htmlspecialchars($item['embed_url']); ?>">
            <input type="hidden" name="embeds[enabledHidden][<?= $i ?>]" value="<?= $item['is_enabled']; ?>">
          </div>
        <?php endif; ?>
      <?php endforeach; ?>
    </div>

    <button type="button" class="btn btn-dark" id="add-link-button">
      Add Button <i class="fas fa-plus"></i>
    </button>
    <button type="button" class="btn btn-primary ms-2" id="add-embed-button">
      Add Media <i class="fas fa-play-circle"></i>
    </button>
  </div>
</div>

Relevant PHP Code (Form Processing):

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // Retrieve the items_order field
    $items_order = $_POST['items_order'] ?? '';
    $sequence = explode(',', $items_order);
    $position = 1;
    
    foreach ($sequence as $seg) {
        list($type, $idxStr) = explode('-', $seg);
        $idx = (int)$idxStr;
        
        if ($type === 'link') {
            // Example: retrieve posted link data using the rebuilt indexes
            $link_text = $_POST['links']['link_text'][$idx] ?? '';
            $link_url  = $_POST['links']['link_url'][$idx] ?? '';
            // Process link data (insert/update in database)...
        } elseif ($type === 'embed') {
            $embed_type = $_POST['embeds']['embed_type'][$idx] ?? '';
            $embed_url  = $_POST['embeds']['embed_url'][$idx] ?? '';
            // Process embed data...
        }
        $position++;
    }
}

After sorting, the items_order hidden field is rebuilt based on the data-index attributes assigned to each item. However, because links and embeds are re-indexed separately (using different counters) but then rebuilt in a single loop (using the loop’s index), there can be a mismatch. For example, the generated order might be “embed-0,link-2” or “embed-0,link-0,embed-1,link-1” even when the DOM order is mixed. This causes the PHP code to reference the wrong indexes in the arrays (or even missing indexes), leading to empty values being submitted for one or more items.

Logs:

==== DEBUG POST DATA ====
POST: Array
(
    [items_order] => embed-0,link-2
    [icons_order] => 
    [icons] => Array
        (
            [icon_class] => Array
                (
                    [0] => icon icon-youtube-square
                    [1] => fab fa-twitch
                    [2] => icon icon-x
                    [3] => fab fa-pinterest
                )
            [icon_url] => Array
                (
                    [0] => https://www.youtube.com/asdwdada
                    [1] => https://www.twitch.tv/asdwa
                    [2] => https://x.com/xxx
                    [3] => https://www.pinterest.com/asdw
                )
            [enabledHidden] => Array
                (
                    [0] => 1
                    [1] => 1
                    [2] => 1
                    [3] => 1
                )
            [is_popup] => Array
                (
                    [0] => 1
                    [1] => 0
                    [2] => 0
                    [3] => 0
                )
            [popup_content] => Array
                (
                    [0] => <p>asdadw</p>
                    [1] => <p><br></p>
                    [2] => <p><img src=&quot;data:image/jpeg;base64,...&quot;></p>
                    [3] => <p><br></p>
                )
        )
    [embeds] => Array
        (
            [embed_type] => Array
                (
                    [0] => أنغامي
                )
            [embed_url] => Array
                (
                    [0] => https://soundcloud.com/jiinzo/exsanguination
                    [1] => 
                )
            [enabledHidden] => Array
                (
                    [0] => 1
                )
        )
    [links] => Array
        (
            [icon_class] => Array
                (
                    [0] => fab fa-viber
                )
            [link_text] => Array
                (
                    [0] => فايبر
                )
            [link_url] => Array
                (
                    [0] => viber://chat?number=viber://chat?number=...
                )
            [enabledHidden] => Array
                (
                    [0] => 1
                )
            [is_popup] => Array
                (
                    [0] => 0
                )
            [popup_content] => Array
                (
                    [0] => <p><br></p>
                )
        )
)
DEBUG: items_order sequence: Array
(
    [0] => embed-0
    [1] => link-2
)
DEBUG Embed => idx: 0 | embed_type: أنغامي | embed_url: https://soundcloud.com/jiinzo/exsanguination | is_enabled: 1
DEBUG Link => idx: 2 | link_text:  | link_url:  | icon_class:  | is_enabled: 1 | is_popup: 0 | popup_cont: 

What might be causing the hidden input values to be emptied after sorting?

How can I modify my JavaScript code so that the hidden fields and the items_order field accurately reflect the current order of items, preserving all their values?

Any insights, suggestions, or alternative approaches would be greatly appreciated. Thanks in advance for your help!