Bulma CSS, clear button in input search text field

I have a search text field like this one:

    <div class="field">
      <p class="control has-icons-left has-icons-right">
        <input class="input is-normal is-rounded" type="text" placeholder="Search...">
        <span class="icon is-small is-left">
          <i class="fa-solid fa-filter"></i>
        </span>
      </p>
    </div>

I want to add a clear button on it, that clears the text in the field if something is written on it. It would be nice if it appears only if there is some text in the field.

Thanks for the help.

return bounding box of transformed text element using SVG.js?

I am using SVG.js and trying to fetch the bounding box of a transformed text. I made a small example of my use case:

    this.draw.attr({ width: 200, height: 200 });

        const text = this.draw
            .text("some text is here")
            .attr({ x: 50, y: 50, transform: "rotate(45) scale(1.1 1.1)" });

        const textbbox = text.rbox();
        const textBorder = this.draw
            .rect(textbbox.w, textbbox.h)
            .attr({ fill: "none", "stroke-width": 1, stroke: "black" })
            .move(textbbox.x, textbbox.y);
        return this.draw;

Whenever I am trying to use rbox(), it returns the following error:
enter image description here

Thanks,

Mat

How do I properly do the integration of the website, server, and database?

I have an assignment that requires creating the website, server and sql database of a travel company. The task is on the creation of adding listing and updating listing. The following are my codes that I have worked on. I have successfully created the server side and tested on postman which works, however, I am facing difficulty in writing the connection between the server and the website. When the form is filled and the “submit” button is hit, there is no response and nothing gets sent to the database. Hope I can get some light shed on why the html page is not responding and why no info is passed on to the database.
Thank you very much in advance!
p/s Please pardon if my codes look really messy or nonsensical, as this is my very first time attempting something like this. I’ve only started out learning programming, so am still doesn’t feel quite comfortable with coding.

`**App.py**`
from flask import Flask, request, jsonify, render_template #, redirect, url_for
from flask_cors import CORS
from model.listing import Listing
from model.User import User
from validation.Authorisation import *

from dotenv import load_dotenv
load_dotenv() #to load environment variables from .env file

app = Flask(__name__, template_folder='../website', static_folder='../website')
CORS(app)


#Add listing
@app.route('/travel', methods=["POST"])
@login_required
def insertListing():

    try:
        
        # retrieve required data
        listingJSON=request.json
        title=listingJSON['title']
        description=listingJSON['description']
        price=listingJSON['price']
        country=listingJSON['country']
        travelPeriod=listingJSON['travel_period']
        imageURL=listingJSON['imageURL']

        #call model
        recs=Listing.insertListing(title, description, price, country, travelPeriod, imageURL)

        msg=str(recs)+" record(s) inserted"
        return jsonify({"message":msg}),201

    except Exception as err:

            print(err)
            return jsonify ({"Message": "Error"}), 500


#Update Listing

@app.route('/updatelisting/<int:travelID>',methods=['PUT'])
@login_required
def updateListing(travelID):

    print(g.role)
    print(g.userid)

    if g.role!="admin":
        return jsonify({"Message":"You are not authorised."}),401

    try:
        #retrieve req data
        listingJSON=request.json
        title=listingJSON['title']
        description=listingJSON['description']
        price=listingJSON['price']
        country=listingJSON['country']
        travelPeriod=listingJSON['travel_period']
        imageURL=listingJSON['imageURL']
    
    
        #call model 
        recs=Listing.updateListing(title, description, price, country, travelPeriod, imageURL)

        msg=str(recs)+" record(s) updated"
        return jsonify({"message":msg}),200

    except Exception as err:

        print(err)
        return jsonify({"Message":"Error"}),500
if __name__ == "__main__":
    app.run(debug=True)

**addListing.html**

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Add Travel Listing | Travel Website</title>
    <link rel="stylesheet" href="style.css"> </head>
    <script
    src="https://code.jquery.com/jquery-3.6.0.min.js"
    integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
    crossorigin="anonymous"></script>
    <script src="./addListing.js" type="text/javascript"></script>


<body>
    <header>
    </header>

    <main>
        <h1>Add Travel Listing</h1>
        <form id="listingForm" action="/travel" method="post" enctype="multipart/form-data">
            <div>
                <label for="title">Listing Title:</label>
                <input type="text" id="title" name="title" required>
            </div>

            <div>
                <label for="description">Description:</label>
                <textarea id="description" name="description" rows="5" required></textarea>
            </div>

            <div>
                <label for="country">Country:</label>
                <input type="text" id="country" name="country" required>
            </div>

            <div>
                <label for="price">Price:</label>
                <input type="number" id="price" name="price" min="0" step="0.01" required>
            </div>

            <div>
                <label for="travelPeriod">Travel Period:</label>
                <input type="text" id="travelPeriod" name="travelPeriod" required>
            </div>

            <div>
                <label for="imageURL">Upload Image:</label>
                <input type="text" id="imageURL" name="imageURL">
            </div>

            <button type="submit" a href="listingadded.html">Add Listing</button>
        </form>
    </main>

    <footer>
    </footer>

    <script src="addListing.js"></script>
</body>
</html>`

**addListing.js**
document.addEventListener(“DOMContentLoaded”, function () {
// add a submit event listener to the form
document.getElementById(‘listingForm’).addEventListener(‘submit’, function (event) {
// prevent form submission
event.preventDefault();

        var isValid = true;
        var message = "";

        var title = document.getElementById('title').value;
        var description = document.getElementById('description').value;
        var price = document.getElementById('price').value;
        var country = document.getElementById('country').value;
        var travelPeriod = document.getElementById('travelPeriod').value;
        var imageURL = document.getElementById('imageURL').value;

        // Perform validation
        if (title.trim() === "") {
            isValid = false;
            message += "Title is required.n";
        }
        // Perform validation for other fields...

        // Display validation message if any
        if (!isValid) {
            alert(message);
            return; // Exit function if validation fails
        }

        // Send a request to the server
        fetch('http://localhost:5000/travel', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                title: title,
                description: description,
                price: price,
                country: country,
                travelPeriod: travelPeriod,
                imageURL: imageURL
            }),
        })
        .then(response => response.json())
        .then(data => {
            // Handle the response from the server
            if (data.status === 'success') {
                alert(data.message);
                // Redirect to listingadded.html upon successful submission
                window.location.href = "listingadded.html";
            } else if (data.status === 'error') {
                alert(data.message); // Display error message
            } else {
                console.error('Unexpected response from server:', data);
            }
        })
        .catch(error => {
            console.error('Error:', error);
            alert('An error occurred while processing your request.');
        });
    });
});

I tried chatGPT, googling, watching Youtube, everything. Nothing seemed to be able to resolved the issue, not even chatGPT can pinpoint the issue

Remove audible popping sound when pausing audio with Javascript

When you pause an audio element with javascript using audio.pause(); you can hear an audible pop.

This occurs when a waveform is stopped/cut in the middle of a wave, rather than at a zero-crossing.

I have been looking for a way to resolve this and seen alot of people suggesting quickly fading out like this:

var fadeAudio = setInterval(function () {
    if (audio.volume <= 0.0) {
        clearInterval(fadeAudio);
        audio.volume = 0;
    }
    if (audio.volume != 0.0){
        audio.volume -= 0.1;
    }
}, 200);

This however will give a worse end result with a descending series of clicks instead.

What is the best way to stop audio in javascript without having any popping sound

Check for referrer or file:// [duplicate]

I’m looking for a solution that will recognize requests from browser and requests from iframe. => I only want to display the informations in the IFrame.

It’s easy to check this with the referrer option. But when the iframe is downloaded into a local file:// the referrer is empty. How can I check if the protocol is file://?

Thank you!

When using multiple stores in Svelte, the information from one store does not update

I’m having issues with stores in Svelte. Currently, I’m using derived to update a filter as the stores get updated.

Here’s an example of the function:

export const FILTERED_SORTED_BIDS = derived([PURCHASE_BIDS, FILTER_PARAMS, SORT_PARAMS], ([$PURCHASE_BIDS, $FILTER_PARAMS, $SORT_PARAMS]) => {
    let filteredData = $PURCHASE_BIDS;
    let filterCounter = 0;

    if ($FILTER_PARAMS.priority) {
        filteredData = filteredData.filter((item) => item.purchaseBid.priority == $FILTER_PARAMS.priority)
        filterCounter += 1
    }
    // More filter conditions...
}

This way, every time PURCHASE_BIDS, FILTER_PARAMS, or SORT_PARAMS changes, FILTERED_SORTED_BIDS should update. The problem here is that if I’m filtering using FILTER_PARAMS and I make a change in PURCHASE_BIDS, the change doesn’t reach the derived function.

I make changes in PURCHASE_BIDS using an update like this:

PURCHASE_BIDS.update(bids => {
    bids[index].purchaseBid.priority = temPriority;
    return bids;
});

From what I’ve read in the documentation, that should be enough. However, the updated value doesn’t reach the derived function, causing reactivity issues. If I’m filtering, for example, by priority in my list, when I assign a new one, the previous one remains. However, if I’m not filtering (i.e., not using FILTER_PARAMS), there’s no problem. I hope someone can guide me; it’s my first time asking here. Thank you very much!

I hope that regardless of whether I’m filtering or not, the updated values ​​reach the derived function, and thus avoid the reactivity problems I’m having.

How can I skip certificate validation with a Fetch API request within the browser?

I have the following code running in the browser:

  const response = await fetch(`${url}`, {
    method: 'POST',
    headers: {
      Authorization: `Basic ${authorization}`,
    },
    body: loginData,
  })

when I call this, I get the following response back from the server:

<URL> net::ERR_CERT_AUTHORITY_INVALID

I control the server and it is using a self-signed certificate.

In my fetch request, I want to ignore or skip the certificate validation.

I have tried:

  const response = await fetch(`${url}`, {
    method: 'POST',
    headers: {
      Authorization: `Basic ${authorization}`,
    },
    body: loginData,
    agent: false,
    rejectUnauthorized: false,
  })

but the behavior remains the same.

How can I skip the validation?

why is captcha verification with variable for “solution” asked before it is solved?

I implemented friendly captcha to a form and need to do a verification. I am not sure if it has to be done once or with every puzzle so I want to have the “solution” as a variable.

Sadly it already starts looking for “solution” even though the captcha hasn’t started yet. How can I prevent this?

This is my current code for the verification:

<script>
document.addEventListener('DOMContentLoaded', () => {
    // Das <input>-Element mit dem Namen "frc-captcha-solution" auswählen
    const solutionInput = document.querySelector('input[name="frc-captcha-solution"]');

    // Überprüfen, ob das Element gefunden wurde
    if (solutionInput) {
        // Funktion zur Verarbeitung der Verifikationsanfrage
        const processVerification = (solution) => {
            const secret = ''; // Setzen Sie hier Ihren API-Schlüssel ein
            const sitekey = ''; // Optional: Setzen Sie hier Ihren Sitekey ein

            // Verifizierungsanfrage senden
            fetch('https://api.friendlycaptcha.com/api/v1/siteverify', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    solution,
                    secret,
                    sitekey,
                }),
            })
            .then(response => response.json())
            .then(data => {
                console.log(data);
                // Hier können Sie das Verifikationsergebnis verarbeiten
                if (data.success) {
                    console.log('CAPTCHA erfolgreich verifiziert!');
                } else {
                    console.error('CAPTCHA-Verifikation fehlgeschlagen:', data.errors);
                }
            })
            .catch(error => console.error('Fehler bei der Verifikationsanfrage:', error));
        };

        // Überwachen Sie das "change"-Event des <input>-Elements
        solutionInput.addEventListener('change', () => {
            // Den Wert des <input>-Elements als dynamischen Lösungswert setzen
            const solution = solutionInput.value;

            // Verarbeitung der Verifikationsanfrage aufrufen
            processVerification(solution);
        });
    } else {
        console.error('Das <input>-Element wurde nicht gefunden.');
    }
});
</script>

How to make JS draw elemnts in expected order

I have the following problem. There is some script that takes 2-5 seconds to complete and during this time I want to decorate the screen with loder gif. If there is no data it should display message that data is not awailable and otherwise it should draw graphs.
But what happens if I have the code that requests data and process graphs the loader does not apper as it waits till everythin is processed and only then appears and immedeatly is replaced by graph.

If I comment the code with the request. The message that data is not awailable appears right away(and it should not) and then the loader shows itself and then after an instance it desappears leaving just the message. As you can see on the screenshot the message and the loader apper simulteneously but the should not.

I assume tha JS first process all operations and then draw the result right away, not following my order. How can I tell the JS that it should process my comand(draw the loader) and only then process other things? Would be very greatful for your help.

    <div class="main-container-right">
            <!-- Графики -->
            <div class="graph-container" style="display: none;">
              <div id="mass-time-graph-container" class="derivative-graph-container"> -</div>
              <div id="temperature-graph-container" class="temperature-graph-container">-</div>
            </div>
            <div class="no-data-message data-not-awailable" style="display: none;">Data is not awailable</div>
            <div class="no-data-message data-loading" style="display: none;">
              <img class="waiting-animation" src="img/loading.gif" title="Данные подгружаются" style="margin-left: 5px; cursor: pointer;">
              <div>Data is loading</div>
            </div>
            <!-- END Графиков -->
          </div>
// -- Выбор испытания
    $('body').on('click', '.tr-content', function(){
        $('.data-not-awailable').fadeOut(1)
// -- THE Message should be display none
        $('.graph-container').fadeOut(1)
// -- THE Loader should display
        $('.data-loading').fadeIn()
        
// -- SOME code that takes 2-5 second

            $('.graph-container').fadeOut(1)
// -- THE Loader should display none
            $('.data-loading').fadeOut(1)
// -- THE Message should be display
            $('.data-not-awailable').fadeIn(1)

    })

enter image description here

Display problem on a mobile device, but only on a few phones. Section blinks/ flashes on the screen

I’ve got a problem. I tried to create a hotspot map, and it’s working fine right now, but I have some display issues when I check it on two phones. The section starts to blink like on the screen.

Page: https://hoffmannteile.de/

enter image description here

On other phones, everything is okay. I don’t know if it’s a resolution problem or something else because when I try it on Chrome with different resolutions in Device Mode, it doesn’t even blink once. I have to fix it because one of them is my boss’s phone 🙂

CSS

    .map-section {
      background-color: transparent;
      padding: 20px;
      max-width: 800px;
      font-family: 'Open Sans', sans-serif;
      margin: auto;
      display: block;

    }

    .map-container {
        position: relative;
    }

    .hotspoters {
      top: 0;
      left: 0;
      position: absolute;
      width: 100%;
      height: 100%;
      display: flex;
      flex-direction: column;
      justify-content: space-around;
      align-items: center;
      pointer-events: none;
    }

    .hotspoters h3{
      font-family: 'Open Sans', sans-serif;
      font-size: 2vmin;
      text-transform: uppercase;
    }

    .clickspoter{
      display: flex;
      width: 6vmin;
      height: 6vmin;
      background-color: #6200ff8f;
      z-index: 2;
      cursor: pointer; 
      pointer-events: auto;
      justify-content: center;
      align-items: center;
    }

    .hotspoter {
    position: relative;
    width: 2vmin;
    height: 2vmin;
    box-shadow: 0 0 0 0 rgba(131, 4, 4, 0.7);
    background: #ad0000;
    cursor: pointer;
    animation: pulse 2.5s infinite cubic-bezier(0.55, 0, 0, 0.7);
    pointer-events: auto;
    
    &:hover {
      animation: none;
    }
    
    &.deactivate {
      color: #000;
      background: #999;
      animation: none;
    }
      
    }
        /*SPOTS POSITION*/
    /*belgien*/
    .hot2{
      top: 36.5%;
      left: 10%;
      position: absolute;

    }
    /*niederlande*/
    .hot3{
      top: 23.5%;
      left: 8.7%;
      position: absolute;
    }
    /*osterreich*/
    .hot4{
      top: 82%;
      left: 58%;
      position: absolute;
    }
    /*deutschland*/
    .hot5{
      top: 38%;
      left: 51%;
      position: absolute;
    }
    /*polen*/
    .hot6{
      top: 35%;
      left: 72%;
      position: absolute;
    }

    /*COUNTRY POSITION*/

    /*belgien*/
    .ctr2{
      top: 39.5%;
      left: 5%;
      position: absolute;
    }
    /*niederlande*/
    .ctr3{
      top: 26.5%;
      left: 11%;
      position: absolute;
    }
    /*osterreich*/
    .ctr4{
      top: 74%;
      left: 50%;
      position: absolute;
    }
    /*deutschland*/
    .ctr5{
      top: 40%;
      left: 25%;
      position: absolute;
    }
    /*polen*/
    .ctr6{
      top: 26%;
      left: 70%;
      position: absolute;
    }

    /*styles for SVG*/
    .schweiz, .belgien, .niederlande, .ostrreich, .deutschland, .polen {
      fill: #FFFFFF;
      stroke: #610000;
      stroke-miterlimit: 10;
      transition: fill 0.5s ease, opacity 0.5s ease;
    }

    .schweiz:hover, .belgien:hover, .niederlande:hover, .ostrreich:hover, .deutschland:hover, .polen:hover {
      fill: #ad0000;
      opacity: 0.5;
    }

    .noclick {
      fill: #E8E8E8;
      stroke: #7A0000;
      stroke-miterlimit: 10;
    }

    .info-box {
      display: none;
      position: absolute;
      top: 100%;
      left: 50%;
      transform: translateX(-50%);
      background-color: #fff;
      border: 1px solid #ccc;
      padding: 30px;
      box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
      z-index: 1;
    }

    .map-info {
      display: none;
      position: absolute;
      top: 0%;
      left: 50%;
      transform: translate(-50%, 0%);
      padding: 30px;
      background-color: #fff;
      box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
      z-index: 95;
      border: #ad0000;
      border-style: solid;
      border-width: 3px;
    }

    /* Styl dla tła z widocznym efektem overlay */
    .map-overlay {
      display: none;
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background-color: rgba(255, 255, 255, 0.85);
      z-index: 90;
    }

    /* Styl dla przycisku zamykającego okno */
    .map-btn {
      position: absolute;
      top: 10px;
      right: 15px;
      cursor: pointer;
      font-weight: 900;
      font-size: 20px;
    }

    .map-btn:hover{
      color: #ad0000;
      transform: scale(0.8);
    }

    /* Styl dla div.map-details */
    .map-details {
      width: 60vmin;
      padding: 0vmin;
      box-sizing: border-box;
    }

    /* Styl dla małego nagłówka z nazwą kraju */
    .country-name {
      color: #333;
      font-weight: 600;
      font-size: 2vmin;
      margin-top: 1vmin;
    }

    /* Styl dla zwykłego nagłówka z nazwą miasta */
    .city-name {
      color: #000;
      font-weight: 700;
      font-size: 4vmin;
      margin-top: 0.5vmin;
      box-sizing: border-box;
    }

    /* Styl dla paragrafu z kodem pocztowym i numerem telefonu */
    .address-info {
      color: #555;
      font-size: 2.5vmin;
      margin-top: 0.5vmin;
    }

    .tel-info {
      color: #555;
      margin-top: -1.5vmin;
      font-size: 2.5vmin;
    }

    /* Styl dla guzika */
    .call-button {
      background-color: #ad0000;
      color: #fff;
      padding: 10px;
      border: none;
      text-decoration: none;
      display: inline-block;
      font-size: 2vmin;
      cursor: pointer;
      transition: background-color 0.3s, border 0.3s, color 0.3s;
      margin-top: 10px;
      border: 2px solid #ad0000;
      font-weight: 600;
    }

    /* Efekt hover dla guzika */
    .call-button:hover {
      background-color: #fff;
      border: 2px solid #ad0000;
      color: #ad0000;
      font-weight: 600;
    }

    @keyframes pulse {
      to {
      box-shadow: 0 0 0 3vmin rgba(255, 255, 255, 0);
      }
    }

    @media (max-width:490px){
    .call-button {
        font-size: 4vmin;
    }

    .tel-info {
        font-size: 4vmin;
    }

    .address-info {
        font-size: 4vmin;
    }

    .city-name {
        font-size: 6vmin;
    }

    .country-name{
        font-size: 3.5vmin;
    }

    .hotspoters h3 {
    font-size: 2.3vmin;
    }

    .map-container{
        padding-top: 12%;
        padding-bottom: 12%;    
    }

            /*SPOTS POSITION*/
    /*belgien*/
    .hot2{
      top: 40.5%;
      left: 10%;
    }
    /*niederlande*/
    .hot3{
      top: 31%;
      left: 9.5%;
    }
    /*osterreich*/
    .hot4{
      top: 73%;
      left: 58%;
    }
    /*deutschland*/
    .hot5{
      top: 42%;
      left: 51%;
    }
    /*polen*/
    .hot6{
      top: 38%;
      left: 72%;
    }

    /*COUNTRY POSITION*/

    /*belgien*/
    .ctr2{
      top: 42%;
      left: 5%;
    }
    /*niederlande*/
    .ctr3{
      top: 32.5%;
      left: 11.5%;
    }
    /*osterreich*/
    .ctr4{
      top: 68%;
      left: 49%;
    }
    /*deutschland*/
    .ctr5{
      top: 40%;
      left: 25%;
    }
    /*polen*/
    .ctr6{
      top: 30%;
      left: 70%;
    }
}

HTML

<section class="map-section">
    <div class="map-container">

        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 498.1 315.8">
            <path d="m71.1 181.4-2-3.5a137 137 0 0 1-.3-6.4l3.2-3.1 3-3.6c.3-.3 2.7-.3 3.1-.3l-.4-7.1c4.5-.2 3 .5 3-3.7-.2-3.8.5-2.9-3.2-2.8l2.8-6c0-2.5-.3-6-.4-8.5h-.1l-.2-3-6.8-6.1-6.8-6.1-3.4.1-3 3.1-.3.3-3.6.1-.1-3.2-10.1-2.6c0-.3-2.8 0-2.9 0l-3.2 3.1.2 3.2-10.1.5c-4 .1-2.9.8-3.3-3.1l-3.5-2.8-3.4.2-.2-3.5-3.4.2-3.2 3.6-3.5-3.3.2 3.4-6.3 3.2.1 3.2.3 6.2 3.3 3c.4 0 .3 2.3.3 2.6v.7l3.1-.2 3.1-.1h.2l.3 6.4 6.5-.3c.4-.3.2 2.9.3 3v.3l3.7 6.1c2.9-.2 6.9-.2 9.8-.5l.5 9.7-3 2.9-.2.2 3.5 3.3 6.7-.3-.2-3.5 3.4-.2.1 3.5 3.3 2.7.2.2.2 3.2 3.3 2.9.2.2.1 2.4v.6l3.2-.1c1.7 1.6 5.2 4.7 7 6.1l.2 3.2 3.2-3.4 3.4-.1.7-.4s1.6-5.7 1.4-5.8z" class="belgien"></path>
            <path d="M82.7 188.4c3.9-.2 2.9.4 2.8-3.3l-.3-6.3-.2-3.4-6.7-6-.2-4.9-2.6.1c-.4-.3-3.3 3.6-3.5 3.8l-3.2 3.1.3 6.4 2 3.5c.1.1-1.5 5.8-.8 5.5 3.9.8 9.3 2.5 13.3 3a12 12 0 0 0-.9-1.5z" class="noclick"></path>
            <path d="m55.8 121.5.1 3.2c.2-.1 3.9.1 3.8-.4l2.8-3.1h.2l3.4-.1 3.3 3c2.3 1.9 8 7.1 10.3 9.2l.2 3c.2.1 0-1 .1-1 .2-.3 6.3-2.9 5.8-3.5l.5-.2-.2-3.2-.6-12.1 5.9-3.4 9.5-3.5 3.1 2.9 9.6-.5 3.2-.1.1-.4c.3.1 2.7-9.4 2.9-9.5l-.2-3.2-3.1-2.8L119 93c-.2-.2.3-.5.4-.7l-.6-12 3-.2v-.4h.2l-.5-9.1 2.7-3.1.4-.4-2.1-1.8-2.6 2.4-3.2.2-.6-12.7-6.7.3-3 3.6-6.6 3.3-.3-6.5-3.4 3.6-3.1.1-3.4.2-6.6 3.3-3.2 3.4.3 6.2.7 12.9-6.2 6.5-6.7.3-.3-6.2 3.2-3.5-3.4.1 6.4-6.5-.2-3.2L70 70c-9 .4-5.5-.9-9.8 6.8l.3 6.2-3 3.5.1 3-3.6.2.2 3.2-3 3.4-6.7.3.3 6.4c3.8 0 3.3-1.4 3.5 2.8l-6.3 3.5-.3-6.2-3.6.2.6 12.4 3.6-.2 3.1 3.1.2.2 10.2 2.7z" class="niederlande"></path>
            <path d="M327.1 244.9h.2l2.3-1.1c0-.4-3.6-4-3.9-4.4l.9-2.8c-2.5-3.5-1.6-2.6-5.7-2.5l-3.2-.7-5-2.3-1-1.9-2-1.8-1.8-2.7c-2.1-.3-7.4.3-9.5.3-.7-.5-2.9-2.7-3.7-3l-12.5.6c-.8.7-2.4 2.3-2.8 3.3l.1 3.2-3 3.3-12.7.6-1.3-.6-2.4-2.2c-.6-.2-2.5-.1-3.1-.1l.2 3.2-9.8.5.1 3-5.7 6.6-9.9.4.5 9.3 3.6 3.3.1 2.9.2 3.2 3.1 3 .3 6.3-3 .2.2 3-.9-.7v.1l-2.7-2.2-.3-6.3-6.3-2.9-3 .1.2 3.2-3.6-3-12.7.6-3.1 3.3-3 .1-3.4.2-3.2-3-3.2 3.3-6.5.3c0-.6-.2-2.6-.1-3.2l-6.2-2.9-3.2 6.5-3 .1c-4.2 3.6-2.1 4.2-6.5.3l-3.2.1-1.5-1.4-5.2-4.6-3.2.2-2.9 3.3-.9-.4v2.9l.8-.1 2.7 3.1-.7 2.2 2.4 1.2-.3 3.8c1.5.9 4.4 3.5 5.7 4.8l12.7-.6 3.2-.1.3 6.3 6.5-.3 6-3.4-.2-3.2 3.2-.2 3.4 3 9.7-.5 6.2-.3 6.3 5.7.5.4.2 3 3.2 3 3.5 2.8 6.2-.3 9.6-.4 3.4 3.2 2.8-.2c.2 0 .7 0 .8.2l5.5-1.9 2.8-.1 3.9 4.2 6.4-.3 3.8 2.6.7-2.8 4.4-1.9 3.9.7c-.5-.6 2.1-5 2.3-5.6h.6l12.9-.6c2.7.2 5.8-1.2 8.3-2.1l3.7.7 4-3.5c.1-.1 2.2-5.4 2.5-5-.1-.3 2.9-.2 3-.3l2.6-6.3-.3-6.1h.5v-.4c3.4-.4 3.1.9 2.9-2.9l-.2-3-3.6-3-.2-3.2h.4v-.3l3.8-.2 2.9-1.6-.5 1.5c.3-.2.1 1.2.2 1.2l3.2.7c0-.2-.4-1.8-.1-1.9v-.2l2.6-3c-1.4-3.4-3-8.8-5.2-11.7l2-.9z" class="ostrreich"></path>
            <path d="m102.5 256.7 2.6 2.2-.1-3 6.6 2.7 3.5-.2 15.6-.7 6.6-.3.2 3.4 6.2-.2.1 2.9 6.6 2.9 2.9-3.3 3.2-.2 5.8 5.2.9.8 3.2-.1c4.4 3.9 2.2 3.3 6.5-.3l3-.1 3.2-6.5 6.2 2.9c-.1.6.2 2.6.1 3.2l6.5-.3 3.2-3.3 3.2 3 3.4-.2 3-.1 3.1-3.3 12.7-.6 3.6 3-.2-3.2 3-.1 6.3 2.9.3 6.3 3.6 2.8-.2-3c4.1-.2 2.8.3 2.8-3.5l-.2-3-.6-.6-2.5-2.4-.3-6.1c-.6-.6-3.1-2.7-3.6-3.3l-.5-9.3 9.9-.4 5.7-6.6-.1-3 9.8-.5-.2-3.2-2-2.6-3-3.7c-1.5-1-4-3.4-5-4.9l-.3-.4-3.1.1-3.3-2.8-7-12.2-3.9-3.1c.2-2.1-.3-6.9-.6-9l-2.5-3.5-3.8-2.5-.3-6.4-2.6-.2-4.1-5.6-.4-7c.5-.3 3.6 2.9 3.9 3.2l.2 3.2 5.9-3.6c.2-.1 3.4 3 3.6 3.2l5.9-.6.3-.1 4.2-2.8 1.8-.7 3.4-.1 2.3-3.9 3.9-.2 8.4-5.9c1.8-1.4 4.9-4.5 6.3-6.3l6.7-3.6c.3.1 3.4 3 3.8 3.2l.2 3.2 2.6-.3c0-.2 3.1-3.2 3.2-3.4l-.6-12.2 2.8-3.3c-3.6 0-2.9 1-3.1-2.8l-.7-15.7-3.8-6.2-.1-3.2-.3-3.3 3.3-3.3-3.2.1h-.2l-3.1-3-.1-3-3.4-3-3.6-6.2c1.7-1.5 4.7-4.8 6.2-6.6l-.3-6.1c-.3-4.5-.2-10.8-.5-15.4l-9.7.4-.3-6.4-.3-6.3-9.6.5-.2-3.2-3.2-2.8c-.2-4.2.5-3.1-3.5-3l-2.9 3.3-6.5.3c-3.2 1.6-9.5 4.9-12.5 6.7l-3.2-3 .2 3.2-12.9.6-6.6-2.9 3.5-.2c-.1-3.7-.7-2.8 2.9-3.1l-.3-6.5-6.5.3-2.8 3.5-3.5-6.2-6.4.3-.2-3.2-6.4.3-.2-3.2 3.2-3.3a97.5 97.5 0 0 1-6.9-5.9l-1-.8-1.4 1.3 1.3-1.4-2.2-1.7c-.1-.1-5.8.5-5.6 0h-.6l-2.9-2.6-2.8.1c0-.9-.2-.6-.9-.6l.5 9.5 3.1 2.8.2 3.2-6.3 3.5-3 .1c.3 3.8-.8 3.2 3.2 3l.3 6.3 6.6 2.9-2.8 3.1 2.5 1.8 3.4 4.8-1.7 3.4-1.7-2.9-1.5-3.1c-3.1.2-7.5-.5-10.6-.4l.6 12.7-3 3.3.1 2.9-3.5-5.7-.3-6.4-3.2.1.2 3.2-3 .1-.2-3.2 2.9-3.3-6.6-2.9-15.8.7.2 3.2-3.1 3.3c.3 4-.6 3.1 3.4 3l.2 3.2 3.3 2.8-.4.4-2.7 3.1.5 9.1h-.2v.4l-3 .2.6 12-.4.5v.2l-2.5 2.8 3.1 2.8.2 3.2-2.7 9.4c-.2 0-.2.4-.2.5l-12.8.6-3.1-2.9-9.5 3.5-5.9 3.4.2 2.8.6 12.4-.5.2v.4l-5.8 3.1v1l.4 8.5-2.8 6c3.7 0 3-1 3.2 2.8-.1 4.2 1.5 3.6-3 3.7l.6 12c1.6 1.5 5.1 4.5 6.7 6.1l.5 9.7c0 3.7 1.2 3.1-2.8 3.3l6.8 11.7 3.4 3 6.3 2.9 6.7-.3 3.1 2.8 6.5-.3 3 3 .3.3-9.2 9.7-2.7 6.5.1 3-3.3 3.3.5 9.2.2 3.2-3.1 3.3.3 6.2.2.1.5.9z" class="deutschland"></path>
            <path d="m492.1 148.9-2.4-1-.2-4 2.3-1.2-5.9-6.9-2.5-4.6-4.7-3c2.1-3.2 2-2-.2-5l1.7-9.2-1.1-1.2c-.5-1.3 1.3-10.2 1.5-11.7l-5.7-1-2.7-3.7 11.4-8.4c0-.4 1.2-3.1 1.2-3.4l.7-2.2c-.2-2.2-.1-11-1.5-12.8l-1.2-3.4-5.7-7-1.9-2.2-.4-9.1-2.5-2-1.3-4.6-.3-6.7-7.1-5-4.8-1-5.6-3.5-.2-.1 2.2-3.7-3.5.2 1-.5.9-4.5c-.5-2.2-1.3-6-2.5-8l-2.6-5.2-5.7-1.7-5 1.9-2.6 3.5-1.1 1.3-10.1.5h-.8l-1-2.5-2.7-3.5c-1.8.5-6 1.4-7.9 1.2.2 4-.3 2.8 3.4 2.8l-2.9 6.3-3.1 3.3-6.2.3-.5-9.3L393 14l.2 3.2-5.4 4.7 5.7 1.7.2 2.9-3 3.5-3 .2.5 9.2-9.7.5-.1-3.2-3.2.1-9.3 3.6-3.5-3-.5-9.5-3.2-2.8-.2-3.2-9.7.5-3 3.3-3.2.2-6.4-2.9-3 3.3-3.2.2c.2 4 .5 2.7-3.1 3.1l-3.1 3.5-3.4-3.2a75.6 75.6 0 0 1-5.9 6.8l-3 3.1-3.2.2-3 3.3-3.2.2c0 3.8 1.1 3.1-2.9 3.3l-9.7.5-6.2 3.5-2.9 6.5-2.8 3.1 3.1 2.8.2 3.4-.9-.4-4.7.2-3.6-4.2c-.4 5.5.2 11.6.4 17.1a64.5 64.5 0 0 1-6.2 6.6l3.6 6.2 3.4 3 .1 3 3.1 3h.2l3.2-.1-3.5 3 .2 3.2.1 3.2 3.8 6.2.7 15.7c.2 3.7-.6 2.9 3.1 2.8l-2.8 3.3.6 12.2c.3-.2 1.4-1.8 1.6-2.2l4.6-.9 3.1-.1.6 12.2 3.2-.2 3.4 3 3.2-.2 6.4 2.9h.4l6-.3 3.4 3-6.1 6.6h.5l6-.3c.1-.1 3.3 2.8 3.4 2.8l3.5 6-.6-3.6.8-1.6 2.4-1.5 3.3.4-3.4-1.3-.3-2c2.3.6 7.6 0 10 0l3.4 2.8c.2-.1.3-.7.4-.9l2.7-2.4c2 2.7 7.3 10.3 10 12.2l6.6 2.7 6.4-.3 3.2 3 6.7 5.8h.4l6-.2 3.4 3.2c.3-.1 0-1.5.1-1.7l2.7-2.5 2.4-1.2c.2-.1 4.3-1.2 4.2-1.5l.1.1 3.1 2.7.3 6.3.4-.4v-1l1.8-1.6-.1-4.4 7-3 3.3 3.5 3-.1 3.1-3.1.4 9.2c.3.3 6.5-4.3 6.8-4.5l4-.4 4.6-5.1 3.7 6.2h.2l2.8-.1c3.1 2.5 7.1 6.2 10.1 8.8l3.2-.1 5.3-.2h.9l1.2 4.6 3.2-4.8-.4-3.3.7-2.6-.3-6.3c.4-2.6 1.5-8.4 2.3-10.9l2.6-3.7 3.4-1c1-2.2 3.2-7.1 4.3-9.1l6.2-5.8 6.2.5 3.5-2.7 2-6.9-2.5-4.2z" class="polen"></path>
            <path d="M278.7 153.6c.1.3-2.7.4-2.8.5l-.2-3.2c-.2-.3-3.7-3-3.8-3.2l-6.7 3.6a46.9 46.9 0 0 1-6.3 6.3l-8.4 5.9-3.9.2-2.3 3.9-3.4.1-1.8.7-4.2 2.8-.3.1-5.9.6c-.2-.2-3.3-3.3-3.6-3.2l-5.9 3.6-.2-3.2c-.3-.2-3.5-3.4-3.9-3.2l.4 7 4.1 5.6 2.6.2.3 6.4 3.8 2.5 2.5 3.5c.4 2.2.7 6.9.6 9l3.9 3.1 7 12.2 3.3 2.8 3.1-.1 2.4 2.9c2.9 2 5.8 5.9 7.9 8.7.2.1 3-.1 3.1.1l2.4 2.2c.9 1 6.4.3 7.5.3l6.4-.3 3-3.3-.1-3.2c.4-1 2-2.6 2.8-3.3l12.7-.6 3.5 3 9.4-.5.1.1 1.8 2.7 2 1.8 1 1.9c1 .5 5.8 2.7 6.9 2.7l2.4-5.6.4-5 2.6-4.3c2.5-1 7.5-2.7 10.1-3.3l6.6-5 3-.9 3.2 1.2c1.8 1.8 5.7 4.3 7.9 5.4l3.9-.1 4.5-3.5c1.7-3 5.4-8.9 7.3-11.8l3.6-3.1 1-1.7-2.9-2.6c-1.8-1.4-5.1-4.5-6.7-6l-6.4.3-6.6-2.7a79.3 79.3 0 0 1-10-12.2l-2.7 2.4c-.1.2-.1.8-.4.9l-3.4-2.8c-2.4 0-7.7.7-10 0l.3 2 3.4 1.3-3.3-.4-2.4 1.5-.8 1.6.6 3.6-3.5-6s-3.3-2.9-3.4-2.8l-6 .3h-.5l6.1-6.6-3.4-3-6 .3h-.4l-6.4-2.9-3.2.2-3.4-3-3.2.2a498 498 0 0 0-.6-12.2c-1.9-.1-5.8.6-7.7 1-.6 1.9-3.2 4.3-4.4 5.6z" class="noclick"></path>
            <path d="m459.6 205.2-9.2.4c-1.9-1.1-5.2-4.6-7-6l-3.3-2.8-2.8.1c-.3.5-3.8-6.2-4-6.2l-4.6 5.1-4 .4-6 4.3-.4.3v-.1l-.5.1-.4-9.2-3.1 3.1-3 .1-3.3-3.5-7 3 .1 4.4-1.8 1.6v1l-.4.4-.3-6.3c-.2-.1-3.2-3.1-3.4-2.6a29 29 0 0 0-6.4 2.4l-2.7 2.5c0 .2.2 1.5-.1 1.7l-3.4-3.2c-.3-.1-6.7.5-6.6.1l-1 1.7-3.6 3.1-4 6.2-3.3 5.5-4.5 3.5-3.9.1a35.7 35.7 0 0 1-7.9-5.4l-3.2-1.2-3 .9-6.6 5c-2.6.5-7.7 2.3-10.1 3.3l-2.6 4.3-.4 5-2.4 5.6c.9.5 4.1.2 5.1.1l2 2.7-.9 2.8 4.1 4.3-4.6 2.1 1.5 2.2-.6-1.4 7.3 4.7.5.4h.9l3.1 2.6 2.2-.1c1.7 1.3 4.9 4.2 6.4 5.7.1.4 6.1-.2 6.4-.1l7.9-.3 8-3.1 2.8-.2-2-2.6 1.9-1 .3-3 4.9-.8 4.5.4 6.7-.3 6-3.5 3-3.3 6.3-3.5a185 185 0 0 0 5.9-6.6l-.1-2.9 3.3-3.3 15.8-.7 6.2-.2.2 3.2 3.2-.2c.1.3 1.1.1 1.3.1l2.6 2.4 5.7-2.9.8.3.5-.3.6-.3 1.5 1.7 3.1 1.2.5 1.2.6-4.5-1.2-2 .9-3.6 1.5-2.8 2.8-.1-1-3.8 1.8-2.4 3.4-2.2-.7-2.2-1.5 2.3-1.3-4.9z" class="noclick"></path>
            </svg>

        <div class="hotspoters">
            <div class="clickspoter hot2" onclick="showInfo(2)"><div class="hotspoter"></div></div>
            <div class="clickspoter hot3" onclick="showInfo(3)"><div class="hotspoter"></div></div>
            <div class="clickspoter hot4" onclick="showInfo(4)"><div class="hotspoter"></div></div>
            <div class="clickspoter hot5" onclick="showInfo(5)"><div class="hotspoter"></div></div>
            <div class="clickspoter hot6" onclick="showInfo(6)"><div class="hotspoter"></div></div>
    
            <h3 class="ctr2">Belgien</h3>
            <h3 class="ctr3">Niederlande</h3>
            <h3 class="ctr4">Östrreich</h3>
            <h3 class="ctr5">Deutschland</h3>
            <h3 class="ctr6">Polen</h3>
        </div>
        <div class="map-overlay" id="map-overlay" onclick="showInfo()"></div>
        <div class="map-info" id="map-info">
            <span class="map-btn" onclick="closeInfo()">X</span>
            <div class="map-details">
                <div class="country-name" id="country-name"></div>
                <div class="city-name" id="city-name"></div>
                <p class="address-info" id="address-info"></p>
                <p class="tel-info" id="tel-info"></p>
                <p class="tel-info" id="tel-info-2"></p>
                <a href="#" id="call-button" class="call-button" onclick="callButtonClick()">Anrufen</a>
            </div>
        </div>
    
      </div></section>

JS

<script async="">
        function showInfo(hotspoterId) {
            var countryNameElement = document.getElementById("country-name");
            var cityNameElement = document.getElementById("city-name");
            var addressInfoElement = document.getElementById("address-info");
            var telInfoElement = document.getElementById("tel-info");
            var telInfo2Element = document.getElementById("tel-info-2");
            var callButtonElement = document.getElementById("call-button");
    
            switch (hotspoterId) {
                case 2:
                    countryNameElement.textContent = "Belgien";
                    cityNameElement.textContent = "PEER";
                    addressInfoElement.textContent = "Postleitzahl: 3900";
                    telInfoElement.textContent = "Tel: 0032 411271367";
                    telInfo2Element.textContent = "";
                    callButtonElement.href = "tel:0032411271367";
                    break;
                case 3:
                    countryNameElement.textContent = "Niederlande";
                    cityNameElement.textContent = "ZAANDAM";
                    addressInfoElement.textContent = "Postleitzahl: 1505";
                    telInfoElement.textContent = "Tel: 0031 612936220";
                    telInfo2Element.textContent = "";
                    callButtonElement.href = "tel:0031612936220";
                    break;
                case 4:
                    countryNameElement.textContent = "Östrreich";
                    cityNameElement.textContent = "ILZ";
                    addressInfoElement.textContent = "Postleitzahl: 8262";
                    telInfoElement.textContent = "Tel: 0043 6602273462";
                    telInfo2Element.textContent = "";
                    callButtonElement.href = "tel:00436602273462";
                    break;
                case 5:
                    countryNameElement.textContent = "Deutschland";
                    cityNameElement.textContent = "GÖRLITZ";
                    addressInfoElement.textContent = "Postleitzahl: 02826";
                    telInfoElement.textContent = "Tel: 0049 15905517928";
                    telInfo2Element.textContent = "";
                    callButtonElement.href = "tel:004915905517928";
                    break;
                case 6:
                    countryNameElement.textContent = "Polen";
                    cityNameElement.textContent = "PIOTRKÓW TRYB.";
                    addressInfoElement.textContent = "Postleitzahl: 97300";
                    telInfoElement.textContent = "Tel: 0048 501102760";
                    telInfo2Element.textContent = "Tel: 0048 501102760";
                    callButtonElement.href = "tel:0048 501102760";
                    break;
            }
    
            document.getElementById("map-info").style.display = "block";
            document.getElementById("map-overlay").style.display = "block";
        }
    
        function closeInfo() {
            document.getElementById("map-info").style.display = "none";
            document.getElementById("map-overlay").style.display = "none";
        }
    </script>  

I try to use px, vw, vmin, rem, etc.
I try to change SVG.
I try to use different display modes on different divs, but nothing works for me

P.S. Purple squares are only to show clickable area.

Avoid tab stops in multi-line template literals with indentation

Is there a way to avoid unnecessary tabstops caused by indentation?

If you use tabs instead of spaces in the editor, tabstops are saved as /t, which actually belong to the code formatting, but not to the string.

I would like to structure my code as in example 1, but have the output of example 2.

// example 1
if (true) {
    var txt = `<div>
                            <article>
                                <h1>Nice indentation</h1>
                                <p>but too many tabstops saved</p>
                            </article>
                        </div>`;
    console.log(JSON.stringify(txt));
}

// example 2
if (true) {
    var txt = `<div>
    <article>
        <h1>not nice indentation</h1>
        <p>but fewer tabstops saved</p>
    </article>
</div>`;
    console.log(JSON.stringify(txt));
}

The indentation by tabstops in the snippet looks a bit strange. This is how code should look in the editor:

if (true) {
  var txt = `<div>
              <article>
                <h1>Nice indentation</h1>
                <p>but too many tabstops saved</p>
              </article>
            </div>`;
}

Reinitialise array of click events for links after page has dynamically changed [duplicate]

I am trying to make a simple site and convert it to an SPA using vanilla javascript.

I want to target all of my hyperlinks which start with an '/' as these are internal to my site.

Works fine for pages loaded in the DOM initially from the server. But if I dynamically add more links to the page that contain the same property I need a way to recalculate my list of internal links. This is a simplified version of a slightly more complex iteration.

Snippet below, but I also made a codepen: https://codepen.io/lharby/pen/OJqoRpx

  const trigger = document.querySelector(".add-template");
  const wrapper = document.querySelector(".wrapper");
  const links = document.querySelectorAll("a");
  const internal = [...links]?.filter((item) => item.getAttribute("href")?.startsWith("/"));
  internal.forEach((item) => item.classList.add("internal"));

  const getLinks = () => {
    const links = document.querySelectorAll("a");
    const internal = [...links]?.filter((item) => item.getAttribute("href")?.startsWith("/"));
    internal.forEach((item) => item.classList.add("internal"));
    console.log(internal, internal.length);
  };

  const recalculateInternal = () => {
    getLinks();
    internal.forEach((item) => {
      item.addEventListener("click", (event) => {
        event.preventDefault();
        console.log(event.target);
      });
    });
  };

  recalculateInternal();

  const template = `
    <ul>
        <li><a href="/link4">Link 4</a></li>
        <li><a href="/link5">Link 5</a></li>
        <li><a href="#">Link 6</a></li>
        <li><a href="https://some-site.com">Link 7</a></li>
    </ul>
    `;

  trigger.addEventListener("click", () => {
    wrapper.insertAdjacentHTML("beforeend", template);
    recalculateInternal();
  });
 <nav>
      <ul>
        <li><a href="/link1">Link 1</a></li>
        <li><a href="#">Link 2</a></li>
        <li><a href="/another-link">Link 3</a></li>
      </ul>
    </nav>
    <section>
      <p>Heading</p>
      <div>This is some article text with an <a href="/article-link">internal</a> link</div>
    </section>
    <section>
      <div>
        <p>Section heading</p>
        <p>Another article with an <a href="https://google.co.uk">external</a> link</p>
      </div>
    </section>
    <button class="add-template">Add template</button>
    <div class="wrapper"></div>

When I trigger the event, the links dynamically added to the array of internal links are reflected in the console. But they do not appear to have the click event added dynamically. My guess is each time new dynamic links are added I need someway to remove them from all items with a forEach loop and add them again with the new links in the DOM.

enter image description here

I have researched adding and removing event handlers for an array of elements after using a forEach loop and I don’t understand how to get anything to work. removeEventListener requires a listener name.

I tried to add internal.forEach((item) => item.replaceWith(item.cloneNode(true)));

Inside this function:

  trigger.addEventListener("click", () => {
    wrapper.insertAdjacentHTML("beforeend", template);
    internal.forEach((item) => item.replaceWith(item.cloneNode(true)));
    recalculateInternal();
  });

From what I understand that should remove all event handlers from those items. And they should be reinitialised again inside my recalculateInternal function.

For reference

Javascript/DOM: How to remove all event listeners of a DOM object?

removeEventListener without knowing the function

POST https://192.168.3.64:8080/save net::ERR_SSL_PROTOCOL_ERROR

I’m writing a plugin for Google Chrome, when a button is clicked, I find an element on the page and try to send data to the backend by REST API. But every time I get the same error POST net::ERR_SSL_PROTOCOL_ERROR.

As I understand it, the problem is that I can send a request to HTTP from HTTPS. The plugin is written in JAVASCRIPT, and the backend is written in JAVA.

function sendRequest(id, className, xpath, sum) {

    let url = window.location.href;
    let domain = url.hostname

    const data = {
        elementId: id,
        className: className,
        xPathPrice: xpath,
        domain: domain,
        url: url,
        currentPrice: sum
    };

    const jsonData = JSON.stringify(data);

    const xhr = new XMLHttpRequest();

    xhr.onload = function () {
        if (xhr.status === 200) {
            const response = xhr.responseText;
            console.log(response);
        } else {
            console.error('Error', xhr.status);
        }
    };

    xhr.open('POST', 'http://192.168.3.64:8080/track/save');
    
    xhr.setRequestHeader('Content-Type', 'application/json');

    
    xhr.send(jsonData);
}

Plesse, tell me, how can I fix this?

I’m new to JAVASCRIPT, so I don’t even understand how to fix this. I couldn’t find a solution on the Internet.
enter image description here

Javascript group elements with identical classnames

I want to select all elements with class name find-me and group them in separate arrays (or NodeLists) based on their other classes, if idential. Here is an example:

<div class="find-me one two">
  Element 1
</div>
<div class="find-me one two">
  Element 2
</div>
<div class="find-me one two three">
  Element 3
</div>
<div class="find-me one two three">
  Element 4
</div>
<div class="find-me one two four">
  Element 5
</div>
<div class="find-me one two">
  Element 6
</div>
<div class="one two">
  Element 7
</div>

My goal is to have:

  • One array or NodeList with elements 1, 2 and 6 (find-me, one, two)
  • One array or NodeList with elements 3 and 4 (find-me, one, two, three)
  • One array or NodeList with element 5 (find-me, one, two, four)
  • Element 7 should not be taken into account since it doesn’t have the find-me class

I suppose I have to use document.querySelectorAll('.find-me') to first get a NodeList of all the elements I am interested in.

But then? I was thinking I could compare the list of classes from the current element with the previous one but how can I keep track of what element goes to what group? Any idea how to achieve that?

React redirect using useNavigate() after validation and submition of form, using routing with loader and action

So I have build a demo site with a form of submiting a new user.

The files:

App.jsx:

import React from 'react';
import './App.css';
import {
  RouterProvider,
  createBrowserRouter
} from 'react-router-dom';
//components
import Home from './pages-views/Home.jsx';
import AboutUs from './pages-views/AboutUs.jsx';
import Products from './pages-views/Products.jsx';
import Product from './pages-views/Product.jsx';
import Users from './pages-views/Users.jsx';
import UsersError from './pages-views/UsersError.jsx';
import User from './pages-views/User.jsx';
import UserError from './pages-views/UserError.jsx';
import NewUser from './pages-views/NewUser.jsx';
import ContactUs from './pages-views/ContactUs.jsx';
//layouts
import RootLayout from './components/RootLayout.jsx';
import ErrorLayout from './components/ErrorLayout.jsx';
//loaders
import { loadUsers, loadUser } from './loaders/loaders.jsx';
//actions
import { validateAndSubmitNewUser } from './actions/validateAndSubmitNewUser.jsx';

const myRouter = createBrowserRouter([
  {
    path: '/',
    element: <RootLayout />,
    //catches every error on every child Route that NOT HAVE a errorElement property
    errorElement: <ErrorLayout />,
    children: [
      {
        path: '/',
        element: <Home />,
      },
      {
        path: '/about-us',
        element: <AboutUs />,
      },
      {
        path: '/products',
        element: <Products />,
      },
      {
        path: '/product/:id',
        element: <Product />,
      },
      {
        path: '/users',
        element: <Users />,
        loader: loadUsers,
        errorElement: <UsersError />,
      },
      {
        path: '/user/:id',
        element: <User />,
        loader: loadUser,
        //errorElement: <UserError />,
      },
      {
        action: validateAndSubmitNewUser,
        path: '/new-user',
        element: <NewUser />,
      },
      {
        path: '/contact-us',
        element: <ContactUs />,
      },
    ],
  },
]);

export default function App() {
  return (
    <>
      <RouterProvider router={myRouter} />
    </>
  );
}

MainBody.jsx:

import { Outlet, useRouteError } from 'react-router-dom';

export default function MainBody() {

  let error = useRouteError();
  
  const isError = (error != null);
  console.log('is Error? ', isError);
  console.log(error);
  
  return (
    <>
      <Outlet />
      {isError ? (
        <>
          <p>Error details:</p>
          {/*printed when I throw new Error('User not found') on loader*/}
          <p>{error.name}</p>
          <p>{error.message}</p>
          <p>{error.stack}</p>
          <p>----------</p>
        </>
      ) : (
        <p></p>
      )}
    </>
  );
}

Users.jsx:

import { Link, useLoaderData, useNavigation } from 'react-router-dom';
import UserCard from '../components/UserCard.jsx';

export default function Users() {
  
  let pageState = useNavigation().state; //return idle | submitting | loading as value
  console.log(pageState);

  const users = useLoaderData();

  return (
    pageState === 'loading' ? (
      <>
        <p>Products page</p>
        <p>Loading....</p>
      </>
    ) : (
      <>
        <p>This is Users page</p>
        <Link
          to="/new-user"
          class="btn btn-outline-primary"
          style={{ margin: '8px' }}
        >
          Add new User
        </Link>
        {users.map((user) => (
          <Link to={'/user/' + user.id} key={user.id}>
            <UserCard name={user.name} userData={user} />
          </Link>
        ))}
      </>
    )
  );
}

validateAndSubmitNewUser.js (this is the action of Route path “/new-user”)

export async function validateAndSubmitNewUser({ params, request }) {
    
    let formUserData = await request.formData();
    const user = {
        name,
        username,
        email,
        street,
        streetNumber,
        city,
        zipcode,
        phone,
        website,
    };
    
    user.name = formUserData.get('name');
    user.username = formUserData.get('username');
    user.email = formUserData.get('email');
    user.street = formUserData.get('street');
    user.streetNumber = formUserData.get('street-number');
    user.city = formUserData.get('city');
    user.zipcode = formUserData.get('zipcode');
    user.phone = formUserData.get('phone');
    user.website = formUserData.get('website');

    //variable validate will be the errors obj or null: that is what validateNewUser(user) returns
    let validate = validateNewUser(user);//works fine

    if (validate === null) {
        //just a api call to https://jsonplaceholder.typicode.com/users/ to submit user
        //returns the submited data as json
        let data = await submitNewUser(user);
    }
    
    return validate;
    
}

NewUser.jsx (here is the problem)

import clsx from 'clsx';
import { Form, useActionData, useNavigate } from 'react-router-dom';

export default function NewUser() {
    const navigate = useNavigate();
    const errors = useActionData();
    console.log('display errors ', errors);

    //if there is not errors redirect-navigate to /users page
    if (errors === null) {
        console.log("navigate(/users)");
        navigate("/users");//** (I think so) THIS IS RESPONSIBLE FOR THE PROBLEM-ERROR. See error stack below
    }

    return (
        <Form method="post" action="/new-user">
            <div className="input-group mb-4">
            <span className="input-group-text" id="name">
                Name
            </span>
            <input
                type="text"
                name="name"
                className={clsx('form-control', errors?.name && 'is-invalid')}
                aria-label="name input"
                aria-describedby="nameFeedback"
            />
            <div id="usernameFeedback" className="invalid-tooltip">
                {errors?.name}
            </div>
            </div>
            <div className="input-group mb-4">
            <span className="input-group-text" id="username">
                Username
            </span>
            <input
                type="text"
                name="username"
                className={clsx('form-control', errors?.username && 'is-invalid')}
                aria-label="username input"
                aria-describedby="usernameFeedback"
            />
            <div id="usernameFeedback" className="invalid-tooltip">
                {errors?.username}
            </div>
            </div>
            <div className="input-group mb-3">
            <span className="input-group-text" id="email">
                Email
            </span>
            <input
                type="text"
                name="email"
                className={clsx('form-control', errors?.email && 'is-invalid')}
                aria-label="Sizing example input"
                aria-describedby="emailFeedback"
            />
            <div id="emailFeedback" className="invalid-tooltip">
                {errors?.email}
            </div>
            </div>

            <div className="input-group mb-3">
            <span className="input-group-text" id="street">
                Street
            </span>
            <input
                type="text"
                name="street"
                className={clsx('form-control', errors?.street && 'is-invalid')}
                aria-label="Sizing example input"
                aria-describedby="streetFeedback"
            />
            <div id="streetFeedback" className="invalid-tooltip">
                {errors?.street}
            </div>
            </div>
            <div className="input-group mb-3">
            <span className="input-group-text" id="street-number">
                Number
            </span>
            <input
                type="text"
                name="street-number"
                className={clsx('form-control', errors?.streetNumber && 'is-invalid')}
                aria-label="Sizing example input"
                aria-describedby="street-number-feedback"
            />
            <div id="street-number-feedback" className="invalid-tooltip">
                {errors?.streetNumber}
            </div>
            </div>
            <div className="input-group mb-3">
            <span className="input-group-text" id="city">
                City
            </span>
            <input
                type="text"
                name="city"
                className={clsx('form-control', errors?.city && 'is-invalid')}
                aria-label="Sizing example input"
                aria-describedby="cityFeedback"
            />
            <div id="cityFeedback" className="invalid-tooltip">
                {errors?.city}
            </div>
            </div>
            <div className="input-group mb-3">
            <span className="input-group-text" id="zipcode">
                Zipcode
            </span>
            <input
                type="text"
                name="zipcode"
                className={clsx('form-control', errors?.zipcode && 'is-invalid')}
                aria-label="Sizing example input"
                aria-describedby="zipcodeFeedback"
            />
            <div id="zipcodeFeedback" className="invalid-tooltip">
                {errors?.zipcode}
            </div>
            </div>
            <div className="input-group mb-3">
            <span className="input-group-text" id="phone">
                Phone
            </span>
            <input
                type="text"
                name="phone"
                className={clsx('form-control', errors?.phone && 'is-invalid')}
                aria-label="Sizing example input"
                aria-describedby="phoneFeedback"
            />
            <div id="phoneFeedback" className="invalid-tooltip">
                {errors?.phone}
            </div>
            </div>
            <div className="input-group mb-3">
            <span className="input-group-text" id="website">
                Website
            </span>
            <input
                type="text"
                name="website"
                className={clsx('form-control', errors?.website && 'is-invalid')}
                aria-label="Sizing example input"
                aria-describedby="websiteFeeback"
            />
            <div id="websiteFeeback" className="invalid-tooltip">
                {errors?.website}
            </div>
            </div>
            <button type="submit" className="btn btn-outline-primary" name="submit">
            Submit
            </button>
        </Form>
    );
}

What I want to achieve is after a success validation and submition to be redirected to path “/users”.
Now what happen is that the browser memory/processing looks to overflow, because of a rendering loop(I think so)

/*
Warning: Cannot update a component(`RouterProvider`) while rendering a different component(`NewUser`).
To locate the bad setState() call inside`NewUser`,
follow the stack trace as described in https://reactjs.org/link/setstate-in-render
NewUser@http://localhost:5173/src/pages-views/NewUser.jsx?t=1707325029056:22:20
RenderedRoute@http://localhost:5173/node_modules/.vite/deps/react-router-dom.js?v=6a7590ff:3550:7
Outlet@http://localhost:5173/node_modules/.vite/deps/react-router-dom.js?v=6a7590ff:3918:3
MainBody@http://localhost:5173/src/components/MainBody.jsx:21:15
RootLayout
RenderedRoute@http://localhost:5173/node_modules/.vite/deps/react-router-dom.js?v=6a7590ff:3550:7
RenderErrorBoundary@http://localhost:5173/node_modules/.vite/deps/react-router-dom.js?v=6a7590ff:3507:5
DataRoutes@http://localhost:5173/node_modules/.vite/deps/react-router-dom.js?v=6a7590ff:4660:7
Router@http://localhost:5173/node_modules/.vite/deps/react-router-dom.js?v=6a7590ff:3932:7
RouterProvider@http://localhost:5173/node_modules/.vite/deps/react-router-dom.js?v=6a7590ff:4477:7
App react-dom.development.js:86:29

​*/