Ayuda con una plantilla HTML, para un proyecto Spring Boot con Thymeleaf [closed]

tengo un problema en este documento HTML. Resulta que yo tengo una tabla con registros de productos y al final unos botones para eliminar esos registros. Sin embargo al agregar el atributo ‘th:atrr’, me lanza un error. No se si hace parte de Thymeleaf o de Spring.

Cada que se presiona ese botón, se hace una petición de tipo DELETE para eliminar un producto usando su id a un backend por medio de JS:

<body>
    <nav th:replace="~{/fragments/fragments.html :: navbar}"></nav>

    <div class="container-fluid">
        <div class="row">
            <div class="col-6 scrollable-table">
                <table class="table mt-5 shadow border">
                    <thead>
                        <tr>
                            <th scope="col">Código</th>
                            <th scope="col">Nombre del producto</th>
                            <th scope="col">Cantidad en bodega</th>
                            <th scope="col">Precio</th>
                            <th scope="col">Eliminar</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr th:each="producto : ${productos}">
                            <th th:text="${producto.getProduct_id}" scope="row" class="align-middle"></th>
                            <td th:text="${producto.getProduct_nombre}" class="align-middle"></td>
                            <td th:text="${producto.getProduct_cant}" class="align-middle"></td>
                            <td th:text="${producto.getProduct_precio}" class="align-middle"></td>
                            <td class="align-middle text-center">
                                <button type="button" class="btn btn-outline-danger" th:attr="data-id=${producto.id}" onclick="eliminarProducto(this)">
                                    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
                                        class="bi bi-trash-fill" viewBox="0 0 16 16">
                                        <path
                                            d="M2.5 1a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1H3v9a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V4h.5a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H10a1 1 0 0 0-1-1H7a1 1 0 0 0-1 1zm3 4a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 .5-.5M8 5a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-1 0v-7A.5.5 0 0 1 8 5m3 .5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 1 0" />
                                    </svg>
                                </button>                                
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
function eliminarProducto(btn) {

            var id = btn.getAttribute("data-id");

            console.log(id);

            // Confirmar con el usuario antes de realizar la eliminación
            var confirmacion = confirm("¿Estás seguro de que quieres eliminar este producto?");

            if (confirmacion) {
                // Realizar la solicitud DELETE al backend
                fetch(`http://localhost:8080/api/v1/producto/${id}`, {
                    method: 'DELETE',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                })
                    .then(response => {
                        if (!response.ok) {
                            throw new Error('Error al eliminar el producto');
                        }
                        // Actualizar la interfaz o realizar otras acciones necesarias después de la eliminación
                        // Por ejemplo, puedes recargar la página o actualizar la lista de productos.
                        location.reload();
                    })
                    .catch(error => {
                        console.error('Error:', error);
                        // Manejar errores, mostrar mensajes al usuario, etc.
                        alert('Error al eliminar el producto');
                    });
            }
        }
Sun Jan 14 22:39:32 COT 2024
There was an unexpected error (type=Internal Server Error, status=500).
An error happened during template parsing (template: "class path resource [templates/PRODUCTOS.html]")
org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/PRODUCTOS.html]")

Deseo encontrar una solución. Quiero hacer la petición al backend correctamente, y que se envié el id del producto para usarlo en la petición.

Hide select all checkbox when search data not in list of ng-multiselect-dropdown

I am using ng-multiselect-dropdown version ^0.3.8 in my Angular project v11.It’s working fine except one condition which occur when-

1- open select dropdown and search random thing which is not in list like ‘xxxx’.

In this scenario it show select all button which is quite confusing. It’s give impression of selecting all value which are present in list.
If anyhow I can hide this checkbox please tell me.
Thanks in advance!!

enter image description here

How to set react quill border color on focus?

I need my quill editor focus color to be a custom color I have. I feel like I’ve tried almost everything!

    .ql-custom-container .ql-container {
    @apply border-gray-600;
    height:500px
}

    .ql-custom-container .ql-snow.ql-toolbar {
        @apply border-gray-600;
    }

.ql-custom-container .ql-container:focus {
    @apply border-nwgreen;
    height: 500px;
}

All of this works beyond the last piece. Any advice?

Button Problems in JS

I keep getting the error “Uncaught TypeError: Cannot read properties of null (reading ‘addEventListener’)” and I cannot figure out what’s wrong with my code.

I expected it to run my code immediately, but it gave me the error, so I looked up a solution and tried putting the JavaScript code into my HTML code, but it still didn’t work so I’m coming here.

HTML, CSS, and JS code respectively:

<DOCTYPE html>
  <html>

  <head>
    <meta charset="UTF-8">
    <title>Project</title>
  </head>

  <body>
    <div margin><span class="span1"> </span></div>
    <h1>Button Game</h1>
    <h2><span class="span2"> </span></h2>
    <p><button class="button1">Press</button></p>
    <p><button class="button2"><span class="span3">Press?</span></button></p>

  </html>
body {
  padding: 4rem;
  font-family: "Trebuchet MS";
}

button {
  background-color: red;
  color: whitesmoke;
}
const btnElement = document.querySelector("button1");
const btnElement1 = document.querySelector("button2");
let spanElement = document.querySelector("span1");
const spanElement1 = document.querySelector("span2");

btnElement.addEventListener("click", () => {
  const yourName = prompt("Please enter your name.");
  spanElement2.textContent = yourName;
});

How to use Leaflet Terminator together with the Heatmap

I have a code where, upon running the Leaflet terminator, the heatmap disappears, but the terminator runs successfully. However, when I remove the terminator, the heatmap appears. Below is my code snippet:

<script src=" https://unpkg.com/@joergdietrich/[email protected]/L.Terminator.js"></script>
<script>
function runMap() {
        map = new L.map('map', {

            maxZoom: 10,
            minZoom: 0.1,
            attributionControl: false, //This is to hide the leaflet label at the bottom right of the map

        });
        // L.tileLayer('<?= $map_url ?>').addTo(map);
        // L.terminator().addTo(map);
        var screen_height = $(window).height();
        var initial_zoomLevel = 3;
        if (screen_height <= 768) {
            initial_zoomLevel = 2;
        }

        if (default_zoom_level > 0) {
            initial_zoomLevel = default_zoom_level;
        }

        map.setView(new L.LatLng(15, 0), initial_zoomLevel);

        // add logo to watermark bottom left
        L.Control.Watermark = L.Control.extend({
            onAdd: function(map) {
                var img = L.DomUtil.create('img');
                img.src = '<?= $cloud_icon ?>';
                //                img.style.width = '100px';
                img.style.margin = '0 0 18px 18px';
                return img;
            },
            onRemove: function(map) {
                // Nothing to do here
            }
        });

        L.control.watermark = function(opts) {
            return new L.Control.Watermark(opts);
        }

        L.control.watermark({
            position: 'bottomleft'
        }).addTo(map);

     
        generateMapHeatData();

        //add heatmap layer to map
        var cfg = {
            // radius should be small ONLY if scaleRadius is true (or small radius is intended)
            // if scaleRadius is false it will be the constant radius used in pixels
            "radius": 5,
            "maxOpacity": .5,
            "minOpacity": .02,
            blur: .75,
            gradient: {
                // enter n keys between 0 and 1 here
                // for gradient color customization
                '.35': '#00e500',
                '.40': '#00e500',
                '.50': '#00e500'
            },
            // scales the radius based on map zoom
            "scaleRadius": true,
            // if set to false the heatmap uses the global maximum for colorization
            // if activated: uses the data maximum within the current map boundaries
            //   (there will always be a red spot with useLocalExtremas true)
            "useLocalExtrema": false,
            // which field name in your data represents the latitude - default "lat"
            latField: 'lat',
            // which field name in your data represents the longitude - default "lng"
            lngField: 'lng',
            // which field name in your data represents the data value - default "value"
            valueField: 'count'
        };
        // heatmap
        var heatmapLayer = new HeatmapOverlay(cfg);
        heatmap_layer = heatmapLayer.addTo(map);
        heatmapLayer.setData(mapHeatData);
        // add markers layer to map
        markers_layer = L.layerGroup().addTo(map);
        markers_event_layer = L.layerGroup().addTo(map);
        machine_markers_layer = L.layerGroup().addTo(map);
        machine_idle_layer = L.layerGroup().addTo(map);
        machine_down_layer = L.layerGroup().addTo(map);
        machine_sale_layer = L.layerGroup().addTo(map);

        // echart
        overlay = new L.echartsLayer3(map, echarts);
        chartsContainer = overlay.getEchartsContainer();
        overlay.initECharts(chartsContainer);
   
    }

   function generateMapHeatData() {
        var heatmap_data = [];
        for (var key in machine_coordinate_list) {
            var unique_id = key;
            var coordinate_data = machine_coordinate_list[key];

            var heat_item = {
                lat: coordinate_data.location_coordinate_lat,
                lng: coordinate_data.location_coordinate_lng,
                count: 1
            }
            heatmap_data.push(heat_item);
        }
        mapHeatData["max"] = 35;
        mapHeatData["data"] = heatmap_data;
    }
</script>

I tried placing the terminator before generating the heatmap data, but only the terminator appeared. Conversely, if I execute the terminator after the heatmap data, only the heatmap data is displayed, and the terminator does not execute. Now, I want both the heatmap data and terminator to be shown together on the map

Stripe checkout info does not save to Firestore Cloud Server

I am currently planning to implement a new Stripe checkout function on my Firebase web app. The link to the Stripe checkout is working, but for some reason when I tested a payment, the payment details does not save to Firestore Cloud for some reason. The Stripe webhook that is used by the project says that there is a HTTP 500 error despite the payment did work through the system.

The portions shown is the relevant code used for the project.

/public/billing.js

const checkoutButton = document.getElementById('pay-button')
const createStripeCheckout = firebase.functions().httpsCallable('createStripeCheckout')
const stripe = Stripe('pk_test_INSERT_STRIPE_PKEY')

checkoutButton.addEventListener('click', () => {
  createStripeCheckout()
    .then(response => {
      const sessionId = response.data.id
      stripe.redirectToCheckout({ sessionId: sessionId })
    })
})
window.logout = function (){
    signOut(auth) 
    .then(function () {
        alert("Logout successfully!");  
        window.location.href = '/Login/index.html';
    })
    .catch(function (err){
        alert("Logout Error: " + err)
        console.log(err)
    })
}

/functions/index.js

exports.stripeWebhook = functions.https.onRequest(async (req, res) => {
  const stripe = require("stripe")(functions.config().stripe.token);
  let event;

  try {
    const whSec = functions.config().stripe.payments_webhook_secret;

    event = stripe.webhooks.constructEvent(
        req.rawBody,
        req.headers["stripe-signature"],
        whSec,
    );
  } catch (err) {
    console.error("⚠️ Webhook signature verification failed.");
    return res.sendStatus(400);
  }

  const dataObject = event.data.object;

  await admin.firestore().collection("orders").doc().set({
    checkoutSessionId: dataObject.id,
    paymentStatus: dataObject.payment_status,
    shippingInfo: dataObject.shipping,
    amountTotal: dataObject.amount_total,
  });

  return res.sendStatus(200);
});

Leaflet Marker Cluster – click button in table to open popup inside cluster spiderfy

i will click button in table to open popup inside cluster spiderfy, but it not open the popup
but if not cluster spiderfy disable popup is work

var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
                    maxZoom: 19,
                    attribution: 'Powered by Geoapify | © OpenMapTiles &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
                }),
                latlng = L.latLng(<?= $center['lat'].','.$center['lng'] ?>);

            var map = L.map('maps-leaflets', {
                center: latlng,
                zoom: 5,
                layers: [tiles],
                fullscreenControl: true,
                fullscreenControlOptions: { // optional
                    title: "Show me the fullscreen !",
                    titleCancel: "Exit fullscreen mode"
                }
            });
            const _markersDays = [];
            var _tracksDays = L.polyline(tracks, { color: '#ff6d6d' }).addTo(map);
            var _coordsDays = L.polyline(coords, { color: '#329cf2' }).addTo(map);

            var markers = L.markerClusterGroup({
                spiderfyOnMaxZoom: true, // Enable spiderfy on max zoom
                showCoverageOnHover: true, // Show cluster coverage on hover
                maxClusterRadius: 5, // Set the maximum radius of a cluster in pixels
                // disableClusteringAtZoom: 19, // Disable clustering at a certain zoom level
            });
            markers.on('clusterclick', function (a) {
                a.layer.zoomToBounds();
            });
            var bounds = new L.LatLngBounds();

                var markerData = <?= $leftlet_marker ?>;
                // Add markers to the cluster group
                markerData.forEach(function (marker) {
                    var individualMarker = L.marker([marker.lat, marker.lng], {
                        id: marker.id,
                        title: marker.title,
                        icon: L.divIcon({
                            className: 'custom-icon',
                            iconSize: [24, 41],    // Width and height of the icon
                            iconAnchor: [18, 41],  // Anchor point of the icon (relative to the center)
                            popupAnchor: [1,-34],  // Popup anchor point (relative to the icon)
                            html: marker.icon
                        }),
                    }).bindPopup(marker.popup);
                    markers.addLayer(individualMarker);
                    //   add marker into array
                    _markersDays.push(individualMarker); 
                    bounds.extend(individualMarker.getLatLng());
                });
                bounds['_northEast']['lat'] = bounds['_northEast']['lat'] + 0.2;
                bounds['_southWest']['lat'] = bounds['_southWest']['lat'] - 0.2;
                map.fitBounds(bounds);
            map.addLayer(markers);

            // Attach a click event to the button
            $('.btn-show').on('click', function (e) {
                focusOnMarkerById($(this).attr('data'));
            });
            
            // Function to focus on a marker by its ID
            function focusOnMarkerById(markerId) {
                markers.eachLayer(function (layer) {
                    if (layer.options.id === markerId) {
                        // Trigger a click event on the marker
                        layer.fire('click');
                        map.setView(layer.getLatLng(), 22);
                        layer.openPopup();
                    }
                });
            }

Can someone help me? Thank you
imageproblems

I’ve tried several times from the gpt chat and asked friends but haven’t found the right answer. I hope here I can get it.

How can I secure my api endpoint from a client component without requiring user to log in using next.js

Im building a portfolio site and within it there is a chatbot and a contact us form. Both the chatbot and contact us form read/write to the database. Im using supabase. I have apis built in server side components and I’m calling the api endpoint in my client side component.

Usually I would have some sort of user login, retrieve the auth token for the session and pass it to the server for validation via auth headers on the client on each request. The problem is since its a portfolio site there is no need for users to log in.

My chatbot and contact us endpoint are accessible through postman so anyone can essentially use them.

Can I implement a mechanism to generate an auth token from the client without them logging in and then validate it on the server? Is there any other way to go about this?

why does vis.js selectNode event cause node to stick to mouse pointer?

Am learning vis.js and trying to fire a simple custom event when a network node is clicked using the code below. The undesired behaviour I see is that on selecting a node with single click, the node then follows the mouse pointer until another click, whereupon the node is ‘released’ from the mouse. Is there an option I should set to prevent this undesired behaviour?

      let ids = properties.nodes;
      console.log("clicked", JSON.stringify(ids));
      const selectEvent = new CustomEvent("node", {
        bubbles: true,
        detail: { ids: ids }
      });
      this.dispatchEvent(selectEvent);
    });```

Is there an option to reset values of state based on buttons clicked?

I am trying to create an application using React Js, basically the application consists of a series of filters which have a unique value each one, based on the selected elements a text string is created to fetch a specific file, to each filter I have assigned a variable to identify the id of the currently selected button. Sometimes the appearance of a filter depends on another one and the filtering options are not always the same. In the simple cases the program works but when I make complex query I have a problem because I can’t return the value of the variable assigned to a filter to “-1” or something undefined so that it doesn’t interfere in the text string that searches the file.

I am open to any suggestions for implementation, additionally I add an image of how the filters look like.
app filters

for example if I select one of the buttons on the first line which would be a filter, the id value of the third and fourth filter should revert to -1 since based on the options above something can change below and each option has a unique id

What I have tried is to create a component called FilterGroup which is composed of other CustomButton components, the first component is filled according to an array of options that are passed as props. Next I leave the code of each one, and the code of App.jsx

(I know I should refactor it)

import { useEffect, useState, useCallback } from 'react'
import Board from './components/Board'
import Filter from './components/Filter'
import './App.css'
import { 
  initialStackOptions,
  positionOptions,
  initialSequenceOptions,
  tooltipOptions,
  extraActionsOptions,
  thirdOptions,
  leftPositionOptions,
  rightPositionOptions,
  actionStackOptions

 } from './constants';

function App() {
  // Sequence
  const [playerSequenceFilterId, setPlayerSequenceFilterId] = useState(0)
  // Position
  const [leftPositionFilterId, setLeftPositionFilterId] = useState(10)
  const [rightPositionFilterId, setRightPositionFilterId] = useState(-1)
  // Extra action usually
  const [thirdFilterId, setThirdFilterId] = useState(-1)
  // Opponnent position for extra action
  const [secondLeftPositionFilterId, setSecondLeftPositionFilterId] = useState(-1)
  const [secondRightPositionFilterId, setSecondRightPositionFilterId] = useState(-1)
  // Extra action 2
  const [fifthFilterId, setFifthFilterId] = useState(-1)

  //Last position for extra action 2
  const [thirdLeftPositionFilterId, setThirdLeftPositionFilterId] = useState(-1)
  const [thirdRightPositionFilterId, setThirdRightPositionFilterId] = useState(-1)

  // Our Effective stack
  const [effectiveStackFilterId, setEffectiveStackFilterId] = useState(5)

  // Action stack
  const [actionStackFilterId, setActionStackFilterId] = useState(-1)

  const [data, setData] = useState({})


  const getTooltipValueById = (id) => tooltipOptions.find((option) => option.id === id)?.value || '';

  const getLeftPositionOptions = () => {
    if (playerSequenceFilterId === 0) return leftPositionOptions["9000000"]
    else if (playerSequenceFilterId === 1) return leftPositionOptions["9000001"]
  }

  const getRightPositionOptions = () => {
    if (playerSequenceFilterId === 1) return rightPositionOptions["9000001"]
  }

  const getThirdOptions = () => {
    if (playerSequenceFilterId === 0 && leftPositionFilterId === 10) return thirdOptions["9000000"]
    else if (playerSequenceFilterId === 0 && [11, 12, 13, 14].includes(leftPositionFilterId)) return thirdOptions["9000001"]
    else if (playerSequenceFilterId === 1) return thirdOptions["9000002"]
    else if (playerSequenceFilterId === 2 && leftPositionFilterId === 15 && [10, 11, 12, 13, 14].includes(rightPositionFilterId)) return thirdOptions["9000003"]
    else if (playerSequenceFilterId === 2 && [10, 11, 12, 13].includes(leftPositionFilterId) && [11, 12, 13, 14].includes(rightPositionFilterId)) return thirdOptions["9000004"]
  }

  const queryFilename = useCallback(() => {
    let string = ''
    const playerSequenceValue = initialSequenceOptions.find((option) => option.id === playerSequenceFilterId)?.value || ''
    const leftPositionValue = positionOptions.find((option) => option.id === leftPositionFilterId)?.value || ''
    const rightPositionValue = positionOptions.find((option) => option.id === rightPositionFilterId)?.value || ''
    const thirdFilterValue = extraActionsOptions.find((option) => option.id === thirdFilterId)?.value || ''
    const secondLeftPositionValue = positionOptions.find((option) => option.id === secondLeftPositionFilterId)?.value || ''
    const secondRightPositionValue = positionOptions.find((option) => option.id === secondRightPositionFilterId)?.value || ''
    const fifthFilterValue = extraActionsOptions.find((option) => option.id === fifthFilterId)?.value || ''
    const thirdLeftPositionValue = positionOptions.find((option) => option.id === thirdLeftPositionFilterId)?.value || ''
    const thirdRightPositionValue = positionOptions.find((option) => option.id === thirdRightPositionFilterId)?.value || ''
    const effectiveStackValue = initialStackOptions.find((option) => option.id === effectiveStackFilterId)?.value || ''
    const actionStackValue = initialStackOptions.find((option) => option.id === actionStackFilterId)?.value || ''

    const variables = [
      playerSequenceValue,
      leftPositionValue,
      rightPositionValue,
      thirdFilterValue,
      secondLeftPositionValue,
      secondRightPositionValue,
      fifthFilterValue,
      thirdLeftPositionValue,
      thirdRightPositionValue,
      effectiveStackValue,
      actionStackValue,
    ]
    
    const numberOfNonEmptyValues = variables.filter((value) => value !== '').length

    switch (playerSequenceFilterId) {
      case 0:
        switch (numberOfNonEmptyValues) {
          case 3:
            string += `${playerSequenceValue}-${leftPositionValue}-${effectiveStackValue}`
            break
          
          case 6:
            string += `${playerSequenceValue}-${leftPositionValue}-${thirdFilterValue}-${secondLeftPositionValue}-${effectiveStackValue}-${actionStackValue}`
            break

          case 7:
            string += `${playerSequenceValue}-${leftPositionValue}-${thirdFilterValue}-${secondLeftPositionValue}.${secondRightPositionValue}-${effectiveStackValue}-${actionStackValue}`
            break

          case 8:
            string += `${playerSequenceValue}-${leftPositionValue}-${thirdFilterValue}-${secondLeftPositionValue}-${fifthFilterValue}-${thirdLeftPositionValue}-${effectiveStackValue}-${actionStackValue}`
            break

          case 10:
            string += `${playerSequenceValue}-${leftPositionValue}-${thirdFilterValue}-${secondLeftPositionValue}.${secondRightPositionValue}-${fifthFilterValue}-${thirdLeftPositionValue}.${thirdRightPositionValue}-${effectiveStackValue}-${actionStackValue}`
            break
        }
        break
    }

    string += '.json'

    return string
  }, [
    playerSequenceFilterId,
    leftPositionFilterId,
    rightPositionFilterId,
    thirdFilterId,
    secondLeftPositionFilterId,
    secondRightPositionFilterId,
    fifthFilterId,
    thirdLeftPositionFilterId,
    thirdRightPositionFilterId,
    effectiveStackFilterId,
    actionStackFilterId
  ])

  useEffect(() => {
    const filename = queryFilename()
    fetch(`./micro_stakes/${filename}`)
      .then(res => res.json())
      .then(json => setData(json))
      .catch(err => console.log(err))
  }, [
    queryFilename,
    playerSequenceFilterId,
    leftPositionFilterId,
    rightPositionFilterId,
    thirdFilterId,
    secondLeftPositionFilterId,
    secondRightPositionFilterId,
    fifthFilterId,
    thirdLeftPositionFilterId,
    thirdRightPositionFilterId,
    effectiveStackFilterId,
    actionStackFilterId
  ])

  let actionStack = (playerSequenceFilterId === 0 && leftPositionFilterId !== -1 && (rightPositionFilterId,
    thirdFilterId,
    secondLeftPositionFilterId,
    secondRightPositionFilterId,
    fifthFilterId,
    thirdLeftPositionFilterId,
    thirdRightPositionFilterId,
    actionStackFilterId) === -1) ? true : false 

  return (
    <>
    <h2>Preflop Helper</h2>
      <div className="filters">
        <Filter 
        header={getTooltipValueById(1000000) || ''}
        options={initialSequenceOptions}
        updateSelectedId={setPlayerSequenceFilterId}
        selectedId={playerSequenceFilterId}
        doSomethingAfterClick={queryFilename}
        identificator='playerSequence'
        strict={true}
        />

        {
          initialSequenceOptions[playerSequenceFilterId]?.positionDouble ? (
            <>
            <Filter
            header={initialSequenceOptions[playerSequenceFilterId]?.headersPositionDouble[0].value}
            options={getLeftPositionOptions() || []}
            updateSelectedId={setLeftPositionFilterId}
            selectedId={leftPositionFilterId}
            doSomethingAfterClick={queryFilename}
            identificator='firstPosition'
            strict={true}
          />
                <Filter
            header={initialSequenceOptions[playerSequenceFilterId]?.headersPositionDouble[1].value}
            options={getRightPositionOptions() || []}
            updateSelectedId={setRightPositionFilterId}
            selectedId={rightPositionFilterId}
            doSomethingAfterClick={queryFilename}
            identificator="secondPosition"
            strict={true}
            />
            </>
          ) : (
            <Filter
            header={initialSequenceOptions[playerSequenceFilterId]?.headerPositionUnique.value}
            options={getLeftPositionOptions() || []}
            updateSelectedId={setLeftPositionFilterId}
            selectedId={leftPositionFilterId}
            doSomethingAfterClick={queryFilename}
            identificator='firstPosition'
            strict={false}
            />
          )  
        }
        <Filter 
          header={initialSequenceOptions[playerSequenceFilterId]?.headerThirdFilter.value}
          options={getThirdOptions() || []}
          updateSelectedId={setThirdFilterId}
          selectedId={thirdFilterId}
          doSomethingAfterClick={queryFilename}
          identificator='thirdFilter'
          strict={false}
        />

        {
          thirdFilterId !== -1 ? (
            <>
                  <Filter 
                    header={getTooltipValueById(1000008)}
                    options={positionOptions || []}
                    updateSelectedId={setSecondLeftPositionFilterId}
                    selectedId={secondLeftPositionFilterId}
                    doSomethingAfterClick={queryFilename}
                    identificator='thirdFilter'
                    strict={false}
                />
            </>
          ) : (
            <></>
          )
        }

        <Filter 
        header={getTooltipValueById(1000002) || ''}
        options={initialStackOptions}
        updateSelectedId={setEffectiveStackFilterId}
        selectedId={effectiveStackFilterId}
        doSomethingAfterClick={queryFilename}
        identificator='effectiveStack'
        strict={true}
        />
        { 
        actionStack ? (
        <></>
        ) : (        
        <Filter 
        header={getTooltipValueById(1000007) || ''}
        options={actionStackOptions}
        updateSelectedId={setActionStackFilterId}
        selectedId={actionStackFilterId}
        doSomethingAfterClick={queryFilename}
        identificator='actionStack'
        strict={true}
        />
        )          
        }
      </div>

      <Board data={data}/>
    </>
  )
}

export default App

Jest – Is it possible to mock a function in all mounted components for every test file

here is an example of a test file

it('test case 1', () => {
       wrapper = shallowMount(Login, {
         store,
        localVue,
        mocks: {
           $router
           $GlobalVarForAllComponents // i want this variable to be assigned to every component i mock globally
         }
       })
       expect(true).to(true)
})

I want the $GlobalVarForAllComponents to be automatically assigned to every test case i write, without having to explicitly write this for every single test, is this possible to use a global setting to do this?

Does IntersectionObserver consider visible a div that is inside the viewport, but covered by another div?

I’m having issues with Intersection Observer and don’t really know what’s the problem. So I’ve got a question as I’m curious:

  • Let’s imagine 2 divs A & B
  • A & B are both 100vw by 100vh (full viewport)
  • They’re both moving together, same position
  • B is above A and fully covers A

Is Intersection Observer supposed to consider A as visible when it is inside the viewport? Even though it’s fully covered?

By “visible” I mean isIntersecting = true

How to assign copy to clipboard button to specific text HTML & JavaScript

I’m trying to create a number of buttons on my site to copy respective texts to clipboard, but all the buttons seem to be copying the last text.

I used a different id attribute for each text to be copied and a matching id attribute in the JavaScript getElementById() area for that text.

I’m thinking maybe I need to use unique onclick() functions for each of them instead of copyClipboard() for all of them.

P.S: I’m not a programmer, I’m more of a script kiddie.

Here is the code I used…

(Both buttons end up copying the second text. I want each button to copy its respective text.)



<script>

function copyClipboard() {

    var copyText = document.getElementById("one").innerHTML;

   

    var input = document.createElement("input");

    input.value = copyText;

    document.body.appendChild(input);

    input.select();

    document.execCommand("copy");

    document.body.removeChild(input);

  }</script>

<button onclick="copyClipboard()">copy</button>

<p id="one">first</p>


<script>

    function copyClipboard() {

        var copyText = document.getElementById("two").innerHTML;

       

        var input = document.createElement("input");

        input.value = copyText;

        document.body.appendChild(input);

        input.select();

        document.execCommand("copy");

        document.body.removeChild(input);

      }</script>

   

    <button onclick="copyClipboard()">copy</button>

    <p id="two">second</p>

Uncaught DOMException when fetching data from backend to assign to reactive object

I am simply attempting to fetch some data from my backend and assign that data to a reactive object, but I am getting the following error:

Uncaught (in promise) DOMException: An attempt was made to use an object that is not, or is no longer, usable

the objects variable is being assigned the returned list of objects from my backend, and the backend is returning the correct data. The first fetch function is fetching that data and assigning it to the objects variable, and I think that is where the problem is. Do I need to put this fetch block into a lifecycle hook? I have been stuck on this for a while.

my script block:

import { onBeforeMount, onMounted, reactive, ref } from 'vue'
import { getCookie } from '../helpers/get_cookie.js'
import { useRouter } from 'vue-router'
import { useStore } from 'vuex'

var objects = ref([]);
let store = useStore();
let token = getCookie('token');
let route = useRouter();
let hostname = store.state.hostname.hostname
let date = ref();
let name = ref();
let creator = ref();
let origin = ref();
let description = ref();
let tags = ref();

let creators_dropdown = ref([]);
let tags_dropdown = ref([]);

fetch(`${hostname}museum_objects/get_all_objects/`, {
        method: "get",
        headers: {
            'Content-type': 'application/json',
            'authorization': `Token ${token}`,
        },
    }).then((res) => res.json()).then((response) => {
            objects.value = response
    }
);

function createObject() {
    var formData = new FormData()
    const fileInput = document.querySelector('#thumbnail');
    const file = fileInput.files[0];
    formData.append("thumbnail", file, file.name);
    formData.append("date", date.value);
    formData.append("name", name.value);
    formData.append("creator_id", creator.value);
    formData.append("origin", origin.value);
    formData.append("description", description.value);
    formData.append("tags", 1);

    fetch(`${hostname}museum_objects/create_object/`, {
        method: 'POST',
        headers: {
            'Authorization': `Token ${token}`,
        },
        body: formData
    })
        .then((response) => {
            console.log("Object created:" + response.status)
        })
        .catch((error) => {
            console.log(error);
        });
}

let views = ref({ grid: false, thumbnail: true, list: false })

function change_view(view) {
    for (var item in this.views) {
        this.views[item] = false;
    }
    this.views[view] = true;
}

function getObjectDetails(id) {
    let token = getCookie('token');
    const requestOptions = {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': `Token ${token}`,
        },
    };
    fetch(`${hostname}museum_objects/get_object/${id}/`)
        .then(() => {
            route.push({ name: 'object_details', params: { id: id } });
        })
        .catch((error) => {
            console.log(error);
        });
}

function populate_form_data() {
    let creators_set = new Set();
    objects.value.forEach(t => creators_set.add(JSON.stringify({ 'name': t.creator.name, 'id': t.creator.id })));
    creators_set.forEach(t => creators_dropdown.value.push(JSON.parse(t)));

    let tags_set = new Set();
    for (let object of objects.value) {
        for (let tag of object.tags) {
            tags_set.add(JSON.stringify(tag))
        }
    }
    tags_set.forEach(t => tags_dropdown.value.push(JSON.parse(t)));
}
</script>```

Stack Trace:
Uncaught (in promise) DOMException: An attempt was made to use an    object that is not, or is no longer, usable
    patchDOMProp runtime-dom.esm-bundler.js:515
    patchProp runtime-dom.esm-bundler.js:630
    mountElement runtime-core.esm-bundler.js:5270
    processElement runtime-core.esm-bundler.js:5203
    patch runtime-core.esm-bundler.js:5075
    mountChildren runtime-core.esm-bundler.js:5331
    mountElement runtime-core.esm-bundler.js:5238
    processElement runtime-core.esm-bundler.js:5203
    patch runtime-core.esm-bundler.js:5075
    mountChildren runtime-core.esm-bundler.js:5331
    mountElement runtime-core.esm-bundler.js:5238
    processElement runtime-core.esm-bundler.js:5203
    patch runtime-core.esm-bundler.js:5075
    mountChildren runtime-core.esm-bundler.js:5331
    mountElement runtime-core.esm-bundler.js:5238
    processElement runtime-core.esm-bundler.js:5203
    patch runtime-core.esm-bundler.js:5075
    mountChildren runtime-core.esm-bundler.js:5331
    mountElement runtime-core.esm-bundler.js:5238
    processElement runtime-core.esm-bundler.js:5203
    patch runtime-core.esm-bundler.js:5075
    mountChildren runtime-core.esm-bundler.js:5331
    mountElement runtime-core.esm-bundler.js:5238
    processElement runtime-core.esm-bundler.js:5203
    patch runtime-core.esm-bundler.js:5075
    mountChildren runtime-core.esm-bundler.js:5331
    processFragment runtime-core.esm-bundler.js:5546
    patch runtime-core.esm-bundler.js:5061
    componentUpdateFn runtime-core.esm-bundler.js:5755
    run reactivity.esm-bundler.js:178
    update runtime-core.esm-bundler.js:5861
    setupRenderEffect runtime-core.esm-bundler.js:5869
    mountComponent runtime-core.esm-bundler.js:5659
    processComponent runtime-core.esm-bundler.js:5612
    patch runtime-core.esm-bundler.js:5087
    componentUpdateFn runtime-core.esm-bundler.js:5820
    run reactivity.esm-bundler.js:178
    update runtime-core.esm-bundler.js:5861
    callWithErrorHandling runtime-core.esm-bundler.js:158
    flushJobs runtime-core.esm-bundler.js:362
    promise callback*queueFlush runtime-core.esm-bundler.js:275
    queueJob runtime-core.esm-bundler.js:269
    effect runtime-core.esm-bundler.js:5857
    triggerEffect reactivity.esm-bundler.js:373
    triggerEffects reactivity.esm-bundler.js:363
    triggerRefValue reactivity.esm-bundler.js:966
    effect reactivity.esm-bundler.js:1123
    triggerEffect reactivity.esm-bundler.js:373
    triggerEffects reactivity.esm-bundler.js:358
    triggerRefValue reactivity.esm-bundler.js:966
    effect reactivity.esm-bundler.js:1123
    triggerEffect reactivity.esm-bundler.js:373
    triggerEffects reactivity.esm-bundler.js:358
    triggerRefValue reactivity.esm-bundler.js:966
    effect reactivity.esm-bundler.js:1123
    triggerEffect reactivity.esm-bundler.js:373
    triggerEffects reactivity.esm-bundler.js:358
    triggerRefValue reactivity.esm-bundler.js:966
    effect reactivity.esm-bundler.js:1123
    triggerEffect reactivity.esm-bundler.js:373
    triggerEffects reactivity.esm-bundler.js:358
    triggerRefValue reactivity.esm-bundler.js:966
    set value reactivity.esm-bundler.js:1010
    finalizeNavigation vue-router.mjs:3353
    pushWithRedirect vue-router.mjs:3218
    promise callback*pushWithRedirect vue-router.mjs:3185
    push vue-router.mjs:3110
    install vue-router.mjs:3551
    use runtime-core.esm-bundler.js:3763
    <anonymous> main.js:11
runtime-dom.esm-bundler.js:515:6