JavaScript code to change href if contains a link

I want to create a script that changes the href of a button only if it contains a link or a period, since URLs normally contain periods (if it contains a link, I want to replace it with another one, for example google.com). However, the script I have changes all hrefs regardless of their content.

<script>
        window.onload = function() {
        var anchors = document.getElementsByClassName("elementor-button");
        for (var i = 0; i < anchors.length; i++) {
        anchors[i].href = "https://google.com"
        }
        }
</script>

How to import variables from one function to another in javascript?

I wanted to make simple multiplication from 2 variables that I collected before by prompt() and I performed every check to see if anything is wrong but everything in logs seems fine. But as soon as I want to make this multiplication it throws out NaN.

I tried logging every input i got and everything was fine.

let kurs1 = 0;
let stawka1 = 0;
//function stawka() {
//    const stawka1 = parseFloat(prompt("Podaj stawkę."));
//    document.getElementById("p1").innerHTML = "Stawka wynosi: " + stawka1 + "zł.";
//}
function druzyny() {
  let druz = prompt("Podaj drużynę pierwszą.");
  let druz2 = prompt("Podaj drużynę drugą.");
  document.getElementById("druzyna1").innerHTML = "Drużyna pierwsza: " + druz;
  document.getElementById("druzyna2").innerHTML = "Drużyna druga: " + druz2;
}

function stawka() {
  const stawka1 = parseInt(prompt("Podaj stawkę."));
  if (isNaN(stawka1)) {
    console.log("Błąd: Stawka to nie liczba.");
    return;
  }
  console.log("Stawka:", stawka1);
  document.getElementById("p1").innerHTML = "Stawka wynosi: " + stawka1 + "zł.";
}

function kurs() {
  const kurs1 = parseInt(prompt("Podaj kurs."));
  console.log("Kurs:", kurs1);
  document.getElementById("kurs").innerHTML = "Kurs wynosi: " + kurs1 + "x";
}

function mozlwygr(stawka1, kurs1) {
  const wygrana = stawka1 * kurs1;
  console.log(wygrana)
}

function mozlwygr(stawka1, kurs1) {
  if (isNaN(stawka1) || isNaN(kurs1)) {
    console.log("Błąd: Stawka lub kurs to nie liczba.");
    return;
  }
  let wygrana = stawka1 * kurs1;
  document.getElementById("mozliwawygrana1").innerHTML = "Możliwa wygrana: " + wygrana + "zł.";
}
<button id="butt-wyjdz" type="button" class="btn btn-info" onclick="stawka()">Ustaw stawkę</button>
<button id="butt-kurs" type="button" class="btn btn-info" onclick="kurs()">Ustaw kurs</button>
<button id="butt-kurs" type="button" class="btn btn-success" onclick="mozlwygr()">Oblicz możliwą wygraną</button>
<button type="button" class="btn btn-secondary" id="liveAlertBtn" onclick="losuj(), mozlwygr()">Przewiduj</button>
<button id="butt-druz" type="button" class="btn btn-info" onclick="druzyny()">Drużyny</button>
<script src="gamb1.js"></script>
<script src="scriptsite.js"></script>

Alter the default footer when generating pdf using printtopdf

I am working with the page.printToPDF module in a Node.js project to generate a PDF with custom page numbers using the footerTemplate. I want to skip the page number on the first page but still generate it. The page numbers should start from page 2 onwards.

I understand that we can use the footerTemplate to insert page numbers, but I’m unsure how to skip numbering on the first page while still generating it in the PDF output.

How can I configure page.printToPDF to:

  1. Generate the first page without a page number.

  2. Start numbering from page 2, but include the first page in the final output?

I tried using the pageRanges option to skip the first page, but it doesn’t generate page 1 at all. Here’s the code I used

const pdf = await page.printToPdf({

path: 'output.pdf',

format: 'A4',

printBackground: true,

displayHeaderFooter: true,

footerTemplate: `<div style="font-size:12px;width:100%;text-align:right;"><span class="pageNumber"></span></div>`,

pageRanges: '2-',  // This skips page 1 entirely, but I want to generate page 1 without numbering

});

await browser.close();

})();


This works to start printing from page 2, but it completely excludes page 1 from the PDF. I need to include page 1 in the document but without any page number on it. How can I achieve that?

Cannot set property of undefined, on all method

I’m currently a beginner to intermediate with JavaScript, and I’m trying to get used to intermediate JavaScript for development with template literals. I worked on a class to handle the heavy lifting of defining the template, but after many try, I’m still stuck on the same error.

Cannot set property of undefined

on all my method, and frankly have no idea why it act this way

default async function TemplateElement(
    container,
    innerhtml,
    css = { fetchUrl: null, customCss: null },
    json = { fetchUrl: null, data: null },
    event = [{ type: null, selector: null, action: null }]
) {

    if (!container || typeof container !== "string") {
        throw new Error("Le conteneur doit être un nom de balise HTML valide ou un élément.");
    }
    if (typeof innerhtml !== "string") {
        throw new Error("innerhtml doit être une chaîne de caractères valide.");
    }

    this.template = {
        innerhtml: innerhtml || "",
        Json: json,
        container: container || "div",
        Css: css,
        event: event,
    };

    await this.applyCss();
    return this.contentHandler();
}

TemplateElement.prototype.applyCss = Object.freeze(async function () {
    function newStyle(data, id = null) {
        if (id && document.getElementById(id)) return;
        
        const style = document.createElement("style");
        if (id) style.id = id;
        style.innerText = data;
        style.type = "text/css";
        document.head.appendChild(style);
    }

    if (this.template.Css) {
        if (this.template.Css.fetchUrl) {
            try {
                const response = await fetch(this.template.Css.fetchUrl);
                const data = await response.text();
                newStyle(data, 'fetched-style'); // Assigner un ID pour le CSS récupéré
            } catch (error) {
                console.error("Échec de la récupération du CSS :", error);
            }
        }
        if (this.template.Css.customCss) {
            newStyle(this.template.Css.customCss, 'custom-style'); // Assigner un ID pour le CSS personnalisé
        }
    }
});

TemplateElement.prototype.content = Object.freeze(function (data = {}) {
    const template = document.createElement(this.template.container);
    template.innerHTML = this.template.innerhtml;

    if (this.template.event) {
        this.eventHandler(template);
    }

    return template; // Élément HTML
});

TemplateElement.prototype.contentHandler = Object.freeze(async function () {
    let data = this.template.Json.data || {};

    if (this.template.Json.fetchUrl) {
        try {
            const response = await fetch(this.template.Json.fetchUrl);
            const fetchedData = await response.json();
            data = { ...data, ...fetchedData }; // Fusionner les données récupérées avec les données existantes
        } catch (error) {
            console.error("Erreur :", error);
        }
    }
    
    return this.content(data);
});

TemplateElement.prototype.eventHandler = Object.freeze(function (target) {
    const listenTo = [...new Set(this.template.event.map(event => event.type))];

    listenTo.forEach(eventType => {
        target.addEventListener(eventType, (e) => {
            this.locateChild(e.target, e.type); // Localiser l'élément d'événement et le type d'événement
        });
    });
});

TemplateElement.prototype.locateChild = Object.freeze(function (interactedWith, eventType) {
    this.template.event.forEach(({ type, selector, action }) => {
        if (type === eventType && interactedWith.matches(selector)) {
            action(); 
        }
    });
});

How to make GET requests to multiple links at the same time and obtain the values ​of the returned results in sequence for conditional judgment?

Make requests for multiple links at the same time, and conditionally judge the value of the first returned result.

If the conditions are met, the values ​​of subsequent request results will not be obtained.

If they are not met, the values ​​of the second and third returned results will be obtained in sequence.

Perform conditional judgment. If the conditions are met, the subsequent values ​​will not be obtained. If the conditions are not met, the subsequent values ​​will also be obtained.

I wrote a piece of code using AI. Looking at the comments and actual results, it seems that it first obtains a request result, performs judgment, and then waits for all remaining result requests to be completed, and then performs conditional judgment.

It does not wait for the requested results to be obtained in sequence and then perform conditions.

Promise.all() will wait for all the results then do the judgment, and I think I should not use it.

    const promises = [];
    // List of links to request
    var urlavl = 'https://www.aaa.com'; 
    var urlero = 'https://www.bbb.com';
    var urlkuti = 'https://www.ccc.com';

    var urls = [urlwiki,urlero,urlkuti]; 
    // Traverse the linked list, initiate a request and store Promise and corresponding conditions
    urls.forEach((url) => {
        promises.push(new Promise((resolve, reject) => {
            GM_xmlhttpRequest({
                method: "GET",
                url: url,
                onload: function(response) {
                    let domNew = new DOMParser().parseFromString(response.responseText, 'text/html');
                    resolve(domNew);
                },
                onerror: function(error) {
                    resolve('ERROR' + url); 
                }
            });
        }));
    });
    Promise.race(promises)
        .then((data) => {
        // Determine whether the first completed request meets the corresponding conditions
        if(data.indexOf('#') > -1) {
            console.log(data);
            
            // Cancel other outstanding requests
            promises.forEach(promise => {
                if (promise.cancel) {
                    promise.cancel();
                }
            });
        } else {
            // console.log(`The link does not meet the conditions, waiting for other results...`);

            // Promise.all() Wait for all requests to complete
            Promise.all(promises)
                .then(results => {
                // Traverse all results and find results that meet the corresponding conditions
                console.log('Search again')
                results.forEach((data) => {
                    if(data.indexOf('#') > -1) {
                        console.log(data);
                    // console.log(`The link meets the conditions:`, response);
                    }
                });
            })
                .catch(error => {
                console.error("ERROR:", error);
            });
        }
    })
        .catch(error => {
        console.error("ERROR:", error);
    });

Redirection code wheere user will wnter after the login

enter image description here

enter image description here

enter image description here

The above images is for the continuos code flow!

The error “Failed to load resource: the server responded with a status of 404 (Not Found)” indicates that the requested resource could not be found on the server. In the context of integrating Autodesk APS with BIM360, this could be due to several reasons, such as an incorrect URL endpoint, a typo in the route path, or the resource not being available on the server. It’s crucial to check that the endpoint URL is correctly specified in the code and that the server is configured to handle requests at that endpoint. Ensure that the route paths in the code match those defined on the server and verify that the server is properly set up to respond to the requests being made.

what should i do next to resolve this error?

How to keep the div 100% of the parent container when scaling the div?

I am trying to build a canvas like element using div.

I have a div element that is acting as a canvas, this div element can zoom and pan. This div.canvas element is placed inside a container. I achieve the zooming and panning effects using css transforms scale and translate.

example
(the black is the container, the green is the div.canvas and inner red square is inner element)

Every time, I zoom out the div(acting as canvas) width and height is also scaled down and not is not 100% to the container.

here’s a codesandbox that can replicate the problem. (use +, – keys for zooming)

// import "./styles.css";

let scale = 1;

window.addEventListener("keydown", (e) => {
  if (e.key === "+") {
    scale += 0.2;
  } else if (e.key === "-") {
    scale -= 0.2;
  }
  // console.log("scale: ", scale);
  document.getElementById("canvas").style.transform = `scale(${scale})`;
});
body {
  font-family: sans-serif;
  height: 100vh;
  width: 100%;
}

#app {
  width: 100%;
  height: 100%;
  position: relative;
  display: flex;
  background-color: brown;
}

.canvas {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: green;
}

.element {
  position: absolute;
  top: 50px;
  left: 50px;
  width: 100px;
  height: 100px;
  background-color: blue;
}
<!DOCTYPE html>
<html>
  <head>
    <title>JavaScript Sandbox</title>
    <meta charset="UTF-8" />
  </head>

  <body>
    <div id="app">
      <div class="canvas" id="canvas">
        <div class="element"></div>
      </div>
    </div>

    <!-- <script src="./index.mjs" type="module"></script> -->
  </body>
</html>

You’ll notice every time you scale down pressing - key, the div.canvas becomes smaller as well.

how can I ensure everytime I zoom, it affects only the contents inside the div.canvas instead of the div itself or how can I make sure that the div.canvas is always 100% of the parent container?

How can I enable multiple values after initialization?

Good morning!

I have a form which have several TomSelect Control and my aim is conditionally allow multiple values in one TomSelect control.

In one case it allows only one value and in another case it allows multiple values.

A “normal” SelectBox can be edited by JavaScript

selBox.setAttribute("multiple", true);

But I doesn’t work on TomSelect. How can I solve this idea?

selBox.setAttribute("multiple", true);

Thanks in advance,

Axel

Provide response of array based on “InputPassdate” in Angular

I have a JSON reponse.

Input JSON Data:

[
{
“created_date”: “2010-01-01T00:00:00”,
“end_date”: “2010-03-01T00:00:00”,
“price”: “A”,
“created_by”: “ABC”
},
{
“created_date”: “2010-03-01T00:00:00”,
“end_date”: “2010-06-01T00:00:00”,
“price”: “A”,
“created_by”: “ABC”
},
{
“created_date”: “2010-09-01T00:00:00”,
“end_date”: “2010-12-01T00:00:00”,
“price”: “B”,
“created_by”: “XYZ”
},
{
“created_date”: “2010-12-01T00:00:00”,
“end_date”: “2011-03-01T00:00:00”,
“price”: “B”,
“created_by”: “XYZ”
},
{
“created_date”: “2011-03-01T00:00:00”,
“end_date”: “2011-06-01T00:00:00”,
“price”: “B”,
“created_by”: “XYZ”
},
{
“created_date”: “2011-06-01T00:00:00”,
“end_date”: “2011-12-01T00:00:00”,
“price”: “B”,
“created_by”: “XYZ”
},
{
“created_date”: “2012-06-01T00:00:00”,
“end_date”: “2012-12-01T00:00:00”,
“price”: “C”,
“created_by”: “PQR”
}
]

First object from above array :
{
“created_date”: “2010-01-01T00:00:00”,
“end_date”: “2010-03-01T00:00:00”,
“price”: “A”,
“created_by”: “ABC”
}

When I passed “InputPassdate” then it generate new response with below three output cases.

Three cases:
A) If “InputPassdate” is smaller than first object of both created_date and end_date i.e. “2009-12-31T00:00:00” then display all others objects in array.

Input :
“InputPassdate” : “2009-12-31T00:00:00”

Output JSON:
[
{
“created_date”: “2010-01-01T00:00:00”,
“end_date”: “2010-06-01T00:00:00”,
“price”: “A”,
“created_by”: “ABC”
},
{
“created_date”: “2010-09-01T00:00:00”,
“end_date”: “2011-12-01T00:00:00”,
“price”: “B”,
“created_by”: “XYZ”
},
{
“created_date”: “2012-06-01T00:00:00”,
“end_date”: “2012-12-01T00:00:00”,
“price”: “C”,
“created_by”: “PQR”
}
]

B) If “InputPassdate” is greater than first object of created_date and smaller than first object of end_date i.e. “2010-02-01T00:00:00” then it display all corresponding objects in array.

Input :
“InputPassdate” : “2010-04-01T00:00:00”

Output JSON:
[
{
“created_date”: “2010-01-01T00:00:00”,
“end_date”: “2010-06-01T00:00:00”,
“price”: “A”,
“created_by”: “ABC”
},
{
“created_date”: “2010-09-01T00:00:00”,
“end_date”: “2011-12-01T00:00:00”,
“price”: “B”,
“created_by”: “XYZ”
},
{
“created_date”: “2012-06-01T00:00:00”,
“end_date”: “2012-12-01T00:00:00”,
“price”: “C”,
“created_by”: “PQR”
}
]

C) If “InputPassdate” is greater than first and second object or many more of both created_date and end_date i.e. “2010-07-01T00:00:00” then it avoid those obejects and display others obejects in array.

Input :
“InputPassdate” : “2010-07-01T00:00:00”

Output JSON:
[
{
“created_date”: “2010-09-01T00:00:00”,
“end_date”: “2011-12-01T00:00:00”,
“price”: “B”,
“created_by”: “XYZ”
},
{
“created_date”: “2012-06-01T00:00:00”,
“end_date”: “2012-12-01T00:00:00”,
“price”: “C”,
“created_by”: “PQR”
}
]

Forced string formatting to include dashes

String methods are not my strong suit, I’ve been trying to manipulate an input field value that needs to be 24 characters long

  • 21 of those characters are letters or numbers (no special characters other than dash)
  • 3 of those fields are dashes in the 3rd, 8th, and 17th place
  • I’ve got it working when 21 characters have been entered, but struggling to think through if a user adds more than 21 characters, or when a user add say, 30 characters, how do I only keep the first 21 entered & add dashes?

const caseNumberInput = document.querySelector(".theme--mobile #case_number");
caseNumberInput.addEventListener("blur", (e) => {
  //get rid of all special characters other than "-"
  const value = e.target.value.toUpperCase().replace(/[^a-zA-Z0-9 -]/g, "");
  const length = e.target.value.replace(/[^a-zA-Z0-9 -]/g, "").length;

  if (length === 21) {
    //if length is 21, add the dashes in the 3rd, 8th, and 17th places
    caseNumberInput.value = value.slice(0, 2)+ "-" + value.slice(2,6) + "-" + value.slice(6, 14)+ "-" + value.slice(14)
  }

  if (length >= 21) {
    //remove the dashes then add them back so I don't get multipe dashes if they are already existing / keep only 21 characters?
    let newValue = e.target.value.replace(/[^a-zA-Z0-9]/g, "").toUpperCase().slice(0, 21);
    newValue.slice(0, 2)+ "-" + temp.slice(2,6) + "-" + value.slice(6, 14)+ "-" + value.slice(14);
    caseNumberInput.value = newValue
    console.log(newValue)
  }

});

//keyup to remove any special characters except "-"

caseNumberInput.addEventListener('keyup', (e) => {
  e.target.value = e.target.value.toUpperCase().replace(/[^a-zA-Z0-9 -]/g, "")
});

Node.js server request-response cycle understanding

Want to understand about requestresponse cycle in node.js with clarity. When a signal is terminated by browser, user or due to some network issue, aborted event is fired on request object. In this case do both request and response objects become automatically invalid/ discarded after read and write streams are closed by node.js and all the associated event listeners (like data, end) and other references to the objects are also discarded automatically and they become eligible for automatic garbage collection or all the references still need to be removed manually as part of clean-up job?

Also, what happens after successful completion of requestresponse cycle for the same objects.

I want to understand this as I am concerned about leaving some unwanted references to these objects which will not make them eligible for automatic garbage collection which may lead to memory leak in long run.

Server is behaving normally for short term use. Want to understand the long run scenario.

Adjusting position and ranking in a dynamic table

I have created a piece of code that works with a JSON file to store table data, one of the things the user can do when adding entries is set the rank of their entry. Say we have 5 entries:

Rank = 1 (A),2 (B),3 (C),4 (D),5 (E) respectively then they add an entry with Rank = 18 it should automatically become Rank = 6 (F) to follow the sequential order. Now alternatively if they now edit an existing entry (F) with Rank = 6 and edit its rank to become 1 then the new order should be:

Rank = 1 (F)
Rank = 2 (A)
Rank = 3 (B)
Rank = 4 (C)
Rank = 5 (D)
Rank = 6 (E)

But in my implementation this behavior is not observed instead the ranks don’t seem to swap at all.

This is my current code that I am working on:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Mowie Ranking</title>
    <style>
      :root {
        --background-color: #1c1c1c;
        --text-color: #f4f4f4;
        --header-background: #e67e22;
        --header-border: #d35400;
        --container-background: #333;
        --textarea-background: #2c2c2c;
        --border-color: #e67e22;
        --status-text-color: #f1c40f;
        --saved-text-color: #e74c3c;
        --scrollbar-thumb: #e67e22;
        --scrollbar-track: #333;
        --button-background: #d35400;
        --button-text-color: #fff;
        --button-border-color: #e67e22;
        --button-hover-background: #e67e22;
        --button-hover-text-color: #fff;
        --button-delete-background: #c0392b;
        --button-delete-text-color: #fff;
        --button-delete-hover-background: #e74c3c;
        --button-delete-hover-text-color: #fff;
        --input-background: #2c2c2c;
        --input-border-color: #e67e22;
        --input-text-color: #fff;
      }

      body {
        font-family: "Arial", sans-serif;
        margin: 0;
        padding: 0;
        background: var(--background-color);
        color: var(--text-color);
        text-align: center;
      }

      header {
        background-color: var(--header-background);
        color: #fff;
        padding: 20px;
        font-size: 2.5em;
        border-bottom: 3px solid var(--header-border);
        box-shadow: 0 4px 10px rgba(0, 0, 0, 0.5);
        position: relative;
        overflow: hidden;
        z-index: 1;
      }

      header::before {
        content: "";
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background: url("https://www.example.com/halloween-pattern.png")
          no-repeat center center;
        background-size: cover;
        opacity: 0.2;
        z-index: -1;
      }

      .container {
        max-width: 800px;
        margin: 40px auto;
        padding: 20px;
        background: var(--container-background);
        border-radius: 12px;
        box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
        overflow: hidden;
        text-align: left;
      }

      table {
        width: 100%;
        border-collapse: collapse;
        margin: 20px 0;
      }

      th,
      td {
        border: 1px solid var(--border-color);
        padding: 8px;
        text-align: center;
      }

      th {
        background-color: var(--header-background);
        color: #fff;
      }

      td input {
        width: 100%;
        box-sizing: border-box;
        background-color: var(--input-background);
        border: 1px solid var(--input-border-color);
        color: var(--input-text-color);
        padding: 8px;
        border-radius: 4px;
      }

      .add-entry {
        margin-bottom: 20px;
      }

      .add-entry input,
      .add-entry button {
        margin: 5px 0;
        padding: 10px;
        border-radius: 6px;
        border: 1px solid var(--button-border-color);
        background-color: var(--input-background);
        color: var(--input-text-color);
      }

      .add-entry button {
        background-color: var(--button-background);
        color: var(--button-text-color);
        cursor: pointer;
        transition: background-color 0.3s ease, border-color 0.3s ease;
      }

      .add-entry button:hover {
        background-color: var(--button-hover-background);
        border-color: var(--button-hover-background);
      }

      .delete-btn {
        background-color: var(--button-delete-background);
        color: var(--button-delete-text-color);
        border: none;
        padding: 5px 10px;
        border-radius: 6px;
        cursor: pointer;
        transition: background-color 0.3s ease;
      }

      .delete-btn:hover {
        background-color: var(--button-delete-hover-background);
        color: var(--button-delete-text-color);
      }

      ::-webkit-scrollbar {
        width: 12px;
      }

      ::-webkit-scrollbar-track {
        background: var(--scrollbar-track);
        border-radius: 10px;
      }

      ::-webkit-scrollbar-thumb {
        background: var(--scrollbar-thumb);
        border-radius: 10px;
      }

      ::-webkit-scrollbar-thumb:hover {
        background: #d35400;
      }

      body {
        scrollbar-width: thin;
        scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
      }

      .actions-column {
        width: 60px;
      }

      .mowie-column {
        width: calc(100% - 160px);
      }

      th,
      td {
        text-align: center;
      }
    </style>
  </head>
  <body>
    <header>Mowie Ranking</header>

    <div class="container">
      <div class="add-entry">
        <input type="number" id="rank" placeholder="Rank" min="1" />
        <input type="text" id="mowie" placeholder="Mowie Name" />
        <input
          type="number"
          id="rating"
          placeholder="Rating (1-10)"
          min="1"
          max="10"
        />
        <input type="text" id="genre" placeholder="Genre" />
        <button id="add-entry">Add Entry</button>
      </div>
      <table>
        <thead>
          <tr>
            <th class="actions-column">Actions</th>
            <th>Rank</th>
            <th class="mowie-column">Mowie</th>
            <th>Rating</th>
            <th>Genre</th>
          </tr>
        </thead>
        <tbody id="table-body">
          <!-- Table rows will be dynamically inserted here -->
        </tbody>
      </table>
    </div>

    <script>
      const autosaveDelay = 1000; // Autosave delay in milliseconds

      const tableBody = document.getElementById("table-body");

      // WebSocket connection
      const socket = new WebSocket(`wss://${window.location.host}`);

      socket.addEventListener("open", function () {
        console.log("WebSocket is connected.");
      });

      socket.addEventListener("message", function (event) {
        if (event.data instanceof Blob) {
          const reader = new FileReader();
          reader.onload = function () {
            const data = JSON.parse(reader.result);
            updateTable(data);
          };
          reader.readAsText(event.data);
        } else {
          const data = JSON.parse(event.data);
          updateTable(data);
        }
      });

      // Add new entry
      document
        .getElementById("add-entry")
        .addEventListener("click", function () {
          const rank = parseInt(document.getElementById("rank").value, 10);
          const mowie = document.getElementById("mowie").value;
          const rating = document.getElementById("rating").value + "/10";
          const genre = document.getElementById("genre").value;

          if (mowie && rating && genre) {
            let nextRank = rank || tableBody.rows.length + 1;

            if (rank) {
              // Adjust ranks if a rank is provided
              const rows = Array.from(tableBody.rows);
              rows.forEach((row) => {
                const currentRank = parseInt(row.cells[1].innerText, 10);
                if (currentRank >= rank) {
                  row.cells[1].innerText = currentRank + 1;
                }
              });
            }

            const row = tableBody.insertRow();
            row.insertCell(0).innerHTML =
              '<button class="delete-btn">Delete</button>';
            row.insertCell(1).innerText = nextRank; // Assign rank
            row.insertCell(2).innerText = mowie;
            row.insertCell(3).innerText = rating;
            row.insertCell(4).innerText = genre;

            updateAndSave(); // Save the new entry
            document.getElementById("rank").value = "";
            document.getElementById("mowie").value = "";
            document.getElementById("rating").value = "";
            document.getElementById("genre").value = "";
          }
        });

      // Update and save function
      function updateAndSave() {
        const rows = Array.from(tableBody.rows);
        updateTable(updatedData);
        // Create an array to hold the updated data
        const updatedData = rows.map((row, index) => ({
          rank: index + 1, // Assign sequential ranks starting from 1
          mowie: row.cells[2].innerText,
          rating: row.cells[3].innerText,
          genre: row.cells[4].innerText,
        }));

        // Update the table with new ranks
        rows.forEach((row, index) => {
          row.cells[1].innerText = updatedData[index].rank;
        });

        // Send updated data to the server
        fetch(`/save-file`, {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify(updatedData),
        }).catch((error) => console.error("Error saving file:", error));
      }

      // Autosave on content change
      let timeout;
      tableBody.addEventListener("input", function () {
        clearTimeout(timeout);
        timeout = setTimeout(updateAndSave, autosaveDelay); // Autosave after specified delay of inactivity
      });

      // Load the file content when the page loads
      window.onload = function () {
        fetch(`/get-file-content`)
          .then((response) => response.json())
          .then((data) => {
            updateTable(data);
          })
          .catch((error) => console.error("Error loading file:", error));
      };

      // Update table with new data
      function updateTable(data) {
        tableBody.innerHTML = "";
        data.forEach((item) => {
          const row = tableBody.insertRow();
          row.insertCell(0).innerHTML =
            '<button class="delete-btn">Delete</button>';
          row.insertCell(1).innerText = item.rank;
          row.insertCell(2).innerText = item.mowie;
          row.insertCell(3).innerText = item.rating;
          row.insertCell(4).innerText = item.genre;
        });
      }

      // Handle cell editing
      tableBody.addEventListener("dblclick", function (event) {
        const cell = event.target.closest("td");
        if (cell && cell.cellIndex > 0) {
          // Allow editing in all columns except Actions
          const originalText = cell.innerText;
          const input = document.createElement("input");
          input.value = originalText;
          input.style.width = "100%";
          input.style.boxSizing = "border-box";
          input.style.backgroundColor = "var(--input-background)";
          input.style.border = "1px solid var(--input-border-color)";
          input.style.color = "var(--input-text-color)";
          input.style.padding = "8px";
          input.style.borderRadius = "4px";

          cell.innerHTML = "";
          cell.appendChild(input);

          input.focus();
          input.addEventListener("blur", function () {
            const newValue = input.value;
            if (newValue !== originalText) {
              if (cell.cellIndex === 1) {
                // Rank column
                const newRank = parseInt(newValue, 10);
                if (!isNaN(newRank) && newRank > 0) {
                  // Update ranks for rows with rank >= newRank
                  const rows = Array.from(tableBody.rows);
                  rows.forEach((row) => {
                    const rankCell = row.cells[1];
                    const rankValue = parseInt(rankCell.innerText, 10);
                    if (rankValue >= newRank && rankCell !== cell) {
                      rankCell.innerText = rankValue + 1;
                    }
                  });

                  // Update the rank of the current cell
                  cell.innerText = newRank;

                  // Reorder and update ranks
                  sortAndReassignRanks(); // Reorder rows and update ranks
                } else {
                  cell.innerText = originalText;
                }
              } else {
                cell.innerText = newValue;
              }
              updateAndSave(); // Only update and save after changes
            } else {
              cell.innerText = originalText;
            }
          });

          input.addEventListener("keydown", function (event) {
            if (event.key === "Enter") {
              input.blur();
            }
          });
        }
      });

      // Handle row deletion
      tableBody.addEventListener("click", function (event) {
        if (event.target.classList.contains("delete-btn")) {
          const row = event.target.closest("tr");
          row.remove();

          // Adjust ranks after deletion
          updateAndSave(); // Ranks will be sequentially updated in updateAndSave
        }
      });
    </script>
  </body>
</html>

Why is the type can not be referred correctly?

Here is my code. The data is supposed to be referred to as one of the FeeReturnType . However, it is currently referred to as a union type of AllFee[] | ApiOrFileFee[] | DataSvrFee[] | AccountFee[].

export type FeeType = 'ALL' | 'API' | 'FILE' | 'DATA_SVR' | 'ACCOUNT';

export interface AllFee {
  name: string;
  fee: number;
}

export interface ApiOrFileFee {
  integrator_id: string;
  integrator_name: string;
  call_count: number;
  fee: number;
}

export interface DataSvrFee {
  integrator_id: string;
  integrator_name: string;
  count: number;
  fee: number;
}

export interface AccountFee {
  name: string;
  id: string;
  count: string;
  user: string;
  user_id: string;
  fee: number;
}

export type FeeReturnType<T extends FeeType> = 
  T extends 'ALL' ? AllFee[] :
  T extends 'API' | 'FILE' ? ApiOrFileFee[] :
  T extends 'DATA_SVR' ? DataSvrFee[] :
  T extends 'ACCOUNT' ? AccountFee[] :
  never;

function handleFeeData<T extends FeeType>(_type: T, data: FeeReturnType<T>): void {
  switch (_type) {
    case 'ALL':
      data.forEach(item => {
        console.log('All Fee:', item.name, item.fee);
      });
      break;
    case 'API':
    case 'FILE':
      data.forEach(item => {
        console.log('API/File Fee:', item.integrator_id, item.call_count, item.fee);
      });
      break;
    case 'DATA_SVR':
      data.forEach(item => {
        console.log('Data Svr Fee:', item.integrator_id, item.count, item.fee);
      });
      break;
    case 'ACCOUNT':
      data.forEach(item => {
        console.log('Account Fee:', item.name, item.user, item.fee);
      });
      break;
    default:
      break;
  }
}

const allFeeData: AllFee[] = [{ name: 'All Fee', fee: 100 }];
const apiFeeData: ApiOrFileFee[] = [{ integrator_id: '123', integrator_name: 'API Integrator', call_count: 10, fee: 50 }];
const accountFeeData: AccountFee[] = [{ name: 'Account', id: '1', count: '10', user: 'John', user_id: '100', fee: 200 }];

handleFeeData('ALL', allFeeData); 
handleFeeData('API', apiFeeData);  
handleFeeData('ACCOUNT', accountFeeData); 

code

What needs to be added in the google map API referrers if my url is like blob:https://abc.mydomain.com/xyz

I’m using Google Maps in my project. I have the url as blob:https://abc.example.com/xyz
I need to add some restrictions into the google map account. Right now I added
blob:https://xxx.example.com/* as rule, but I am getting Google Maps JavaScript API error:

Google Maps JavaScript API error: RefererNotAllowedMapError
https://developers.google.com/maps/documentation/javascript/error-messages#referer-not-allowed-map-error

I tried to add blob:https://xxx.example.com/* into my google map account, but it didn’t help.

How can I resolve this? Any help will be appreciated.
Thanks.

deleteTask function for Todo app is not working

I’m building a todo app using js, and I’ve been trying to figure out the logic behind why my deleteTask function is not working. This is my first time building a todo app (started learning web dev this March), and after searching for similar issues online I decided to ask here.

Here’s my code so far. // function to delete a task is where the trouble is, could be I’m missing a step.
I tried to apply a function like this

deleteButton.addEventListener('click', function(){

  taskList.removeChild(newTask);

}) 

after seeing a video on Youtube where a developer was explaining how to built a todo app and this way worked for me ! But I want to figure out why my code is not running instead of using a solution that’s worked for someone else.

Below is my JS code

//selecting html elements 

const taskForm = document.getElementById("taskForm");
const taskInput= document.getElementById("taskInput");
const taskList = document.getElementById("taskList");


//  function to add a new task 
function addTask(event){
   event.preventDefault()
   
   
   
// new html element <li> to list our tasks 
   const newTask = document.createElement('li');
   taskList.append(newTask);
   newTask.innerHTML = taskInput.value;

   taskInput.value = ' ';




 // creating a delete button element  
  const deleteButton = document.createElement('button');
  newTask.append(deleteButton);

  deleteButton.setAttribute('class', 'delete-button');

  deleteButton.innerHTML = "Delete";
}


// function to delete a task

function deleteTask(event){
   const newTask = event.target;
   taskList.removeChild(newTask);           
}




// when button "add task" is clicked new task is added 
const button = document.querySelector('.button');
button.addEventListener('click', addTask );


//when button "delete" is clicked a task is removed 
const delButton = document.querySelector('.delete-button');
delButton.addEventListener('click', deleteTask );