The user should see a print result of their current field map

My problem is when I execute the program and insert the instructions I don’t see that print the new value in array 2d.

print() {
        // I can prin the array, thanks design6726512087 he is in the forum of codecademy
        console.clear();
        this._fields.forEach(rows => {
            console.log(rows.join(''));
        });
    }
playGame() {
        while (!this.gameOver) {      
            this.print();      
            const promptInputUser = prompt("Instructions to move is: {u as up}, {d as down}, {l as left} & {r as right}.nWich is your path? ");
            // Call the function to move into array 
            this.instructionsToMove(promptInputUser);
        }
        console.log("Game Over");
    }

When I call the function in playGame() to print the instruction in array but throw a problem: TypeError: Cannot read properties of undefined (reading ‘forEach’).
Also I hope you can understand my english is not the better but I trying to write.

getYouTubeThumbnail function not returning the correct thumbnail URL?

I wrote a function to extract the video ID from a YouTube URL and return the corresponding thumbnail image URL. However, the function doesn’t seem to be working as expected.

const getYouTubeThumbnail = (url: string) => {
  const videoId = url.split("v=")[1];
  return https://img.youtube.com/vi/${videoId}/hqdefault.jpg;
};

When I pass a YouTube video URL like https://www.youtube.com/watch?v=-jz8mrwU_Fc&ab_channel=10Alytics, I expect to get https://img.youtube.com/vi/dQw4w9WgXcQ/hqdefault.jpg, but instead, it seems to either not work or return an incorrect URL.

What am I doing wrong? Is there a better way to extract the video ID?

the function above but it doesn’t work as intended

What is the most efficient way to manage column classes in AgGrid?

My grid has classes that are conditionally added depending on the column type of the value and I currently have a separate file just to house class rules, which looks something like this:

export const deltaClassRules = {
  'ag-right-aligned-cell col-delta col-delta-negative': params => params.value < 0,
  'ag-right-aligned-cell col-delta col-delta-positive': params => params.value > 0,
  'ag-right-aligned-cell col-delta col-readonly': params => params.value === 0 || isNaN(params.value)
}

export const readonlyClassRules = {
  'ag-right-aligned-cell col-readonly': params => params.colDef.type.includes('rightAlignedContent'),
  'col-readonly': params => !params.colDef.type.includes('rightAlignedContent')
}

As you can imagine, when I have to manage conditionals like this, it quickly becomes very messy. Say, for example, I want to be able to add a background to certain columns with the class blue-cell, but these columns can also have classes to align text to the center align-center and other classes that are generated based on their value.

So, I’m wondering what is the most efficient way to manage this?

oscilloscope style – loop getFloatTimeDomainData(timeData) in a circle

I’m doing simple audio visualisations in canvas for fun and found getFloatTimeDomainData(timeData) to deliver the nicest results, cause it is so naturally irregular. One visualisation attempt includes a horizontal wave taking timeData, fixed at both ends by a sine overlay. This works nicely; string vibrates in the middle only.

My attempt to present that same data in circular form must fail, due to the time based nature and float data. However, i’ve seen oscilloscopes do just that and my question is: how would i have to treat timeData. It looks nice as is even with the break in curve, hardly noticeable but i want to know how i could do it. Anyone an idea?

index.html:

<!DOCTYPE html>
<html lang="en" >
<head>
  <meta charset="UTF-8">
  <title>Sound in vis</title>
  <style type="text/css">
  body {background-color:#000000; color:#333333;
  overflow: hidden;} 
  
  canvas {
    background-color:#000000; 
    position: absolute;   
    display: block;
     height: 100%;
     width: 100%;
     top:0;
     left:0;
     //filter: blur(1px); 
     }
     #fps {
      color:#F3F3F3;
     }
</style>
</head>
<body>
<canvas id="myCanvas"></canvas>
<script src="ImprovedNoise.js"></script>
<script src="index_version.js"></script>
</body>
</html>
ImprovedNoise.js
// http://mrl.nyu.edu/~perlin/noise/

var ImprovedNoise = function () {

    var p = [151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,
         23,190,6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,88,237,149,56,87,
         174,20,125,136,171,168,68,175,74,165,71,134,139,48,27,166,77,146,158,231,83,111,229,122,60,211,
         133,230,220,105,92,41,55,46,245,40,244,102,143,54,65,25,63,161,1,216,80,73,209,76,132,187,208,
         89,18,169,200,196,135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226,250,124,123,5,
         202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,223,183,170,213,119,
         248,152,2,44,154,163,70,221,153,101,155,167,43,172,9,129,22,39,253,19,98,108,110,79,113,224,232,
         178,185,112,104,218,246,97,228,251,34,242,193,238,210,144,12,191,179,162,241,81,51,145,235,249,
         14,239,107,49,192,214,31,181,199,106,157,184,84,204,176,115,121,50,45,127,4,150,254,138,236,205,
         93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180];

    for (var i=0; i < 256 ; i++) {

        p[256+i] = p[i];

    }

    function fade(t) {

        return t * t * t * (t * (t * 6 - 15) + 10);

    }

    function lerp(t, a, b) {

        return a + t * (b - a);

    }

    function grad(hash, x, y, z) {

        var h = hash & 15;
        var u = h < 8 ? x : y, v = h < 4 ? y : h == 12 || h == 14 ? x : z;
        return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);

    }

    return {

        noise: function (x, y, z) {

            var floorX = ~~x, floorY = ~~y, floorZ = ~~z;

            var X = floorX & 255, Y = floorY & 255, Z = floorZ & 255;

            x -= floorX;
            y -= floorY;
            z -= floorZ;

            var xMinus1 = x -1, yMinus1 = y - 1, zMinus1 = z - 1;

            var u = fade(x), v = fade(y), w = fade(z);

            var A = p[X]+Y, AA = p[A]+Z, AB = p[A+1]+Z, B = p[X+1]+Y, BA = p[B]+Z, BB = p[B+1]+Z;

            return lerp(w, lerp(v, lerp(u, grad(p[AA], x, y, z), 
                            grad(p[BA], xMinus1, y, z)),
                        lerp(u, grad(p[AB], x, yMinus1, z),
                            grad(p[BB], xMinus1, yMinus1, z))),
                    lerp(v, lerp(u, grad(p[AA+1], x, y, zMinus1),
                            grad(p[BA+1], xMinus1, y, z-1)),
                        lerp(u, grad(p[AB+1], x, yMinus1, zMinus1),
                            grad(p[BB+1], xMinus1, yMinus1, zMinus1))));

        }
    }
}
index_version.js
const myCanvas = document.getElementById("myCanvas");
const ctx = myCanvas.getContext("2d");


var W           = myCanvas.width = window.innerWidth;
var Wcenter = W/2;
var H           = myCanvas.height = window.innerHeight;
var Hcenter = H/2;
var bpmAdd  = H/40;
var mathPI  = Math.PI;
var mathPIhalf = Math.PI/2;
var mathPI2 = Math.PI*2;
var bstate  = true; //toggle bool stop start animation
var fps, fpsInterval, startTime, now, then, elapsed;
fps = 30;
fpsInterval = 1000 / fps;

then = window.performance.now();
startTime = then;

let freqs;
let timeData;

var bumpcount=0;

function round(int){return Math.round(int);}
function map(value, istart, istop, ostart, ostop){
  return ostart + (ostop - ostart) * ((value - istart) / (istop - istart));
}
function percOfRange(value, range, maxval){
    return((value<range) ? Math.round(value*100/range)/100 : maxval);
}
function sin(e){return Math.sin(e);}
function cos(e){return Math.cos(e);}

function degrees_to_radians(degrees){  return degrees * Math.PI;}
function radians_to_degrees(radians){  return radians * 180 / Math.PI;};

function ease(p, g){
  if (p < 0.5)
    return 0.5 * Math.pow(2*p, g);
  else
    return 1 - 0.5 * Math.pow(2*(1 - p), g);} 

let elapsedAV       = [];
var elapsedMean = 0;
var noisePos = 0;
var perlin = new ImprovedNoise();

navigator.mediaDevices.enumerateDevices().then(devices => {
  devices.forEach((d, i) => console.log(d.kind, d.label, i));
  navigator.mediaDevices
    .getUserMedia({ audio: {deviceId: devices[2].deviceId}})
    .then(stream => {
      const context = new (window.AudioContext || window.webkitAudioContext)();
      const analyser = context.createAnalyser();
      analyser.maxDecibels = -2;
      analyser.smoothingTimeConstant = 0.6;

      const source = context.createMediaStreamSource(stream);
      source.connect(analyser);
      analyser.connect(context.destination);
      analyser.fftSize = 1024;

      const bufferlength = analyser.frequencyBinCount;
      freqs = new Uint8Array(bufferlength);
      const tDataLength = 128;
      //timeData = new Uint8Array(bufferlength);
      timeData = new Float32Array(bufferlength);
      var cons = 0;
      var colcount = 0;


      function countcol(inc, max){
        (colcount>max) ? colcount = 0 : colcount +=inc;
        return(colcount);
      }      
                 
      let bars                          = 11;
            let bump                            = 0;
            
      function draw(){
        
        analyser.getByteFrequencyData(freqs);
        //analyser.getByteTimeDomainData(timeData);
        analyser.getFloatTimeDomainData(timeData);
        //analyser.getByteTimeDomainData(freqs);
        const maxvalT                   = Math.max(...timeData);
            const minvalT                   = Math.min(...timeData);
            //console.log(maxvalT + ", " + minvalT);
       
        var average                 = 0;        
        var fLength                 = analyser.fftSize/2; //128,256,512,1024
        

        // Draw bars
        const deltabar              = round(fLength / bars);
        const maxval                    = Math.max(...freqs);
        const minval                    = Math.min(...freqs);
        const indexmax          = freqs.indexOf(maxval);
        const indexmin          = freqs.indexOf(minval);
        const range                 = maxval - minval;
        const rangefactor   = 360 / range * 0.1;
        const radians           = mathPI2 / bars;// * rangefactor;        
        var freqsum                 = 0;
        var freqsumAverage  = 0;
        var fcount                  = 0;
        var fval                        = 1;
        var colArr                      = [];

        for (var i=1; i<5; i++){
          fval = freqs[i];          
          fcount ++;
          freqsum+=fval;
        }
        
        freqsumAverage = round(map( freqsum / fcount,0,256,0,1)*1000)/1000;
        //console.log(freqsumAverage + ", elapsed: " + round(elapsed));

        for (var c=fcount; c<fLength;c++){
            fval = freqs[c];
          freqsum+=fval;
        }        
        let median = round(freqsum / fLength);
                average     = map(median,0,128,0,1);                
        noisePos += 0.01+(average/1000);
        var noiseVal = perlin.noise(noisePos, 0, 0)+0.5;//Math.abs()
        colcount    = round(map(noiseVal,0,1,0,360))%360;
                //console.log(colcount);

          let hue         = colcount;
          let saturation    = (freqsumAverage*30)+70;
          let lum               = (freqsumAverage*20)+30;      
          let alpha             = (freqsumAverage*0.5)+0.5;

                    colArr[0]      = "hsla(" +  hue %360 + ", " + saturation  + "% ," + lum + "%, " + (alpha) + ")";
          colArr[1]      = "hsla(" +  (hue+60 %360) + ", " + saturation  + "% ," + lum + "%, " + (alpha) + ")";
          colArr[2]      = "hsla(" +  (hue+120 %360) + ", " + saturation  + "% ," + lum + "%, " + (alpha) + ")";
          colArr[3]      = "hsla(" +  (hue+180 %360) + ", " + saturation  + "% ," + lum + "%, " + (alpha) + ")";
          colArr[4]      = "hsla(" +  (hue+240 %360) + ", " + saturation  + "% ," + lum + "%, " + (alpha) + ")";

                
        //////////////////////////////////////////////////////////////////////////
        //timedata vis - oscillo style

                //************************************************************************
            //make timedata a circle    
            
            //var cbars     = round(map(sin(now)*freqsumAverage,-1,1,0,bufferlength*freqsumAverage));
            var cbars       = bufferlength;
            let slice   = mathPI2 / cbars;
            var segm        = round(bufferlength/cbars);
                let angle   = slice;
                
                ctx.lineCap = "round";
                var Csize   = 10;

                var curveStartx,curveStarty,vstart; 
                
                ctx.strokeStyle=colArr[3];
                ctx.beginPath();
                
            for(var i = 0; i <= cbars; i++){                    

                var thistimedata = timeData[segm*i];
                    const v = map(thistimedata,-1,1,0,Csize);               
                var cx  = cos(angle)*60;
                var cy  = sin(angle)*60;
                
                var cx2 = cx*v+Wcenter;
                var cy2 = cy*v+Hcenter;

                ctx.lineWidth = v%4;                
                ctx.lineTo(cx2, cy2);
                    
                if(i==0){ curveStartx = cx2/v;curveStarty = cy2/v;vstart=v;}
                angle += slice;
                }
                ctx.lineTo(curveStartx*vstart, curveStarty*vstart);
                ctx.stroke();
                

        //************************************************************************
            //make timedata a horizontal wave - fixed at both ends

                ctx.strokeStyle = colArr[0];
            ctx.beginPath();
            var datarange = bufferlength/2;
            const sliceWidth = W / datarange;
            let x = 0;
            
            //increment to limit signal to 0 at screen borders
                var incr = mathPIhalf/(datarange/2);

                timeData.forEach((data, i) => {

                    //multiply sin of predefined increment with data so as to limit ends of array to 0
                const v = map(sin(incr*i)*data,-1,1,0,1);
                const y = v*H;
                ctx.lineWidth = v*2; 
                if (i === 0) {
                ctx.moveTo(x, y);
                } else {
            ctx.lineTo(x, y);
                }
                x += sliceWidth;
            });             
            ctx.stroke();

            //************************************************************************
            //end timedata to horizontal string
            
      }
            //////////////////////////////////////////////////////////////////////////
      ///end function draw()

      function loop(){
        if(bstate === true ){

            var clearCounter = 0;
            now = performance.now();
            elapsed = round(now - then);
            elapsedAV.push(elapsed);
            
            if( sin(now)>0.5){              
                clear();
            }

            if(elapsedAV.length > 32){              
                        elapsedAV.shift();
                        elapsedMean = round(elapsedAV.reduce((a,b) => a + b)/elapsedAV.length);                     
                        //fps = elapsedMean;
            } 
                    //console.log(elapsed + ", " + elapsedMean);

            if (elapsed >= fpsInterval) {
                
                        //fpsInterval = 1000 / fps;                     
                        bpmAdd  = H/elapsedMean;
            draw();
            then = now - (elapsed % fpsInterval);
            }
            myReq = requestAnimationFrame(loop);
        }
        
      }     
      
      function clear(){
                        ctx.globalCompositeOperation = 'destination-out';
                ctx.fillStyle = "hsla(0, 0% , 0%, 0.1)";
                ctx.fillRect(0, 0, W, H);
                ctx.globalCompositeOperation = 'lighter';               
      }

      function toggle(){
        cancelAnimationFrame(myReq);
        bstate = !bstate;
        myReq = requestAnimationFrame(loop);       
      } 

      window.addEventListener( 'resize',  function(){
            cancelAnimationFrame(myReq);
          W = myCanvas.width = window.innerWidth;
          H = myCanvas.height = window.innerHeight;
          myReq = requestAnimationFrame(loop);
      });

      window.addEventListener( 'click', toggle);
      myReq = requestAnimationFrame(loop);
   });
});

..route sound to browser via virtual cable and allow window to use ‘microphone’.

The question concerns the presented visualisation of timeData in circular form i.e. wrapped around a circle. The result can not be a closed curve as starting point and end point of timedata array don’t match.

Desired result is a closed loop representation aka oscilloscope that displays xy circle continuous. In the example the ends are just connected, which results in a horizontal line there or a visible

JS basics question (submit event handler)

i’ve just began my SWE bootcamp a few months ago and recently began learning about javascript

i was working on an assessment but kept getting this question wrong and was hoping someone would be able to explain this to me:

______________________________

There’s a form with a submit event handler. Let’s say you want to validate the form fields before submitting, but the form is submitted before you can do anything with it. Write code to stop the form from submitting. Please enter your answer without a semicolon.

<form class="form">
  <!-- ... -->
</form>

<script>
  const form = document.querySelector(".form");

  form.addEventListener("submit", function validateFields(event) {
    // code here
  });
</script>

______________________________

i entered preventDefault() but that came out to be incorrect so i’m lost to what am i missing

“HTML Header Loads via HTTP into main html file from a container html file but Fails with File Protocol ” [duplicate]

I loaded the header from container.html using following code in my main html file but it cannot load header locally with the file system (fails to load header when I run it with file://). Could you help me to update it so that it works with both file:// and http://? Thank you.

  <!-- Load Header Navigation -->
            <div id="header-container"></div>
      
      <!-- Scripts -->
        <script src="assets/js/jquery.min.js"></script>
        <script src="assets/js/jquery.dropotron.min.js"></script>
        <script src="assets/js/browser.min.js"></script>
        <script src="assets/js/breakpoints.min.js"></script>
        <script src="assets/js/util.js"></script>
        <script src="assets/js/main.js"></script>


    <!-- Script to Load Header and Initialize Dropdowns -->
    <script>
        $(document).ready(function(){
            $("#header-container").load("container.html", function() {
                // Reinitialize dropdown menus if needed
                // Example: If using dropotron for dropdowns, reinitialize it here
                $('#nav > ul').dropotron();
            });
        });
    </script>

html header loading in main html is not working locally with file://

How to Make a Baseline Bar Behind Stacked Bars in Chart.js?

I’m trying to create a stacked bar chart in Chart.js where one specific bar (labeled “予想” – prediction) acts as a baseline or background layers. The goal is for this bar to sit visually behind other stacked bars, so it acts like a “container” that the other bars cumulatively fill up to.

Or in another way to explain, is like the other bars are filling the main bar. However, I am struggling stacking the main bar behind it.

I created a codepen with the example: https://codesandbox.io/p/sandbox/vigilant-wave-wnvsxn?file=%2Fsrc%2Fcomponents%2FEnergyUsageChart.js%3A22%2C1-88%2C1

  const chartData = {
    labels: ["今日"], // Only today
    datasets: [
      {
        label: "prediction",
        data: [1200], // Only data for today
        backgroundColor: "rgba(237, 239, 255, 0.5)",
        borderColor: "rgba(106, 122, 242, 1)",
        borderWidth: 1,
        borderDash: [5, 5],
        stack: "baseline",
      },
      {
        label: "air-c",
        data: [300],
        backgroundColor: "rgba(88, 181, 247, 1)",
        stack: "filling",
      },
      {
        label: "illumination",
        data: [300],
        backgroundColor: "rgba(71, 68, 222, 1)",
        stack: "filling",
      },
      {
        label: "cooling-case",
        data: [300],
        backgroundColor: "rgba(157, 201, 210, 1)",
        stack: "filling",
      },
      {
        label: "others",
        data: [100],
        backgroundColor: "rgba(182, 193, 200, 1)",
        stack: "filling",
      },
    ],
  };

  const options = {
    responsive: true,
    maintainAspectRatio: false,
    scales: {
      x: { stacked: true },
      y: {
        stacked: true,
        max: 2000,
        ticks: { stepSize: 1000 },
      },
    },
    plugins: {
      legend: { display: false },
      datalabels: { display: false },
      tooltip: {
        callbacks: {
          label: (context) => {
            const label = context.dataset.label || "";
            return `${label}: ${new Intl.NumberFormat("ja-JP", {
              style: "currency",
              currency: "JPY",
            }).format(context.parsed.y)}`;
          },
        },
      },
    },
  };

Thanks!

How to open/utilize Elementor Pro’s built-in lightbox using javascript

In it’s most bare bones form, I’m trying to add some javascript to my WordPress site (created with Elementor Pro) that will open a link as an iframe in Elementor’s built-in lightbox. I don’t need to modify any existing widgets nor do I need to build my own. I just need to attach a click event listener to a specific element that will run the code necessary to open a specified URL in an Elementor lightbox with specified properties.

I know there are codeless ways to have a link open a lightbox and I’m also aware that it can be done by adding certain markup to the element. For this circumstance, let’s just just move forward without either of those being options. As such, I believe I am left with trying to hook into Elementor’s frontend and do it from there.

So far I have:

jQuery(window).on('elementor/frontend/init', () => {
  document.addEventListener('click', function (e) {
    if (e.target.closest('#do-lightbox')) {
      const url = 'https://www.google.com';
      openLightbox(url);
    }
  });

  const openLightbox = url => {
    elementorFrontend.utils.lightbox.showModal({
      type: 'iframe',
      url: url,
      modalOptions: {
        id: 'elementor-lightbox-' + Date.now(),
        entranceAnimation: 'zoomIn',
        exitAnimation: 'zoomOut',
        closeButton: true,
      },
    });
});

This script is enqueued after all Elementor’s frotnend scripts using the elementor/frontend/after_enqueue_scripts hook.

Clicking the element produces the following error:

partner-logos-lightbox.js?ver=1731539592:28 Uncaught TypeError: elementorFrontend.utils.lightbox.showModal is not a function

Typing elementorFrontend.utils.lightbox in the console indicates that it is a fulfilled Promise, and as such does not have a showModal method available. So I guess the error makes sense. i’m just not sure how else to access the lightbox.

Any guidance would be greatly appreciated.

How to set protections on sheet sections both on startup and on cell after user edit

So I am trying to set up a google sheet that dozens of users are going to use and I want to automate the protection schemes since a new sheet is being made everyday. I’m trying to have sheet headers and certain columns protected from all users (besides explicit exceptions) and when an edit is made to a cell, edit permissions for all users are removed. I’ve tried attempting removing permissions both using the onOpen and onEdit functions via setUnprotectedRanges() and the regular range.protect() like in the documentation. But every time I try the onOpen, it breaks the other. I don’t know how to keep setting these because permissions need to be removed for as many users possible (besides editor and owner). Here’s what I have for the cell protection removal after edit that does work:

function onEdit(e) {
  var sheet = e.source.getActiveSheet();
  var editedCell = e.range;
  if (editedCell.getColumn() == 4 && editedCell.getRow() > 1) {
    var link = editedCell.getValue();
    
    // If a link is pasted (non-empty cell)
    if (link != "") {
      var row = editedCell.getRow();
      var currentTime = new Date(); // Get current date and time
      
      // Set the timestamp in column F
      sheet.getRange(row, 6).setValue(currentTime);
      
      // Set the formula in column G to calculate elapsed time
      var elapsedTimeFormula = '=IF(F' + row + '<>"", NOW() - F' + row + ', "")';
      sheet.getRange(row, 7).setFormula(elapsedTimeFormula);

      // Protect the specific cell in column D where the link was pasted
      var cellToProtect = sheet.getRange(row, 4);
      var protection = cellToProtect.protect().setDescription('Cell Locked After Link Added');
      //var me = Session.getEffectiveUser();
      protection.removeEditors(protection.getEditors());
      //if (protection.canDomainEdit()) {
        protection.setDomainEdit(false);
      //}
    }
  }
}

As for protecting certain columns and rows onOpen(), version history failed me there but it was along the lines of:

function onOpen(e) {
  var sheet = e.source.getActiveSheet();
  var protection = sheet.protect().setDescription('Default Protected Headers and Columns');
  var unprotectedLeftOfColumns = sheet.getRange('A2:H1000');
  var unprotectedRightOfColumns = sheet.getRange('J2:N1000');
  protection.setUnprotectedRanges([unprotected]);

  // Ensure the current user is an editor before removing others. Otherwise, if the user's edit
  // permission comes from a group, the script throws an exception upon removing the group.
  //var me = Session.getEffectiveUser(); [Doesn't work for some reason for two users on same computer]
  //protection.addEditor(me);
  protection.removeEditors(protection.getEditors());
  //if (protection.canDomainEdit()) {
    protection.setDomainEdit(false);
  //}

Using these methods I keep getting errors but I can’t find the documentation for them so its really hard trying to debug this. At this point it’s easier to but the header and column protections when copying the sheet, but I’m not the one doing it so I can’t be sure it’s done. The protection app script documentation is starting to look bleak, I wouldn’t even be sure about the other methods like removeEditor() since it’s a large sheet shared by link and speed is key. Any help would be highly appreciated because I can’t find much about any of these issues.

Leaky abstraction with setters and getters in js/ts

I am working on a game. Because I don’t want to marry frameworks, I wrote an abstraction for the graphics engine and am now trying to shoehorn three.js into it.

I am working with gl-matrix for vector math (using vec3, typed arrays), three.js has its own vector classes (using {x:number, y:number, z:number}). My interface for a 3d object looks as follows:

interface Thing{
    ...
    position:vec3
}

and my implementation looks like this:

class ThreeJsThing implements Thing{
    ...
    set position(p:vec3){
        this.mesh.position.set(p[0], p[1], p[2]) // [,,] -> {xyz}
    }
    get position(){
        let p = this.mesh.position
        return vec3.fromValues(p.x, p.y, p.z) // {xyz} -> [,,]
    }
}

Now it’s all fun and games until someone tries to do:

let myThing = new ThreeJsThing()
myThing.position[1] = 5 // only changes a temporary copy that is returned by the getter

And with gl-matrix this is especially a problem because it uses output parameters for performance reasons, internally doing that array assignment above:

vec3.add(myThing.position, a, b)

I know how to work around this problem because I am (now) aware of it, but other contributors are probably also going to choke on this, especially since it fails silently. Just from a clean code point of view, I can’t really pinpoint where I used anti-patterns or bad design or something. I find ThreeJsThing to be as faithful to the interface as possible. I have some suspicions:

  • maybe this is just a general problem with set and get and they should be avoided?
  • maybe set and get should not do copies and only accept/return and internally work with references of the same type?
  • output parameters are frowned upon (but then myThing.position[1] = 5 is still a problem)

Any advice appreciated.

Chrome displays the message “Unable to start camera” in a video conference through the Metered.ca iframe

I have developed a web application in C#/HTML/JS and I am using the embedded iframe feature from Metered Video SDK (metered.ca). The meeting is taking place with only 2 participants. Both are joining the meeting by accessing it through my web application.

The following error is occurring: when a participant accesses the website on my system through an Android device, the message “Unable to start camera” is displayed when entering the meeting. Those who are participating in the meeting through Windows have the image displayed normally. I have already tried to release several security features on Android and Chrome to try to solve it, without success.

What could be the problem? And how can I solve it?

Thanks in advance.

Javascript Snippet needs multiple runs to fill all answers (Forms office)

I have a form from Microsoft (forms.office.com) and I get repetitive questions that I am trying to automate/fill the answers with a Chrome snippet.

It is quite dynamic. For instance, the first question is a radio button and the second question only appears if I select “None of the above”.

My code often fails especially when the input texts need to be filled. I focused on keywords rather than the full question because the HTML is more complex (e.g. it might contain spaces or parts). Some questions have the same keywords. The snipped finally worked but I noticed that I had to run it multiple times so that every question got answered.

        // Array with keywords and answers
    const questionsAndAnswers = [
        { questionKeyword: "first", answerText: "None of the above" },
        { questionKeyword: "second", answerText: "222222" },
        { questionKeyword: "third?", answerText: "333333" },
        { questionKeyword: "fourth", answerText: "444444" },
        { questionKeyword: "fifth", answerText: "Yes" },
        { questionKeyword: "second", answerText: "222222" },
        { questionKeyword: "third?", answerText: "333333" },
        { questionKeyword: "fourth", answerText: "444444" },
        { questionKeyword: "fifth", answerText: "Yes" }
    ];
    
// Function to normalize question text by removing HTML entities and unnecessary spaces
function normalizeText(text) {
    // Replace non-breaking spaces with regular spaces
    text = text.replace(/&nbsp;/g, ' ');

    // Remove any other HTML entities like &lt;, &gt;, &amp;, etc.
    text = text.replace(/&[a-zA-Z0-9#]+;/g, '');

    // Remove any leading/trailing spaces or extra spaces
    text = text.replace(/s+/g, ' ').trim();

    // Return the cleaned text
    return text;
}

// Function to locate and set the answer based on the question keyword(s)
function setAnswerByKeyword(questionKeywords, answerText) {
    // Get all question containers
    const questionContainers = document.querySelectorAll('div[data-automation-id="questionItem"]');

    for (const container of questionContainers) {
        // Get the question text content and normalize it
        const questionTextContent = normalizeText(container.textContent.toLowerCase());

        // Check if the question text includes any of the keywords
        for (let keyword of questionKeywords) {
            if (new RegExp(keyword, "i").test(questionTextContent)) {
                console.log(`Question matched for keyword "${keyword}" in "${questionTextContent}"`);

                // 1. Try to find a matching radio button
                const radioButton = Array.from(container.querySelectorAll('input[type="radio"]')).find(
                    radio => radio.value.toLowerCase() === answerText.toLowerCase()
                );
                if (radioButton) {
                    radioButton.checked = true;
                    radioButton.dispatchEvent(new Event('change', { bubbles: true }));
                    console.log(`Set radio button for "${keyword}" to "${answerText}".`);
                    return;
                }

                // 2. Try to find a text input with `data-automation-id="textInput"` or `type="text"`
                const textInput = container.querySelector('input[type="text"][data-automation-id="textInput"], input[data-automation-id="textInput"]');
                
                if (textInput) {
                    // Adding a delay to ensure the input field is fully ready to accept text
                    setTimeout(() => {
                        textInput.focus();
                        textInput.value = answerText;

                        // Dispatch the necessary events to simulate user interaction
                        textInput.dispatchEvent(new Event('input', { bubbles: true }));
                        textInput.dispatchEvent(new Event('change', { bubbles: true }));
                        
                        console.log(`Set text input for "${keyword}" to "${answerText}".`);
                    }, 500); // Add delay to ensure input fields are ready
                    return;
                }

                // 3. If no input field was found, log a warning
                console.warn(`Input field for "${keyword}" not found in "${questionTextContent}".`);
                return;
            }
        }
    }
    console.warn(`Question containing "${questionKeywords.join(", ")}" not found!`);
}

// Main function to iterate through each question and set the answer
function fillForm() {
    questionsAndAnswers.forEach(qa => setAnswerByKeyword([qa.questionKeyword], qa.answerText));
}

// Run the form-filling function with a slight delay to handle dynamic loading
setTimeout(fillForm, 1000);

Those forms are not as easy as Google forms where my snippets work perfectly. What can I change to fill all the answers without multiple snippet runs?

React using createSelector with dynamic arguments

I created selectors to get a list of users like so:

const selectGroup = (state) => state.group;

const selectGroupUsers = createSelector(
  [selectGroup],
  (group) => group.get('users').toJS()
)

I use it as follows:

const users = useSelector(selectGroupUsers);

These work fine.

Now I am trying to get specific user info using a dynamic path:

const selectUser = createSelector(
  [selectGroup, (_, path)],
  (group, path) => group.getIn(path).toJS()
)

I use this as follows:

const path = ['users', 5, 'data'] // this is a dynamic array value from props

const userData = useSelector(state => selectUser(state, path));

This works, however I get many redux warnings:

Selector unknown returned a different result when called with the same
parameters. This can lead to unnecessary rerenders.

How do I resolve this?

how to make it clean to feed a React template from a local text heavy .json file?

I’m doing an SPA right now and the all thing works well so far. To get different text content and pictures according the view, based on the url path, i pull the data from a .json file, local to the SPA, mean by that i don’t call any API to get data from.

Here’s the structure of that component/layout where i do this templating.
Legal is made of/import HeaderLegal + contentLegal
I call the data into Legal and pass them as props to the 2 other components.

Here’s the code:

// data.json

{  "legals": [
    {
      "id": "pp",
      "title": "Privacy policy",
      "update": "last update: 10/05/2024",
      "section1Ttitle": "Lorem ipsum dolor sit amet, consectetur adipiscing elit",
      "section1Text1": "Lorem ipsum dolor sit amet, consectetur adipiscing elit",
      "section1List": [
        "Lorem ipsum dolor sit amet, consectetur adipiscing elit",
        "Lorem ipsum dolor sit amet, consectetur adipiscing elit",
        "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
      ],
      "section2Ttitle": "Information you choose to give us",
      "section2Text1": "When you use hiko, here are the types of information you chose to give us:",
      "section2List": [
        "Lorem ipsum dolor sit amet, consectetur adipiscing elit",
        "Lorem ipsum dolor sit amet, consectetur adipiscing elit",
        "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
"Lorem ipsum dolor sit amet, consectetur adipiscing elit",
        "Lorem ipsum dolor sit amet, consectetur adipiscing elit",
      ]
    }
}

// Legal component

import HeaderLegal from "../layouts/HeaderLegal";
import ContentLegal from "../layouts/ContentLegal";

const Legal = () => {
  const { id } = useParams();

  const dataLegal = data.legals.find((legal) => legal.id === id);
  return (
    <div>
      <NavLegals />
      <HeaderLegal title={dataLegal.title} text={dataLegal.update} />
      <ContentLegal
        section_1_title={dataLegal.section1Ttitle}
        section_1_text_1={dataLegal.section1Text1}
        section_1_text_2={dataLegal.section1Text2}
        section_1_list={dataLegal.section1List}
        section_2_title={dataLegal.section2Ttitle}
        section_2_text_1={dataLegal.section2Text1}
        section_2_text_2={dataLegal.section2Text2}
        section_2_list={dataLegal.section2List}
      />
    </div>
  );
};

///
// ContentLegal component (that receives the data as props from Legal)

const ContentLegal = ({
  section_1_title,
  section_1_text_1,
  section_1_text_2,
  section_1_list,
  section_2_title,
  section_2_text_1,
  section_2_text_2,
  section_2_list,
}) => {
  return (
    <div>
      <section>
        <h2>{section_1_title}</h2>
        <p>{section_1_text_1}</p>
        <ul>
          {section_1_list &&
            section_1_list.map((element, index) => {
              return <li key={index}>{element}</li>;
            })}
        </ul>
        <p>{section_1_text_2}</p>
      </section>
      <section>
        <h2>{section_2_title}</h2>
        <p>{section_2_text_1}</p>
        <ul>
          {section_2_list &&
            section_2_list.map((element, index) => {
              return <li key={index}>{element}</li>;
            })}
        </ul>
        <p>{section_2_text_2}</p>
      </section>
    </div>
  );
};

It works but as you can see the list of props passed to ContentLegal is long and will increase using this approach and i think i can do better maybe having each section texts from legals array from data.json as object and looping through, but don’t see how to implement such thing nor see another alternative. It’s kind of dirty like it is right now. Could be definitely better.

Any help and suggestion are welcome.

Node-Gyp keeps giving error exit code 1 when trying to use with Electron and robotjs on a Mac

I’ve literally tried everything to get robotjs to work with Electron JS. I’ve reinstalled Xcode, set up Python 3, changed node versions and rebuilt gyp to no avail. I’m trying to capture mouse events outside the Electron app. I’ve also tried iohook and creating my own C++ addon as ChatGPT suggested. A little bit of help would definitely be appreciated. These are the errors I’m getting:

gyp ERR! stack Error: `make` failed with exit code: 1
gyp ERR! stack at ChildProcess.<anonymous> (/Users/***/.nvm/versions/node/v23.2.0/lib/node_modules/node-gyp/lib/build.js:216:23)
gyp ERR! System Darwin 20.3.0
gyp ERR! command "/Users/***/.nvm/versions/node/v23.2.0/bin/node" "/Users/***/.nvm/versions/node/v23.2.0/bin/node-gyp" "build"
gyp ERR! cwd /Users/***/Apps/***-***-desktop/
gyp ERR! node -v v23.2.0
gyp ERR! node-gyp -v v10.2.0
gyp ERR! not ok ```