How can I download a JavaScript library’s source code locally and modify or add custom features? [closed]

I want to download the source code of a JavaScript open-source library (Layerhub Open Source SDK for creating design editors) to my local machine so I can explore the code and add some custom features or modifications.

Can someone please guide me on the following:

How to properly clone or download the library’s source code from GitHub (or another repository)?

What steps are needed to build the library locally after making changes?

How can I test or use my modified version in a local project?

Are there best practices for working with and maintaining a custom fork of an open-source JS library?

Boostrap dropdown into modal

My HTML:

<button id="charts" type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#modal">MODAL</button>

<div class="modal" id="modal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog modal-dialog-scrollable">
        <div class="modal-content">
            <div class="modal-body">
                <div class="btn-group">
                    <button type="button" class="btn btn-dark dropdown-toggle tags" data-bs-toggle="dropdown" aria-expanded="false">TAGS</button>
                    <ul class="dropdown-menu">
                        <li><a class="dropdown-item" href="#">Action</a></li>
                        <li><a class="dropdown-item" href="#">Another action</a></li>
                        <li><a class="dropdown-item" href="#">Something else here</a></li>
                    </ul>
                </div>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-dark" data-bs-dismiss="modal">CLOSE</button>
            </div>
        </div>
    </div>
</div>

JSFiddle: https://jsfiddle.net/82haczmk/

My problem is when I click on the button to open the dropdown menu. The height of the modal-body is not increasing, instead the modal is hidden and I have to scroll into modal-body.

How I can make the modal-body to increases the height?

Code Splitting With Dynamic Routes in Next.js

I’m working on a project using Next.js 15 with the App Router and dynamic routes. I’ve encountered an issue where JavaScript and CSS are not being split into separate chunks as expected when using SCSS modules and components.

This works perfectly when there are no dynamic routes — scripts and styles are properly code-split and loaded per page. However, when using dynamic routing, everything is bundled into a single large chunk. As a result, if I have many pages with different components, all scripts and styles for every page are loaded together, even if only one page is being visited.

Here’s the relevant folder structure:

app
 [locale]
   [[...slug]]
      page.tsx
   layout.tsx
enter code here

Tried dynamic imports inside a route switch:

const renderPage = async () => {
  switch (slug) {
    case 'news':
      const Test = dynamic(() => import('@/components/Test'));
       //or
      const Test = await import('@/components/Test'));
      return <Test />;
    default:
      return 'Hello';
  }
};

Is this a known limitation or bug in Next.js 15 dynamic routing?

How can I enable proper JS and CSS code-splitting when using [[…slug]]?

Are there any recommended workarounds or best practices to avoid loading everything in one chunk?

Accordion symbol not changing when the accordion is clicked

I’m facing an issue with the code below as if i click on an accordion it will open but the Icon symbol “+” will not transform to “-” when it’s opened. the code snippet below is not being activated.
Codepen: https://codepen.io/C3ISR-Everything-Cybersecurity/pen/azbeOEK

  .accordion::after {
                content: '02B';
                font-size: 18px;
                color: #116ce4;
                
                float: right;
                margin-left: 10px;
                transition: transform 0.3s ease-in-out;
        }

        .accordion.active::after {
                content: '2212';
                transform: rotate(45deg);
                color: #777;
        }

  const accordionEl = document.querySelector('.main')
            const panelEls = accordionEl.querySelectorAll('.panel')


            accordionEl.addEventListener('click', ({ target }) => {
            if (target.classList.contains('accordion')) {
                const { nextElementSibling } = target
                panelEls.forEach(panelEl => {
                if (panelEl !== nextElementSibling) {
                    panelEl.classList.remove('open')
                } else {
                    panelEl.classList.toggle('open')
                }
                })
            }
            }) 

/* code below will allow the symbol to change but it will not close other accordions if one is opened.

    var acc = document.getElementsByClassName("accordion");
            var i;
 
            for (let i = 0; i < acc.length; i++) {
                    acc[i].addEventListener("click", function () {
                        this.classList.toggle("active");
                        var panel = this.nextElementSibling;
                        panel.classList.toggle("open");
                    });
                }
           */   
  body {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            background-color: White;
            font-family: Sakkal Majalla;
            direction: rtl;
            position: relative;
            z-index: -2;
            -ms-overflow-style: none;
            
        }
        body::-webkit-scrollbar, body::-webkit-scrollbar-button { display: none; } /* Chrome */


        li {
            list-style: none;
        }

        a {
            text-decoration: none;
        }

        .main{    
            display: grid;
            grid-template-columns: 1fr;
            justify-items: center;
            margin-top: 2rem;
            margin-bottom: 1rem;
        }

        table {
            border: 1px solid #dededf;  
            table-layout: fixed;
            border-collapse: collapse;
            border-spacing: 1px;
            text-align: center;
        }

        th {
            border: 1px solid #dededf;
            background-color: #eceff1;
            color: #000000;
            padding: 5px;
        }

        td {
            border: 1px solid #dededf;
            background-color: #ffffff;
            color: #000000;
            padding: 5px;  
        }
        th:nth-child(1) {  
            width: 30.9rem;
        }

        th:nth-child(2) {  
            width: 10rem;
        }
        th:nth-child(3) {  
            width: 7rem;
        }

        .accordion {
            background-color: #ffffff;
            color: black;
            font-weight: bold;
            cursor: pointer;
            margin-top: 20px;
            padding: 18px;
            border: none;
            text-align: right;
            outline: none;
            font-size: 20px;
            transition: 0.4s;
            width: 50rem;
            border: 1px solid rgb(219, 219, 219);
            border-radius: 8px;
            box-shadow: rgba(100, 100, 111, 0.123) 0px 7px 29px 0px;
        }

        .active, .accordion:hover {
            border-color:  rgb(0, 128, 255);
        }

        .accordion span{
            float: left;
            font-size: 15px;
            color: #116ce4;
        }

        .accordion span::before {
            content:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iZmVhdGhlciBmZWF0aGVyLXVzZXJzIj48cGF0aCBkPSJNMTcgMjF2LTJhNCA0IDAgMCAwLTQtNEg1YTQgNCAwIDAgMC00IDR2MiI+PC9wYXRoPjxjaXJjbGUgY3g9IjkiIGN5PSI3IiByPSI0Ij48L2NpcmNsZT48cGF0aCBkPSJNMjMgMjF2LTJhNCA0IDAgMCAwLTMtMy44NyI+PC9wYXRoPjxwYXRoIGQ9Ik0xNiAzLjEzYTQgNCAwIDAgMSAwIDcuNzUiPjwvcGF0aD48L3N2Zz4=");
            background-size: 15px 15px; /*must match with width and height*/
            display: inline-block;
            width: 15px; 
            height: 15px;
            padding-left: 10px;
            vertical-align: -10%;
        }


           /*I addes a plus sign that will also animate when ypu click on the accordion*/
        .accordion::after {
                content: '02B';
                font-size: 18px;
                color: #116ce4;
                
                float: right;
                margin-left: 10px;
                transition: transform 0.3s ease-in-out;
        }

        .accordion.active::after {
                content: '2212';
                transform: rotate(45deg);
                color: #777;
        }

        .panel {
            max-height: 0;
            overflow: hidden;
            transition: max-height 0.5s ease, padding 0.5s ease;
            padding: 0px;
        }

        .panel.open {
            max-height: 1000px;
            padding: 18px;
        }
   <div class="main">
            <button class="accordion">
                John Doe
            </button>
            <div class="panel">
                <table>
                    <th>company</th>
                    <th>department</th>
                    <th>2025?</th>
                    <tr>
                        <td>COMPANY A</td>
                        <td>FINANCE</td>
                        <td>&#9989;</td>
                    </tr>
                    <tr>
                        <td>COMPANY Z</td>
                        <td>PMO</td>
                        <td>&#10060;</td>
                    </tr>
                </table>
            </div>
                 <button class="accordion">
                John Doe
            </button>
            <div class="panel">
                <table>
                    <th>company</th>
                    <th>department</th>
                    <th>2025?</th>
                    <tr>
                         <td>company A</td>
                        <td>HR</td>
                        <td>&#10060;</td>
                    </tr>
                    <tr>
                       <td>company B</td>
                        <td>HR</td>
                        <td>&#10060;</td>
                    </tr>
                    <tr>
                          <td>company C</td>
                        <td>HR</td>
                        <td>&#10060;</td>
                    </tr>
                </table>
            </div>
                 <button class="accordion">
                John Doe
            </button>
            <div class="panel">
                <table>
                    <th>company</th>
                    <th>department</th>
                     <th>2025?</th>
                    <tr>
                        <td>company A</td>
                        <td>HR</td>
                        <td>&#9989;</td>
                    </tr>
                </table>
            </div>       
    </div>

React js website animations not rendering on mobile platforms

I have created a portfolio website using React js with Node js on VScode to showcase my skillset with a terminal typewriter animation. Everything works perfectly fine on laptop/pc browsers, but when I tried accessing my website on mobile it doesnt show any of the animations even when I switch to desktop website on my android device still no animations playing.

This is my React code ->

import './App.css';
import React, { use, useState } from 'react';
import Windowz from './RoomWindow';
import Table from './Tables';
import Footer from './Footer';
import Contents from './ScreenContent';


function App() {
  
    return (
            <div className="App">
            <Windowz />

            <Contents />

            <Table />
            <Footer />
            </div>
        );
}

export default App;

This is the animation part for windowz showing sun and moon orbit ->

import './App.css';
import React, { useState } from 'react';

function Windowz() {
    //////////////////////////////////////////////////////
    const starsArray = [];
    const stars = 40;
    let x,y = 0;

    // Generate stars randomly using absolute position
    for (let i = 0; i < stars; i++) {
        x = Math.floor(Math.random() * 100 + 1) + "%";
        y = Math.floor(Math.random() * 100 + 1) + "%";
        starsArray.push(x);
        starsArray.push(y);
    }
    //////////////////////////////////////////////////////

    return (
        <div className="bg">
        <div className="x1">
                <div className="cloud"></div>
            </div>

            <div className="x2">
                <div className="cloud"></div>
            </div>

            <div className="x3">
                <div className="cloud"></div>
            </div>

            <div className="x4">
                <div className="cloud"></div>
            </div>

            <div className="x5">
                <div className="cloud"></div>
            </div>
            <div className="sky">
            <div className="sky__phase sky__dawn"></div>
            <div className="sky__phase sky__noon"></div>
            <div className="sky__phase sky__dusk"></div>
            <div className="sky__phase sky__midnight">
                <div id="sky__stars">{starsArray.map((element,index) => {
                    return(<div key={index} style={{ position: "relative", top: element, left: element }}></div>);
                })}</div>
            </div>
        
            <div className="orbit">
                <div className="sun"></div>
                <div className="moon"></div>
            </div>
            
        </div>
        </div>
    );
}

export default Windowz;

and this is the main Screen content part ->

import './App.css';
import React, { useState } from 'react';


function Contents () {

    const [state, setState] = useState(false);
    const [stype, setTyping] = useState("");
    const [state3, setState3] = useState(false);
    ////////////////////////////////// OPTION SELECTION ///////////////////////////////////////
    const [BIO, setBio] = useState(" -bio/");
    const [WORK, setWork] = useState(" -work_Experiences/");
    const [PROJECTS, setProjects] = useState(" -projects/");
    const [state4, setState4] = useState(false);
    const [state5, setState5] = useState(false);
    const [state6, setState6] = useState(false);
    const [state7, setState7] = useState(false);
    const [state8, setState8] = useState(false);
    const [state9, setState9] = useState(false);

    function option1() {
        setTimeout(() => {
            //setState3(false);
            setState4(true);
            setState5(true);
            setState6(false);
            setState7(false);
            setState8(false);
            setState9(false);
            lineThree.classList.remove("typewriter");

        }, 500);
        
    }
    function option2() {
        setState4(false);
        setState5(false);
        setState6(true);
        setState7(true);
        setState8(false);
        setState9(false);
        lineThree.classList.remove("typewriter");

    }
    function option3() {
        setState4(false);
        setState5(false);
        setState6(false);
        setState7(false);
        setState8(true);
        setState9(true);
        lineThree.classList.remove("typewriter");
    }
    function fullScreen() {
        var el = document.getElementById('fake__Screen');
        el.requestFullscreen();
    }

    //////////////////////////////////** OPTION SELECTION **///////////////////////////////////////
    function nextLine1() {
        setTimeout(() => {
            setState(true);
            setTyping("hide");
            console.log("animation ended1");
        }, 2000);
    }
    function nextLine2() {
        setTimeout(() => {
            setState3(true);
            setState(false);
            setTyping("hide");
            console.log("animation ended2");
        }, 2000);
    }
    const lineOne = document.getElementById("line1");
    const lineTwo = document.getElementById("line2");
    const lineThree = document.getElementById("line3");
    if (lineOne) {
        lineOne.addEventListener("animationend", nextLine1);
    }
    if (lineTwo) {
        lineTwo.addEventListener("animationend", nextLine2);
    }
    
    window.onload = () => {
        setTyping("typewriter");
        console.log("applied");
    }

    return (
        <div className="container">
        <div className="laptop">
        <div className="laptop__screen">

            <div className="fakeMenu">
            <div className="fakeButtons fakeClose"></div>
            <div className="fakeButtons fakeMinimize"></div>
            <div className="fakeButtons fakeZoom" onClick={fullScreen}></div>
            </div>
            <div className="fakeScreen" id='fake__Screen'>
                <div id="content">
                    <span className="codeHead">user@sleepyCoderz~$&nbsp;</span>
                    <span id='line1' className={state ? "hide" : stype}>
                        sudo pip i mirza_Asim/portfolio
                    </span><br></br>
                    <span id='line2' className={state ? "typewriter" : "hide" }>
                        ..........!!!content downloaded!  
                    </span>
                    <span id='line3' className={state3 ? "typewriter" : "hide" }>
                        Select the commands to view -&#62; &nbsp;sudo cat&nbsp; <div className='bio' onClick={option1}>{BIO}&nbsp;</div><div className='work' onClick={option2}>{WORK}&nbsp;</div><div className='projects' onClick={option3}>{PROJECTS}&nbsp;</div>
                    </span>
                    <br /><br />
                    <span id='line4' className={state4 ? "linefour" : "hide" }>
                    Professional Summary <br />
                        $~  An experienced engineer with a Master’s degree in Electrical and Computer
                        Engineering, currently pursuing a Full-Stack Web/Cloud Development, AI/ML, 
                        and Cybersecurity IT position.<br /><br />
                        $~  Proficient in a wide range of programming languages, frameworks, and tools.
                         Hands-on experience in building monitoring dashboards, optimizing queries, and
                          deploying solutions in cloud environments, combined with a solid foundation in
                           Cybersecurity and Network management.<br /><br />
                    Skills and Areas of Expertise <br />
                            #   Languages & Framework: JSX, JavaScript, SQL, React.js, HTML, CSS, 
                        Bootstrap, Spring Boot, Node.js, RESTful APIs, python, C#, C++, MATLAB, ROS, 
                        Express, Shell.<br /><br />
                        #   Databases: MySQL, PostgreSQL<br /><br />
                        #   Tools & Technology: GitHub Actions, Docker, Kubernetes, 
                        Cisco Packet tracer, CI/CD Pipelines, Virtualization (Hyper-V), SNMP, 
                        Prometheus, Grafana, InfluxDB, Netbox, Juniper Networks, Unity, CATIA v5, 
                        AutoCAD, Fusion 360, SolidWorks, Camlytics, Simatic Siemens S7 300, 
                        ServiceNow Administrators course.
                    </span><br /><br />
                    <span id='line5' className={state5 ? "typewriter1" : "hide" }>
                        $~: &nbsp;sudo cat&nbsp; <div className='work' onClick={option2}>{WORK}&nbsp;</div><div className='projects' onClick={option3}>{PROJECTS}&nbsp;</div>
                    </span>
                    <span id='line6' className={state6 ? "linesix" : "hide" }>
                    Work Experience<br /><br />
                        Security Intern, Bell, Mississauga ON                                    <br />    
                        #   Conducted research and built monitoring dashboards using Prometheus and 
                        Grafana, provided Level 1 technical support by configuring SNMP for data 
                        collection, and compared Prometheus with InfluxDB for efficiency. 
                        Provisioned new Juniper EX4650 switches, managed Netbox for server room device
                         data as well as network topology building, collaborated with IBM on SNMP 
                         setup, and gained experience in GitLab CI/CD, Docker deployment, Hyper-V 
                         setup, and full-stack web development.<br /><br />

                        Data Scientist Developer, Magnify Access Inc, Toronto (remote internship)  <br />
                        #   Developed expertise in data science techniques for analyzing and 
                        visualizing complex datasets, optimized user queries for accommodation 
                        recommendations, streamlined queries on the Magnify Access platform to improve 
                        user experience, and built an OCR text extraction project using Python's 
                        Tesseract library for accurate data retrieval and processing.<br /><br />

                        Cybersecurity Technology Consultant, Amiviz, Dubai (internship)            <br />
                        #   Gained expertise in EDR and Network Detection solutions with a CrowdStrike 
                        EDR certification, actively participated in cybersecurity strategy meetings 
                        with partner vendors, demonstrated strong knowledge of the AmiViz product 
                        portfolio, networking, and CCNA concepts, and provided technical support for 
                        DIMM Module replacement and troubleshooting in ExtraHop devices at client 
                        premises.<br /><br />

                        Mechatronics Engineer, Magna Innovations, Magna Innovations, Dubai (internship) 2021<br />
                        #   Successfully designed the Automated Sliding Screen Robot development project 
                        using SolidWorks, researched materials, and developed a People Counting program by 
                        successfully establishing TCP socket communication between Python and Unity. Served 
                        as an audiovisual representative at the GITEX 2022 event, handling device 
                        maintenance and optimization.<br /><br />
                    </span>
                    <span id='line7' className={state7 ? "typewriter1" : "hide" }>
                        $~: &nbsp;sudo cat&nbsp; <div className='bio' onClick={option1}>{BIO}&nbsp;</div><div className='projects' onClick={option3}>{PROJECTS}&nbsp;</div>
                    </span>
                    <span id='line8' className={state8 ? "lineeight" : "hide" }>
                    Academic Projects<br /><br />
                        QoS Analysis across Tree, Ring, Half-Mesh, and Full-Mesh Network Technology | Winter 2024<br />               
                        #   Conducted in-depth comparison of Quality of Service (QoS) metrics across 
                        diverse network topologies.<br />
                        #   Utilized Cisco Packet Tracer and Python to simulate and configure network
                         environments realistically.<br />
                        #   Analyzed QoS parameters meticulously to discern nuanced performance differences.<br />
                        #   Established a robust framework for future investigations into network performance.<br /><br />
                        Fake News Detection using CNN-LSTM model (Python)| Winter 2024<br />
                        #   Modified and designed the AI program for improved detection of Fake news present 
                        online employing a combination of CNN and LSTM algorithms to achieve an AUC score 
                        of 97.50%.<br />
                        #   Addressed challenges in processing human language. Aimed to contribute to more 
                        reliable detection systems for a healthier information ecosystem.<br />
                        #   Worked in a group of two for this post-graduation project and successfully 
                        drafted the IEEE research paper.
                    </span>
                    <span id='line9' className={state9 ? "typewriter1" : "hide" }>
                        $~: &nbsp;sudo cat&nbsp;<div className='bio' onClick={option1}>{BIO}&nbsp;</div> <div className='work' onClick={option2}>{WORK}&nbsp;</div>
                    </span>
                </div>
                
            </div>

            </div>
            <div className="laptop__bottom">
                <div className="laptop__under"></div>
                </div>
            <div className="laptop__shadow"></div>  
        </div>
        </div> 
    );
}

export default Contents;

How to control the order of promise’s callback

I have promises like this,

    var results_arr = [];
    var promises = [];
    for (var i = 0 ; i < items.length;i++){
      var url =  `/api/stat/${items[i].id}`;
      promises.push(
        axios.get(url).then(res=>{
          arr.push(res);
          
      }));
    }
    Promise.all(promises).then(function(values) {
      console.log("finishpromise",arr);
    });

This calls the api many times, However I want to push the result in arr as the same order.

How can I make this?

Problem in a recurrency function in node.js

I need a help about my code. My function receives a json (variable named jasonobj) which contains a base64 encoded pdf named “BytesBoleto” among many other fields.

For each “BytesBoleto” ocurrence I have to save a pdf file named boletoXXX.pdf (where XXX is 1 for the first ocurrence, 2 for the 2nd etc) on user Desktop.

Here is my code:

function Base64toPDFandSave (base64String, filename) {

    const fs = require('fs');
    const path = require('path');

    // Remove the prefix if it exists
    const base64Data = base64String.replace(/^data:application/pdf;base64,/, "");

    // Define the path to save the PDF file on the user's desktop
    const desktopPath = path.join(require('os').homedir(), 'Desktop');
    const filePath = path.join(desktopPath, filename);

    // Write the PDF file
    fs.writeFile(filePath, base64Data, 'base64', (err) => {
    if (err) {
    console.error('Error saving the file:', err);
    } else {
    console.log('PDF file saved successfully at:', filePath);
    }
    });

}

function JsontoBase64 (jsonData, filename) {
    // Verifica se jsonData é um objeto
    if (typeof jsonData !== 'object' || jsonData === null) {
        throw new Error("Entrada inválida: deve ser um objeto JSON.");
    }

    // Função recursiva para percorrer o JSON e encontrar os campos "BytesBoleto"
    function procurarBytesBoleto(obj, fname, findex) {
        for (const key in obj) {
            console.log("......")
            console.log(key + "::" + findex.toString());
            if (obj.hasOwnProperty(key)) {
                if (key === 'BytesBoleto' && typeof obj[key] === 'string') {
                    findex= findex+1;
                    console.log("BytesBoleto:"+findex.toString());
                    Base64toPDFandSave(obj[key], fname+findex.toString()+'.pdf');
                } else if (typeof obj[key] === 'object') {
                    console.log("Recursiva:"+findex.toString());
                    procurarBytesBoleto(obj[key], fname, findex); // Chama a função recursivamente
                }
            }
        }
    }
    procurarBytesBoleto(jsonData, filename, 0);    
}

JsontoBase64 (jsonobj, 'boleto');

My problem is: It should be saved boleto1.pdf, boleto2.pdf, boleto3.pdf and so on but the files are all saved named boleto1.pdf (which is wrong).

Could you help me to find the error in my recurrent (recursion) function?

Thanks for the help

Created a function with reused code, but the return value is “undefined”

I’m doing the JavaScript Amazon website creation of “SuperSimpleDev” and I’m stuck for hours.
I tried to fix it with chatGPT but it doesn’t manage to fix the problem no matter what I tried.

I had those 2 functions named “updateCartQuantity” in both files: “14-checkout.js” and “14-amazon.js”:

In 14-amazon.js:

export function updateCartQuantity(){
  let cartQuanity = 0;

  cart.forEach((cartItem)=>{
    cartQuanity += cartItem .quantity;

  });

  document.querySelector('.js-cart-quantity').innerHTML = cartQuanity;
}


  document.querySelector('.js-cart-quantity').innerHTML = cartQuanity;
}

in 14-checkout.js:

function updateCartQuantity(){
  let cartQuantity = 0;

  cart.forEach((cartItem) => {
    cartQuantity += cartItem.quantity;
  });

  document.querySelector('.js-return-to-home-link').innerHTML = `${cartQuantity} items`;
}

Now as you can see, the calculation of the cart’s quantity is reused in both files, so I tried to create a new function that do the calculation separately it in a file named “14-cart.js”. I’m using module in order to get access to the function.

But when I tried, it returns the value “undefined”.

The new implementation:

14-cart.js:

export function calculateCartQuantity(){
  let cartQuantity = 0;

  cart.forEach((cartItem) => {
    cartQuantity += cartItem.quantity;
  });

  return cartQuantity;
}

14-checkout.js:

function updateCartQuantity() {
  const cartQuantity = calculateCartQuantity();
  console.log("Cart quantity is:", cartQuantity);

  document.querySelector('.js-return-to-home-link').innerHTML = `${cartQuantity} items`;
}

14-amazon.js:

export function updateCartQuantity(){

  const cartQuantity = calculateCartQuantity();

  document.querySelector('.js-cart-quantity').innerHTML = cartQuantity;
}

Of course I’ve included the modules and imported the function in both files

enter image description here

Electron app with React Vite + Node.js/Express won’t connect to backend

I have created a React Vite app with Express/Node.js and MongoDB Atlas as the database. It works well on the browser. I want it to be an Electron app. In development, the app functions normally too. Only when building and installing the app, I no longer get access to the backend. Somehow it never starts.

But when I start node server.js through the terminal (I split frontend and backend in separate folders), the built app runs normally.

Why doesn’t it connect automatically? I’ve tried so many solutions but I always get the error:

index-wdmKrBiS.js:60 
 POST http://localhost:5050/api/auth/login net::ERR_CONNECTION_REFUSED
Me  @   index-wdmKrBiS.js:60
m   @   index-wdmKrBiS.js:60
Wf  @   index-wdmKrBiS.js:48
(anonymous) @   index-wdmKrBiS.js:48
dc  @   index-wdmKrBiS.js:48
rr  @   index-wdmKrBiS.js:48
Sr  @   index-wdmKrBiS.js:49
Mg  @   index-wdmKrBiS.js:491

What am I overlooking?

React + jQuery + Bootstrap code injection on Squarespace

I inherited a React 16 app, built with create-create-app, built and deployed to GitHub Pages with a workflow that watches the main branch. My mission is to move it from Netlify to its new homepage on Squarespace. I’d prefer to avoid big changes, e.g. ejecting CRA, at least until the app is loading on the new homepage.

One of the pain points is the JS/CSS build filenames change due to the hashing behavior described here. I was able to load the app on Squarespace by inserting the following into a code block:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous" />
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous" />
<link rel="stylesheet" href="https://my-org.github.io/my-repo/static/css/main.a8d72baf.css" />

<div id="root">Insert app here</div>

<script src="https://my-org.github.io/my-repo/static/js/main.9ca04874.js" defer></script>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>

The problem with this approach is the site goes down whenever the filenames change. I can update Squarespace rather quickly but it’s error prone and tedious. I looked into disabling the hashing behavior but didn’t like the solutions I found, e.g. ejecting CRA. Plus I assume there’s a good reason for it.

So the first thing I tried was generating the HTML snippet above by extracting the relevant lines from build/index.html. I added the following script after the build step in the workflow:

import { JSDOM } from 'jsdom';
import { open } from 'node:fs/promises';

const inPath = 'build/index.html';
const dom = await JSDOM.fromFile(inPath);

const outPath = 'build/embed-snippet.html';
const outFile = await open(outPath, 'w');
const outStream = outFile.createWriteStream();

const links = dom.window.document.querySelectorAll('link[rel=stylesheet]');

for (const link of links) {
  outStream.write(link.outerHTML + 'n');
}

outStream.write('<div id="root">Insert app here</div>n');

const scripts = dom.window.document.querySelectorAll('script');

for (const script of scripts) {
  outStream.write(script.outerHTML + 'n');
}

Then I replaced the contents of the code block on Squarespace:

<div id="root-host">Insert app here</div>

<script>
  const url = 'https://my-org.github.io/my-repo/embed-snippet.html';
  const response = await fetch(url, {cache: 'no-cache'});
  document.getElementById('root-host').innerHTML = await response.text();
</script>

This doesn’t work because scripts inserted with innerHTML don’t execute.

Next, I modified the script to generate another script instead of the HTML snippet:

import { JSDOM } from 'jsdom';
import { open } from 'node:fs/promises';

const inPath = 'build/index.html';
const document = (await JSDOM.fromFile(inPath)).window.document;

const outPath = 'build/embed.js';
const outFile = await open(outPath, 'w');
const outStream = outFile.createWriteStream();

const links = [...document.querySelectorAll('link[rel=stylesheet]')].map(el => {
  return {
    href: el.hasAttribute('href') ? el.getAttribute('href') : undefined,
    integrity: el.hasAttribute('integrity') ? el.getAttribute('integrity') : undefined,
    crossOrigin: el.hasAttribute('crossOrigin') ? el.getAttribute('crossOrigin') : undefined,
  };
});

const scripts = [...document.querySelectorAll('script')].map(el => {
  return {
    src: el.hasAttribute('src') ? el.getAttribute('src') : undefined,
    integrity: el.hasAttribute('integrity') ? el.getAttribute('integrity') : undefined,
    crossOrigin: el.hasAttribute('crossOrigin') ? el.getAttribute('crossOrigin') : undefined,
    defer: el.hasAttribute('defer') ? true : undefined,
    async: el.hasAttribute('async') ? true : undefined,
  };
});

outStream.write(`const links = ${JSON.stringify(links)};

for (const link of links) {
  const el = document.createElement('link');
  el.rel = 'stylesheet';
  el.href = link.href;
  if (link.integrity) el.integrity = link.integrity;
  if (link.crossOrigin) el.crossOrigin = link.crossOrigin;
  document.head.appendChild(el);
}

const scripts = ${JSON.stringify(scripts)};

for (const script of scripts) {
  const el = document.createElement('script');
  el.src = script.src;
  if (script.integrity) el.integrity = script.integrity;
  if (script.crossOrigin) el.crossOrigin = script.crossOrigin;
  if (script.defer) el.defer = true;
  if (script.async) el.async = true;
  document.body.appendChild(el);
}`);

The resulting embed.js looks like this:

const links = [{
  "href": "https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css",
  "integrity": "sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T",
  "crossOrigin": "anonymous"
}, {
  "href": "https://use.fontawesome.com/releases/v5.7.2/css/all.css",
  "integrity": "sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr",
  "crossOrigin": "anonymous"
},
{
  "href": "https://my-org.github.io/my-repo/static/css/main.a8d72baf.css"
}];

for (const link of links) {
  const el = document.createElement('link');
  el.rel = 'stylesheet';
  el.href = link.href;
  if (link.integrity) el.integrity = link.integrity;
  if (link.crossOrigin) el.crossOrigin = link.crossOrigin;
  document.head.appendChild(el);
}

const scripts = [{
  "src": "https://my-org.github.io/my-repo/static/js/main.9ca04874.js",
  "defer": true
}, {
  "src": "https://code.jquery.com/jquery-3.3.1.slim.min.js",
  "integrity": "sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo",
  "crossOrigin": "anonymous"
}, {
  "src": "https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js",
  "integrity": "sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1",
  "crossOrigin": "anonymous"
}, {
  "src": "https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js",
  "integrity": "sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM",
  "crossOrigin": "anonymous"
}];

for (const script of scripts) {
  const el = document.createElement('script');
  el.src = script.src;
  if (script.integrity) el.integrity = script.integrity;
  if (script.crossOrigin) el.crossOrigin = script.crossOrigin;
  if (script.defer) el.defer = true;
  if (script.async) el.async = true;
  document.body.appendChild(el);
}

Here’s the new contents of the code block on Squarespace:

<div id="root">Insert app here</div>
<script src="https://my-org.github.io/my-repo/embed.js"></script>

The problem now is the app only loads about half the time. The other half of the time I get an error like this:

Uncaught TypeError: Cannot read properties of undefined (reading 'fn')
    at util.js:55:5
    at bootstrap.min.js:6:200
    at bootstrap.min.js:6:246

Uncaught TypeError: window.$(...).tooltip is not a function
    at Header.js:18:29

The first error suggests Bootstrap is loading before jQuery, but the scripts are ordered correctly per the BS4 docs.

The second error suggests the React app is loading before Popper. I tried changing the order of the scripts like so:

const scripts = [{
  "src": "https://code.jquery.com/jquery-3.3.1.slim.min.js",
  "integrity": "sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo",
  "crossOrigin": "anonymous"
}, {
  "src": "https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js",
  "integrity": "sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1",
  "crossOrigin": "anonymous"
}, {
  "src": "https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js",
  "integrity": "sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM",
  "crossOrigin": "anonymous"
}, {
  "src": "https://my-org.github.io/my-repo/static/js/main.9ca04874.js",
  "defer": true
}];

But the problem persists. I also tried adding defer to all the scripts, but that didn’t work either. This is really puzzling because according to MDN:

Scripts loaded with the defer attribute will load in the order they appear on the page.

Header.js calls tooltip() inside a useEffect hook:

import React, { useRef, useState , useEffect} from 'react';

const Header = (props) => {
  const myRef = useRef(null);

  useEffect(() => {
    window.$(myRef.current).tooltip();
  }, []);

I read somewhere that the hook runs after the DOM is loaded, similar to $(document).ready, and is the right time/place for stuff like this. Even if that isn’t true, that wouldn’t explain the first error, would it.

I’m about ready to throw my hands up and accept that I (or whoever inherits this project next) have to manually update Squarespace at the exact right moment after each deployment. But there’s gotta be a better way, right?

Cannot use canvaskit-wasm outside of the unpkg CDN on my host machine

I’m trying to use canvaskit-wasm on my local machine, hosted with Python’s HTTP server module. It seems that I can only use CanvasKit through unpkg with:

<script type="text/javascript" src="https://unpkg.com/[email protected]/bin/canvaskit.js"></script>

If I try to use “canvaskit.js” supplied through the official NPM package (https://www.npmjs.com/package/canvaskit-wasm), from the same place as index.html, I get these errors in the Firefox developer console:

wasm streaming compile failed: LinkError: import object field 'memory' is not a Memory canvaskit.js:162:266
falling back to ArrayBuffer instantiation canvaskit.js:162:306
failed to asynchronously prepare wasm: LinkError: import object field 'memory' is not a Memory canvaskit.js:161:444
Aborted(LinkError: import object field 'memory' is not a Memory) canvaskit.js:160:63
Uncaught (in promise) RuntimeError: Aborted(LinkError: import object field 'memory' is not a Memory). Build with -sASSERTIONS for more info.
    Ka http://127.0.0.1:8000/publish/canvaskit.js:160
    CanvasKitInit http://127.0.0.1:8000/publish/canvaskit.js:161
    promise callback*qb http://127.0.0.1:8000/publish/canvaskit.js:161
    CanvasKitInit http://127.0.0.1:8000/publish/canvaskit.js:162
    promise callback*CanvasKitInit/rb/CanvasKitInit< http://127.0.0.1:8000/publish/canvaskit.js:162
    promise callback*rb http://127.0.0.1:8000/publish/canvaskit.js:162
    CanvasKitInit http://127.0.0.1:8000/publish/canvaskit.js:267
    CanvasKitInit http://127.0.0.1:8000/publish/canvaskit.js:267
    <anonymous> http://127.0.0.1:8000/publish/:64
canvaskit.js:160:75

Is this not working due to security policies in Firefox, do I need to build canvaskit-wasm myself in a certain way?

having trouble with onclick. have tried googling

What is wrong with my code?

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Graph maker</title>
    <link rel="stylesheet" href="css.css">
    <script defer src="java.js"></script>
    
</head>
<body>
    <div id="pag1">
        <a href="#" id="btn1">asdf</a>
        <p id="test">1</p>
    </div>

    <div id="pag2">
        <button id="btn2">Create New</button>
    </div>
    
</body>
</html>

js

let pag1 = document.getElementById(p1);
let pag2 = document.getElementById(p2);
let btn1 = document.getElementById(b1);

function show(shown, hidden) {
    document.getElementById(shown).style.display='Block';
    document.getElementById(hidden).style.display='none';
    return false;
}

btn1.onclick(() => {
    alert("asdf");
})

I have tried everything i can think of and google shows me nothing.
I’m trying to make is so when I press the <a> element the next page shows up. the code works when I put the onclick inside the <a> element but if I try it inside the js file nothing works.

Why is the return type of a generic TypeScript function inferred differently for a variable initialization and an assignment?

Given a Typescript function with a generic type that is used for the return type and has a default value, the return type of the function is inferred differently when using the function’s return value to initialize a variable and assigning it to a typed variable.

Here is a simplified example :

function test<T extends Element =  HTMLElement>(elementName:string):T{
  // irrelevant, just returning something
  return document.createElement(elementName) as unknown as T;
}

const e1 = test('div'); // fine, e1's inferred type is HTMLElement
let e2: HTMLElement | undefined;
e2 = test('div'); // Type error

In the first case (e1), everything is fine, the default generic type HTMLElement is used and the type of e1 is inferred to HTMLElement.

In the second case, the type of the return value is inferred to Element and it causes a type error, as Element can’t be assigned to HTMLElement.

Why is the behavior different? Why is the generic default value not used in the second case? Is it expected?

Example in TS playground

Close all other accordions when one is opened

I have the code below which will open and close accordions, I need help if I open one, the rest are closed, my issue with this code is that I can’t close the current opened accordion, if you click on the same accordion it will open, but if you try to click it again it won’t close.

CodePen: [https://codepen.io/C3ISR-Everything-Cybersecurity/pen/azbeOEK]

                const accordionEl = document.querySelector('.main')
const panelEls = accordionEl.querySelectorAll('.panel')

accordionEl.addEventListener('click', ({ target }) => {
  if (target.classList.contains('accordion')) {
    panelEls.forEach(panelEl => {
      panelEl.classList.remove('open')
    })
    
    const { nextElementSibling } = target
    nextElementSibling.classList.add('open')
  }
})
       body {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            background-color: White;
            font-family: Sakkal Majalla;
            direction: rtl;
            position: relative;
            z-index: -2;
            -ms-overflow-style: none;
            
        }
        body::-webkit-scrollbar, body::-webkit-scrollbar-button { display: none; } /* Chrome */


        li {
            list-style: none;
        }

        a {
            text-decoration: none;
        }

        .main{    
            display: grid;
            grid-template-columns: 1fr;
            justify-items: center;
            margin-top: 2rem;
            margin-bottom: 1rem;
        }

        table {
            border: 1px solid #dededf;  
            table-layout: fixed;
            border-collapse: collapse;
            border-spacing: 1px;
            text-align: center;
        }

        th {
            border: 1px solid #dededf;
            background-color: #eceff1;
            color: #000000;
            padding: 5px;
        }

        td {
            border: 1px solid #dededf;
            background-color: #ffffff;
            color: #000000;
            padding: 5px;  
        }
        th:nth-child(1) {  
            width: 30.9rem;
        }

        th:nth-child(2) {  
            width: 10rem;
        }
        th:nth-child(3) {  
            width: 7rem;
        }

        .accordion {
            background-color: #ffffff;
            color: black;
            font-weight: bold;
            cursor: pointer;
            margin-top: 20px;
            padding: 18px;
            border: none;
            text-align: right;
            outline: none;
            font-size: 20px;
            transition: 0.4s;
            width: 50rem;
            border: 1px solid rgb(219, 219, 219);
            border-radius: 8px;
            box-shadow: rgba(100, 100, 111, 0.123) 0px 7px 29px 0px;
        }

        .active, .accordion:hover {
            border-radius: 8px 8px 0px 0px;
            border-color:  rgb(0, 128, 255);
        }

        .accordion span{
            float: left;
            font-size: 15px;
            color: #116ce4;
        }
/* OLD CODE USE BELOW IT
        .panel {
            display: none;
            overflow: hidden;  
        }
*/
.panel {
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.5s ease, padding 0.5s ease;
    padding: 0px;
}

.panel.open {
    max-height: 1000px;
    padding: 18px;
}
   <div class="main">
            <button class="accordion">
                John Doe
            </button>
            <div class="panel">
                <table>
                    <th>company</th>
                    <th>department</th>
                    <th>2025?</th>
                    <tr>
                        <td>COMPANY A</td>
                        <td>FINANCE</td>
                        <td>&#9989;</td>
                    </tr>
                    <tr>
                        <td>COMPANY Z</td>
                        <td>PMO</td>
                        <td>&#10060;</td>
                    </tr>
                </table>
            </div>
                 <button class="accordion">
                John Doe
            </button>
            <div class="panel">
                <table>
                    <th>company</th>
                    <th>department</th>
                    <th>2025?</th>
                    <tr>
                         <td>company A</td>
                        <td>HR</td>
                        <td>&#10060;</td>
                    </tr>
                    <tr>
                       <td>company B</td>
                        <td>HR</td>
                        <td>&#10060;</td>
                    </tr>
                    <tr>
                          <td>company C</td>
                        <td>HR</td>
                        <td>&#10060;</td>
                    </tr>
                </table>
            </div>
                 <button class="accordion">
                John Doe
            </button>
            <div class="panel">
                <table>
                    <th>company</th>
                    <th>department</th>
                     <th>2025?</th>
                    <tr>
                        <td>company A</td>
                        <td>HR</td>
                        <td>&#9989;</td>
                    </tr>
                </table>
            </div>       
    </div>

xterm.js Backspace Not Working After Simulated Autocomplete with TAB

I’m building a terminal interface using xterm.js and handling a remote shell via WebSocket. Autocomplete is server-side—when a user types part of a command like sen and presses TAB, the server responds with send .

To simulate this autocomplete, I call a simulateTyping() function that appends the completed part to the terminal and updates the internal buffer (currentInput):

function simulateTyping(text) {
  for (let ch of text) {
    term.write(ch); // visually show char
    socket.send(JSON.stringify({ msg: 'input', body: ch })); // send to server
    currentInput += ch;
    updateGhost();
  }
}

The problem: backspace only deletes the characters the user typed manually. After simulateTyping(), the autocompleted text (send ) becomes “visually” present, but when the user presses backspace, it only removes the characters originally typed (sen)—not the autocompleted portion.

I’ve tried managing currentInput manually and even injecting characters one-by-one, but xterm.js doesn’t seem to treat these as truly typed input.

Here’s part of the socket.on(‘message’) logic that triggers the autocomplete:

if (promptMatch && typedText.startsWith(lastHistory)) {
  const appendText = typedText.slice(lastHistory.length);
  simulateTyping(appendText); // simulate autocomplete
}

❓How can I make autocompleted text deletable like manually typed input in xterm.js?
Is there a way to “trick” xterm.js into treating this input as if typed by the user?

Do I need to feed it differently to the buffer?

Or is there an addon or API pattern I’m missing?

Any help would be appreciated!