Play a hidden html video tag with javascript

I want to include a video in a html file and instead of showing up the video directly on site opening i want to hide the video and later play it at some point. What i am trying to do is:

<style>
    /* Hide the video element initially */
    #hiddenVideo {
      display: none;
    }
</style>   

<video id="hiddenVideo">
  <!-- Sample video file provided by HTML5 Rocks (CC BY 3.0) -->
  <source src="https://www.html5rocks.com/en/tutorials/video/basics/devstories.mp4" type="video/mp4">
  Your browser does not support the video tag.
</video>

And later i wanna call this element from a js script

var video = document.getElementById("hiddenVideo");

video.style.display = "block";
video.style.position = 'absolute';
video.style.top = '50%';
video.style.left = '50%';
video.style.transform = 'translate(-50%, -50%) rotate(90deg)';
video.style.width = '100vh';
video.style.height = '100vw';
video.style.objectFit = 'contain';
video.autoplay = true;
video.controls = false;
  
document.body.appendChild(video);

video.onloadedmetadata = function() {
  console.log('Video metadata loaded successfully');
  console.log('Video duration:', video.duration);
};
video.onerror = function() {
  console.error('Error loading the video');
};

video.play();

However I couldn’t achieve what i wanted i was trying the hide the video element initially but the video shows up instantly on opening the site.
What wrong i am doing here?

Note: I am trying to play a local video file but i am facing some problems while playing the video i could directly include the video path with video.src but it doesn’t work (shows white screen). I couldn’t even find the video file in file browser (my site is deployed via netlify) but however including the path in the html video tag i could find the video in file browser, so i am trying this method.

TypeError: Module name, ‘lit’ does not resolve to a valid URL

I am trying out WebComponents for the first time and I am trying to use lit for it. It keeps showing this error

My HTML File

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="./styles.css">
  <script type="module" src="app.js"></script>
  <title>Document</title>
</head>
<body>
  <payment-sdk></payment-sdk>
</body>
</html>
import {LitElement, html, css} from 'lit';

I have tried removing the module attribute from the HTML but it still didn’t work. it now gave the error

javascript es6 import "expects exactly one argument"

I am also considering using Babel to compile it, but i do not think it would work since i am still getting errors
I also added "type": "module" in my package,json file

Got an Error !! While Uploading a file in Node js using Formidable

const formidable = require(‘formidable’);
const http = require(‘http’)
const fs = require('fs') http.createServer((req,res) =>{ if (req.url == '/fileupload') { const form = new formidable.IncomingForm();
form.parse(req,function(err,fields,files){

        var oldpath = files.filetoupload.filepath;
        var newpath = '/`home`/invincibleanurag/Desktop/Nodes/upload/'+ files.filetoupload.originalFilename;
        

fs.rename(oldpath, newpath, function (err) {`` if (err) throw err;
res.write(‘File uploaded and moved!’);
res.end();
});
})
} else {
res.writeHead(200,{‘Content-Type’:’text/html’})
res.write(”);
res.write(‘
‘);
res.write(”);
res.write(”);
return res.end(“Over”)
}
}).listen(8080)

node:internal/fs/utils:699
throw new ERR_INVALID_ARG_TYPE(propName, [‘string’, ‘Buffer’, ‘URL’], path);
^

TypeError [ERR_INVALID_ARG_TYPE]: The “oldPath” argument must be of type string or an instance of Buffer or URL. Received undefined
at Object.rename (node:fs:1011:13)
at /home/invincibleanurag/Desktop/Nodes/node.js:10:16
at zalgoSafe (/home/invincibleanurag/Desktop/Nodes/node_modules/dezalgo/dezalgo.js:20:10)
at f (/home/invincibleanurag/Desktop/Nodes/node_modules/once/once.js:25:25)
at IncomingForm. (/home/invincibleanurag/Desktop/Nodes/node_modules/formidable/dist/index.cjs:1210:7)
at IncomingForm.emit (node:events:514:28)
at IncomingForm._maybeEnd (/home/invincibleanurag/Desktop/Nodes/node_modules/formidable/dist/index.cjs:1661:10)
at /home/invincibleanurag/Desktop/Nodes/node_modules/formidable/dist/index.cjs:1420:14 {
code: ‘ERR_INVALID_ARG_TYPE’
}

Node.js v20.10.0

Cursor stuck on ‘wait’ when I go to previous page

Is there a method to have the cursor change to ‘default’ if I have to go back to the previous page? When my login button is clicked, I want to indicate to the user that the next page is loading, so I changed the cursor to ‘wait’. However, if I go back to the login page, the ‘wait’ cursor is apparent instead of ‘default’.

login button:

<div class = "introLogin" onclick = "waitPointer();"><input class = "introLoginInput" type = "submit" name = "submit" value = "Login"></div>

js:

function waitPointer()
{
    document.body.style.cursor = 'wait';
    return true;
}

function defaultPointer()
{
    document.body.style.cursor = 'wait';
    window.onload = function(){document.body.style.cursor='default';}
}

css:

.vIntro .introLogin .introLoginInput
{
    border: 0;
    border-radius: 5px;
    padding:5px 10px;
    background:#000;
    transition: color 0.5s;
    justify-content: center;
    text-align: center;
    font-size: 30px;
    font-family: Brush Script MT, Brush Script Std, cursive;
    color: white;
}

.vIntro .introLogin .introLoginInput:hover
{
    color: gold !important;
    transition: color 0.5s;
}

The cursor changes to ‘wait’ and ‘default’ when the page is fully loaded, but if I go back, I run into the issue of the cursor stuck on ‘wait’.

Razorpay Error: “Amount exceeds maximum amount allowed”

I’m encountering an issue with Razorpay where I’m getting the error message “Amount exceeds maximum amount allowed.” Strangely, this issue does not occurs with lower amounts. I’ve double-checked my code and API calls, but I’m unable to resolve the issue. Can someone help me understand what might be causing this error and how to fix it?

Below is my code

var options = {
    key: 'API_KEY',
    amount: 51000,
    currency: 'INR',
    name: 'Phone Dekho',
    order_id: data.id,
    handler: function (response) {
        console.log('Payment ID: ' + response.razorpay_payment_id);
        if (response.razorpay_payment_id) {
            var model = {
                orderId: data.id,
                razorpayOrderId: response.razorpay_order_id,
                razorpayPaymentId: response.razorpay_payment_id,
                razorpaySignature: response.razorpay_signature,
                amount: data.amount,
                status: "Success",
                addressId: data.addressId,
                userId: data.userId
            }
            addPayment(model);
        }
    },
    prefill: {
        name: data.fullName,
        email: data.email,
        contact: data.phone
    },
    notes: {
    },
    theme: {
        color: '#F46DBE'
    }
};

var rzp = new Razorpay(options);
rzp.open();

I’ve taken the following steps to troubleshoot the issue:

1.Checked the documentation: I reviewed the Razorpay documentation to ensure that I am correctly
implementing the payment flow and setting the amount within the allowed limits.

2.Tested with lower amounts: To verify if the issue is specific to higher amounts, I tested the
integration with lower amounts, it work smoothly with lower amount.

3.Reviewed configuration settings: Verified that the Razorpay configuration, especially the maximum
amount allowed, is correctly set up.

What were you expecting:

I expected the Razorpay integration to process the payment successfully without encountering the “Amount exceeds maximum amount allowed” error. Ideally, the payment process should proceed smoothly, and the handler function should execute as intended, updating the payment status.

The number of lines, in Javascript, is not shown directly when i open the web page. How to show the number of rows immediately?

I’m making a vertical bar that counts the number of rows as the rows are created. There are 2 ways to count rows: The first way is to press a key (addEventListener(“keydown”) to create a row. This happens correctly. The other way, which is what i need for the question, is to directly display all the line numbers as soon as i open the web page.

PROBLEM. The problem is that the number of rows is not displayed as soon as i open the web page. For example, if i have the text in 3 lines, as soon as i open the web page only 1 line is detected. Instead, I would like it to be displayed directly when I open the web page that there are 3 rows. The problem looks like this:

enter image description here

WHAT I WOULD LIKE. I would like to achieve this while also being able to count the rows by pressing a button (as I already do in the code), but I don’t want to encounter a conflict between the two ways. I would like to get this as soon as i open the web page (without pressing any buttons):

enter image description here

How can i achieve this? I’m using this, but it doesn’t work (I’m new to Javascript, sorry):

//VIEW DIRECTLY (WITHOUT PRESSING A BUTTON)
const start2 = textarea.selectionStart;
const end2 = textarea.selectionEnd;

textarea.value =
      textarea.value.substring(0, start2) +
      "t" +
      textarea.value.substring(end2);

Complete code:

const textarea = document.querySelector("textarea");
const numbers = document.querySelector(".numbers");

//WHEN I PRESS KEY
textarea.addEventListener("keyup", (e) => {
  const num = e.target.value.split("n").length;
  numbers.innerHTML = Array(num).fill("<span></span>").join("");
});

textarea.addEventListener("keydown", (event) => {
  if (event.key === "Tab") {
    const start = textarea.selectionStart;
    const end = textarea.selectionEnd;

    textarea.value =
      textarea.value.substring(0, start) +
      "t" +
      textarea.value.substring(end);

    event.preventDefault();
  }
})

//VIEW DIRECTLY (WITHOUT PRESSING A BUTTON)
const start2 = textarea.selectionStart;
const end2 = textarea.selectionEnd;

textarea.value =
      textarea.value.substring(0, start2) +
      "t" +
      textarea.value.substring(end2);
.editor {
  display: inline-grid;
  grid-template-columns: 3em auto;
  gap: 10px;
  line-height: 21px;
  border-radius: 2px;
  overflow-y: auto;
  width: 100%; 3 schermateeeeeeeeeeeeeeee */
}

.editor>* {
  padding-top: 10px;
  padding-bottom: 10px;
}

.numbers {
  text-align: right;
  background: #333;
  padding-right: 5px;
  height: 150px;
}

.numbers span {
  counter-increment: linenumber;
}

.numbers span::before {
  content: counter(linenumber);
  display: block;
  color: #888;
}

textarea {
  line-height: 21px;
  border: 0;
  background: transparent;
  color: #fff;
  min-width: 500px;
  outline: none;
  resize: none;
  padding-right: 10px;
}

textarea::placeholder{
  color: red;
  }

  textarea{
    background-color: black;
    color: green;
  }
<div class="code-area editor">
  <div class="numbers">
    <span></span>
  </div>

<textarea id="htmlCode" placeholder="HTML"  placeholder="PROVA" wrap="off">Test 1
Test 2
Test 3</textarea>
</div>                   
</div>

Do we need to sanitise form inputs in a Nextjs App? [closed]

I want to perform best practices when collecting user input and hopefully will be able to implement sanitisation and validation if necessary.

I have a simple form on my home page that looks like this. Will it be possible for a user to enter any malicious input and cause harm to my application base on my code?

@app/page.tsx

import { useFormState } from 'react-dom'
import { createTutionRequest } from './actions'

const initialState = {
  message: '',
}

export default function Home() {
  const [state, formAction] = useFormState(createTutionRequest, initialState);

  return (
  <form action={formAction}>
      <label htmlFor="name">Name:</label>
      <input type="text" id="name" name="name" minLength={4} maxLength={25} required />
        <button type="submit" aria-disabled={pending}>
            Submit
        </button>
</form>
}

@app/actions.ts

'use server'
export async function createTutionRequest(prevState: any, formData: FormData) {

    const rawFormData = {
        name: formData.get('name')
    }

    // I want to perform the following here
    // 1. sanitisation
    // 2. validation 


    // subsequently I will mutate data / save request to db.

}

I am not sure if sanitisation is required in a NextJS app since there are many things I don’t know that is running under the hood. If it is required as a best practice, can anyone help me with a basic approach for sanitisation of the data so I can extend from there if required?

Why MDN suggest use setTimeout in some situation?

MDN describe

Ensure that execution duration is shorter than interval frequency
If there is a possibility that your logic could take longer to execute than the interval time, it is recommended that you recursively call a named function using setTimeout(). For example, if using setInterval() to poll a remote server every 5 seconds, network latency, an unresponsive server, and a host of other issues could prevent the request from completing in its allotted time. As such, you may find yourself with queued up XHR requests that won’t necessarily return in order.

So i wirite four samples

let start;
let count = 1;
setInterval(() => {
  let b = 0;
  for (let i = 0; i < 100000000; i++) {
    b += i;
  }
  if (!start) start = performance.now();
  else console.log((performance.now() - start) / count++);
}, 200);
let start;
let count = 1;
setInterval(() => {
  let b = 0;
  for (let i = 0; i < 100000000; i++) {
    b += i;
  }
  if (!start) start = performance.now();
  else console.log((performance.now() - start) / count++,b);
}, 200);
function mySetinterval(fn, timeout, ...args) {
  let timer;
  function loop() {
    timer = setTimeout(() => {
      fn(...args);
      loop();
    }, timeout);
  }
  loop();
  return function () {
    clearTimeout(timer);
    timer = null;
  };
}


let start;
let count = 1;
mySetinterval(() => {
  let b = 0;
  for (let i = 0; i < 100000000; i++) {
    b += i;
  }

  if (!start) start = performance.now();
  else console.log((performance.now() - start) / count++);
}, 200);
function mySetinterval(fn, timeout, ...args) {
  let timer;
  function loop() {
    timer = setTimeout(() => {
      fn(...args);
      loop();
    }, timeout);
  }
  loop();
  return function () {
    clearTimeout(timer);
    timer = null;
  };
}
let start;
let count = 1;
mySetinterval(() => {
  let b = 0;
  for (let i = 0; i < 100000000; i++) {
    b += i;
  }

  if (!start) start = performance.now();
  else console.log((performance.now() - start) / count++,b);
}, 200);

I think setInterval actual execute all code,so next loop will happen 200ms after

and setTimeout will execute all code,so time gap will incerase with code exectue by cpu calculate

Is it correctly? And i don’s understand why MDN said XHR will influence setInterval,could you take an example?

Android Chrome occasionally not showing select text on popup

I’m writing a website and when I use it on my android phone in chrome, I SOME TIMES don’t see the text on the select pop up. It’s not every time, but it’s enough to notice it happening.

I don’t typically notice it on other people’s sites so I think it’s me.

I have a feeling it has to do with me populating the html after the dom has rendered (data from ajax request).

The markup looks like a standard select from bootstrap.

I’m using jquery to set the html. It just a normal select, I’m not using any library to convert it or otherwise manipulate it.

Has anyone else ever seen this behavior? What’s the fix?

enter image description here

Calcul points between two scores

I’m engaged in a game where you compete to eat each other’s towers and the score is determined by the number of towers remaining on the grid.

My question is, how can we calculate each other’s final points based on the difference between their final points and their levels?

I tried p1Points, but this isn’t really a good result. I have to find a way to calculate whether you win or lose the match final points.

`
let player1 = {finalScore: 50, level: 2};
let player2 = {finalScore: 14, level: 1};

const p1Points = (player1.finalScore + player2.finalScore) / (player1.level + player2.level);

`

Issues when deleting dynamically loaded component in Sveltekit

I’ve got a page which (at this point) contains only a button. When this button is clicked, a component is dynamically loaded, so if you click it multiple times then multiple components will appear on the page. Each component is a small form that get’s submitted on the form’s save button is clicked.

So far so good, now, when a component is saved, then the save button is hid and a garbage button will be visible. When one clicks on this garbage button, then the component should be deleted.

To do this, I need to keep track of the component created, so I randomly create a string which I pass as part of the properties. As part of the properties, I also pass a callback function that receives the component ID and will be executed when the garbage button is clicked.

Once the garbage button is clicked, then it’ll call the callback function which will remove the component from the list of components by running a filter.

Let’s say I have 2 elements. On each element I’m displaying the random ID it was created with.

enter image description here

If I delete the first element I would expect only the second one to remain. This is somehow happening, the second element I see on screen has the correct ID but for some reason it’s data (the data in its text fields) is not the correct but it is the data of the element that was just deleted.

enter image description here

Any idea what’s going on?

Here’s the main page which contain the button to add elements:

<script>

    import InventoryItem from "../components/InventoryItem.svelte";

    export let formData = {};
    export let inventoryID;

    let inventoryItemComponents = [];

    // Keeps track of the number of components added to inventoryItemComponents and the same

    /**
     * loadNewItemForm loads a new InventoryItem component and adds it to a
     * list of existing components inventoryItemComponents
     */
    const loadNewItemForm = () => {

        // create random string that will be used as a component identifier.
        const componentID = Math.random().toString(36).slice(2);

        inventoryItemComponents = [
            ...inventoryItemComponents,
            [InventoryItem, {
                formAction: "?/saveItem",
                inventoryID: inventoryID,
                componentID: componentID,
                deleteCallbackFn: removeFromList
            }]
        ];

    }

    const removeFromList = id => {

        let updatedList = inventoryItemComponents.filter( inventoryComponent => inventoryComponent[1].componentID != id )
        inventoryItemComponents = [...updatedList];

    }

</script>

<div>

    <div class="inventory-items-list">

        {#each inventoryItemComponents as [component, props]}
            <svelte:component this={component} {...props}>
            </svelte:component>
        {/each}

        <!-- New item button -->
        <div class="float-right">
            <div class="md:p-4  flex item-center justify-center">
                <button
                        class="btn btn-active btn-primary"
                        on:click={loadNewItemForm}>
                    New Item
                </button>
            </div>
        </div>
    </div>
</div>

And here’s the component that’s being loaded:

<script>
    import {enhance} from '$app/forms';
    import ProductLookup from "./ProductLookup.svelte";

    export let inventoryID;
    export let componentID;
    export let deleteCallbackFn;

    /**
     * Local props.
     */
    let inventoryItemID = "";
    let total;
    let productData;
    let purchasedPrice = 0;
    let quantity = 1;

    // Determines whether the save button should be displayed or not.
    let hideSaveBtn = false;

    // Holds a list of errors.
    let errors = {};

    /**
     * Builds the request's payload to the add-inventory-item endpoint.
     * We won't perform any validation at this point.
     */
    const buildPayload = () => {

        return {
            "inventory_id": inventoryID,
            "product": productData,
            "purchased_price": purchasedPrice.toString(),
            "quantity": quantity,
        }
    }

    /**
     * Saves a new inventory item.
     *
     * @param e
     * @returns {Promise<void>}
     */
    const save = async e => {

        e.preventDefault();

        // reset all errors, so they can be repopulated again from scratch.
        errors = {};

        // perform call to internal API.
        const response = await fetch('/api/add-inventory-item', {
            method: 'POST',
            body: JSON.stringify(buildPayload()),
        });

        const parsedResponse = await response.json()

        if (parsedResponse.errors) {
            errors = parsedResponse.errors;
            return;
        }

        inventoryItemID = getInventoryItemIDFromResponse(parsedResponse);

        // if the record was successfully saved then hide the save button since it shouldn't be allowed to be saved again.
        hideSaveBtn = true;
    }

    /**
     * Goes through the API response from adding an item into an inventory and
     * gets the inventory item ID. This has to be done because from the API we're returning
     * the whole inventory object when adding a new item, so we need to figure the ID out.
     *
     * @param apiResponse
     */
    const getInventoryItemIDFromResponse = apiResponse => {

        const inventoryItems = apiResponse.data.attributes.items;
        const item = inventoryItems.filter(item => item.product.id === productData.value);
        return item[0].id;
    }

    const deleteItem = () => {
        deleteCallbackFn(componentID);
    }

    /*
     * Reactive properties.
     */

    // Recalculate total every time either purchasedPrice or quantity change.
    $: total = purchasedPrice * quantity;

</script>

<div class="card w-full bg-base-100 shadow-xl mt-5">

    <form method="POST" class="p-6" use:enhance>
        <h2>ID: {componentID}</h2>
        <div class="md:grid md:grid-cols-12 gap-0.5">

            <!-- Inventory Item ID -->
            <input name="inventory_item_id" type="hidden" value={inventoryItemID} />

            <!-- ID -->
            <input name="inventory_id" type="hidden" value={inventoryID} />

            <!-- Product lookup -->
            <div class="col-span-4">
                <div class="md:w-full md:px-3 mb-6 md:mb-0">

                    <label class="block tracking-wide text-gray-700 text-xs font-bold mb-1" for="product">
                        Product <span class="text-red-600">*</span>
                    </label>

                    <ProductLookup
                            bind:value={productData}
                            customClass="input w-full py-4 font-medium bg-gray-100 border-gray-200 text-sm
                      focus:outline-none focus:border-gray-400 focus:bg-white"
                            id="product"
                            name="product"
                    />
                    {#if errors?.product_id }
                        <small class="text-amber-800">{ errors?.product_id[0]}</small>
                    {/if}
                </div>
            </div>

            <!-- Quantity -->
            <div class="col-span-2">
                <div class="md:w-full md:px-3 mb-6 md:mb-0">
                    <label class="block tracking-wide text-gray-700 text-xs font-bold mb-1" for="quantity">
                        Qty <span class="text-red-600">*</span>
                    </label>
                    <input
                            bind:value={ quantity }
                            class="input w-full md:max-w-xs py-4 font-medium bg-gray-100 border-gray-200 text-sm
                                  focus:outline-none focus:border-gray-400 focus:bg-white"
                            id="quantity"
                            min="1"
                            name="quantity"
                            type="number"
                    />
                    {#if errors?.quantity }
                        <small class="text-amber-800">{ errors?.quantity[0]}</small>
                    {/if}
                </div>
            </div>

            <!-- Purchased Price -->
            <div class="col-span-2">
                <div class="md:w-full md:px-3 mb-6 md:mb-0">
                    <label class="block tracking-wide text-gray-700 text-xs font-bold mb-1" for="purchased_price">
                        Purchased Price <span class="text-red-600">*</span>
                    </label>
                    <input
                            bind:value={ purchasedPrice }
                            class="input w-full md:max-w-xs py-4 font-medium bg-gray-100 border-gray-200 text-sm
                                  focus:outline-none focus:border-gray-400 focus:bg-white"
                            id="purchased_price"
                            min="0"
                            name="purchased_price"
                            type="number"
                    />
                    {#if errors?.purchased_price }
                        <small class="text-amber-800">{ errors?.purchased_price[0]}</small>
                    {/if}
                </div>
            </div>

            <!-- Total -->
            <div class="col-span-2">
                <div class="md:w-full md:px-3 mb-6 md:mb-0">
                    <label class="block tracking-wide text-gray-700 text-xs font-bold mb-1" for="total">
                        Total
                    </label>
                    <input class="input input-ghost w-full max-w-xs" disabled id="total" type="text" value={total}/>
                </div>
            </div>

            <!-- Buttons -->
            <div class="col-span-2">

                <!-- Save button -->
                {#if (!hideSaveBtn)}
                    <div class="">
                        <a href="#" class="flex items-center justify-center link link-hover" on:click={save}>
                            <svg class="w-6 h-6 text-gray-800" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20">
                                <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 19H1.933A.97.97 0 0 1 1 18V5.828a2 2 0 0 1 .586-1.414l2.828-2.828A2 2 0 0 1 5.828 1h8.239A.97.97 0 0 1 15 2v4M6 1v4a1 1 0 0 1-1 1H1m11 8h4m-2 2v-4m5 2a5 5 0 1 1-10 0 5 5 0 0 1 10 0Z"/>
                            </svg>
                        </a>
                    </div>
                {:else }
                    <div class="">
                        <svg class="w-6 h-6 text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20">
                            <path stroke="green" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m7 10 2 2 4-4m6 2a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"/>
                        </svg>
                        <a href="#" class="flex items-center justify-center link link-hover" on:click={deleteItem}>
                            <svg class="w-6 h-6 text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 18 20">
                                <path stroke="darkred" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M1 5h16M7 8v8m4-8v8M7 1h4a1 1 0 0 1 1 1v3H6V2a1 1 0 0 1 1-1ZM3 5h12v13a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V5Z"/>
                            </svg>
                        </a>
                    </div>
                {/if}
            </div>

        </div>

        <div class="flex-row flex">
            <div class="p-2 float-left">
                <span class="px-3 mb-6 text-2xs">(<span class="text-red-600">*</span>) Required</span>
            </div>
        </div>

    </form>


</div>

How do I iterate through files in a web accessable directory?

I am developing a chrome extension, and I want to allow my users to add their own assets to an assets folder. However I can’t figure out how to access the files if I don’t know their exact name.

In manifest.json I have

"web_accessible_resources": [
      {
        "resources": [
            "assets/*"
        ],
        "matches": ["https://example.com"]
      }

and I was able to produce my desired behavior by using

chrome.runtime.getPackageDirectoryEntry(function(dir) {
  dir.createReader().readEntries(function (fr) {
    fr.find(e => e.name == "assets" && e.isDirectory).createReader().readEntries(function (fr) {
        for(i of fr) {
            console.log(chrome.runtime.getURL(i.name))
        }
    })
  })
})

in the developer console, but I discovered after the fact that getPackageDirectoryEntry is foreground only and thus I couldn’t run it in my contentScript. I was not able to find an equivalent in the file system api. Another approach I tried was including a txt document which the user would then add the file paths of any files they wanted, however this seems needlessly unintuitive.