Trying to rotate an image with the javascript canvas [duplicate]

enter image description hereI’m trying to make a rock spawn at a random rotation, for variation, but it is always offset by a certain amount that changes based on the direction, which messes up collision.

Rock.prototype.draw = function () {
    ctx.beginPath();
    ctx.rect(
      this.collider.x - scrollX,
      this.collider.y - scrollY,
      this.collider.w,
      this.collider.h
    );
    ctx.stroke();

    ctx.translate(
      -this.w * 0.1 + this.x - scrollX,
      -this.h * 0.2 + this.y - scrollY
    );
    ctx.rotate(this.dir);
    ctx.drawImage(rockImage, 0, 0, this.w, this.h);
    ctx.rotate(-this.dir);
    ctx.translate(
      -(-this.w * 0.1 + this.x - scrollX),
      -(-this.h * 0.2 + this.y - scrollY)
    );
    ctx.closePath();
};

This is the current function to draw a rock. I was expecting it to be centered, but instead, it looks like this:

Loading a script into a React component gives identifier ‘placeholder’ already been declared error

I am trying to add a cursor effect to my website. The JavaScript file that has the code for the effect is referenced as cursor-effect.js below.

export default function App() {
    const [darkMode, setDarkMode] = useState(false);

    function componentDidMount() {
        const script = document.createElement("script");

        script.src = "/scripts/cursor-effect.js";
        script.async = true;

        document.body.appendChild(script);
    }

    componentDidMount();

I can get the effect to work when I add the script this way but in development I constantly get errors like this.

Identifier 'canvas' has already been declared
SyntaxError: Identifier 'canvas' has already been declared

The errors are always for variables declared in the script file and I think I understand that as the react component is rerendered it is redeclaring the already declared variables from the cursor-effect.js file, but I don’t know how to fix the issue or if this is actually what’s happening. I’m not familiar with best practices around using script tags in React.js or if I should even be trying to use them at all.

I have included the full cursor-effect.js file below…


const canvas = document.getElementById("homePage");
const ctx = canvas.getContext("2d");
const maxParticlesFollowMode = 200;

let followMode = false;
let lum = "0%";

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
let spots = [];

const mouse = {
    x: undefined,
    y: undefined
}

canvas.addEventListener("mousemove", function (event) {
    if (!followMode) return;
    mouse.x = event.x;
    mouse.y = event.y;
    for (let i = 0; i < 2; i++) {
        spots.push(new Particle());
    }
});

function mobileEffect (event) {
    if (followMode) return;
    for (let i = 0; i < maxParticlesFollowMode; i++) {
        spots.push(new Particle());
    }
}


function getRandomInt(min, max) {
    return Math.random() * (max - min) + min;
}

class Particle {
    constructor() {
        //adjust x and y here for offsets from nav-bars and such
        this.x = followMode ? mouse.x : getRandomInt(0, window.innerWidth);
        this.y = followMode ? mouse.y :  getRandomInt(0, window.innerHeight);
        this.size = Math.random() * 2.5;
        this.speedX = Math.random() * 2;
        this.speedY = Math.random() * 2;
        this.color = "hsl(356, 0%, " + lum + ")";
    }
    update() {
        if (followMode) {
            this.x += this.speedX;
            this.y += this.speedY;
            if (this.size > 0.1) this.size -= 0.006;
        } else {
            let changeProbX = Math.random();
            let changeProbY = Math.random();
            let directionProbX = Math.random();
            let directionProbY = Math.random();

            let adjustmentX = 0;
            let adjustmentY = 0;

            if (changeProbX > 0.1) {
                adjustmentX = Math.random()/3;
                if (directionProbX > 0.5) adjustmentX = adjustmentX / -1;
            }
            if (changeProbY > 0.1) {
                adjustmentY = Math.random()/3;
                if (directionProbY > 0.5) adjustmentY = adjustmentY / -1;
            }

            let speedX = this.speedX + adjustmentX;
            let speedY = this.speedY + adjustmentY;

            this.x = (this.x + speedX) % window.innerWidth;
            this.y = (this.y + speedY) % window.innerHeight;
            // if (this.size > 0.1) this.size -= 0.006;
        }
    }

    draw() {
        ctx.fillStyle = this.color;
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
        ctx.fill();
    }
}

function handleParticle() {
    for (let i = 0; i < spots.length; i++) {
        spots[i].update();
        spots[i].draw();
        for (let j = i; j < spots.length; j++) {
            const dx = spots[i].x - spots[j].x;
            const dy = spots[i].y - spots[j].y;
            const distance = Math.sqrt(dx * dx + dy * dy);
            if (distance < 90) {
                ctx.beginPath();
                ctx.strokeStyle = spots[i].color;
                ctx.lineWidth = spots[i].size / 10;
                ctx.moveTo(spots[i].x, spots[i].y);
                ctx.lineTo(spots[j].x, spots[j].y);
                ctx.stroke();
            }
        }
        if (spots[i].size <= 0.3) {
            spots.splice(i, 1); i--;
        }
    }
}

function animate() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    handleParticle();
    requestAnimationFrame(animate);
}

window.addEventListener('resize', function () {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
})

window.addEventListener('mouseout', function () {
    mouse.x = undefined;
    mouse.y = undefined;
})

animate();
mobileEffect();

lodas deepClone or deepClone from clone_deep npm returns same instance

What I’m observing now is making me question reality. Of course I’m working with Javasript.

I have following code (clone-deep npm package v 4.0.1)

    let deepCloned = cloneDeep(obj);
    
    if (deepCloned === obj) {
        debugger;
    }

and of course in some cases the debugger is hit. When I change it to lo dashes implementation

    let deepCloned = _.cloneDeep(obj);
    
    if (deepCloned === obj) {
        debugger;
    }

same behavior can be observed. So I have to be missing something really fundamental here. What is it?

Suitescript 2.x client script works perfectly in Firefox but stops functioning in Google chrome

I wrote a simple client script using the saveRecord function to copy some info from the header values to the line item fields that correspond. When testing on Firefox I get the expected outcome of each line item field populated with the respective field from the header however, when I test on google chrome no errors are thrown but the script stops working resulting in values seemingly being copied but the lines aren’t committed so the data disappears. Sometimes it will not save at all and get stuck on a search box (one of the fields is a select field) with the correct data in it but a slash(/) mysteriously added at the end. Does anyone know a fix?

function saveRecord(scriptContext) {

        try{
            var context = scriptContext.currentRecord
            var ran = false;
            var classValue = context.getText({
                fieldId: 'class'
            })
            var jobNumber = context.getText({
                fieldId: 'custbody_job_number'
            })
            var count = context.getLineCount({
                sublistId: 'item'
            })
            if(context.getText({fieldId: 'custbody_job_number'}) != '' && context.getText({fieldId: 'class'}) != '' ){
                console.info('All fields have data prepare for transfer')
                for(var i = 0; i <= count; i++){ 
                    context.selectLine({
                        sublistId: 'item',
                        line: i
                    })
                    if(context.getCurrentSublistText({sublistId: 'item', fieldId: 'item'}) != ''){
                        context.setCurrentSublistText({
                            sublistId: 'item',
                            fieldId: 'class',
                            text: classValue
                        })
                        context.setCurrentSublistValue({
                            sublistId: 'item',
                            fieldId: 'customer',
                            value: jobNumber
                        })
                        context.commitLine({ 
                            sublistId: 'item',
        
                        })
                    }   
                }
                ran = true
            }```

CSP does not work as expected (it allows React SPA to load things when is set to ‘none’)

SPA & Network screenshot

I have a React SPA with only one request to my Node.js + express server with header “Content-Security-Policy” set to default-src ‘none’. Although it still loads everything. What am I doing wrong? P.S: incognito mode does not help, I use latest version of Chrome.

I’ve checked syntax adding it to tag and it worked but I want to be able to make my web app more secure via HTTP.

How to organize the opening of a minimized application through the tray bar?

the following code is available. For some reason, two applications open at startup, one of which is active (it can be opened through the Tray Bar), the second is not, I can’t figure out where it comes from

    const { app, BrowserWindow } = require("electron");
    
    const createWindow = () => {
      const win = new BrowserWindow({
        width: 800,
        height: 600,
      });
    
      win.loadFile("index.html");
    };
    
    app.whenReady().then(() => {
      createWindow();
      app.on('activate', () => {
        if (BrowserWindow.getAllWindows().length === 0) {
          createWindow()
        }
      })
    })
    
    app.on('window-all-closed', () => {
      if (process.platform !== 'darwin') {
        app.quit()
      }
    });
    
    
    // Anton's work
    
    const {Tray, Menu, nativeImage } = require('electron/main')
    
    let tray;
    let mainWindow;
    
    app.whenReady().then(() => {
      const icon = nativeImage.createEmpty()
      tray = new Tray(icon);
    
      const contextMenu = Menu.buildFromTemplate([
        { label: 'Open FroggApp', type: 'normal',
            click: function() { 
              mainWindow.show()
                  }
        },
        { type: 'separator' },
        { label: 'Options', type: 'normal' },// if options will be?
        { type: 'separator' },
        { label: 'Close FroggApp', type: 'normal',
            click: function() { 
                app.quit(); 
                   }
         }
       
      ]);
    
      tray.setToolTip('Frog application');
      tray.setContextMenu(contextMenu);
    })
    
    
    app.on('ready', () => {
      mainWindow = new BrowserWindow({ width: 800, height: 600 });
      mainWindow.show();
    });
   

I tried to sort through the options for organizing the function to open the minimized application window, but I get errors: referenceerror or an error using the show() function.

I expected to open a minimized application through the Tray Bar

Problem with Joi validation: Joi.when() condition ignored

I have this Joi schema:

const Joi = require('joi');

const DB_CONST = {
DEFAULT_MEDIUM_STRING: 255,
DEFAULT_STRING: 100
};

const FUNCTIONTYPE = {
A: 'A',
B: 'B'
};

const Testata = Joi.object().keys({flusso: Joi.string().max(DB_CONST.DEFAULT_MEDIUM_STRING).required(),
functiontype: Joi.string().valid(...Object.values(FUNCTIONTYPE)).required(),
});

const Cliente = Joi.object().keys({
codclicrm: Joi.string().max(DB_CONST.DEFAULT_STRING).required(),
idcli: Joi.string().max(DB_CONST.DEFAULT_MEDIUM_STRING).required(),
});

const body = Joi.object().keys({
TESTATA: Testata.required(),
CLIENTE: Joi.when('TESTATA.functiontype', {
is: 'A',
then: Cliente.optional(),
otherwise: Cliente.required()
})
});

if I try to validate a body with TESTATA.functiontype set to ‘A’ and no CLIENTE aggregate, the validation returns ” ‘CLIENTE’ is required “- While I was expecting that the validation went ok…

Dialog modal not showing [closed]

I don’t get why the modal is not showing. I’m not using bootstrap btw, only html and js.

const modal     = document.querySelector(".modal");
const openModal = document.querySelector(".new_teacher");

openModal.addEventListener("click", () => {
  modal.showModal();
})
<div class="card">
  <div class="card-header">
    <b>Teacher List</b>
    <span class="">
      <button id="new_teacher">
      <i class="fas fa-plus"></i>New Teacher</button>
    </span>
  </div>
  <div class="card-body">
    <h1>Hello World</h1>
  </div>
</div>
<dialog class="modal" id="modal">
  <div class="modal-header">
    <b>Add New Teacher</b>
  </div>
  <div class="modal-body">
    <h1>Hello</h1>
  </div>
</dialog>

I followed some guides on YouTube regarding dialog modals, and I tried searching for solutions online and can’t seem to find one.

Qualtrics JavaScript: Randomizing and Displaying One Choice from Multiple Subsets in a Qualtrics Rank Order Question

I’m working on a Rank Order question in Qualtrics and need help achieving a specific design using JavaScript. Here’s what I want to do:

Problem:
I have three different categories of choices:

A (A1, A2, …)
B (B1, B2, ….)
C (C1, C2 …)
Each category has 4 choices. What I need to do is randomly select and display one option from each category (so 3 total), shuffle the order in which they appear, and hide the rest. I also need to ensure the Rank Order drag-and-drop functionality still works after the randomization.

What I’ve Tried:
I’ve written a JavaScript code to randomly pick one choice from each category and hide the rest, but I’m facing issues with reinitializing the Rank Order functionality.

Qualtrics.SurveyEngine.addOnload(function() {

    // Define the blocks with their choices
    var groupAChoices = [
        "A1", "A2", "A3", "A4"
    ];

    var groupBChoices = [
        "B1", "B2", "B3", "B4"
    ];

    var groupCChoices = [
        "C1", "C2", "C3", "C4"
    ];

    // Randomly pick one option from each group
    var groupAPick = groupAChoices[Math.floor(Math.random() * groupAChoices.length)];
    var groupBPick = groupBChoices[Math.floor(Math.random() * groupBChoices.length)];
    var groupCPick = groupCChoices[Math.floor(Math.random() * groupCChoices.length)];

    // Combine the selected choices into an array
    var selectedChoices = [groupAPick, groupBPick, groupCPick];

    // Randomize the order of the selected choices
    for (let i = selectedChoices.length - 1; i > 0; i--) {
        let j = Math.floor(Math.random() * (i + 1));
        [selectedChoices[i], selectedChoices[j]] = [selectedChoices[j], selectedChoices[i]];
    }

    // Display the randomized choices
    this.getChoiceContainer().innerHTML = "<ul>" + selectedChoices.map(choice => "<li>" + choice + "</li>").join('') + "</ul>";
});

With the code, the survey preview displays the random choices but the drag and drop functions is not available anymore after running the code. I couldn’t find any fix for this problem. Can anyone help me?

Chartjs > Display tooltip on two charts when hovered over anyone of the chart

on Hover tooltip works for one chart at a time, it should display tooltip on both the charts. The second chart does displays active points but not the tooltip. The tooltip is a custom one used here.

const lineChartOptions: ChartOptions<"line"> = {
    responsive: true,
    maintainAspectRatio: false,
    interaction: {
      mode: "index",
      intersect: false,
    },
    onHover: handleHover,
    plugins: {
      crosshair: {
        value: 10, // Adjust this value as needed
        line: {
          color: "red", // crosshair line color
          width: 1, // crosshair line width
        },
        sync: {
          enabled: true, // enable trace line syncing with other charts
          group: 1, // chart group
          // suppressTooltips: false, // suppress tooltips when showing a synced tracer
        },
        zoom: {
          enabled: false,
        },
      },
      legend: {
        display: false,
      },
      tooltip: {
        position: "nearest", 
        enabled: false, // Disable the default tooltip
        external: customTooltip, // Enable custom tooltip
        callbacks: {
          beforeTitle: function (context) {
            // return[context.parsed.y]
            return [`${context[0].label}`];
          },
          label: function (context) {
            console.log(context);
            if (context.datasetIndex === 0) {
              return `<div class="flex flex-col">
                      <div class="flex items-center mt-1">
                        <div class="w-2 h-2 bg-[#8C94BD] rounded-full mr-2"></div>
                        <div class="block text-[#8C94BD]">$${context.parsed.y} <span class='text-black pl-2'>${context.dataset.label}</span></div>
                      </div>
                    </div>`;
            }
            if (context.datasetIndex === 1) {
              return `<div class="flex flex-col">
                      <div class="flex items-center mt-1">
                        <div class="w-2 h-2 bg-[#C3C34B] rounded-full mr-2"></div>
                        <div class="block text-[#C3C34B]">$${context.parsed.y} <span class='text-black pl-2'>${context.dataset.label}</span></div>
                      </div>
                    </div>`;
            }
            return context.label;
          },
          title: function (context) {
            //Display month and year
            // return context[0].label;
          },
        },
      },
    },

    scales: {
      x: {
        border: {
          dash: [4, 8],
          width: 0,
        },

        ticks: {
          callback: function (val: any) {
            // Hide every 2nd tick label
            const label = this.getLabelForValue(val);
            if (label[0] === "Jul") {
              const year = label[1]; // Since label is in the format [month, year]
              return year;
            }
            return null;
          },
        },
        offset: true, // This will extend the line chart beyond the data points
        // display: false
        grid: {
          display: true, // Hides/show X-axis gridlines
        },
      },
      y: {
        // offset: true,
        border: {
          dash: [4, 8],
          width: 0,
        },
        //to start with 0 tick
        beginAtZero: true,
        ticks: {
          autoSkip: false,
          maxTicksLimit: 6,
          callback: function (value) {
            return "$" + value;
          },
        },
        grid: {
          display: true, // Hide/Shows Y-axis gridlines
        },
      },
    },
  };
<Line id="chart1" data={data} options={lineChartOptions} />
<Line id="chart2" data={data} options={lineChartOptions} />

https://www.youtube.com/watch?v=TQ7XYMTr7t4
This is exactly what needs to be achieved but how can it be done the same in nextjs

I try fetching my data on the server bisically this signup page, I got cors policy error even I got it configure on the server

I got request policy error, I need some help guys Im stuck just a beginner here!
this is my frontend code using this function to fetch data in the server,

  signup: async (email, password, name) => {
    set({ isLoading: true, error: null });
    try {
      const options = {
        credentials: "include",
        method: "POST",
        headers: { "Content-Type": "aplication/json" },
        body: JSON.stringify({ email, password, name }),
      };

      const response = await fetch(`${API_URI}/signup`, options);

      if (!response.ok) {
        throw new Error("Network response was not ok");
      }

      const data = await response.json().catch((error) => {
        throw new Error("Error parsing JSON response: " + error.message);
      });
      console.log(data);
      set({ user: data.user, isAuthenticated: true, isLoading: false });
    } catch (error) {
      set({
        error: error.message || "Error signing up",
        isLoading: false,
      });
    }
  },
}));

Here is my backend configure the cors , Im using locahost for now:

import express from "express";
import { connectionDB } from "./db/connectionDB.js";
import dotenv from "dotenv";
import authRoutes from "./routes/auth.route.js";
import cookieParser from "cookie-parser";
import cors from "cors";

dotenv.config();
const app = express();
app.use(cors({ origin: "http://localhost:3000/", Credential: true }));
app.use(express.json());
app.use(cookieParser());

app.get("/", (req, res) => {
  res.send("Hellow Word1234!");
});

app.use("/api/auth", authRoutes);

connectionDB().then(() => {
  app.listen(3001, () => {
    console.log("Server is Running in Port 3000");
  });
});

signup:1 Access to fetch at ‘http://localhost:3001/api/auth/signup’ from origin ‘http://localhost:3000’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: The ‘Access-Control-Allow-Origin’ header has a value ‘http://localhost:3000/’ that is not equal to the supplied origin. Have the server send the header with a valid value, or, if an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.Understand this error
auth.store.jsx:23
POST http://localhost:3001/api/auth/signup net::ERR_FAILED

How to prepend line number cells as a HTML column to a given table matrix?

What I have so far:

I’m working on a very generic table based on a configuration. This table is generated based on a graph, the final calculated data structure is

type TableMatrix = Cell[][];

interface Cell {
  isCoveredByPreviousCell: boolean;
  rowspan: number;
  offset: number;
  hasContent: boolean;
  columnIndex: number;
}

I grabbed data from a correct table to test with ( Playground with test data )

Sidenote: Based on this data I know there will be 14 columns to render

When it comes to rendering I decided to use VueJs ( Playground Link )

<script setup>
import { tableMatrix } from './data.ts'
</script>

<template>
  <table>
    <thead>
      <tr>
        <th v-for="headerIndex in 14">
          Header {{ headerIndex }}
        </th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="(row, rowIndex) in tableMatrix" :key="rowIndex">
        <!-- Inser line number cell here -->
        <template v-for="(cell, columnIndex) in row" :key="columnIndex">
          <td v-if="cell.isCoveredByPreviousCell" :style="{ 'display': 'none' }"/>
          <td v-else :rowspan="cell.rowspan">
            <template v-if="cell.hasContent">
              <div>I belong to col {{ cell.columnIndex + 1 }}</div>
            </template>
          </td>
        </template>
      </tr>
    </tbody>
  </table>
</template>

<style>
table, th, td {
  border: 1px solid black;
}
</style>

What I want to achieve:

I want to add line numbers to every leading row.

A row is a leading row if every cell in that row is not covered by a previous cell. Pseudo example: (row /* Cell[] */ ).every((cell) => !cell.isCoveredByPreviousCell);

So for this example ( the first leading row in the first data column might have multiple cells but not in this example ) the desired output would be

enter image description here

What I’ve tried so far:

I thought I could create a structure that knows the correct row index for a line number cell and the required rowspan.

const lineNumbersMatrix = computed(() => {
  interface LineNumberInfo {
    index: number;
    rowspan: number;
  }

  const matrix = new Map<number, LineNumberInfo>();

  let currentLineIndex = 0;

  for (let rowIndex = 0; rowIndex < tableMatrix.value.length; rowIndex++) {
    const row = tableMatrix.value[rowIndex];
    
    // skip if not a leading row
    if (row.some((cell) => cell.isCoveredByPreviousCell)) {
      continue;
    }

    let lineNumberRowspan = 1;

    for (const cell of row) {
      if (lineNumberRowspan >= cell.rowspan) {
        continue;
      }

      lineNumberRowspan = cell.rowspan;
    }

    matrix.set(rowIndex, {
      index: currentLineIndex,
      rowspan: lineNumberRowspan
    });

    currentLineIndex ++;
  }

  return matrix;
});

After that I thought I could add a new table header

<th>Line</th>

and replace the comment

<!-- Inser line number cell here -->

with

<td v-if="lineNumbersMatrix.has(rowIndex)" :rowspan="lineNumbersMatrix.get(rowIndex)!.rowspan">{{ lineNumbersMatrix.get(rowIndex)!.index }}</td>

to get this Result, which seems to work as expected.

Unfortunately my real project renders an additional blank column at the end of the table

enter image description here

and I can’t reproduce it in the sandbox…

I’m assuming my approach is not 100% correct and there might be better ways. Do you have any ideas how to solve this?