Convert array of objects into an array of array elements

I have below array of objects input as follows

input = [
  { metadata: { name: "1.24.18", branch: "DEVELOP" } },
  { metadata: { name: "1.24.15", branch: "RELEASE" } }
];

I want the output as shown below

output = [
    [ '1.24.18' , 'DEVELOP'],
    [ '1.24.15' , 'RELEASE']
]

In order to achieve this, i use the below code

input.map((el) => [el?.metadata?.name + ", " + el?.metadata?.branch]);

Using above code, i get the output as this instead

output = [
    [ '1.24.18 , DEVELOP'],
    [ '1.24.15 , RELEASE']
]

Does anyone know how to seperate the values and put comma seperation between them

Can a chrome extension scrape for urls, then access those urls to scrape their html files?

I’m learning about scraping and chrome extensions at the moment. So I want to build one that scrape s the UberEats websites. It grabs the links to restaurants menu’s and accesses their html file to scrape the name of restaurants.

This is just proof of concept to know if I can even scrape the html in a url in the first place. My main goal is to do the scraping when the user searches of a dish on UberEats website where it loads a bunch of restaurant, and my extensions scrapes the html of the url of those restaurants to find matching dishes.

I don’t want to use puppeteer or selenium since they require a separate backend, where my extension need to access using an api. I don’t have a server nor do I want to host one. So I want to do all of this on the extension.

So far, I got the part where it extract the URLs, and now I need to access those URLs. I learned about background scripts, and fetch(). I tried using fetch to get a response from the URLs I scraped and then return the html to be scraped later on.

But it didn’t work and my catch error keeps getting returning these for every link I try to scape. It doesn’t show up on the console but on the chrome://extensions.

Error scraping data for URL: https://www.ubereats.com/ca/store/woking-dragon-chop-suey-house-langley/zzIphhS4XhaTOx7uDFoHsQ ReferenceError: error is not defined
Context
background.js
Stack Trace
background.js:55 (anonymous function)

 }
        } catch (error) {
55            console.error('Error scraping data for URL:', fullURL, error);
        }
    }
    return storeNames;
}

If there is better approach then what i’ve done, please let me know thank you.

The rest of my code:

Manifest.json

{
  "manifest_version": 3,
  "name": "Food Delivery Scraper",
  "description": "Scrape & Summarize Food Delivery Data",
  "version": "1.0",
  "background": {
      "service_worker": "background.js"
  },
  "action": {
      "default_popup": "popup.html"
  },
  "permissions": [
      "activeTab",
      "scripting"
  ],
  "host_permissions": [
      "https://www.ubereats.com/*"
  ],
  "content_scripts": [
      {
          "matches": ["https://www.ubereats.com/*"], 
          "js": ["popup.js"],
          "run_at": "document_idle"
      }
  ]
}

background.js

function parseLink(URL) {
    const baseURL = "https://www.ubereats.com";
    return baseURL + URL;
}

async function fetchHTML(fullURL) {
    fetch(fullURL)

    .then(response => {
        // Checking if the response is successful
        if (!response.ok) {
        throw new Error('Network response was not ok');
        }
        // Parsing the response as text
        console.log(response.text());
    })
    .then(html => {
        // Once HTML is retrieved, you can scrape the data from it
        return html;
    })
    .catch(error => {
        console.error('There was a problem with the fetch operation:', error);
    }); throw error; // Rethrow to handle outside
}

function scrapeMenuData(html) {
    const tempDiv = document.createElement('div');
    tempDiv.innerHTML = html;
    const storeTitleElement = tempDiv.querySelector('h1[data-testid="store-title-summary"]');
    if (storeTitleElement) {
        const storeTitle = storeTitleElement.textContent.trim();
        console.log('Store Title:', storeTitle);
        return storeTitle;
    } else {
        console.log('Store Title element not found');
        return null;
    }
}

async function scrapeLinks(cards) {
    const storeNames = [];
    for (const card of cards) {
        const fullURL = parseLink(card.url);
        try {
            console.log("await fetchHTML");
            const html = await fetchHTML(fullURL);
            console.log("scrapeMenuData");
            const storeTitle = scrapeMenuData(html);
            if (storeTitle) {
                storeNames.push(storeTitle);
            }
        } catch (error) {
55:**            console.error('Error scraping data for URL:', fullURL, error);**
        }
    }
    return storeNames;
}

chrome.runtime.onMessage.addListener(
    function (request, sender, sendResponse) {
        if (request.action === "scrapeData") {
            scrapeLinks(request.cards).then(storeNames => {
                sendResponse({storeNames: storeNames});
            });
            return true; // Indicates response will be sent asynchronously
        }
    }
);

popup.js

// popup.js

document.getElementById('scrapeApp').addEventListener('click', async () => {
    let [tab] = await chrome.tabs.query({active: true, currentWindow: true});

    chrome.scripting.executeScript({
        target: {tabId: tab.id},
        function: getCardsData,
    }, (injectionResults) => {
        for (const frameResult of injectionResults) {
            chrome.runtime.sendMessage({
                action: "scrapeData",
                cards: frameResult.result
            }, response => {
                console.log('Scraped Names:', response.storeNames);
                updateUI(response.storeNames);
            });
        }
    });
});

function getCardsData() {
    const cards = Array.from(document.querySelectorAll('[data-testid="store-card"][href]')).map(card => ({
        url: card.getAttribute('href')
    }));
    return cards;
}

function updateUI(storeNames) {
    const main = document.querySelector('main');
    main.innerHTML = ''; // Clear previous results
    storeNames.forEach(name => {
        const div = document.createElement('div');
        div.textContent = name;
        main.appendChild(div);
    });
}

Move the scroll bar by scrolling on the page

Take a look at the following code:

 function getScrollPercent() {
            const h = document.documentElement;
            const st = 'scrollTop';
            const sh = 'scrollHeight';
            const clientHeight = h.clientHeight;
            const scrollTop = h[st];
            const scrollHeight = h[sh];

            return scrollTop / (scrollHeight - clientHeight) * 100;
        }

        function update_scroll() {
            const scrollPercent = getScrollPercent();

            document.getElementById("scroll-line").style.height = `${scrollPercent}%`;
            document.getElementById("progress").textContent = Math.round(scrollPercent) + '%';
        }

        window.addEventListener('scroll', update_scroll);
        update_scroll();
 .content-site {
        height: 500vh;
    }

    #main_box {
        position: fixed;
        right: 50px;
        bottom: 80px;
    }

    #body_box {
        width: 100px;
        height: 100px;
        background: #b0ffcb;
        box-shadow: 0 0 4px #050030;
        border-radius: 50% !important;
        position: relative;
        overflow: hidden;
    }

    #progress {
        position: absolute;
        top: 40%;
        left: auto;
        z-index: 3;
        color: #f00;
        display: block;
        margin: 0 auto;
        width: 100%;
        text-align: center;
    }

    #scroll-line {
        width: 100%;
        position: absolute;
        top: 0;
        left: 0;
        border-radius: 50%;
        z-index: 2;
        background-color: #050030;
    }
    
    
    <div class="content-site"></div>
  
  <footer>
        <div id="main_box">
            <div id="body_box">
                <div id="scroll-line"></div>
                <p id="progress"></p>
            </div>
        </div>
    </footer>

As you can see, I have implemented a progress bar that changes state based on the scroll position of the page.

Now, instead of changing the background color of the element on scroll, I want to create a progress ring around the element that changes its state as the page is scrolled.

Here is an example of what I am looking for:

https://codepen.io/christianmair/pen/dLVbze

The problem with the example above is that it uses SVG, which makes the code very complex.

I want to do this with the code I have written so far, but I have tried many ways and have not been able to achieve the desired result.

merge two objects conditionally in Lodash

I have two setting config

const defaultSetting = {
  level1: {
    setting1: "defaultValue1",
    nested: true,
    home: "africa"
  },
  level2: {
    setting2: "defaultValue3"
  }
};

const initialSetting = {
  level1: {
    setting1: "initialValue1", // This value will override defaultSetting's value
    nested: false // This value will override defaultSetting's value
  },
  level2: {
    nested: true // This value will override defaultSetting's value, adding a new property not in defaultSetting's level2
  }
};

What I am trying to achieve is that I want to merge initialSetting into defaultSetting, such that:

  1. The structure of defaultSetting dictates the final structure.
  2. Values from initialSetting overwrite those in defaultSetting where they
    exist.
  3. If initialSetting contains keys not present in
    defaultSetting, they are not included in the final object.
  4. If defaultSetting contains keys not present in initialSetting, their
    default values are retained.

I want to strictly adhere to the structure of defaultSetting while selectively pulling in values from initialSetting.

I have this code

const mergeTwoObjects = (obj11: NestedObject | undefined, obj2: NestedObject): unknown => {
 const result: NestedObject = {};
  const obj1 = obj11 ?? {};

  (Object.keys(obj2) as Array<keyof typeof obj2>).forEach((key) => {
    if (Object.prototype.hasOwnProperty.call(obj1, key)) {
      if (typeof obj1[key] === "object" && typeof obj2[key] === "object") {
        result[key] = mergeTwoObjects(
          obj1[key] as NestedObject,
          obj2[key] as NestedObject,
        ) as NestedObject;
      } else {
        result[key] = obj1[key];
      }
    } else {
      result[key] = obj2[key];
    }
  });
  return result;
};

But the requirement came as that I can not build my function from scratch rather than that I should be using lodash and make code simple without many loops

I tried this but it did not work

function mergeSettings(defaultSetting, initialSetting) {
  return _.mergeWith({}, defaultSetting, initialSetting, (objValue, srcValue, key, object, source, stack) => {
     console.log(objValue);
      if (_.isObject(objValue) && _.isObject(srcValue)) {
          // Return undefined to let _.mergeWith handle the deep merge of these objects
          return undefined;
        }
        if(
    // If srcValue is undefined, use objValue (from defaultSetting)
    return srcValue === undefined ? objValue : srcValue;
  });
}

const finalSetting = mergeSettings(defaultSetting, initialSetting);

I am new to Lodash, can anyone please help me achieve this

Amazon v3 javascript SDK not returning any data when working with IAMClient

Including some other bits and pieces i have the following code to create a new IAM user with the amazon v3 javascript sdk.

const client = new IAMClient({
            credentials: {
                accessKeyId: "accesskey",
                secretAccessKey: "secretkey",
            },
            region: this.region, // eu-central-1
        });
const command = new CreateUserCommand({
   UserName: "MyTestUser",
});
const response = await client.send(command);

From the docs (https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/iam/command/CreateUserCommand/) it seems like i should be getting a javascript object that should look something like this:

{
  "User": {
    "Arn": "arn:aws:iam::123456789012:user/Bob",
    "CreateDate": "2013-06-08T03:20:41.270Z",
    "Path": "/",
    "UserId": "AKIAIOSFODNN7EXAMPLE",
    "UserName": "MyTestUser"
  }
}

But what i am actually getting is this (seems like its only the metadata):

{
   "httpStatusCode":200,
   "requestId":"9111ea22-0d64-44f8-9c2c-225424f77fb3",
   "attempts":1,
   "totalRetryDelay":0
}

The funny thing about that is, that in the Network Tab of Chromes developer tools the data i want seems to be there.
The response the sdk receives from amazon looks like this:

<CreateUserResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">
  <CreateUserResult>
    <User>
      <Path>/</Path>
      <UserName>MyTestUser</UserName>
      <Arn>arn:aws:iam::525123112340:user/MyTestUser</Arn>
      <UserId>AIDAXUVAXXXXXXXXCHWWD</UserId>
      <CreateDate>2024-04-15T21:42:12Z</CreateDate>
    </User>
  </CreateUserResult>
  <ResponseMetadata>
    <RequestId>99d79e72-fa7a-4fed-843a-e63b7feb6e22</RequestId>
  </ResponseMetadata>
</CreateUserResponse>

package.json

"dependencies": {
    "@aws-sdk/client-iam": "^3.515.0",
    "@aws-sdk/client-s3": "^3.515.0",
    "@aws-sdk/s3-request-presigner": "^3.523.0",
    ...
}

Reinstalling and updating the packages brought no change whatsover (not that i thought that that would help) and to be honest im stuck at the moment.
Please not that i switched from V2 to V3 recently and did not notice the issue until now so im pretty new to V3.

Any advice is highly appreciated.

In my GoogleAppScript program the HTML2 is not capturing my document when sending to the Google Drive via Mobile Device

My web app is hosted on Google App Script and the purpose of it is to collect signatures and send the signed document to a designated Google Drive Folder. Essentially when I use a desktop or laptop to sign the document the program works as intended. The picture of the whole document is taken with the signature and filled out info and is sent to the Google Drive Folder. However when I lauch the web app on my phone and press send with the fields filled out the program sends a blank png file, with no screenshot. The web app is rendered and all the other functions work, it just does not send a picture of the signed document on mobile devices. I am assuming it has something to do with the HTML2 or the size of the canvas.

<!doctype html>
<html lang="en">

<head>
  <base target="_top">
  <meta charset="utf-8">
  <link rel="icon"/>
  <meta name="viewport" content="width=device-width, initial-scale=1"/>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
    integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous" />
  <link rel="stylesheet" href="style.css" />
  <script src="https://html2canvas.hertzen.com/dist/html2canvas.min.js"></script>
  <title>Liability From</title>
</head>

<body>
  <header id="header">
    <div id="logo">
      <h1> Liability form </h1>
    </div>
    <div class="margin"> </div>
  </header>

  <main>
    <div class="paper">
      <div id="app" class="container">
        <div class="margin text-center">
          <div class="canvas mx-auto">
            <h1> LIABILITY FROM </h1>
            <br>
            <p> Description</p>
          </div>
          <div id="messageContainer" class="alert alert-success" style="display: none;"> Signature sent successfully!
          </div>
          <br>
          <div id="checkboxContainer" class="checkbox">
            <span class="red-asterisk">*</span><input type="checkbox" id="checkbox">
            <label for="checkbox"> <strong>I ACKNOWLEDGE </strong></label>
          </div>

          <div class="name-date">
            <div class="print-name">
              <label for="print-name"><span class="red-asterisk">*</span><strong>Name:</strong> </label>
              <input type="print-name" id="name" name="name" class="custom-border">
            </div>

            <div class="email-section">
              <label for="print-email"><span class="red-asterisk">*</span><strong>Email:</strong></label>
              <input type="email" id="email" name="email" class="custom-border" class="validate">
            </div>

            <div class="date-section">
              <label for="date"><span class="red-asterisk">*</span><strong>Today's Date:</strong></label>
              <br>
              <input type="date" id="date" name="date" class="custom-border">
            </div>

          </div>

          <p> <strong> Signature: </strong> </p>
          <br>
          <canvas id="sig" width="700px" height="150px" class="border" style="cursor: crosshair;"></canvas>

          <div>
            <button type="button" class="pill" id="clearSig">Clear</button>

            <button type="button" class="pill" id="send">Send</button>
            <button type="button" class="pill" disabled id="load">
              <span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
              Sending...
            </button>
          </div>


        </div>
      </div>
    </div>
  </main>
</body>

<footer class="footer">
  <div class="footerContainer">
    <p class="copyright">Form</p>
  </div>
</footer>

<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"
  integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js"
  integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"
  integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/signature_pad.umd.min.js"></script>
<script src="/src/Code.js"> </script>

<script>

  document.getElementById('load').style.display = 'none'
  let signaturePad;

  function setupSignatureBox() {
    const canvas = document.getElementById("sig");
    signaturePad = new SignaturePad(canvas);
  }

  function clearSignature() {
    signaturePad.clear();
  }

  const sendToDrive = () => {
    try {
      const nameInput = document.getElementById("name").value.trim();
      const dateInput = document.getElementById("date").value.trim();
      const emailInput = document.getElementById("email").value.trim();
      let checkboxChecked = document.getElementById("checkbox").checked;

      let existingAlert = document.getElementById("errorAlert");
      if (existingAlert) {
        existingAlert.remove();
      }

      if (!checkboxChecked) {
        throw new Error('Please acknowledge the terms of the liability!');
      }

      if (!nameInput) {
        throw new Error('Please enter your NAME!');
      }

      if(!emailInput){
        throw new Error('Please enter your EMAIL ADDRESS!')
      }

      if (!dateInput) {
        throw new Error('Please enter today's DATE!');
      }

      if(signaturePad.isEmpty()){
        throw new Error('Please sign the document!');
      }

      const today = new Date(new Date().toLocaleDateString()).toISOString().slice(0, 10);
      if (dateInput !== today) {
        throw new Error('Please enter TODAY'S date!');
      }

      document.getElementById('send').style.display = 'none';
      document.getElementById('load').style.display = 'inline';

      let mainContent = document.getElementById("app");
      mainContent.style.width = window.innerWidth + "px";

      html2canvas(mainContent).then(function (canvas) {
        const imageData = canvas.toDataURL();
        google.script.run.withSuccessHandler(function () {
          document.getElementById('messageContainer').style.display = 'block';
          document.getElementById('load').style.display = 'none';
          setTimeout(function () {
            document.getElementById('messageContainer').style.display = 'none';
          }, 3000);
        }).recieveSignature(nameInput, emailInput, imageData);
      });
    } catch (error) {
      displayError(error.message);
    }
  }

  const displayError = (errorMessage) => {
    let alertDiv = document.createElement('div');
    alertDiv.className = 'alert alert-danger';
    alertDiv.id = 'errorAlert';
    alertDiv.textContent = errorMessage;

    let checkboxDiv = document.querySelector('.checkbox');
    checkboxDiv.parentNode.insertBefore(alertDiv, checkboxDiv);
  }

  document.getElementById("clearSig").addEventListener("click", clearSignature);
  document.getElementById("clearSig").addEventListener("touchend", clearSignature);
  document.getElementById("send").addEventListener("click", sendToDrive);
  document.getElementById("send").addEventListener("touchend", sendToDrive);
  document.addEventListener("DOMContentLoaded", setupSignatureBox);
</script>

</html>

JavaScript:

function doGet() {
  return HtmlService.createTemplateFromFile("index").evaluate();
}

const recieveSignature = (nameInput,emailInput,encodedImage) => {
  const data = encodedImage.split(",")[1];
  const dataDecoded = Utilities.base64Decode(data);
  let fileName = (`${nameInput}_signed.png`)
  const signatureAsPictureBlob = Utilities.newBlob(dataDecoded).setName(fileName);
  DriveApp.getFolderById(GoogleDriveFolder).createFile(signatureAsPictureBlob);
  GmailApp.sendEmail(emailInput, 'Thanks for the submission!', 'Confirmation')
  return "Signature sent successfully!";
}

nextjs FileReader throws 405

In my nextjs app I use FileReader to upload file into a gallery. It works in dev mode but if I build and start it, the upload throws 405.

the function that takes the file:

export const getImage = (file: any) => {
    if (!file) {
        return Promise.resolve(null);
    }
    if (file.id) {
        return Promise.resolve({ id: file.id });
    }
    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.readAsDataURL(file.originFileObj);
        reader.onload = () => resolve({ id: null, fileName: file.name, content: reader.result });
        reader.onerror = (error) => reject(error);
    });
};

In dev mode upon the upload, the network shows it as an xhr POST reqeuest. I don’t really know why.

In my next.config I use a rewrite, maybe related to this:

rewrites: async () => {
        return [
            {
                source: "/api/:slug*",
                destination: `${process.env.API_BASE_URL}/api/:slug*`,
                basePath: false,
            },
        ];
    },

How to import the published/installed version of the same package

My package has a dev dependency of the same package (the last published version).

What is the best way to refer the the installed (inside node_modules) version of said package?

I have an:

"exports": "./source/index.js"

field in my package.json for the consumers of the package to import. So if I do:

import {x} from "packageName"

it will resolve to .source/index.js. But I want the runtime to resolve to the copy inside node_modules.

Should I create a barrel file that exports this?:

"./node_modules/packageName/source/index.js"

I tried a more ergonomic way by importing from node_modules using package.json’s

"imports": { #something: "./node_modules/packageName/source/index.mjs"}

but I think it’s forbidden: I get

Error [ERR_INVALID_PACKAGE_TARGET]: Invalid "imports" target

CSS backdrop-filter + backface-visibility not working on iOS

I have created a flipcard with text content on the front and the back.

I have applied a blur

.blur {
  backdrop-filter: blur(9px);
  -webkit-backdrop-filter: blur(9px);
}

to the card but on iOS is very glitchy.

I have searched the web and found similar issues but nobody was using blur with

backface-visibility: hidden

I have created a codepen to share the code (see here), and this is a gif showing the glitch on
iOS Chrome

I searched and found similar issues with backdrop-filter but the solutions for these problems were to apply -webkit-backdrop-filter which i have already applied and not working in my case.

dis-order for creating a button for auto-create a column

i have a page in php that contains a table with column (the use of this page to make a transaction item quantity from the supplier).

I made a button with it’s function in java script in case when i press the button, automatically create a new column in the table, all the code is running every thing is working, my goal is to add a new column according to the product item’s that i’ve recieved (supplier needs list) with multiple product’s defined by it’s items

when i press the button, the new column created beside”not in a new line as a column” of the current column and the action kicked me outside the page “supplier.php”.

supplier.php

<?php
session_start();

if (!isset($_SESSION['user'])) {
  header('location: login.php');
  exit(); // Make sure no further code is executed after redirection
}

$_SESSION['table'] = 'stock_products';
$_SESSION['redirect_to'] = 'product-add.php';
$user = $_SESSION['user'];
?>

<!DOCTYPE html>
<html>
<head>
  <title>Add Product - Inventory Management System</title>
  <?php include('partials/app-header-script.php'); ?>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
</head>
<body>
  <div id="dashboardMainContainer">
    <?php include('partials/app-sidebar.php'); ?>
    <?php include('./database/connection.php'); ?>

    <div class="dashboard_content_container" id="dashboard_content_container">
      <?php include('partials/app-topnav.php') ?>
      <div class="dashboard_content">
        <div class="dashboard_content_main">
          <div class="row">
            <div class="column column-12">
              <h1 class="sectionheader"><i class="fa fa-plus"></i> Create Arrived Marchandises</h1>
              <div id="useraddformcontainer">

                <form method="post" action="purchase_script.php">
                  <h2>Purchase Transaction</h2>
          <table id="myTable">
  <thead>
    <tr>
      <th>Product</th>
      <th>Product Item</th>
      <th>Quantity Recieved</th>
      <th id="newColumnHeader"></th>
    </tr>
  </thead>
  <tbody id="product_items">
    <tr id="row1">
      <td>
        <select name="product_id[]" id="product_id_1" onchange="fetchDesignations(1)">
          <option value="">Select Product</option>
          <?php
          // Retrieve products from the database (already in your code)
          $sql = "SELECT idstkproduct, product_name FROM stock_products ORDER BY product_name ASC";
          $stmt = $conn->prepare($sql);
          $stmt->execute();
          $products = $stmt->fetchAll(PDO::FETCH_ASSOC);

          // Populate the dropdown with product options
          foreach ($products as $product) {
            echo '<option value="' . $product['idstkproduct'] . '">' . $product['product_name'] . '</option>';
          }
          ?>
        </select>
      </td>
      <td>
        <select name="designation_id[]" id="designation_id_1">
          <option value="">Select Item</option>
        </select>
      </td>
      <td><input type="number" name="quantity[]" id="quantity_1" min="1"></td>
      <td id="newCell_1"></td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <td colspan="2">

        <button id="addNewColumn" onclick="addColumn()">Add New Column</button>

      </td>
    </tr>
  </tfoot>
</table>

<script>
const addColumn = () => {
  [...document.querySelectorAll('#myTable tbody tr')].forEach((row, i) => {
    const firstCell = row.children[0]; // Get the first cell of the row

    // Determine data type based on the first cell's element type
    let newElement;
    if (firstCell.tagName === 'SELECT') {
      newElement = document.createElement("select"); // Create a new select element
    } else if (firstCell.tagName === 'INPUT' && firstCell.type === 'number') {
      newElement = document.createElement("input");
      newElement.setAttribute('type', 'number'); // Create a new number input
    } else {
      newElement = document.createElement("input");
      newElement.setAttribute('type', 'text'); // Default to text input
    }

    const cell = document.createElement("td");
    cell.appendChild(newElement);

    // Insert the new cell before the first child of the row
    row.insertBefore(cell, row.firstChild); 
  });

  // Update the new column header (optional)
  const newColumnHeader = document.getElementById("newColumnHeader");
  newColumnHeader.textContent = "New Column"; // Change this to your desired text
};


</script>

                  <button type="submit">Record entry</button>
                </form>

                <?php if(isset($_SESSION['response'])) {
                  $response_message = $_SESSION['response']['message'];
                  $is_success = $_SESSION['response']['success'];
                  ?>
                  <div class="responsemessage">
                    <p class="responsemessage <?= $is_success ? 'responsemessage__success' : 'responsemessage__error'?>">
                      <?= $response_message ?>
                    </p>
                  </div>
                  <?php unset($_SESSION['response']); }?>
              </div>
            </div>
          </div>
        </div>
      </div>

      <?php include('partials/app-scripts.php');?>
    </body>
</html>

javascript.js :

function fetchDesignations(productIdElementId) {
  var productId = $('#product_id_' + productIdElementId).val();
  $.ajax({
    url: 'get_designations.php',
    type: 'POST', // Ensure POST method for data sending
    data: { idstkproduct: productId }, // Use 'idstkproduct' as the data key
    dataType: 'json',
    success: function(data) {
      var designationDropdown = $('#designation_id_' + productIdElementId);
      designationDropdown.empty(); // Clear existing options
      designationDropdown.append('<option value="">Select Item</option>'); // Add default option
      if (data && $.isArray(data)) {
        $.each(data, function(index, designation) {
          designationDropdown.append($('<option>', {
            value: designation.value, // Use 'idstkdesign' for value
            text: designation.text // Use 'designation' for text
          }));
        });
      }
    },
    error: function(xhr, status, error) {
      console.error('An error occurred:', error);
    }
  });
}

Multiple splide carousels- how can I store each carousel in a forLoop as a separate variable so I can use splide.go() to advance slides?

This may be more of a javascript question with .forEach loops but basically the loop makes a new splide carousel each time the module is used.

Tl;DR: if I have a .forEach loop how can I save each of the splide carousels as a variable? is it possible?

Before, I had a function that took a data-id to correspond to a specific image in the splide carousel and passed it through the splide.go(); function to advance the carousel to a specific image when clicking corresponding buttons.

Ever since making a .forEach loop this breaks (because I don’t have a splide variable anymore like before). How can I make a variable for each carousel that I can then use to advance the slide how it should be?

The code will break because it has Hubl (Hubspot) code for the fields/data id info

$(document).ready(function() {
  var splide = new Splide('#features-image-carousel', {
    pagination: false,
    autoplay: false,
    arrows: true,
    navigation: false,
    type: 'loop',
    perPage: 1,
  }).mount();

  $('.features-top-tab .button-primary').click(function() {
    let id = $(this).data('id');
    splide.go(id - 1);
  });


  var button = document.querySelector('.features-image-carousel-container .features-top-tab .button-primary');
  button.classList.add('active');

  $(function() {

    $(".features-image-carousel-container .features-top-tab .button-primary").on("click", function(e) {
      $('.features-image-carousel-container .features-top-tab .button-primary').not(this).removeClass('active')
      $(this).addClass("active")
    })

  });
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<div class="features-carousel">
  <section class="splide" id="features-image-carousel" aria-label="Splide Basic HTML Example">
    <div class="splide__arrows">
      <button class="splide__arrow splide__arrow--prev">
                         </button>
      <button class="splide__arrow splide__arrow--next">
                         </button>
    </div>

    <div class="splide__track">
      <ul class="splide__list">

        <li class="splide__slide">

          <img data-src="{{ item.src }}" src="{{ item.src|escape_url }}" alt="{{ item.alt|escape_attr }}" {{ loadingAttr }} {{ sizeAttrs }}> {% endif %}
        </li>
        {% endfor %}
      </ul>
    </div>
    <div class="features-top-tab-row">
      {% for item in module.top_carousel_tab %}
      <div class="features-top-tab">
        <div data-id="{{loop.index}}" class="button-primary">
          {% inline_text field="top_carousel_tab_text" value="{{ item.top_carousel_tab_text }}" %}
        </div>
      </div>

      {% endfor %}
    </div>
  </section>
</div>

My .forEach loop is here (where it broke because there is no variable to attach to the .go() function:

$(document).ready(function(){

    document.querySelectorAll('.splide').forEach(carousel => new Splide( carousel, {
 pagination: false,
    autoplay: false,
    arrows: true,
        navigation:false,
    type: 'loop',
    perPage: 1,
} ).mount());

Info on the splide.go() command is here: https://splidejs.com/components/controller/

is the if statement missing a condition? [duplicate]

so my division function needs an if statement if dividing by 0 and i have written one but the problem is depending on the operator error message is there regardless of the input numbers even if it does not contain 0 as one of the numbers. Or returns infintiy if 0 is presence. the code below returns infinity so i am wondering if my if statement condition is wrong?

const input = [6, 25, 0];
const findSum = input.reduce((acc, num) => acc + num, 0);
console.log(findSum);

let i;
if (input[i] === 0) {
  throw new Error(findSum + " / " + input);
}
const divBy = (findSum, arr, targ) => findSum / arr[targ];
const divNum = divBy(findSum, input, 2)
console.log(divNum);

Image component will not render valid s3 url aftering fetching and setting state in useEffect

I’m trying to render an image via Image component after retrieving the url from s3 (using aws amplify). The fetch and setting state is done in useEffect, and getUrl is implemented following example in https://docs.amplify.aws/javascript/build-a-backend/storage/download/. When the page renders, the image displays as just a grey boxscreenshot of grey box rendered:

import React, { useEffect, useState } from 'react';
import { Text, StyleSheet, View } from 'react-native';
import { Card, Image } from 'react-native-elements';
import { getUrl } from 'aws-amplify/storage';

const TestFetch2 = () => {
    const [imageSource, setImageSource] = useState(null);
    const productImage = "IMG_0006.jpg"

    useEffect(() => {
        console.log("---USE EFFECT CALLED---")
        const getImage = async () => {
            try {
                const imageResponse = await getUrl({
                    key: productImage
                })
                setImageSource({
                    uri: imageResponse.url
                });
                console.log("INSIDE USEEFFECT GETIMAGE: ", imageSource)
            } catch (e) {
                console.log(e);
            }
        };
        getImage()
        console.log("INSIDE USEEFFECT: ", imageSource)
    }, [])

    return (
        <Card containerStyle={styles.cardContainer}>
            {console.log("RETURN: ", imageSource)}
            {imageSource && (
                <Image source={imageSource} style={styles.productImage} />
            )}
            {!imageSource && (
                <View style={styles.altView}>
                    <Text>Product Image</Text>
                </View>
            )}
        </Card>
    );
};

export default TestFetch2;

I’ve set various console.log statements to see what is happening, and here is what I see:

 LOG  RETURN:  null
 LOG  ---USE EFFECT CALLED---
 LOG  INSIDE USEEFFECT:  null
 RETURN:  {"uri": <valid url fetched from getUrl> }
 LOG  INSIDE USEEFFECT GETIMAGE:  null
 RETURN:  {"uri": <valid url fetched from getUrl> }

I’ve testing the url to be valid by both opening it in browser and hardcoding source={imageSource} to the actual url string: in both cases, the image renders.
url hardcoded as source={{uri: }
I understand that the two console.logs inside of useEffect are returning null because getUrl is an async function, and therefore the console.logs run before the state is set. However, the console.log in return statement does hold valid urls, and also the check to ensure imageSource exists imageSource && passes (upon loading, I can see “Product Image” string displayed for a split second before the image becomes empty, making me believe that at first imageSource was empty then after useEffect, the state was updated with the url and the component reloaded.

I’ve tried a few different approached:

  1. Move getImage() defining to outside of useEffect. Same result
  2. Change getImage() to return the result, then use the return result to call setState in useEffect instead of inside of getImage() function. Same result
    useEffect(() => {
        const imageResponse = getImage()
        setImageSource({
            uri: imageResponse.url
        });
    }, [])
    const getImage = async () => {
        try {
            const imageResponse = await getUrl({
                key: productImage
            })
            return imageResponse
        } catch (e) {
            console.log(e);
        }
    };
  1. Try different ways of setting source: src=, source={imageSource}