Struggling with javascript game logic: Word guessing challenge

I’m studying JavaScript, and as an exercise, I decided to copy a little game I like to help me learn, but I’m struggling and would like to know if someone can explain how to solve this.

I don’t like asking for help, but after two days of struggling and asking AI, I decided to come here.

The game consists of guessing the word of the day, and it has the following behavior:

  1. If the letter exists in the word of the day, mark it as isPresent true;
  2. If the letter exists in the exact same position as in the word of the day, mark it as isCorrect true;
  3. If the first letter matches the first letter in the word of the day, mark it as isFirst true;
  4. If the last letter matches the last letter in the word of the day, mark it as isLast true.

I’m having a lot of difficulty with this part:

  1. If there are letters in the same sequence as in the word of the day, mark them as isNeighbor. For example, if the word of the day is “example” and the guess is “imply”, “mpl” should get isNeighbor true. I wrote this part, but it doesn’t work in all cases;
  2. If the letters are not in the exact same position in the guess and in the word of the day, but they are in the same order, they should be marked as isCorrect true. If the word of the day is “example” and the guess is “permit”, “p” and “e” would be isCorrect, but “m” wouldn’t, as in “example”, it appears before “p”. I simply don’t know what to do, and I’ve been stuck here for two days.

Here’s a screenshot of the game instructions I’m copying, so you can understand better.

My code looks like this:

// Word of the day
const WORD_OF_THE_DAY = "example";

// Main function
const guessWord = (inputValue) => {
  let originalLetterUsed = Array(WORD_OF_THE_DAY.length).fill(false);

  /**
   * Finds the index of the first occurrence of an unused letter from the word of the day.
   * @param {string} letter - Letter to find in the word of the day.
   * @returns {number} - The index of the letter, or -1 if not found.
   */
  const findAvailableLetterIndex = (letter) => WORD_OF_THE_DAY.split('').findIndex((char, charIdx) => {
    return char === letter && !originalLetterUsed[charIdx];
  });

  const word = [...inputValue].map((letter, letterIdx) => {
    const availableIndex = findAvailableLetterIndex(letter);
    let currentLetter = {
      letter,
      isCorrect: false,
      isPresent: false,
      isNeighbor: false,
      isFirst: false,
      isLast: false
    }

    // If the letter exists in the word of the day
    if (availableIndex > -1) {
      originalLetterUsed[availableIndex] = true;
      currentLetter.isPresent = true;

      // Checks if the next letter in the typed word matches the next letter of the word of the day,
      // or if the previous letter in the typed word matches the previous letter of the word of the day
      if (
        inputValue[letterIdx + 1] === WORD_OF_THE_DAY[availableIndex + 1] ||
        inputValue[letterIdx - 1] === WORD_OF_THE_DAY[availableIndex - 1]
      ) {
        currentLetter.isNeighbor = true;
      }

      // Check if the current letter mathes with the letter of the word of the day in the same position
      if (letter === WORD_OF_THE_DAY[availableIndex]) {
        currentLetter.isCorrect = true;
      }

      // Check if the letter is in the correct order
      /* if (???) {
        currentLetter.isCorrect = true;
      } */

      // Check if the first letter matches
      if (letterIdx === 0 && letter === WORD_OF_THE_DAY[0]) {
        currentLetter.isFirst = true;
      }

      // Check if the last letter matches
      if (letterIdx === inputValue.length - 1 && letter === WORD_OF_THE_DAY[WORD_OF_THE_DAY.length - 1]) {
        currentLetter.isLast = true;
      }
    }

    return currentLetter;
  });

  return word;
}

console.log("permit", guessWord("permit"));
console.log("imply", guessWord("imply"));
console.log("excuse", guessWord("excuse"));
console.log("example", guessWord("example"));

How to return an element to its original state with Javascript?

After Declaring a Javascript function on an Html Element which is to be invoked when an event takes place, i want to add another event listener which is event like onmouseout and then the html element will return to its original form i.e to its former state.

I tried creating another Function() adding “document.getElementById(“”)innerHTML = ” something like that. The thing is I don’t even know how to do it please help me out here, I need detailed explanation please.

Adding Form Inputs Dynamically with Javascript and Thymeleaf

I’m wondering what is the most idiomatic/optimal solution is for adding form elements dynamically with Javascript and Thymeleaf. For context, I have a form that is being generated server side like so:

<form
    th:action="@{/some/path})}"
    th:object="${pathBulletinForm}"
    method="post"
    class="mb-3 border rounded needs-validation"
    novalidate
    id="bulletinForm"
>
    <select th:field="*{conditionRating}" type="select" id="conditionRating" name="conditionRating" class="form-select">
        <option label="-- Select a Condition --" value=""></option>
        <option th:each="pathConditionOpt : ${T(com.francisbailey.pathbulletin.persistence.model.PathCondition).values()}" th:value="${pathConditionOpt}" th:text="${pathConditionOpt.displayName}" th:attr="data-description='descriptionFor' + ${pathConditionOpt.name}"></option>
    </select>
    <a href="#" id="addConditionRating"><i class="bi bi-plus-circle"></i> Add Rating</i>
</form>

Now, what I’d like to do is for the user to click a button and it will automatically append an identical select drop down to the form. In other words they can have multiple “conditionRatings” appended to the form. This is easy enough to do in pure javascript/client side, but I like having the drop down generated server side since the values are coming from an enum and single source of truth.

I’m not sure what the best way to do this is. Setting this template value in Javascript looks possible, but kind of ugly.

For adding the form element I know I can do something like:

<script>
const ratingButton = document.getElementById("addConditionRating");
const form = document.getElementById("bulletinForm")

ratingButton.addEventListener(e => {
    form.appendChild(`<select>My Condition Ratings Template Here?</select>`);    
});
</script>

However, I’m not sure on how to set the actual select drop down in there. I also need to bind a listener to each drop down to display a server side rendered description/label underneath the drop down.

How to Implement Vertical Scrollable Image Gallery with Thumbnails and Swiper on Mobile?

I am trying to create a product gallery similar to the one on the Gymshark product page (Link) for my ecommerce store product page. The gallery should work as follows:

Desktop Version:

The product thumbnails should be displayed in a vertical scrollable column on the left side.
When a user clicks or hovers over a thumbnail, the main image on the right should update accordingly.
A scroll progress indicator should show how far the user has scrolled through the thumbnails.
Mobile Version:

On mobile, I want the gallery to switch to a horizontal swipe-able image slider (using something like Swiper.js or bootstrap carousel).

d3js multi-translucent area chart with indicator readout on hover

I am experimenting with different styles for charts – and I am wondering how to create this kind of shaded translucent multi-area chart with indicator readout on hover

enter image description here

my current build — regular multi-lines
https://codesandbox.io/p/sandbox/magical-wiles-forked-wnzkfk

basic area chart example

<!DOCTYPE html>
<meta charset="utf-8">

<!-- Load d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>

<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>

<script>

// set the dimensions and margins of the graph
var margin = {top: 10, right: 30, bottom: 30, left: 50},
    width = 460 - margin.left - margin.right,
    height = 400 - margin.top - margin.bottom;

// append the svg object to the body of the page
var svg = d3.select("#my_dataviz")
  .append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .append("g")
    .attr("transform",
          "translate(" + margin.left + "," + margin.top + ")");

//Read the data
d3.csv("https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/3_TwoNumOrdered_comma.csv",

  // When reading the csv, I must format variables:
  function(d){
    return { date : d3.timeParse("%Y-%m-%d")(d.date), value : d.value }
  },

  // Now I can use this dataset:
  function(data) {

    // Add X axis --> it is a date format
    var x = d3.scaleTime()
      .domain(d3.extent(data, function(d) { return d.date; }))
      .range([ 0, width ]);
    svg.append("g")
      .attr("transform", "translate(0," + height + ")")
      .call(d3.axisBottom(x));

    // Add Y axis
    var y = d3.scaleLinear()
      .domain([0, d3.max(data, function(d) { return +d.value; })])
      .range([ height, 0 ]);
    svg.append("g")
      .call(d3.axisLeft(y));

    // Add the area
    svg.append("path")
      .datum(data)
      .attr("fill", "#cce5df")
      .attr("stroke", "#69b3a2")
      .attr("stroke-width", 1.5)
      .attr("d", d3.area()
        .x(function(d) { return x(d.date) })
        .y0(y(0))
        .y1(function(d) { return y(d.value) })
        )

})

</script>

I try to make a class to turn my react neater. and now use efffect or requestAnimation make my game controller disconect [closed]

my old gamePage look like this :

import React, { useEffect, useState, useRef } from 'react';
import GamepadManager from '../utils/GamepadManager';
import Stick from '../utils/Stick';
import PlatoTemplate from '../organisms/platoTemplate';
import mapConfigFile from '../assets/mapConfig/BepoStyle.json';
import '../styles/gamePage.css';
import LetterFall from '../organisms/LetterFall';
import { useDispatch, useSelector } from 'react-redux';
import { hit } from '../controler/lettersSlice';
import { addPrintableLetters } from '../controler/printableLettersSlice';

export default function GamePage() {
  const dispatch = useDispatch();
  const mapConfig = mapConfigFile;
  const letters = useSelector((state) => state.letters);
  const printableLetters = useSelector((state) => state.printableLetters);
  const lettersRef = useRef(letters);
  const [plato, setPlato] = useState(mapConfig.plato[0]);
  const [key, setKey] = useState('');
  const requestRef = useRef();
  let lastButtonPressed = [];

  useEffect(() => {
    lettersRef.current = letters;
  }, [letters]);

  useEffect(() => {
    lettersRef.current = printableLetters;
  }, [printableLetters]);

  useEffect(() => {
    const Gamepad = new GamepadManager();
    const leftStick = new Stick(0, 0);
    const rightStick = new Stick(0, 0);

    const selectPlato = ({ leftStickPosition, rightStickPosition }) => {
      const findedPlato = mapConfig.plato.find(plato => {
        return plato.joystick[0] === leftStickPosition && plato.joystick[1] === rightStickPosition;
      });
      setPlato(findedPlato);
      return findedPlato;
    };

    const selectKey = (curentPlato, buttonsPressed) => {
      const buttonPresse = buttonsPressed.findIndex(button => button === true);

      //je suis pas super fiere de mon systéme de gestion des input je me prendrais la tete dessus plus tard
      if (buttonPresse === -1) {
        lastButtonPressed = [];
      }
      if (buttonPresse === -1 || curentPlato === null || curentPlato === undefined) return;
      if (lastButtonPressed.includes(buttonPresse)) return;
      lastButtonPressed.push(buttonPresse);


      console.log(lettersRef.current);
      const keyPressed = curentPlato.KeyTab[mapConfig.buttonId[buttonPresse]];
      dispatch(hit(keyPressed));
      setKey(keyPressed);
    };

    const getGamepadsInfo = () => {
      const gamepadState = Gamepad.getState();
      if (gamepadState == null) return;

      leftStick.setDirection(gamepadState.axes[0], gamepadState.axes[1]);
      rightStick.setDirection(gamepadState.axes[2], gamepadState.axes[3]);

      const curentPlato = selectPlato({ leftStickPosition: leftStick.getDirection(), rightStickPosition: rightStick.getDirection() });
      selectKey(curentPlato, gamepadState.buttonsPressed);
    };

    const gameLoop = () => {
      getGamepadsInfo();
      requestRef.current = requestAnimationFrame(gameLoop);
    };

    requestRef.current = requestAnimationFrame(gameLoop);

    return () => cancelAnimationFrame(requestRef.current);
  }, [mapConfig]);

  const test = () => {
    console.log(letters);
  }

  const addPlato = (platoId) => {
    console.log(platoId);
    const plato = mapConfig.plato.find(plato => plato.id === platoId);
    //mettre les non selectionner en gris
    mapConfig.plato.forEach(plato => {
      plato.selected = false;
    });
    plato.selected = true;
    console.log(plato);
    Object.entries(plato.KeyTab).forEach(([buttonId, key]) => {
      if (key && key !== "void" && key !== "" &&
        !["Space", "Backspace", "Tab", "Enter", "Esc"].includes(key)) {
        if (key.length === 1) {
          dispatch(addPrintableLetters(key));
        }
        else if (key.length > 1) {
          dispatch(addPrintableLetters(key.slice(0, 1)));
        }
      }
    });
  }


  return (
    <div className='gamePage'>
      <button onClick={test}>test</button>

      <button onClick={addPlato}>test2</button>
      {plato != null ? <PlatoTemplate plato={plato} /> : null}
      <LetterFall />
      <div className='key'>{key}</div>

      <div className='score'>{letters.length}</div>
      <div className='map' onClick={() => console.log('click')}>
        {mapConfig.plato.map(plato =>
          <div
            className={plato.selected ? 'selected' : 'notSelected'}
            onClick={() => {
              console.log('Plato clicked:', plato.id);
              addPlato(plato.id);
            }}>
            <PlatoTemplate key={plato.id} plato={plato} />
          </div>
        )}
      </div>
    </div>
  );
}

and now i just replace all whit this :

import React, { useEffect, useState, useRef } from 'react';
import GamepadManager from '../utils/GamepadManager';
import Stick from '../utils/Stick';
import PlatoTemplate from '../organisms/platoTemplate';
import mapConfigFile from '../assets/mapConfig/BepoStyle.json';
import '../styles/gamePage.css';
import LetterFall from '../organisms/LetterFall';
import { useDispatch, useSelector } from 'react-redux';
import { hit } from '../controler/lettersSlice';
import { addPrintableLetters } from '../controler/printableLettersSlice';
import MapConfig from '../utils/MapConfig';


export default function GamePage() {
  const dispatch = useDispatch();

  const mapConfig = new MapConfig(mapConfigFile);
  const letters = useSelector((state) => state.letters);
  const printableLetters = useSelector((state) => state.printableLetters);
  const lettersRef = useRef(letters);
  const [plato, setPlato] = useState(mapConfig.platos[0]);
  const [key, setKey] = useState('');
  const requestRef = useRef();
  let lastButtonPressed = [];
  const lastTime = useRef(0);


  useEffect(() => {
    lettersRef.current = letters;
  }, [letters]);

  useEffect(() => {
    lettersRef.current = printableLetters;
  }, [printableLetters]);

  useEffect(() => {
    const Gamepad = new GamepadManager();
    const leftStick = new Stick(0, 0);
    const rightStick = new Stick(0, 0);

    const selectPlato = ({ leftStickPosition, rightStickPosition }) => {
      const findedPlato = mapConfig.platos[0] ;//mapConfig.platos.find(plato => plato.sameJostick([leftStickPosition, rightStickPosition]));
      setPlato(findedPlato);
      return findedPlato;
    };


    const selectKey = (curentPlato, buttonsPressed) => {
      const buttonPresse = buttonsPressed.findIndex(button => button === true);

      //je suis pas super fiere de mon systéme de gestion des input je me prendrais la tete dessus plus tard
      if (buttonPresse === -1) {
        lastButtonPressed = [];
      }
      if (buttonPresse === -1 || curentPlato === null || curentPlato === undefined) return;
      if (lastButtonPressed.includes(buttonPresse)) return;
      lastButtonPressed.push(buttonPresse);


      console.log(lettersRef.current);
      const keyPressed = curentPlato.keys[mapConfig.buttons[buttonPresse]];
      dispatch(hit(keyPressed));
      setKey(keyPressed);
    };

    const getGamepadsInfo = () => {
      const gamepadState = Gamepad.getState();
      if (gamepadState == null) return;
      leftStick.setDirection(gamepadState.axes[0], gamepadState.axes[1]);
      rightStick.setDirection(gamepadState.axes[2], gamepadState.axes[3]);

      const curentPlato = selectPlato({ leftStickPosition: leftStick.getDirection(), rightStickPosition: rightStick.getDirection() });
      selectKey(curentPlato, gamepadState.buttonsPressed);
    };

    const gameLoop = (timestamp) => {
      if (timestamp - lastTime.current >= 1000) { 
        console.log("timestamp:", timestamp)
        getGamepadsInfo(); 
        lastTime.current = timestamp;
      }
      requestRef.current = requestAnimationFrame(gameLoop);
    };

    requestRef.current = requestAnimationFrame(gameLoop);

    return () => cancelAnimationFrame(requestRef.current);
  }, [mapConfig]);


  const addPlato = (platoId) => {
    console.log(platoId);
    const plato = mapConfig.platos.find(plato => plato.id === platoId);
    //mettre les non selectionner en gris
    plato.selected = true;

    plato.keyList.forEach(key => {
      dispatch(addPrintableLetters(key));
    })
  }


  return (
    <div className='gamePage'>
      {plato != null ? <PlatoTemplate plato={plato} /> : null}
      <LetterFall />
      <div className='key'>{key}</div>

      <div className='score'>{letters.length}</div>
      <div className='map' >
        {mapConfig.platos.map(plato =>
          <div key={plato.id}
            className={plato.selected ? 'selected' : 'notSelected'}
            onClick={() => {
              addPlato(plato.id);
            }}>
            <PlatoTemplate key={plato.id} plato={plato} />
          </div>
        )}
      </div>
    </div>
  );
}

i replace requestAnimationFrame whit setTimeout and it work again . but i want to use requestAnimationFrame !

my MapConfig is just a setter

import Plato from "./PlatoHandler";

export default class MapConfig {

    constructor(mapConfig) {
        this.buttons = mapConfig.buttonId;
        this.platos = [];
        mapConfig.plato.forEach(plato => {
            this.platos.push(new Plato(plato));
        });
    }
}

and same for plato class

whit a litel extra if function

export default class Plato {

    constructor(plato) {
        this.id = plato.id;
        this.joystick = plato.joystick;
        //liste de touche mapper avec l'id des touches
        this.keys = plato.KeyTab;
        this.selected = false;

        //lister les touches
        this.keyList = []; 
        // Object.entries(plato.KeyTab).forEach(([buttonId, key]) => {
        //     if (key && key !== "void" && key !== "" &&
        //         !["Space", "Backspace", "Tab", "Enter", "Esc"].includes(key)) {
        //         this.keyList.push(key);
        //     }
        // });
    }

    sameJostick(joystick) {
        if (this.joystick[0] === joystick[0] && this.joystick[1] === joystick[1]) {
            return true;
        }
        return false;
    }
}

also i can show you my gamepadcontroller. is realy basic

export default class GamepadManager {
    /**
     * Initializes the GamepadManager object and sets up event listeners for gamepad connection and disconnection.
     * Also starts the gamepad loop to update the gamepad state at each frame.
     */
    controllerIndex = {
        index: null,
    };

    constructor() {

        window.addEventListener('gamepadconnected', (event) => {
            console.log('Gamepad connected:', event.gamepad);
            this.controllerIndex = event.gamepad.index;
        });

        window.addEventListener('gamepaddisconnected', (event) => {
            console.log('Gamepad disconnected:', event.gamepad);
            this.controllerIndex = null;
        });

    }

    updateGamepadState() {
        if (!this.gamepad) {
            return;
        }

        this.previousGamepadState = { ...this.currentGamepadState };
        this.currentGamepadState = {
            buttons: this.gamepad.buttons.map(button => button.pressed),
            axes: this.gamepad.axes.map(axis => axis.toFixed(2)),
        };
    }

    getState() {
        if (this.controllerIndex === null) return null;
        const gamepad = navigator.getGamepads()[this.controllerIndex];
        if (!gamepad) return null;

        return {
            buttonsPressed: gamepad.buttons.map(el => el.pressed),
            axes: gamepad.axes.map(axis => axis.toFixed(2)),
        };
    }

}

i will ad more funciton in this 2 class later and make game page litter .

i asking myself i am supose to do some

react return in class ?

so i can make a function to return this in mapConfig

<div className='map' >
        {mapConfig.platos.map(plato =>
          <div key={plato.id}
            className={plato.selected ? 'selected' : 'notSelected'}
            onClick={() => {
              addPlato(plato.id);
            }}>
            <PlatoTemplate key={plato.id} plato={plato} />
          </div>
        )}
      </div>

or we are not supos to use react like this ?

Chart.js 3.9 and Vue: Unable to handle onClick event

Usually, StackOverflow is my last resort cause I don’t enjoy being annoyed and I assume neither do you, but I’m desperate.

I want to capture a click on a graph Bar but I don’t see a trace in the logs that the click event has been thrown. I was using Chart.js 2.8.9 but upgraded to 3.9 thinking it could be a bug.

This is my vue file where I load the Graphics:

<template>
    <div>
        <h4>Gráficas de miembros activos</h4>
        <div>
            <!-- Pasamos chartData y el evento bar-clicked -->
            <bar-chart :chart-data="datos" :opciones="opciones" @bar-clicked="handleBarClick" />
        </div>
    </div>
</template>

<script>
    import BarChart from "../components/BarChart";
    import api from "@/api";

    export default {
        name: "Graficas",
        components: { BarChart },
        data() {
            return {
                datos: {},   // Datos del gráfico
                opciones: {} // Opciones del gráfico
            };
        },
        methods: {
            graficar: function (sector_id) {
                api.graficas(sector_id).then((r) => {
                    this.datos = r.data; 

                    // Configuración de colores y bordes de las barras
                    this.datos.datasets[0].backgroundColor = [
                        'rgba(255, 99, 132, 0.2)',
                        'rgba(255, 159, 64, 0.2)',
                        'rgba(255, 205, 86, 0.2)',
                        'rgba(75, 192, 192, 0.2)',
                        'rgba(54, 162, 235, 0.2)',
                        'rgba(153, 102, 255, 0.2)',
                        'rgba(201, 203, 207, 0.2)'
                    ];
                    this.datos.datasets[0].borderColor = [
                        'rgb(255, 99, 132)',
                        'rgb(255, 159, 64)',
                        'rgb(255, 205, 86)',
                        'rgb(75, 192, 192)',
                        'rgb(54, 162, 235)',
                        'rgb(153, 102, 255)',
                        'rgb(201, 203, 207)'
                    ];
                    this.datos.datasets[0].borderWidth = 1;

                    // Opciones del gráfico
                    this.opciones = {
                        scales: {
                            y: {
                                beginAtZero: true
                            }
                        },
                        responsive: true,
                        maintainAspectRatio: false,
                        height: 300
                    };
                })
                .catch(error => {
                    console.log(error);
                });
            },
            handleBarClick({ data, dataIndex, datasetIndex }) {
                // Este método captura el evento bar-clicked y muestra la información del clic
                console.log(`Clicked bar at index ${dataIndex} in dataset ${datasetIndex}:`, data);
            }
        },
        mounted() {
            const sector_id = this.$route.params.id ?? 0;
            this.graficar(sector_id);
        },
    };
</script>

And this is the class we created to extend Chart.js:

import { Chart, registerables } from 'chart.js';

Chart.register(...registerables); // Registro de todos los componentes necesarios

export default {
  props: {
    chartData: {
      type: Object,
      required: true
    },
    opciones: {
      type: Object,
      default: () => ({})
    }
  },
  mounted() {
    const canvas = this.$refs.canvas;

    // Verificamos que el canvas existe y tiene contexto 2D
    if (!canvas || !canvas.getContext) {
      console.error("No se pudo obtener el contexto del canvas.");
      return;
    }

    const ctx = canvas.getContext('2d');

    // Configuración de las opciones de la gráfica
    this.opciones.scales = {
      y: {
        beginAtZero: true
      }
    };
    this.opciones.plugins = {
      datalabels: {
        color: "black",
        textAlign: "center",
        anchor: 'start',
        font: {
          weight: "bold",
          size: 14,
        }
      }
    };
    this.opciones.responsive = true;
    this.opciones.maintainAspectRatio = false;
    this.opciones.hover = {
      mode: 'nearest',
      intersect: true
    };
    this.opciones.interaction = {
      mode: 'index',
      intersect: false
    };

    // Establecemos una altura fija para el canvas a través de CSS
    canvas.style.height = '400px';
    canvas.style.width = '100%'; 

    // Instancia del gráfico
    this.chartInstance = new Chart(ctx, {
      type: 'bar',
      data: this.chartData,
      options: {
        ...this.opciones,
        onClick: (event, elements) => {
          console.log('onClick event triggered');
          if (elements.length > 0) {
            const element = elements[0];
            const dataIndex = element.index;
            const datasetIndex = element.datasetIndex;
            console.log('Data point clicked:', dataIndex, datasetIndex);
            const data = this.chartData.datasets[datasetIndex].data[dataIndex];
            this.$emit('bar-clicked', { data, dataIndex, datasetIndex });
          } else {
            console.log('No elements clicked.');
          }
        }
      }
    });

  },
  watch: {
    chartData(newData) {
      if (this.chartInstance) {
        this.chartInstance.data = newData;
        this.chartInstance.update();
      }
    },
    opciones(newOptions) {
      if (this.chartInstance) {
        this.chartInstance.options = newOptions;
        this.chartInstance.update();
      }
    }
  },
  beforeDestroy() {
    if (this.chartInstance) {
      this.chartInstance.destroy();
    }
  },
  render(h) {
    return h('canvas', { ref: 'canvas' });
  }
};

The JSON returned by the backend is simple, so the error shouldn’t be there:

    {
  "datasets": [
    {
      "data": [
        15,
        5,
        0,
        0,
        0
      ],
      "label": "Sector San Felipe De Jesus"
    }
  ],
  "labels": [
    "Matrimonios",
    "MaRes",
    "Ju00f3venes",
    "Adolescentes",
    "Asistentes Eclesiales"
  ]
}

The Graphic is shown but I don’t see a trace in the logs for the click. Any ideas?
Graph is shown but nothing in the logs

How to display data from Google Sheet in a Section Header within a Google Form?

I have a Google spreadsheet that lists customers and identifies store locations for each:

Customer Location
Customer A New York
Customer A San Jose
Customer B New York

I have a Google Form that will ask the user what their customer name is (Customer A).
Based on this, I want to show a list of all the locations currently entered into the Google Spreadsheet within the Google Form as regular text.

For example, if Customer A started to use the form, it would show ‘New York, San Jose’ in a text field.

I’ve been trying to create an Apps Script to query the spreadsheet, filter the results based on the customer name, and then log the results as the description (or HelpText) for a SectionHeaderItem.

However, I’m not having a lot of luck. Most of the related questions I can find deal with how to create new questions based off of spreadsheet data, not just how to display the information.

Any thoughts would be most welcome!

How do I add other language support to monaco?

I am building a development application, thus I need an embedded code editor. Monaco is really nice for this since it is friendly to use and its features are very familiar for anyone coding with vs-code.
I write my app in java, so the monaco editor needs to be embedded into html with vanilla javascript. In other words: using the react-version of monaco isn’t an option.

I have downloaded the monaco files from the official website and put them aside this html file:

<!DOCTYPE html>
<html>
<head>
    <!-- ... -->
    <link rel="stylesheet" data-name="vs/editor/editor.main" href="./min/vs/editor/editor.main.css">
    <!-- ... -->
</head>
<body>
    <div id="container"></div>
    <script src="./min/vs/loader.js"></script>
    <script>
        require.config({
            paths: {
                'vs': './min/vs'
            }
        });
    </script>
    <script src="./min/vs/editor/editor.main.nls.js"></script>
    <script src="./min/vs/editor/editor.main.js"></script>
    <script>
    const editor = monaco.editor.create(document.getElementById('container'), {
            value: 'def main()ntprint("Hello world!")',
            language: 'python',
            //some more options
            autoClosingPairs: [{ open: '{', close: '}' },{ open: '[', close: ']' },{ open: '(', close: ')' },{ open: '"', close: '"' },{ open: ''', close: ''' }],
        });

    </script>
</body>
</html>

This displays a nice editor and it has basic syntax highlighting, but none of the hover and autocomplete features.
When the language is changed to javascript, it is fully featured, but on python and other langauges it only has syntax highlighting.

How do I add autocomplete and hover-info for pyhton?
I found some codes to start a language server, but adding it had no effect.

Trying to setup UTM parameters on a clients Wix site with form v2 and keep receiving “…type does not exist in FormValues”

I have spent so many hours just trying to figure out why Velo cannot recognize my form field key/field title to assign a utm parameter to the field… and no I am not misspelling the field key or getting it wrong. The goal here is to take a utm parameter from an ad campaign and place it into a hidden empty field within the Wix v2 Form.

The code below should taking the utm parameter utm_source from the URL, then locates the form called #djform which is located on the page, and then it should be calling setFieldValues to insert the value from the custom parameter utm_source into the hidden empty field which is called utmsource_1

I keep receiving this exact error:

Argument of type ‘{ utmsource_1: string; }’ is not assignable to parameter of type ‘FormValues’. Object literal may only specify known properties, and ‘utmsource_1’ does not exist in type ‘FormValues’.

import wixLocationFrontend from 'wix-location-frontend';

$w.onReady(function() {

    const query = wixLocationFrontend.query;
    let utmSource = decodeURIComponent(query.utm_source).toString();

    // // Use direct element ID references to set values
    if (query.utm_source) {
        $w('#djform').setFieldValues({
        utmsource_1: utmSource,
        });
    }
});

For some reason Velo can’t recognize utm_source1 when I’m trying to set that hidden Field Value to a specified utm parameter… the Field Value should be what is essentially an element ID or in this case, a Field Key

Here is the setFieldValues documentation from Velo – https://dev.wix.com/docs/velo/api-reference/$w/wix-forms-v2/set-field-values

Thermal Printer USB x App Flutter Web (WINDOWS)

I need your help.

I’m developing a web application (Flutter) that needs to communicate with thermal printers (EPSON, STAR or even the more common and cheaper mini ones). I tried using WEBUSB API and it didn’t work on Windows, only on the MacBook. Since I’m using a thermal printer, the WEBSERIAL API worked on Windows, but it doesn’t work for EPSON thermal printers.

I researched how iFood handles this and discovered that an .exe is downloaded that makes this communication with the printer and their web application. So, I tried to develop something that would allow local communication of my application with the USB port, using a node.js server, with escpos, escpos-usb, express, usb-detection, serial port libraries. After several attempts, I always get the same error: LIBUSB_ERROR_IO. I checked and discovered that I would need to use another drive in my printer to make the communication I need. However, I didn’t want to have to mess with the driver since the printer will be used by other applications, including ifood, and this driver update may stop it from working. Does anyone have any idea what I can do to get around this situation?

Thank you and sorry for my bad English.

I tried to develop something that would allow local communication of my application with the USB port, using a node.js server, with escpos, escpos-usb, express, usb-detection, serial port libraries.

Some codes:

const usb = require('usb');  // Biblioteca para comunicação USB
const express = require('express');
const bodyParser = require('body-parser');

const app = express();

// Função para converter string em buffer binário
function stringToBuffer(str) {
    return Buffer.from(str, 'utf-8');
}

// Middleware para processar os dados binários (raw)
app.use(bodyParser.raw({ type: 'application/octet-stream' }));

// Função para enviar mensagem simples para a impressora
async function sendTestMessage() {
    return new Promise((resolve, reject) => {
        try {
            // Detecta todos os dispositivos USB conectados
            const devices = usb.getDeviceList();
            const printerDevice = devices.find(device => {
                console.log(device.deviceDescriptor);
                const { idVendor, idProduct } = device.deviceDescriptor;
                console.log(`Dispositivo encontrado: VendorId=${idVendor}, ProductId=${idProduct}`);
                
                // Filtra pelo VendorId e ProductId conhecidos
                return idVendor === 1155 && idProduct === 22304;
            });

            if (!printerDevice) {
                reject(new Error('Nenhuma impressora USB encontrada.'));
                return;
            }

            // Abre o dispositivo USB
            printerDevice.open();

            // Acesse a interface de comunicação (normalmente interface 0)
            const iface = printerDevice.interfaces[0];

            if (iface.isKernelDriverActive()) {
                iface.detachKernelDriver();  // Desvincula o driver do kernel (se necessário)
            }

            // Ativa a interface para enviar dados
            iface.claim();

            // Identificar endpoints de saída (OUT)
            const outEndpoints = iface.endpoints.filter(endpoint => endpoint.direction === 'out');

            if (outEndpoints.length === 0) {
                reject(new Error('Nenhum endpoint de saída (OUT) encontrado.'));
                return;
            }

            // Usar o primeiro endpoint de saída disponível
            const endpoint = outEndpoints[0];
            console.log(`Usando endpoint de saída número ${endpoint.address}`);

            // Mensagem curta para teste
            const testMessage = stringToBuffer('Teste de impressão');

            // Enviar a mensagem curta para o endpoint de saída
            endpoint.transfer(testMessage, (err) => {
                if (err) {
                    reject(new Error('Erro ao enviar dados para o dispositivo USB: ' + err.message));
                } else {
                    console.log('Mensagem enviada com sucesso para o dispositivo USB!');
                    resolve('Mensagem enviada com sucesso para o dispositivo USB!');
                }
            });

            // Fechar o dispositivo após a impressão
            printerDevice.close();

        } catch (error) {
            reject(new Error('Erro ao imprimir via USB: ' + error.message));
        }
    });
}

// Endpoint para enviar uma mensagem curta de teste
app.get('/send-test', async (req, res) => {
    try {
        const result = await sendTestMessage();
        res.send(result);  // Envia uma resposta de sucesso
    } catch (error) {
        console.error('Erro ao tentar imprimir:', error);
        res.status(500).send('Erro ao tentar imprimir: ' + error.message);
    }
});

// Rodando o servidor na porta 3000
app.listen(3000, () => {
    console.log('Servidor rodando em http://localhost:3000');
});

I try WEBUSB API, WEBSERIAL API and node.js server.

Cannot enter my code into a question without getting an error

Follow the pictures. This is driving me crazy and seems to make no sense at all.

before error

after error

So I can enter a few lines of code without a problem, but then the next line of code makes it improperly formatted??? The code is formatted properly, as can be seen from the pictures. Am I a total dummy and missing something or am I right to be totally pissed at this stupid bug?

Assert that Template.fromStack() contains resources with specified logical ids

I’m refactoring a cdk stack in ts that has hit the resource limit. Since it contains stateful resources, I want to be sure that the refactored stack refers to the same resources, and not new resources, which could trigger undesirable outcomes, such as orphaning or deletion.

To address this, I’m looking to write a unit test that asserts that the template generated from a stack contains resources with a given set of logical ids. I’ve seen ways to assert that resources with given properties exist, but not that resources with given ids exist.

How can I check that a stack contains resources with given logicalIds? I want to do something like the below:


describe('MyStack', () => {
  test('synthesizes with expected logical IDs', () => {
    const app = new cdk.App();
    const stack = new MyStack(app, 'MyStackDev', {
      deploymentEnvironment: 'dev',
    });

    const template = Template.fromStack(stack);

    const expectedLogicalIds = [
      apiGatewayDev,
      lambdaDev,
      webSocketLambdaDev,
      devLambdaWithConcurrentProvisioning,
      neptuneBastionHostDev,
      neptuneClusterDev,
      auroraClusterDev,
      sevenndevimages,
      sevenndevprivate,
      sparkQueryLogs,
      shareLinks,
      webSocketInstances,
      flowInteractionLog,
    ];

    expectedLogicalIds.forEach((logicalId) => {
      // NOTE: if I need to apply the type, then I'll need to do some more work
      //       to make sure the right type is matched with the right logical id
      //       either way, I don't expect it to work as written because I don't
      //       believe this is proper usage of hasResourceProperties, as the 
      //       logical id is actually the key of the resource object
      expect(
        template.hasResourceProperties('AWS::Lambda::Function', { LogicalId: logicalId }),
      ).toBeTruthy();
    });
  });
});

JavaScript Cookie consent code keeps showing up after selection has been made

I’m using this code to create a custom cookie consent banner on Webflow for a client. On the original site https://google-consent-mode.webflow.io/ it appears to functioning properly, it remembers when a selection is made from a user and doesn’t reappear when the site is reloaded.

But when I clone the site, the banner appears after each reload not remembering my selection https://google-consent-mode.webflow.io/

Here’s the read only link in Webflow: https://preview.webflow.com/preview/google-consent-mode-cookie-consent-bann?utm_medium=preview_link&utm_source=designer&utm_content=google-consent-mode-cookie-consent-bann&preview=8054fe45be8a93ef82b1ea1fa5475aec&workflow=preview

I believe the issue is that when a selection is made, the variable ‘consentMode’ is not being updated with a value, thus the below code runs showing the banner each time:

// If consentMode has not been set, show Cookie Banner
  if(localStorage.getItem('consentMode') === null) {
    document.getElementById('cw-cookie-banner').style.display = 'block';
  }

Here’s the full code, please help!

<!-- Cookie Consent Mode by Code & Wander -->
<script>
    // Check selection
  document.getElementById('cw-cookie-icon').addEventListener('click', function() {
    setConsentCheckboxes();
    hideOptions();
    document.getElementById('cw-cookie-banner').style.display = 'block';
  })
  
  // Hide Cookie Banner
  function hideBanner() {
    document.getElementById('cw-cookie-banner').style.display = 'none';
  }
  
  // Hide more options
  function hideOptions() {
    document.getElementById('cw-cookie-options').style.height = '0px';
  }
    
  // If consentMode has not been set, show Cookie Banner
  if(localStorage.getItem('consentMode') === null) {
    document.getElementById('cw-cookie-banner').style.display = 'block';
  }
  
  //Logic to populate the preferences
  function setConsentCheckboxes() {
    uncheckAllConsentCheckboxes();
    
    const consentModeString = localStorage.getItem('consentMode');

    if (consentModeString) {
        const consentMode = JSON.parse(consentModeString);
      
        const consentMapping = {
          'functionality_storage': 'consent-necessary',
          'ad_storage': 'consent-ad-marketing',
          'analytics_storage': 'consent-analytics',
          'ad_user_data': 'consent-ad-user',
          'ad_personalization': 'consent-ad-personalization',
          'personalization_storage': 'consent-personalization',
          'security_storage': 'consent-security',
        };

        Object.entries(consentMapping).forEach(([storageKey, checkboxId]) => {
          const checkbox = document.getElementById(checkboxId);

         if (checkbox) {
            const isChecked = consentMode[storageKey] === 'granted';
            checkbox.checked = isChecked;

            const checkboxDiv = checkbox.previousElementSibling;
            if (checkboxDiv) {
              if (isChecked) {
                checkboxDiv.classList.add('w--redirected-checked');
              } else {
                checkboxDiv.classList.remove('w--redirected-checked');
              }
            }
          }
        });
    }
    }
  
  //Logic to uncheck all checkboxes
  function uncheckAllConsentCheckboxes() {
    ['consent-analytics', 'consent-ad-personalization', 'consent-ad-marketing', 'consent-ad-user', 'consent-personalization', 'consent-security'].forEach(checkboxId => {
        const checkbox = document.getElementById(checkboxId);
        if (checkbox) {
      checkbox.checked = false;
      
        const checkboxDiv = checkbox.previousElementSibling;
        if (checkboxDiv && checkboxDiv.classList.contains('w--redirected-checked')) {
          checkboxDiv.classList.remove('w--redirected-checked');
        }
        }   
    });
    }

  // Logic to update the preferences
  document.getElementById('cw-btn-accept-all').addEventListener('click', function() {
    setConsent({
      necessary: true,
      analytics: true,
      adpersonalized: true,
      admarketing: true,
      aduser: true,
      personalized: true,
      security: true,
    });
    hideBanner();
  });

  document.getElementById('cw-btn-accept-some').addEventListener('click', function() {
    setConsent({
      necessary: true,
      analytics: document.getElementById('consent-analytics').checked,
      adpersonalized: document.getElementById('consent-ad-personalization').checked,
      admarketing: document.getElementById('consent-ad-marketing').checked,
      aduser: document.getElementById('consent-ad-user').checked,
      personalized: document.getElementById('consent-personalization').checked,
      security: document.getElementById('consent-security').checked,
    });
    hideBanner();
  });

  document.getElementById('cw-btn-reject-all').addEventListener('click', function() {
    setConsent({
      necessary: true,
      analytics: false,
      adpersonalized: false,
      admarketing: false,
      aduser: false,
      personalized: false,
      security: false,
    });
    hideBanner();
  }); 
  
  // Map the preferences to Google Consent Mode 
  function setConsent(consent) {
    const consentMode = {
      'functionality_storage': consent.necessary ? 'granted' : 'denied',
      'ad_user_data': consent.aduser ? 'granted' : 'denied',
      'ad_storage': consent.admarketing ? 'granted' : 'denied',
      'analytics_storage': consent.analytics ? 'granted' : 'denied',
      'ad_personalization': consent.adpersonalized ? 'granted' : 'denied',
      'personalization_storage': consent.personalized ? 'granted' : 'denied',
      'security_storage': consent.security ? 'granted' : 'denied',
    };
    gtag('consent', 'update', consentMode);  
    localStorage.setItem('consentMode', JSON.stringify(consentMode));
  }
  
</script>

JS was never my strong suit, and I’ve forgotten most of what I’ve learned. I remember enough of the logic to speculate that the consentMode value isn’t being updated, otherwise the Show Cookie Banner Boolean expression wouldn’t run. I tried adding 'consentMode':true, to the logic to update the preferences, which obviously didn’t work.

Any help is hugely appreciated!