How to use generic types in JSDoc to represent an instance of a (class) type

I am fairly sure this is not possible, but figured someone out there may know more.

I have a simple object factory in JavaScript that I’m using to minimize heap allocs of the same service objects. Something like this:

/**
 * @param {class} cls 
 */
getService(cls) {
  let service = this._services.get(cls); // this._services is a Map
  if(!service) {
    service = Reflect.construct(cls);
    this._services.set(cls, service);
  }
  return service;
}

This is then called with something like

const service = ServiceFactory.getInstance().getService(SomeServiceType)

I’m trying to figure out the JSDoc to accurately represent the type of the return object.

In the above example, the service constant will be an instance of SomeServiceType, but I can’t quite figure out the correct JSDoc annotations (if it’s even possible)

I’ve tried all kinds of permutations of using @template, but I think there’s some syntax missing from JS, or JSDoc, to allow for this (the lack of a Class type perhaps)

For example, this does not work, but is of the ilk I’m looking for:

/**
 * @template T
 * @param {class<T>} cls 
 * @returns {T}
 */
getService(cls) {
  let service = this._services.get(cls);
  if(!service) {
    service = Reflect.construct(cls);
    this._services.set(cls, service);
  }
  return service;
}

Anyone else trying to make javascript do unnatural things? 😉

How to efficiently toggle components using Mithril.js

I have a list of some data. I want to display and edit that data.
My Home component iterates over this data and display using Item component it Each row has data and edit button. After clicking on edit it displays the EditItem component which is used to edit data.

It is working fine. But I think it renders whole Home component when I edit item. Is there any better way to do it?

// Item component
var Item = {
    view: function(vnode) {
        return m("tr", [
            m("td", vnode.attrs.id),
            m("td", vnode.attrs.text),
            m("td", m("button", {onclick: function() {
                vnode.attrs.edit(vnode.attrs.index);
            }}, "Edit"))
        ]);
    }
}

// EditItem component
function EditItem(vnode) {
    var value =  vnode.attrs.text // save value of text
    return {view: function(vnode) {
        return m("tr", [
            m("td", vnode.attrs.id),
            m("td", m("input", {value: value, oninput: (e)=> {                value = e.target.value
            }})),
            m("td", m("button", {onclick: function() {
                vnode.attrs.save(value);
            }}, "Save"))
        ]);
    }}
}

// Home component
var Home = {
    view: function() {
        return m("div", [
            m("table", {border: 1}, [
                m("thead", [
                    m("tr", [
                        m("th", "ID"),
                        m("th", "Text"),
                        m("th", "Actions")
                    ])
                ]),
                m("tbody", [
                    this.data.map((row, index) => {
                        if (this.editingIndex === index) {
                            return m(EditItem, {
                                id: row.id,
                                text: row.text,
                                index: index,
                                save: function(value) {
                                    Home.editingIndex = null;
                                    row.text = value;
                                }
                            });
                        } else {
                            return m(Item, {
                                id: row.id,
                                text: row.text,
                                index: index,
                                edit: function(index) {
                                    Home.editingIndex = index;
                                }
                            });
                        }
                    })
                ])
            ])
        ]);
    },
    data: [
        {id: 10, text: "Item 1"},
        {id: 20, text: "Item 2"},
        {id: 30, text: "Item 3"}
    ],
    editingIndex: null
};

// Mount Home component
m.mount(document.body, Home);
<!DOCTYPE HTML>
<html>
    <head>
        <title>Learning Mithril.js</title>
    </head>
    <body>
    <script src="https://unpkg.com/mithril/mithril.min.js"></script>
    </body>
</html>

Thanks!

Javascript failing to add `text` to the `option`

Why is this javascript failing to add text to the option?

I can manually put <ul><option>one</option></ul>. That works.

It is only the JS failing to add text in between.

This must be as <option>one</option>.

Other attributes are assigned ok.

const listbox = document.getElementById('list');
data = ['one','two','three']
data.forEach((obj) => {
                const option = document.createElement('option');
                option.text = obj;
                option.textContent = obj;
                console.log(option.textContent);
                console.log(option.text);
                option.value = obj;
                option.label = obj;
                option.textContent = obj.display;
                listbox.appendChild(option);
            });
<ul id="list">
  
  
</ul>

Text of Option is not visible.

enter image description here

I cant find the problem with my Livescore website api?

I am struggling to find this problem, I have a problem where I get this error message: “TypeError: Cannot read properties of undefined (reading ‘fixture’)”. It happens when i try to declare the variable ‘fixture’. I had problems before following the code myself. I decided to get the source code from the video to see how it was working and understand why mine isn’t, but the problem is still there for the source code from the video. I have attached the source code if that will help to find the problem.

I’m not sure how to fix this problem as the YouTube video I am following has not encountered this problem as well and there is no answer in the comments. It would be appreciated if someone could help or fix the problem with me, or help me to understand.

//getting the DOM elements
var elapsedTime = document.querySelector("#elapsed");
var homeTeamImage = document.querySelector("#homeLogo");
var homeTeamName = document.querySelector("#homeName");
var awayTeamImage = document.querySelector("#awayLogo");
var awayTeamName = document.querySelector("#awayName");
var lastMatchGoal = document.querySelector("#goals");
var matchTable = document.querySelector("#matchTable");


//the functions to create an element
function addMatchTile(data){
    //createing the tile div
    var matchtile = document.createElement('div');
    matchtile.classList.add("match-tile");

    //creating the home match box
    var homeTeam = document.createElement('div');
    homeTeam.classList.add("team");
    //creating the image and the text
    var homeTileTeamName = document.createElement('p');
    homeTileTeamName.innerHTML = data['teams']['home']['name'];
    var homeTileTeamLogo = document.createElement('img');
    homeTileTeamLogo.src=data['teams']['home']['logo'];
    homeTeam.appendChild(homeTileTeamLogo);
    homeTeam.appendChild(homeTileTeamName);

    var awayTeam = document.createElement('div');
    awayTeam.classList.add("team");
    //creating the image and the text
    var awayTileTeamName = document.createElement('p');
    awayTileTeamName.innerHTML = data['teams']['away']['name'];
    var awayTileTeamLogo = document.createElement('img');

    awayTileTeamLogo.src=data['teams']['away']['logo'];
    awayTeam.appendChild(awayTileTeamLogo);
    awayTeam.appendChild(awayTileTeamName);

    //createing the score
    var score = document.createElement('p');
    score.innerHTML = data['goals']['home'] + " - " + data['goals']['away'];

    //append all the element to the parent
    matchtile.appendChild(homeTeam);
    matchtile.appendChild(score);
    matchtile.appendChild(awayTeam);

    matchTable.appendChild(matchtile);
}
//fetching the data
fetch("https://v3.football.api-sports.io/fixtures?live=all", {
    "method": "GET",
    "headers": {
        "x-rapidapi-host": "v3.football.api-sports.io",
        "x-rapidapi-key": "3c6eed4924msh5abf596bfc6c0ecp129bfdjsn26e848ba87cc"
    }
})
.then(response => response.json().then(data => {
    var matchesList = data['response'];
    var fixture = matchesList[0]['fixture'];
    
    var goals = matchesList[0]['goals'];
    var teams = matchesList[0]['teams'];
    console.log(matchesList.length);
   //Now let's set our first match
   elapsedTime.innerHTML = fixture['status']['elapsed'] + "'";
   homeTeamImage.src = teams['home']['logo'];
   homeTeamName.innerHTML = teams['home']['name'];
   awayTeamImage.src = teams['away']['logo'];
   awayTeamName.innerHTML = teams['away']['name'];
   lastMatchGoal.innerHTML = goals['home']+ " - " + goals['away'];

   for(var i = 1; i<matchesList.length;i++){
       addMatchTile(matchesList[i]);
   }

}))
.catch(err => {
    console.log(err);
});
@import url('https://fonts.googleapis.com/css2?family=Roboto');

*{
    margin: 0;
    padding: 0;
    outline: 0;
    font-family: 'Roboto', sans-serif;
    text-align: center;
}

body{
    height: 100vh;
    background-image: url(https://mrwallpaper.com/images/hd/uefa-champions-league-star-sky-design-4naonnwbj0ncjr50.jpg);
    background-size: cover;
    background-repeat: no-repeat;
    background-position: center;
}

.container{
    position: absolute;
    padding: 16px;
    top: 50%;
    left: 50%;
    transform: translate(-50%,-50%);
    width: 50%;
    background-color:#FAFAFA;
    text-align: center;
    border-radius: 4px;
    text-transform: uppercase;
    text-align: center;
}

.title-box{
    margin: 25px 0;
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    justify-content: space-around;
    align-items: center;
    width: 100%;
    font-size: 1.5em;
   
    
}
.title-box #goals{
    font-size: 1.8em;
}
.team{
    width: 100px;
}
.team img{
    height: 54px;
    width: 54px;
}
.matches-table{
    margin-top: 50px;
    display: flex;
    flex-direction: column;
}
.match-tile{
    position: relative;
    left: 50%;
    transform: translateX(-50%);
    margin: 10px 0;
    display: flex;
    flex-direction: row;
    justify-content: space-around;
    align-items: center;
    
}
.match-tile img{
    width: 52px;
    height: 52px;
}
.match-tile p{
    font-size: 1.2rem;
}

.match-tile #goals{
    font-size: 1.8rem;
}
.match-tile .team{
    width: 100px;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <title>Document</title>
</head>
<body>
    <div class="container">
        <h1>Scoreboard</h1>

        <div class="title-box">
            <p>Local Team</p>
            <p id="elapsed"> 45'</p>
            <p>Visitor Team</p>
        </div>
        <div class="title-box">
            <div class="team">
                <img id="homoLogo">
                <p id="homeName">Team Name</p>
            </div>
            <p id="goals">3 - 1</p>
            <div class="team">
                <img id="awayLogo">
                <p id="homeName">Team Name</p>
            </div>
        </div>
        <hr>
        <div id="matchTable" class="matches-table">
        </div>
    </div>
    <script src="script.js"></script>
</body>
</html>

Why does the async loop `File.stream().getReader().read()` may block main thread?

<input type="file" id="el">
<code id="out"></code>
const el = document.getElementById('el');
const out = document.getElementById('out');
el.addEventListener('change', async () => {
  const file = el.files?.[0];
  if (file) {
    const reader = file.stream().getReader();
    out.innerText = JSON.stringify({ fileSize: file.size });
    let received = 0;
    while (true) {
      const chunk = await reader.read();
      if (chunk.done) break;

      // chunk.value.forEach((it) => it + 1);

      received += chunk.value.byteLength;
      out.innerText = JSON.stringify({
        fileSize: file.size,
        process: `${received} / ${file.size} (${((received / file.size) * 100).toFixed(2)}%)`,
      });
    }
  }
});

The code above works well, <code> will show progress in real-time.
But if I add the line chunk.value.forEach((it) => it + 1);, the main thread seems to be blocked, the page stops responding until the file processing is completed. (Test in Edge 125)

I can use requestAnimationFrame to fix it.
But why does it happen, is there a better way than requestAnimationFrame?

NextJS state array is empty when accessed inside of functions but rendering items in the DOM

I have a state variable in my react app that stores an array of objects which are sent from a flask server then rendered in a list on the page. Inside one of my functions I need to access this array but whenever I try to use this value I get an empty list even though I can see the values in the array being rendered on the page.

This is the function that is attempting to access the events state array but the line
let newEvent = { ...events[0] }; is initializing newEvent to {}.

  const addEvent = (action_event: any) => {
    const transformedEvent = {
      ...JSON.parse(action_event),
      camera: "Face",
    };

    if (parseInt(transformedEvent.cont)) {
      let newEvent = { ...events[0] };
      newEvent.frameEnd = transformedEvent.frameEnd;
      setEvents((events) => [newEvent].concat(events.slice(1)));
    } else {
      delete transformedEvent.cont;
      setEvents((events) => [transformedEvent].concat(events));
    }
  };

For some context if (parseInt(transformedEvent.cont)) will never be true before the else block is called so events should always have at least one element

I’m rendering the array with the following code:

          {events.map((event, index) => (
            <Box key={index} className={styles.liveClasBox}>
              <Typography
                textAlign={"center"}
                width={150}
                textTransform={"capitalize"}
              >
                {event.label.replaceAll("_", " ")}
              </Typography>
              <Divider orientation="vertical" flexItem />
              <Typography
                textAlign={"center"}
                width={150}
              >{`From: Frame #${event.frameStart}`}</Typography>
              <Divider orientation="vertical" flexItem />
              <Typography
                textAlign={"center"}
                width={150}
              >{`To: Frame #${event.frameEnd}`}</Typography>
            </Box>
          ))}

I’ve tried accessing the events array in different functions but its always empty with a length of 0. I read a post about a similar issue and that issue was caused by mutating the state array without using the update function (setEvents) but I don’t believe I’m doing that anywhere. I’ve included the full code file below in case I’m missing something

"use client";
import React, { useState, useEffect, act } from "react";
import { Box, Typography, Divider } from "@mui/material";
import styles from "./page.module.css";
import { LiveFrame, Event } from "./types";

export default function Demo() {
  const [livePredictStream, setLivePredictStream] = useState<LiveFrame[]>([]);

  const [events, setEvents] = useState<Event[]>([]);

  const [frame, setFrame] = useState(null);

  useEffect(() => {
    const eventSource = new EventSource(`http://127.0.0.1:5000/video_feed`);
    eventSource.onmessage = (event) => {
      const data = JSON.parse(event.data);
      if (data.action_event != 0) {
        addEvent(data.action_event.replaceAll("'", '"'));
        setFrame(data.image);
      }
      addLivePredictions(data.actions_predictions, data.first_frame_num);
    };
    return () => {
      eventSource.close();
    };
  }, []);

  const addEvent = (action_event: any) => {
    const transformedEvent = {
      ...JSON.parse(action_event),
      camera: "Face",
    };

    if (parseInt(transformedEvent.cont)) {
      let newEvent = { ...events[0] };
      newEvent.frameEnd = transformedEvent.frameEnd;
      setEvents((events) => [newEvent].concat(events.slice(1)));
    } else {
      delete transformedEvent.cont;
      setEvents((events) => [transformedEvent].concat(events));
    }
  };

  const addLivePredictions = (predictions: string[], startingFrame: string) => {
    const transformPredictions: LiveFrame[] = predictions.map(
      (prediction, index) => ({
        value: prediction,
        frameNum: parseInt(startingFrame) + index,
        camera: "Face",
      })
    );
    transformPredictions.reverse();

    setLivePredictStream((livePredictStream) =>
      [...transformPredictions].concat(livePredictStream)
    );
  };

  const removeLivePredictions = () => {
    let tempArr = livePredictStream.slice(0, 30);
    setLivePredictStream(tempArr);
  };

  useEffect(() => {
    if (livePredictStream.length > 150) {
      removeLivePredictions();
    }
  }, [livePredictStream]);

  const videoSource = frame
    ? URL.createObjectURL(new Blob([frame], { type: "image/jpeg" }))
    : "";

  return (
    <Box className={styles.pageContainer}>
      <Box className={styles.cameraContainer}>
        <Box>
          <Typography variant="h6" textAlign="center">
            Face Cam
          </Typography>
          <Box className={styles.cameraWrapper}>
            <video
              src={videoSource}
              className={styles.video}
              autoPlay
              width={300}
              height={300}
            />
          </Box>
        </Box>
        {/* <Box>
          <Typography variant="h6" textAlign="center">
            Body Cam
          </Typography>
          <Box className={styles.cameraWrapper}>BODY</Box>
        </Box> */}
      </Box>
      <Box className={styles.listContainer}>
        <Box className={styles.liveClasContainer}>
          <Typography variant="h5" textAlign={"center"} fontWeight={500}>
            Event Feed
          </Typography>
          {events.map((event, index) => (
            <Box key={index} className={styles.liveClasBox}>
              <Typography
                textAlign={"center"}
                width={150}
                textTransform={"capitalize"}
              >
                {event.label.replaceAll("_", " ")}
              </Typography>
              <Divider orientation="vertical" flexItem />
              <Typography
                textAlign={"center"}
                width={150}
              >{`From: Frame #${event.frameStart}`}</Typography>
              <Divider orientation="vertical" flexItem />
              <Typography
                textAlign={"center"}
                width={150}
              >{`To: Frame #${event.frameEnd}`}</Typography>
            </Box>
          ))}
        </Box>
        <Box className={styles.liveClasContainer}>
          <Typography variant="h5" textAlign={"center"} fontWeight={500}>
            Live Frame Classification
          </Typography>
          {livePredictStream.map((prediction, index) => (
            <Box key={index} className={styles.liveClasBox}>
              <Typography
                textAlign={"center"}
                width={150}
              >{`Frame #${prediction.frameNum}`}</Typography>
              <Divider orientation="vertical" flexItem />
              <Typography textAlign={"center"} width={150}>
                {prediction.value}
              </Typography>
            </Box>
          ))}
        </Box>
      </Box>
    </Box>
  );
}

why is my multiple IF statement not working as it should be? [closed]

“When I execute the code, it returns the previous value and will not register the next If statement in the flow (picture attached is just part of the flow. It’s pretty much a repeat of actions and the error happens on the last IF statement (it keeps taking the prior output). I have been trying to figure it out all day and not sure what the issue is.
function Logictest22() {

var No = Xrm.Page.getAttribute("ecaat_contractactioncompete").getValue() != 1;
var notUnauthorized = Xrm.Page.getAttribute("ecaat_procurementtype").getValue() != 987760002;
var Unauthorized = Xrm.Page.getAttribute("ecaat_procurementtype").getValue() == 987760002;
var SoleSource = Xrm.Page.getAttribute("ecaat_procurementtype").getValue() == 987760000;
var Emergency = Xrm.Page.getAttribute("ecaat_procurementtype").getValue() == 987760001;
var blanket = Xrm.Page.getAttribute("ecaat_procurementtype").getValue() == 987760003;
var Supplemental = Xrm.Page.getAttribute("ecaat_procurementtype").getValue() == 987760004;
var valueone = Xrm.Page.getAttribute("ecaat_contractactionamount").getValue() <= 25000;
var valuetwo = Xrm.Page.getAttribute("ecaat_contractactionamount").getValue() > 25000 <= 100000;
var valuethree = Xrm.Page.getAttribute("ecaat_contractactionamount").getValue() >100000 <=500000;
var valuefour = Xrm.Page.getAttribute("ecaat_contractactionamount").getValue() > 500000 <= 402563256232656;

if (No && valueone && SoleSource || No && valueone && Emergency || No && valueone && blanket || No && valueone && Supplemental) {
    Xrm.Page.ui.tabs.get("Contract Information").setVisible(true);
    Xrm.Page.ui.tabs.get("Documents").setVisible(true);
    Xrm.Page.ui.tabs.get("General").setVisible(false);
    Xrm.Page.ui.tabs.get("Contract Actions").setVisible(false);
    Xrm.Page.ui.tabs.get("Non Compete").setVisible(false);
    Xrm.Page.ui.tabs.get("Bidders").setVisible(false);
    Xrm.Page.ui.tabs.get("Approvals").setVisible(true);
}

else if (No && valuetwo && SoleSource || No && valuetwo && Emergency || No && valuetwo && blanket || No && valuetwo && Supplemental ) 
{
    Xrm.Page.ui.tabs.get("Contract Information").setVisible(true);
    Xrm.Page.ui.tabs.get("Documents").setVisible(true);
    Xrm.Page.ui.tabs.get("General").setVisible(false);
    Xrm.Page.ui.tabs.get("Contract Actions").setVisible(false);
    Xrm.Page.ui.tabs.get("Non Compete").setVisible(true);
    Xrm.Page.ui.tabs.get("Bidders").setVisible(false);
    Xrm.Page.ui.tabs.get("Approvals").setVisible(true);
}

P5js won’t allow me to go in 4 directions with my object

I am having trouble implementing 4 direction movement.

I tried to do booleans to determine if you are going left or right, because of this line.
I have been trying for so long to figure out how to do this.

if (player1Move.x > 0){
    player1Move.x
}

here is the project

function setup() {
  textAlign(CENTER);
  createCanvas(displayWidth, displayHeight);
  player1Pos = createVector(width/4,height/3.33,150)
  player1Move = createVector(0,0) //vel,alc|
  player1Deaccel = 0
  right = false
  left = false
  up = false
  dowm = false

}

function draw() {
  background(220);
  circle(player1Pos.x, player1Pos.y, player1Pos.z); 
  velocity()
  keyMovement()
}
function mousePressed(){
  fullscreen(true)
}
function velocity(){
  player1Move.x += player1Move.y
  player1Pos.x += player1Move.x
}
function keyMovement(){
  if (keyIsDown(68)){
    player1Move.y = 0.1
  }
    if (!keyIsDown(68)){
    player1Move.x -=0.25
  }
  if(player1Move.x < 0 ){
    player1Move.x = 0
  }
  
  
  if (player1Pos.x > width-75){
    player1Pos.x = width-75
  }
    if (player1Pos.x < 75){
    player1Pos.x = 75
  }
}
  ///////////////////////////
  

Using onEdit to trigger different functions on different sheets

I am working on a sheet that is recording inputs (scores) from multiple entry sheets. A data set on any given sheet has multiple entries, so I wanted to create a trigger to log the data when there is a full data set. I would use a button to submit/log the data to the main data log, but I intend to use a mobile version of Google Sheets to record data in the field, so I am using the onEdit() function using a checkbox to trigger the logging of the data and resetting of the entry form.

I have written a script that executes what I desire, but I am having trouble when I try to expand the script the 2nd – 4th entry sheets. Right now, as written, the entry works on the ‘Entry1’ sheet. However, when I try to execute the script from ‘Entry2’, it logs data from ‘Entry1’ and resets and rolls forward ‘Entry1’, as well as clearing the entries from ‘Entry2’, but not rolling the sheet forward to prepare for the subsequent entry.

What I am seeking is to have the script execute the appendScoreData function on the sheet in which the checkbox is checked (via onEdit). Right now, it seems to be performing some functions on entry sheets other than the one I am targeting.

MY CODE:

/** @OnlyCurrentDoc */

function appendScoreData1() {
  var ss = SpreadsheetApp.getActiveSpreadsheet()

//Collect Data1
var sourceSheet = ss.getSheetByName('Entry1');
var sourceRange = sourceSheet.getRange('Scores1');
var sourceVals = sourceRange.getValues().flat();

//Append Score Data1
const destinationSheet = ss.getSheetByName('DATA')
destinationSheet.appendRow(sourceVals)

//Clear Content
ss.getRange('GrossScores1').clearContent()

//Update Entry Form to Next Hole
ss.getRange('NextHole1').copyTo(ss.getRange('CurrentHole1'), SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);

//Active Cell Reset
ss.getRange('FirstScore1').activate();


};

function appendScoreData2() {
  var ss = SpreadsheetApp.getActiveSpreadsheet()

//Collect Data2
var sourceSheet2 = ss.getSheetByName('Entry2');
var sourceRange2 = sourceSheet2.getRange('Scores2');
var sourceVals2 = sourceRange2.getValues().flat();

//Append Score Data2
const destinationSheet = ss.getSheetByName('DATA')
destinationSheet.appendRow(sourceVals2)

//Clear Content
ss.getRange('GrossScores2').clearContent()

//Update Entry Form to Next Hole
ss.getRange('NextHole2').copyTo(ss.getRange('CurrentHole2'), SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);

//Active Cell Reset
ss.getRange('FirstScore2').activate();


};

function onEdit(e) {
var range = e.range;
var spreadSheet = e.source;
var sheetName = spreadSheet.getActiveSheet().getName();

if (range.sheetName = 'Entry1' && range.columnEnd == 3 && range.columnStart == 3 && range.rowEnd == 15 && range.rowStart == 15) {
  appendScoreData1();
  range.uncheck()
}

else if (range.sheetName = 'Entry2' && range.columnEnd == 3 && range.columnStart == 3 && range.rowEnd == 15 && range.rowStart == 15) {
  appendScoreData2();
  range.uncheck()
}    

}

Why would my parent route in express not pass down the req.params object to its child route?

I’m building an express application that has a users table in its database and a friends table. The point of the friends table is to be a many-to-many table that keeps track of friend requests between users. Since friends are ultimately always going to be tied to users, I wanted my express routes for friends to be a child router to the users router. However, my req.params properties in the parent routes are not being passed down to my friends routes.

I’ve set up the users routes like this:

const friendRoutes = require("./friends");
const router = express.Router({ mergeParams: true });
router.use('/:username/friends', friendRoutes);

My only friends route for now is:

router.post("/request/:receiver", ensureCorrectUserOrAdmin, async function (req, res, next) {
    try{
        // validate that request follows friendNewSchema
        const validator = jsonschema.validate(req.body, friendNewSchema);
        if( !validator.valid ) {
            const errs = validator.errors.map(e => e.stack);
            throw new BadRequestError(errs);
        }

        // make new request with Friend.request
        console.log("Friend Request Body: ", req.body);
        console.log("Friend Request Params: ", req.params);
        const friendRequest = await Friend.request(req.params.username, req.params.receiver);
        console.log("Successfully made Friend Request: ", friend);

        // return json of friendRequest with a status code of 201
        return res.status(201).json({ friendRequest });
    }
    catch (err) {
        return next(err);
    }
});

The specific problem I am running into is that the route is /users/:username/friends/request/:receiver but the :username route variable is never defined when my friends route is called. I checked the middleware function and it never touches/modifies the req.params object. What should I do to get the child route to access the parent route variable?

appwrite is not giving user’s profile image in response for oAuth

I’m using appwrite for google OAuth, but when I access user by

const user = await account.get();

then it gives only this object..

{
    "$id": "...",
    "$createdAt": "...",
    "$updatedAt": "...",
    "name": "...",
    "registration": "...",
    "status": true,
    "labels": [],
    "passwordUpdate": "",
    "email": "...",
    "phone": "",
    "emailVerification": true,
    "phoneVerification": false,
    "mfa": false,
    "prefs": {},
    "targets": [
        {
            "$id": "...",
            "$createdAt": "...",
            "$updatedAt": "...",
            "name": "",
            "userId": "...",
            "providerId": null,
            "providerType": "email",
            "identifier": "..."
        }
    ],
    "accessedAt": "..."
}

i want user’s profile image also

enter image description here
I’ve selected all the options in auth menu but it still not giving user’s profile image in response.

JavaScript Module Object Cannot be Identified, Resulting in this Error: “TypeError: Cannot read properties of undefined (reading ‘getNodeItem’)”

As a preface for my question, I am very new to JavaScript and come from a strongly-typed language background (e.g. Java and C++). Although I have prior experience with JavaScript, I am not entirely familiar with its underlying mechanisms and struggle to engage with the problems posed by dynamic typing. This has not deterred me from trying very hard to not only appreciate the language, but learn to use it effectively.

With that out of the way, I tried to create a Doubly-Linked List using Node.js as a practice problem; I am quite familiar with the data structure, so I figured this would be a safe starting point for me. I am also trying to only use ES Modules to construct individual Nodes of the Doubly-Linked List. This self-imposed constraint was intended to push me outside of my comfort zone with classes and utilize the most recent JS innovations available.

However, it seems my choice to use ES Modules is not panning out. In summary, the return value of the functions getRightNode() and getLeftNode() do not have a return value that JS can identify properly. I say this because my efforts to call the function getNodeItem() does not work and throws the following error message:

console.log(`right = ${ temp.getNodeItem() }`);
                             ^

TypeError: Cannot read properties of undefined (reading 'getNodeItem')

I believe this problem is a direct result of me creating an object without using a classified type. This assertion could be wrong, but it appears to me that the return values of getLeftNode() and getRightNode() cannot be properly tied back to Node objects created by NodeModuleFactory, hence the program’s inability to call the unknown object’s function and the error is thrown.

My questions are as follows:

  1. Is there a way to fix this and allow the program to call the getNodeItem() function from the returned value of getRightNode() and getLeftNode()?
  2. Am I using ES Modules incorrectly/should I simply be using classes for this?

Any insight about this would be greatly appreciated, as I am unsure how to proceed at this stage and feel as though I am missing something.

// File: NodeModuleFactory.js
"use strict"; // <- Requires us to use the best practices for JavaScript coding.

/**
 * Determines whether the parameter passed into the function is a Node by checking
 * to see if it has certain functions.
 * @param check A variable that we will verify whether it is or is not a Node of some
 * kind.
 * @returns {boolean} Where a false value means the parameter is not a Node, and true
 * means it is a Node.
 */
function isNode (check) {
    return (typeof check === "object" &&
        typeof check.getLeftNode() === "object" &&
        typeof check.getRightNode() === "object" &&
        typeof check.getLeftNode === "function" &&
        typeof check.getRightNode === "function" &&
        typeof check.getNodeItem === "function" &&
        typeof check.setLeftNode === "function" &&
        typeof check.setRightNode === "function");
}

/**
 * Allows for the creation of NodeModule objects.
 * @param leftNode This should either be a NodeModule or undefined and will be treated
 * as the NodeModule to the left of the newly created NodeModule object.
 * @param rightNode This should either be a NodeModule or undefined and will be treated
 * as the NodeModule to the right of the newly created NodeModule object.
 * @param item This is the item being stored within the newly created NodeModule
 * object.
 * @returns {undefined|{getRightNode(): NodeModule, setLeftNode(*): void,
 * getNodeItem(): *, setRightNode(NodeModule): void, getLeftNode(): NodeModule}}
 * A NodeModule object that can be accessed and modified within a doubly-linked
 * list data structure. All NodeModule objects will have an immutable item property.
 */
export function create(leftNode, rightNode, item)
{
    // Check to see if either leftNode or rightNode are actually a NodeModule object
    // or set to undefined. If neither of these are the case, then return undefined.
    if (!(leftNode === undefined || isNode(leftNode)) ||
        !(rightNode === undefined || isNode(rightNode)))
        return undefined;

    // 'Private' data members of the NodeModule object.
    let left = leftNode;
    let right = rightNode;

    return {
        /**
         * Obtains the NodeModule object directly to the left of this NodeModule
         * object.
         * @returns {NodeModule} Should be a NodeModule object.
         */
        getLeftNode() {
            return left;
        },

        /**
         * Obtains the NodeModule object directly to the right of this NodeModule
         * object.
         * @returns {NodeModule} Should be a NodeModule object.
         */
        getRightNode() {
            return right;
        },

        /**
         * Obtains this NodeModule object's item that is contained within.
         * @returns {*} Could be any item stored within the LinkedList structure.
         */
        getNodeItem() {
            return item;
        },

        /**
         * Mutates the left data member if newLeft can be determined to be a
         * NodeModule object or undefined.
         * @param newLeft The object or undefined value that should replace the
         * current left data member.
         * @returns {boolean} True means that the reassignment was successful, while
         * false means that the reassignment was unsuccessful.
         */
        setLeftNode(newLeft) {
            if ((newLeft === undefined || isNode(newLeft))) {
                left = newLeft;
                return true;
            }

            return false;
        },

        /**
         * Mutates the right data member if newLeft can be determined to be a
         * NodeModule object or undefined.
         * @param newRight The object or undefined value that should replace the
         * current right data member.
         * @returns {boolean} True means that the reassignment was successful, while
         * false means that the reassignment was unsuccessful.
         */
        setRightNode(newRight) {
            if ((newRight === undefined || isNode(newRight))) {
                right = newRight;
                return true;
            }

            return false;
        }
    };
}
// File: main.js
"use strict"; // <- requires strict adherence to JavaScript best practices.

import { create as newNode } from "./NodeModuleFactory.js";

let head = newNode(undefined, undefined, 0);
let tail = newNode(head, undefined, 1);
console.log(head.setRightNode(tail));

console.log("head");
console.log(`cur = ${ head.getNodeItem() }`);
console.log(`right = ${ head.getRightNode().getNodeItem() }`);

console.log("ntail");
console.log(`left = ${ tail.getLeftNode().getNodeItem() }`);
console.log(`cur = ${ tail.getNodeItem() }`);

Can’t get rid of previously created custom menu

I created an app script that included a custom menu. Even though I’ve delated the script the custom menu persists & it still executes the functionality. Can’t seem to purge it. Have closed and reopened sheet, have cleared cache, have opened the sheet in incognito mode, no luck.

I expected to delete the script, save the deletion, close the sheet & reopen it & the custom menu and associated script would be gone.

Why doesn’t the same called value equal NaN in one function and not the other when they’re identical?

I am relatively new to coding.

I’m making a character sheet using html, css, and javascript. Within this character sheet, I am using javascript to update certain parts based on input.

Right now, I have an input number for level, which once an input takes place, it spits out a resulting number called Combat Mastery, which is this code below.

html code:

<div class="content-row">
      <label class="field-title">Combat Mastery</label>
      <p id="cm" type="number" class="field-data"></p>
    </div>

Here is the java function that finds the Combat Mastery value:

function combatMastery() {
  // get the input element and it's value
  let inputElement = document.getElementById('c-level');
  let inputVal = inputElement.value;
  
  //lets get the calculation to divide by 2 and round up
  let cm = Math.ceil(inputVal/2);
  console.log("CM Value:", cm);
  
  //DISPLAY IT
  let result = document.getElementById('cm');
  result.textContent = cm;
}

This works perfectly fine for my uses (at this point and time).

I have 4 “abilities” that all have a numeric value, based on a number input.

I have a separate area called “saves” which players can choose to ‘specialize’ in. When they ‘specialize’ in it, they click a checkbox, which is supposed to add the ‘ability’ score and the ‘combat mastery’ score together, and output a result.

Below is one example of a WORKING script that correctly functions as I expect it to. I’ve debugged this and find that the chaValue and cmValue (which might get added together) are both NUMBERS.

function chaSave() {
  let checkbox = document.getElementById('cb-save-cha');
  let chaValue = parseInt(document.getElementById('cha').value);
  let cmValue = parseInt(document.getElementById('cm').textContent);
  let saveChaElement = document.getElementById('save-cha');
  
  if (checkbox.checked){
    let chaSaveResult = chaValue + cmValue;
    saveChaElement.textContent = chaSaveResult;
  }
  else {
    saveChaElement.textContent = chaValue;
  }
  console.log("CHAcmValue:",cmValue);
  console.log("CHA value:",chaValue);
};

For 3 of the 4 “abilities” the “save functions” above work, except for the last one.

Here’s the java for the intelligence save that shows NaN when the checkbox is checked:

function intSave() {
  let checkbox = document.getElementById('cb-save-int');
  let intValue = parseInt(document.getElementById('int').value);
  let cmValue = parseInt(document.getElementById('cm').textContent);
  let saveIntElement = document.getElementById('save-int');
  
  if (checkbox.checked){
    let intSaveResult = intValue + cmValue;
    saveIntElement.textContent = intSaveResult;
  }
  else {
    saveIntElement.textContent = intValue;
  }
  console.log("INTcmValue:",cmValue);
  console.log("INT value:",intValue);
};

the INTcmValue returns NaN in the console, but I am so lost as to why that is?

The html as a reference for both the Cha save and the Int save is here:

<div class="content-row">
        <input id="cb-save-cha" type="checkbox" oninput="handleChaInput()">
        <label class="field-title" data-dice-type="1d20" data-modifier="no-mod" data-label="Save Charisma">Charisma</label>
        <p id="save-cha" type="number" class="field-data-short"></p>
          </div>
      
      <div class="content-row">
        <input id="cb-save-int" type="checkbox" oninput"handleIntInput()">
        <label class="field-title" data-dice-type="1d20" data-modifier="no-mod" data-label="Save Intelligence">Intellect</label>
        <p id="save-int" type="number" class="field-data-short"></p>
      </div>

To me, the cmValue within the chaSave function and the intSave function are pulling from the same place. I’ve even copied the cmValue line from the chaSave and pasted it directly into the intSave function, and the intSave operates such that when the checkbox for that save is checked, it still returns NaN.

I’m confused because in all other instances (the other 3 abilities) the save function works perfectly… why is it returning NaN when it’s IDENTICAL to the others? What am I missing?

Please keep in mind I am very new to java and I need to be explained like I’m 5 what’s happening.

Please see above. I tried duplicating the code, and have gone over the relevant html areas and java code and to me it appears identical, it’s just spitting out NaN for an unknown reason when it works everywhere else.

Why can’t I set a private field in a function called from a superclass constructor? [duplicate]

When I run the following code in Node.js:

class Superclass {
  constructor() {
    this.setPrivateField();
  }

  setPrivateField() {
    // No implementation
  }
}

class Subclass extends Superclass {
  #field;
  setPrivateField() {
    console.log(this);
    this.#field = 1;
  }
}

new Subclass();

it prints:

Subclass {}
test.js:16
    this.#field = 1;
                ^

TypeError: Cannot write private member #field to an object whose class did not declare it
    at Subclass.setPrivateField (test.js:16:17)
    at new Superclass (test.js:5:10)
    at new Subclass (test.js:12:1)
    at Object.<anonymous> (test.js:20:1)
    at Module._compile (node:internal/modules/cjs/loader:1434:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1518:10)
    at Module.load (node:internal/modules/cjs/loader:1249:32)
    at Module._load (node:internal/modules/cjs/loader:1065:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:158:12)
    at node:internal/main/run_main_module:30:49

Node.js v22.2.0

This doesn’t make sense to me. The field is declared in Subclass, and the type of the object it’s being assigned to is confirmed to be Subclass. What’s going on? It seems like a bug in V8, although I’ve confirmed that the same behavior happens in Firefox as well.