ThreeJS, Textures incorrect after exporting with GLTFExporter

I wrote a simple application to merge a number of FBX (the first for the model / materials and the additionals for the animations) from Mixamo to produce a GLB / GLTF to be used in Godot, as I had enough of doing it manually via Blender, but I am facing an odd behaviour.

When I export the model using the GLTFExporter the textures are totally messed up.

This is the code for the export

const exporter = new GLTFExporter();

// Parse the input and generate the gltf output
exporter.parse(
    mainModel,
    // called when the gltf has been generated
    function(gltf) {
        // download the gltf file
        const blob = new Blob([JSON.stringify(gltf)], {type: 'text/plain'});
        const link = document.createElement('a');
        link.download = 'model.gltf';
        link.href = URL.createObjectURL(blob);
        link.click();
    },
    // called when there is an error in the generation
    function ( error ) {
        console.log( 'An error happened' );
        console.log(error);
    },
    {
        binary: false,
        animations: mainModel.animations,
        maxTextureSize: 4096,
        includeCustomExtensions: true
    }
);

This is the result (on the left the correct one meanwhile on the right the exported one)

correct-incorrect-model

Is it a known issue? Am I doing something incorrect?

Thanks for the help!

How to correctly extract URL parameters in Next.js 14 API routes without ‘req.query’ undefined error?

I’ve been upgrading to Next.js 14 and encountered an issue when trying to access dynamic route parameters. I’m following the official docs to handle a DELETE request and extract the ‘id’ from the URL, but I’m running into a TypeError: Cannot destructure property ‘id’ of ‘req.query’ as it is undefined. The error persists despite following the new patterns suggested in Next.js 14. How do I properly access dynamic route parameters in API routes with this latest version? Below is the snippet causing trouble:

export async function GET(req) {

  console.log(req.query)

  const { id } = req.query;

}

What’s the correct method to avoid this error and successfully extract parameters in Next.js 14 API routes?

I tried following too.

import { useRouter, useParams } from 'next/navigation'
const params = useParams();
const id = params.id;

Inject HTML metadata into a URL loaded in Cypress

I want to write Cypress tests for a website that is being loaded as an iFrame in a parent environment. The parent environment injects metatags when loading the site, and I need to replicate this functionality in Cypress.

Do to so, I need to fetch the contents of a URL passed by a test runner, modify the <head></head> of the HTML to add meta tags like this:

metaTag.setAttribute("dark-mode", "true");

then load the site with the metadata. However, if I fetch the contents, add metadata, but then run cy.visit(URL), only the unmodified site is loaded.

I know Cypress allows accessing metatags, but does it support injecting them?

How to get dropdown menu in prompt, with data from mysql table?

I am trying to create calendar where I can add event(class with student), edit and delete event. And it’s ok, it’s working, but I would like to have an dropdown menu/list with students names (the names are stored in database “calendar” table “students”), so I can just click on student name not to type it every time. I have this files and code:

index.php:


<?php
//index.php




?>
<!DOCTYPE html>
<html>
 <head>
  <title>Title</title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.4.0/fullcalendar.css" />
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.css" />
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.4.0/fullcalendar.min.js"></script>
  <script>
   
  $(document).ready(function() {
   var calendar = $('#calendar').fullCalendar({
    editable:true,
    header:{
     left:'prev,next today',
     center:'title',
     right:'month,agendaWeek,agendaDay'
    },
    events: 'load.php',
    selectable:true,
    selectHelper:true,
    select: function(start, end, allDay)
    {
     var title = prompt("Enter Event Title");
     if(title)
     {
      var start = $.fullCalendar.formatDate(start, "Y-MM-DD HH:mm:ss");
      var end = $.fullCalendar.formatDate(end, "Y-MM-DD HH:mm:ss");
      $.ajax({
       url:"insert.php",
       type:"POST",
       data:{title:title, start:start, end:end},
       success:function()
       {
        calendar.fullCalendar('refetchEvents');
        alert("Added Successfully");
       }
      })
     }
    },
    editable:true,
    eventResize:function(event)
    {
     var start = $.fullCalendar.formatDate(event.start, "Y-MM-DD HH:mm:ss");
     var end = $.fullCalendar.formatDate(event.end, "Y-MM-DD HH:mm:ss");
     var title = event.title;
     var id = event.id;
     $.ajax({
      url:"update.php",
      type:"POST",
      data:{title:title, start:start, end:end, id:id},
      success:function(){
       calendar.fullCalendar('refetchEvents');
       alert('Event Update');
      }
     })
    },

    eventDrop:function(event)
    {
     var start = $.fullCalendar.formatDate(event.start, "Y-MM-DD HH:mm:ss");
     var end = $.fullCalendar.formatDate(event.end, "Y-MM-DD HH:mm:ss");
     var title = event.title;
     var id = event.id;
     $.ajax({
      url:"update.php",
      type:"POST",
      data:{title:title, start:start, end:end, id:id},
      success:function()
      {
       calendar.fullCalendar('refetchEvents');
       alert("Event Updated");
      }
     });
    },

    eventClick:function(event)
    {
     if(confirm("Are you sure you want to remove it?"))
     {
      var id = event.id;
      $.ajax({
       url:"delete.php",
       type:"POST",
       data:{id:id},
       success:function()
       {
        calendar.fullCalendar('refetchEvents');
        alert("Event Removed");
       }
      })
     }
    },

   });
  });
   
  </script>
 </head>
 <body>
  <br />
  <h2 align="center"><a href="#">Title</a></h2>
  <br />
  <div class="container">
   <div id="calendar"></div>
  </div>
 </body>
</html>


load.php

<?php

//load.php

$connect = new PDO('mysql:host=localhost;dbname=calendar', 'root', 'password');

$data = array();

$query = "SELECT * FROM events ORDER BY id";

$statement = $connect->prepare($query);

$statement->execute();

$result = $statement->fetchAll();

foreach($result as $row)
{
 $data[] = array(
  'id'   => $row["id"],
  'title'   => $row["title"],
  'start'   => $row["start_event"],
  'end'   => $row["end_event"]
 );
}

echo json_encode($data);

?>

insert.php

<?php

//insert.php

$connect = new PDO('mysql:host=localhost;dbname=calendar', 'root', 'password');

if(isset($_POST["title"]))
{
 $query = "
 INSERT INTO events 
 (title, start_event, end_event) 
 VALUES (:title, :start_event, :end_event)
 ";
 $statement = $connect->prepare($query);
 $statement->execute(
  array(
   ':title'  => $_POST['title'],
   ':start_event' => $_POST['start'],
   ':end_event' => $_POST['end']
  )
 );
}


?>

update.php

<?php

//update.php

$connect = new PDO('mysql:host=localhost;dbname=calendar', 'root', 'password');

if(isset($_POST["id"]))
{
 $query = "
 UPDATE events 
 SET title=:title, start_event=:start_event, end_event=:end_event 
 WHERE id=:id
 ";
 $statement = $connect->prepare($query);
 $statement->execute(
  array(
   ':title'  => $_POST['title'],
   ':start_event' => $_POST['start'],
   ':end_event' => $_POST['end'],
   ':id'   => $_POST['id']
  )
 );
}

?>

delete.php

<?php

//delete.php

if(isset($_POST["id"]))
{
$connect = new PDO('mysql:host=localhost;dbname=calendar', 'root', 'password');
 $query = "
 DELETE from events WHERE id=:id
 ";
 $statement = $connect->prepare($query);
 $statement->execute(
  array(
   ':id' => $_POST['id']
  )
 );
}

?>

Database “calendar”.
Table “students” with columns: id, student_name
Table “event” with columns: id, title, start_event, end_event

I try some changes but I didn’t get result which I want.

Emoji Mart Picker categories not responding to click events in Stimulus Controller

I’m integrating the Emoji Mart Picker into a Stimulus controller and encountering an issue: the category icons in the picker are unresponsive to clicks, preventing category switching. The picker initializes correctly, and I can select emojis, but I can’t switch categories. There are no console errors.

Here are the steps I’ve taken:

  • Ensured that Emoji Mart does not list React as a dependency, as my project isn’t using React.
  • Tried installing React to see if it would resolve the issue, which it didn’t.
  • Attempted to follow the documentation for non-React environments, but the issue persists.

I’m also unclear on the role of the data property during the Picker’s initialization and whether it’s related to this issue. The documentation at Emoji Mart’s GitHub doesn’t seem to require it explicitly for basic functionality.

Here’s my package.json snippet for relevant dependencies:

jsonCopy code

"dependencies": {
    "@emoji-mart/data": "^1.1.2",
    "emoji-mart": "^5.5.2",
    // ... other unrelated packages ...
}

And here’s a concise version of my current Stimulus controller setup:

javascriptCopy code

// EmojiPicker_controller.js
import { Controller } from '@hotwired/stimulus';
import * as EmojiMart from "emoji-mart";

export default class EmojiPicker_controller extends Controller {
    // ... other methods ...

    connect() {
        // ... code to check for mobile and initialize picker ...
        this.picker = new EmojiMart.Picker({
            set: 'twitter',
            theme: 'dark',
            onEmojiSelect: (emoji) => this.onEmojiSelect(emoji),
            // ... more options ...
        });

        // ... append to body, set class, and hide ...
    }

    // ... other methods ...
} 

I’ve also tried different variations of initializing the picker with data passed in, to no avail.

Has anyone experienced this or have suggestions on what could be going wrong?

Uncaught SyntaxError: The requested module does not provide an export named ‘subscribeToTopic’ (at Appointment.vue:28:10)

I am trying to import a function located in a separate javascript file into the Vue project that I am working on. I am sure that the route of the file is correct but I keep on receiving an error like this.
Uncaught SyntaxError: The requested module ‘/@fs/C:/Users/david/OneDrive/바탕 화면/Gothenburg University/Mini Project (Distributed Systems)/group3/MQTT-Connector/listSlots.js’ does not provide an export named ‘subscribeToTopic’ (at Appointment.vue:28:10)

I am importing the file like this

import { subscribeToTopic } from '../../../MQTT-Connector/listSlots'

And the function is exported like this

export function subscribeToTopic() {
    try {
        mqttSubscriber.subscribeToTopic('slot-details');
        console.log("Slot details saved as a json file.")
    } catch (error) {
    console.error('Error retrieving slot details:', error.message);
    }
}

Thanks a lot in advance!!

I tried everything like trying to use const instead of import statement or try using export default. However, I had no luck

How to keep to select boxes in sync based on zustand store value in react?

One of the requirements for an web app i’m working on is to have multiple languages, to implement this i’m using i18n and zustand to store the new set language and have it accessible in any component/page.

I have two select boxes, one in the navbar and another in the footer of the page to set language.
The problem is, when i set a new language in one select box, the page is translated, but i want the other select box to have it’s default value as the new language set(picking it up from zustand store), so in both the navbar and the footer would have the same default value and be synced whenever one has changed.

For example the page starts with portuguese, but if i change it to english, the other select box still has the old value(portuguese), altho it’s default value is set to the value in zustand store.

I’ve thought and tried couple solutions like storing the language in local storage and then get it or creating a function that runs always but none worked for me. Also wasn’t alble to find anyonw with a similiar problem when researching it.

Bellow follows the code for the navbar component, the footer component and the zustand store.

Navbar:

import {
  BtnWrapper,
  LanguageSelector,
  Link,
  Logo,
  NavBar,
  NavListItem,
  NavlinkItemHighlighted,
  Navlist,
  RegisterAndLoginButton,
} from "./NavbarWithoutLogin.styles";
import { useTranslation } from "react-i18next";
import { useWebSiteLanguageStore } from "../../../store/WebSiteLanguageStore";

export const Nav = () => {
  const { t } = useTranslation()
  const websiteLanguageStore = useWebSiteLanguageStore()

  return (
    <>
      <NavBar>
        <Logo>logo</Logo>
        <Navlist>
          <NavlinkItemHighlighted>
            <span>{t("navbarLink1")}</span>
          </NavlinkItemHighlighted>
          <NavListItem>
            <Link>{t("navbarLink2")}</Link>
          </NavListItem>
          <NavListItem>
            <Link>{t("navbarLink3")}</Link>
          </NavListItem>
          <NavListItem>
            <Link>{t("navbarLink4")}</Link>
          </NavListItem>
          <NavListItem>
            <Link>{t("navbarLink5")}</Link>
          </NavListItem>
          <NavListItem>
            <RegisterAndLoginButton>
              {t("navbarLoginButton")}
            </RegisterAndLoginButton>
            |
            <RegisterAndLoginButton>
              {t("navbarRegisterButton")}
            </RegisterAndLoginButton>
          </NavListItem>
        </Navlist>
        <BtnWrapper>
          <LanguageSelector
            defaultValue={websiteLanguageStore.currentlySelectedLanguage}
            onChange={(e) =>
              websiteLanguageStore.changeCurrentlySelectedLanguage(
                e.target.value
              )
            }
          >
            <option value="pt">{t("navbarLanguageSelectorOption1")}</option>
            <option value="fr">{t("navbarLanguageSelectorOption2")}</option>
            <option value="en">{t("navbarLanguageSelectorOption3")}</option>
            <option value="de">{t("navbarLanguageSelectorOption4")}</option>
            <option value="tt">{t("navbarLanguageSelectorOption5")}</option>
            <option value="es">{t("navbarLanguageSelectorOption6")}</option>
          </LanguageSelector>
        </BtnWrapper>
      </NavBar>
    </>
  );
};

Footer:

import {
  LinkBox,
  LinkBoxUlLi,
  Footer,
  Copyright,
  CopyrightText,
  HelpCenterBox,
  LanguageSelector,
} from "./PageFooter.styles";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCopyright } from "@fortawesome/free-solid-svg-icons";
import {
  faFacebook,
  faLinkedin,
  faSquareInstagram,
  faYoutube,
} from "@fortawesome/free-brands-svg-icons";
import { useTranslation } from "react-i18next";
import { useWebSiteLanguageStore } from "../../../store/WebSiteLanguageStore";

export const PageFooter = () => {
  const { t } = useTranslation();
  const websiteLanguageStore = useWebSiteLanguageStore();

  return (
    <>
      <Footer>
        <div>
          <b>{t("footerFistSectionTitle")}</b>
          <LinkBox>
            <LinkBoxUlLi>
              <a>{t("footerFirstSectionOptions1")}</a>
            </LinkBoxUlLi>
            <LinkBoxUlLi>
              <a>{t("footerFirstSectionOptions12")}</a>
            </LinkBoxUlLi>
            <LinkBoxUlLi>
              <a>{t("footerFirstSectionOptions13")}</a>
            </LinkBoxUlLi>
          </LinkBox>
        </div>
        <div>
          <b>{t("footerSecondSectionTitle")}</b>
          <LinkBox>
            <LinkBoxUlLi>
              <a>{t("footerSecondSectionOption")}</a>
            </LinkBoxUlLi>
            <LinkBoxUlLi>
              <a>{t("footerSecondSectionOption2")}</a>
            </LinkBoxUlLi>
            <LinkBoxUlLi>
              <a>{t("footerSecondSectionOption3")}</a>
            </LinkBoxUlLi>
            <LinkBoxUlLi>
              <a>{t("footerSecondSectionOption4")}</a>
            </LinkBoxUlLi>
          </LinkBox>
        </div>
        <div>
          <b>{t("footerThirdSectionTitle")}</b>
          <LinkBox>
            <LinkBoxUlLi>
              <a>{t("footerThirdSectionOption")}</a>
            </LinkBoxUlLi>
            <LinkBoxUlLi>
              <a>{t("footerThirdSectionOption2")}</a>
            </LinkBoxUlLi>
          </LinkBox>
        </div>
        <div>
          <b>{t("footerThirdSectionTitle")}</b>
          <LinkBox>
            <LinkBoxUlLi>
              <HelpCenterBox>
                {t("footerFourthSectionHelpCenterBox")}
              </HelpCenterBox>
            </LinkBoxUlLi>
          </LinkBox>
          <span>{t("footerFourthSectionLanguageSelector")}: </span>
          <LanguageSelector
            defaultValue={websiteLanguageStore.currentlySelectedLanguage}
            onChange={(e) => {
              websiteLanguageStore.changeCurrentlySelectedLanguage(
                e.target.value
              );
            }}
          >
            <option value="pt">{t("footerLanguageSelectorOption1")}</option>
            <option value="fr">{t("footerLanguageSelectorOption2")}</option>
            <option value="en">{t("footerLanguageSelectorOption3")}</option>
            <option value="de">{t("footerLanguageSelectorOption4")}</option>
            <option value="tt">{t("footerLanguageSelectorOption5")}</option>
            <option value="es">{t("footerLanguageSelectorOption6")}</option>
          </LanguageSelector>
        </div>
        <div>
          <b>{t("footerFollowUsSectionTitle")}</b>
          <LinkBox>
            <LinkBoxUlLi>
              <a>
                <FontAwesomeIcon icon={faFacebook} size="xl" />
              </a>{" "}
              <a>
                <FontAwesomeIcon icon={faSquareInstagram} size="xl" />
              </a>{" "}
              <a>
                <FontAwesomeIcon icon={faYoutube} size="xl" />{" "}
                <a>
                  <FontAwesomeIcon icon={faLinkedin} size="xl" />
                </a>{" "}
              </a>{" "}
            </LinkBoxUlLi>
          </LinkBox>
        </div>
      </Footer>
      <Copyright>
        <CopyrightText>
          <FontAwesomeIcon icon={faCopyright} /> {t("footerCopyWrightText")}{" "}
        </CopyrightText>
      </Copyright>
    </>
  );
};

zustand store:

import { create } from "zustand";
import i18n from "../i18n";

type WebSiteLanguageSettings = {
  currentlySelectedLanguage: string
  changeCurrentlySelectedLanguage: (language: string) => void
}

export const useWebSiteLanguageStore = create<WebSiteLanguageSettings>(
  (set) => {
    return {
      currentlySelectedLanguage: i18n.language,
      changeCurrentlySelectedLanguage(language) {
        i18n.changeLanguage(language)
        this.currentlySelectedLanguage = language
      },
    };
  }
);

I’m using styled-components, if the style files are needed i can post it here.

WooCommerce cart update causes section to disappear after AJAX refresh

I’m experiencing a peculiar issue with my WooCommerce cart where the coupon section disappears after an AJAX refresh, but only under specific conditions. The problem arises when:

  1. A coupon is applied to the cart.
  2. The quantity of an item is then updated.
  3. The “Update cart” button is pressed.
  4. Post-AJAX, the coupon section completely vanishes.

However, if a product is removed from the cart, the subsequent AJAX update causes the coupon section to reappear. This unexpected behavior occurs without any evident errors in the JavaScript console.

Here’s the problematic section handling the coupon application and the update button:

<div class="cart-coupon-container">
    <!-- Coupon and update button -->
    <button type="submit" class="button update-cart" name="update_cart" value="<?php esc_attr_e( 'Update cart', 'woocommerce' ); ?>">
        <?php esc_html_e( 'Update cart', 'woocommerce' ); ?>
    </button>
    <?php do_action( 'woocommerce_cart_actions' ); ?>
    <?php wp_nonce_field( 'woocommerce-cart', 'woocommerce-cart-nonce' ); ?>
    <?php if ( wc_coupons_enabled() ) : ?>
        <div class="coupon">
            <label for="coupon_code" class="screen-reader-text"><?php esc_html_e( 'Coupon:', 'woocommerce' ); ?></label>
            <input type="text" name="coupon_code" class="input-text" id="coupon_code" value="" placeholder="<?php esc_attr_e( 'Coupon code', 'woocommerce' ); ?>" />
            <button type="submit" class="button" name="apply_coupon" value="<?php esc_attr_e( 'Apply coupon', 'woocommerce' ); ?>">
                <?php esc_html_e( 'Apply coupon', 'woocommerce' ); ?>
            </button>
            <?php do_action( 'woocommerce_cart_coupon' ); ?>
        </div>
    <?php endif; ?>
</div>

I expect the coupon section to remain visible and functional after any AJAX updates in the cart. For a clearer understanding of the issue, I have attached a video demonstrating the problem:
https://share.zight.com/z8udgzYx

Any insights into what might be causing this behavior or suggestions for a fix would be greatly appreciated.

How to decode PKCS#7/ASN.1 using Javascript?

Recently I started to work on Apple app store receipt validation and due to the deprecation of the legacy /verifyReceipt endpoint, I decided to go for on-device validation. The guideline described gives a step-by-step solution for MacOS however we want to perform this validation in the backend service using NodeJs. For the purpose of this validation information defined in the PCKS7# container is required to be decoded. Here my knowledge comes short as I am unable to retrieve this information (e.g. receipt_creation_data, bundle_id) I managed to convert the receipt from PCKS7 to ASN.1 but could not find a way to retrieve the actual key values from it. I tried several libraries like node-forge, asn1js, asn1.js. What I found really useful were these resources:

AFAIK the information should be encoded in OCTET STRING format
enter image description here

What is the purpose of using “Null” as a condition into IF statements?

I’d like to create a timer using JavaScript but I had this problem when I wanted to understand the code:

What is the purpose of writing this code in if statements :

let [seconds, minutes, hours] = [0, 0, 0];
let displayTime = document.getElementById("displayTime");
let timer = null;

function stopwatch() {
    seconds++;
    if (seconds == 60) {
        seconds = 0;
        minutes++;
        if (minutes == 60) {
            minutes = 0;
            hours++;
        }
    }

    let s = seconds < 10 ? "0" + seconds: seconds;
    let m = minutes < 10 ? "0" + minutes: minutes;
    let h = hours < 10 ? "0" + hours: hours;
    displayTime.innerHTML = h + ":" + m +":"+ s;
}

function watchStart() {
    if(timer !== null) { 
        clearInterval(timer);
    }
    timer = setInterval(stopwatch, 1000);
}

When does this condition materialize and if we assume that it has achieved what it does?

I hope my question is understandable to everyone.

React + Material UI is it posible to change scrollbar to buttons

I have a component that shows a scrollable list of cards. Is it possible to change the scrollbar to buttons to move between the cards.
Image of my solution

Tis would be my code

<Box
        style={{
          flexWrap: "wrap",
          justifyContent: "space-around",
          overflow: "hidden",
          width: "70%",
          overflowX: "scroll",
        }}
      >
        <Grid container spacing={3} style={{ flexWrap: "nowrap" }}>
          {data.map((data, index) => {
            const { Title, Summary } = data;
            return (
              <Grid item>
                <Card sx={{ width: 300 }}>
                  <CardMedia
                    sx={{ height: 140 }}
                    image="/static/images/cards/contemplative-reptile.jpg"
                    title="green iguana"
                  />
                  <CardContent>
                    <Typography gutterBottom variant="h5" component="div">
                      {Title}
                    </Typography>
                    <Typography variant="body2" color="text.secondary">
                      {Summary}
                    </Typography>
                  </CardContent>
                </Card>
              </Grid>
            );
          })}
        </Grid>
      </Box>

db2 javascript/Node.js – ensure SQL data extraction completed before next instruction

I am trying to understand how to use javascrip/Node.js functions to ensure SQL data extraction is completed before writing to console.log (or web server). Reading up on promises, promised-based drivers, async functions, but have not got example working.

using node v18.17.1 on IBM i (AS400)

Example:

// npm install idb-pconnector
function get_data() {
    const { Connection, Statement, } = require('idb-pconnector');

    async function execExample() {
        const connection = new Connection({ url: '*LOCAL' });
        const statement = new Statement(connection);

        const results = await statement.exec('SELECT * FROM QIWS.QCUSTCDT');

       console.log(`1. results:n ${JSON.stringify(results)}`);        
        // return results;
        return JSON.stringify(results);
    }
    data = execExample().catch((error) => {
    console.error(error);    
    });    
}

data = get_data();
console.log("2." + data);

Stale Element found error while trying to use Selenium Web Scraper on the Home Depot website

I have been dealing with an issue of getting stale elements while attempting to web scrape the home depot wood and composites page using Selenium Web Driver. I have tried multiple solutions including adding a waitForStableElemets method. I’m not sure if the error is generating from that method or from the wood_and_composites method.

async function wood_and_composites(){
    let driver = await new Builder().forBrowser("chrome").build();
    //console.log(driver.toString())

    //driver.get("https://www.ebay.com");//test to make sure it works
    driver.get("https://www.homedepot.com/b/Building-Materials/N-5yc1vZaqns"); //goes to the building materials page of home depot

     const cardTitles = await driver.findElements(By.className("etchVisualNavigationStory__card__title"));//should be the title of each component on the page

    //iterates through all the cardTitles on the website provided
    for(const item of cardTitles){
        const title = await item.getText();
        //console.log(title)
        //checks to see if an item matches the label "Lumber" and then clicks it
        if(title.includes("Lumber")){
            await item.click();
            //console.log("Lumber has been found and has been selected"); //TEST STATEMENT
            //goes to page consisting of all lumber and composites.
            const sidebar = await driver.wait(until.elementLocated(By.className("navigational-layout__side-navigation")), 10000);
            //the .wait() should wait 10 seconds before looking for the sidebar component to ensure everything is loaded in correctly.
            const unorderedList = sidebar.findElement(By.tagName("ul"));
            const listItems = await unorderedList.findElements(By.tagName("li"));
            //checks to see if the sidebar contains the link for all lumber and composites
            for(const listItem of listItems){
                const itemText = await listItem.getText();
                //console.log(itemText);
                if(itemText.includes("Shop All Lumber & Composites")) {
                    await listItem.click();
                    //attempts to find all the prices on the page
                    const woodPrices = await driver.wait(until.elementsLocated(By.css(".price-format__main-price")), 10000);
                    const prices = await driver.findElements(By.xpath("//div[contains(@class, 'price-format__main-price')] | //*[@id='bulk-price']"));
                    const names = await driver.findElements(By.xpath("//div[contains(@class, 'product-header__title--clamp--4y7oa product-header__title--fourline--4y7oa')]"));

                    // Wait for all elements to be visible
                    // Function to handle stale elements and ensure they are visible
                    const waitForStableElements = async (elements) => {
                        return driver.wait(async () => {
                            const refreshedElements = await Promise.all(elements.map(async (el) => {
                                try {
                                    const displayed = await el.isDisplayed();
                                    if (!displayed) {
                                        const parent = await el.findElement(By.xpath("./.."));
                                        return parent.isDisplayed();
                                    }
                                    return displayed;
                                } catch (error) {
                                    return false; // Element is stale or no longer present
                                }
                            }));
                            return refreshedElements.every(Boolean);
                        }, 20000);
                    };

                    // Wait for all elements to stabilize
                    await waitForStableElements(names);

                    //USED TO FORMAT THE STRING SO THE PRICE AND NAME ARE TOGETHER
                    //if (prices.length === names.length) { //currently there are 20 prices and 12 names for some reason
                    for (let i = 0; i < names.length && i+1 < prices.length; i++) {
                        const cost = await prices[i+1].getText(); // Use i+1 for prices
                        const dollars = cost.slice(0, cost.length - 2);
                        const cents = cost.slice(cost.length - 2);
                        const formattedPrice = dollars + "." + cents;

                        const name = await names[i].getText();

                        const output = `Price: ${formattedPrice} Product: ${name}`;
                        console.log(output);
                    }
                }
            }
            break;
        }
    }

     setInterval(function(){
         driver.close();
    }, 15000)
}

With the addition of the waitForStableElements method i tried to refresh the stale elements on the page, so that they could be retrieved. i am able to find 20 prices and 12 product names, but there should be 24 total on the first page. I am not sure why there are still stale elements being found.

Toggle button how to return true if it is ON and false if is OFF

Newbie to front-end world i am trying to implement a logic when a toggle button is on i want to return True and when it is turned off i want to return False

Below is my HTML

 <div class="toggle-button">

    <body>
      <label class="showLabel" for="show">Toggle on or off :</label>
      <label class="toggle">
        <input class="toggle-input" type="checkbox" (click)="helper();" />
        <span class="toggle-label" data-off="OFF" data-on="ON"></span>
        <span class="toggle-handle"></span>
      </label>
    </body>
  </div>

</div>

in typescript i have global variable that i want to be filled with either true or false when toggle is turned on or off –

Typescript global variable –

isToggled=false (if toggle is off)

or

isToggled=true (if toggle is on)

I would appreciate any help