Canvas API not working correctly for Google Extension

I am working on a Google Extension that translates images on websites. I used the Google Vision API to extract the text from the images, and with those coordinates from the text, I used Canvas to draw white rectangles on top of the original text so I can add the translated text. However, the rectangles are not positioning correctly. They sometimes appear to the side, and I have to zoom in for the rectangles to fit properly. I am still new to JavaScript and Canvas, so any advice would be helpful!

The problemThe problem and my code

chrome.runtime.onMessage.addListener((message) =>{
    if (message.event === "coordsReady"){
        chrome.storage.local.get('coordinates', (coords) =>{
            const coordinates = coords.coordinates
            if (coordinates){
                console.log("coordinates are here in content", coordinates)

                coordinates.forEach((coord) => {
                    const vertices = coord.vertices
                    const text = coord.text
                    console.log(text)
                    console.log(vertices)

                    const xValues = vertices.map((vert) => vert.x)
                    const yValues = vertices.map((vert) => vert.y)
                  
                    const maxX = Math.max(...xValues)
                    const maxY = Math.max(...yValues)

                    const minX = Math.min(...xValues)
                    const minY = Math.min(...yValues)
        
                    const width = maxX - minX
                    console.log("Width:", width)

                    const height = maxY - minY
                    console.log("Height:", height)

                    ctx.fillStyle ='white'
                    ctx.fillRect(minX,minY,width,height)
                    console.log(`Rectangle at (${minX}, ${minY}) with width ${width} and height ${height}`);
                })
            } else {
                console.log("nothing")
            }
        }) 
    }
})

How to add TypeScript types to a NPM package that uses function prototype [duplicate]

I’m trying to use a 3rd party package that exports a class like this:

function Person(name) {
   this.name = name
}

Person.prototype.shout = function() {
    console.log(this.name + ": ahhh!")
}

module.export = Person

In a typescript project I’m trying to provide a persons.d.ts file to be able to use it, so far I’ve tried:

declare module "persons" {
    interface Person {
        new(name: string): Person;
        readonly shout: () => void;
    }

    export = Person;
}

After adding the proper tsconfig.json settings I get the following error:

Usage:

import Person from 'persons';

const person = new Person('john'); // Error is here
person.shout()
'Person' only refers to a type, but is being used as a value here.ts(2693)

Most of the guides I’ve read cover declarations and somewhat more modern idioms of packages however I’m not seen an example for function prototypes.

I’m also not 100% that my import statement is correct. Any guidance would be appreciated!

navigator.mediaDevices is undefined | Safari iOS 18 | served via https

We run a WebRTC app in browser. It’s served via https.

In Safari on some modern iOS devices, navigator.mediaDevices is undefined.

It occurs on one iPhone 13 running iOS 18.0.1,
but doesn’t occur on a seemingly identical device (another iPhone 13 running iOS 18.0.1).

On that device, other webpages such as https://www.onlinemictest.com/webcam-test break as well.

In production logs, I can see that it happened for these iPhones’ user-agents:

  • Mozilla/5.0 (iPhone; CPU iPhone OS 18_2_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1
  • Mozilla/5.0 (iPhone; CPU iPhone OS 18_0_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0.1 Mobile/15E148 Safari/604.1
  • Mozilla/5.0 (iPhone; CPU iPhone OS 14_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148

All that I can find online tells me to verify the origin is secure (it is),
and to verify iOS is up-to-date (it is).

I checked said iPhone 13’s device’s settings and couldn’t find anything suspicious.

Any help will be appreciated <3

Javascript: smooth animation between two frames

I have a video element in my html page and I play frame by frame by seeking to the frame of my time by following this: HTML5 frame-by-frame viewing / frame-seeking?. This type of playback is choppy; my question is: if I had two frame times, would it be possible to smooth out the playback between them(I read about frame interpolation, but couldn’t find any javascript libraries)?

player code:

const playerObject = $('#videoElement').get(0);

function seekToTime(ts){
playerObject.pause();
playerObject.currentTime = ts;
}

tdl error after packaging with electron packager

Hello and thank you all for your help.
I am trying to package an app with electron-packager, among the dependencies of this app is the js tdl module.
I have configured tdl to use a precompiled tdlib json interface, everything works perfectly.
From the moment I package the app the interface stops working, the software finds it, tries to use it, but it gives no response. The strange thing is that if I navigate to the package in contents/MacOS and start the app from there, everything works perfectly again.
I’ve been fretting about this problem all day, please help me.

How can I test, using Cypress, that a button correctly redirects to the expected URL?

I am very new to Cypress, so go easy.

We have a React application that, on initial load, presents a “Login with Spotify” button.
The button constructs an auth URL according to the Spotify PKCE authorization flow, and directly sets window.location.href to that constructed URL:

//spotifyAuth.js

export const getAuthorizationURL = async () => {
  logMessage(`Getting authorization URL...`);
  const authUrl = new URL("https://accounts.spotify.com/authorize");
  const codeVerifier = generateCodeVerifier();
  const codeChallenge = await generateCodeChallenge(codeVerifier);

  // Save the codeVerifier in IndexedDB
  await setCachedEntry('auth', codeVerifier, 'spotify_code_verifier');

  logMessage(`Code verifier: ${codeVerifier}`);

  const state = generateState();
  const params = new URLSearchParams({
    response_type: 'code',
    client_id: CLIENT_ID,
    scope: 'user-library-read',
    state: state,
    redirect_uri: REDIRECT_URI,
    code_challenge_method: 'S256',
    code_challenge: codeChallenge,
  });
  authUrl.search = new URLSearchParams(params).toString();
  const authorizationURL = authUrl.toString();
  logMessage(`Authorization URL: ${authorizationURL}`);
  return { authorizationURL };
};

export const redirectToAuthorizationUrl = async () => {
  logMessage(`Redirecting to authorization URL...`);
  window.location.href = (await getAuthorizationURL()).authorizationURL;
}

To start off with, We are just trying to test that clicking that button redirects to the correct URL.
We read that a single Cypress test cannot span across multiple origins. So, instead of allowing the redirect and attempting to read the new URL, we tried to stub the redirect, block it and read what the application is trying to set window.location.href to:

//login.cy.js

describe('Login Functionality', () => {
    
    describe('When you click Login to Spotify', () => {
        it('constructs the Spotify auth url', () => {
            cy.window().then(window => {
                cy.stub(window.location, 'href').as('redirect')
            })
            cy.visit('/');
            cy.get('.login-button').click();
            cy.get('@redirect').should('be.calledWithMatch', `accounts.spotify.com/authorize`)
        });
    });

});

That resulted an an AssertionError: Timed out retrying after 4000ms: expected redirect to have been called with arguments matching "accounts.spotify.com/authorize", but it was never called.

We then read that you cannot stub window.location.href directly like that. So, we tried to change the application code to set the auth URL in a function and stub that function instead:

//spotifyAuth.js

export const redirectToAuthorizationUrl = async () => {
  logMessage(`Redirecting to authorization URL...`);
  const authUrlToNavigateTo = (await getAuthorizationURL()).authorizationURL;
  window.redirectToSpotifyAuth(authUrlToNavigateTo);
}

window.redirectToSpotifyAuth = function (authUrl) {
  window.location.href = authUrl;
};
//login.cy.js

describe('Spotify Login Flow', () => {
    it('should construct correct Spotify auth URL', () => {
      // Stub the redirect function
      cy.visit('http://localhost:3000/', {
        onBeforeLoad(window) {
            window.redirectToSpotifyAuth = () => {};  
            cy.stub(window, 'redirectToSpotifyAuth').as('redirect');
        },
      });
  
      cy.get('.login-button').click();
  
      // Check that redirectToSpotifyAuth was called with the correct URL
      cy.get('@redirect').should('be.calledWithMatch', `accounts.spotify.com/authorize`);
    });
  });

This resulted in the same AssertionError.

What are we doing wrong?

Jquery Percentage Calculation For Each Option On My Code

originalPriceElement.innerText part is not working, it says “NaN” and I don’t know how to fix it.
-additionalPrice is working but calculatedOriginalPrice not working.
-When I do any action on the additionalPrice value, it says “NaN”
-My goal is to instantly show the percentage calculation every time a different option is selected.

 <div class="product-price" id="current-price" style="color: #0f743b;">{{ price }}</div>
 <div class="product-price-old" id="original-price">{{ original_price }}</div>

 <script>
      function updatePrice(selectElement) {
     
        const selectedOption = selectElement.options[selectElement.selectedIndex];
    
      
        const additionalPrice = selectedOption.getAttribute('data-price');
    
   
        const priceElement = document.getElementById('current-price');
        const originalPriceElement = document.getElementById('original-price');

        if (additionalPrice) {
            const selectedPrice = parseFloat(additionalPrice);
            const calculatedOriginalPrice = additionalPrice / 0.4; 
    
            priceElement.innerText = additionalPrice;
    
     
            originalPriceElement.innerText = calculatedOriginalPrice.toFixed(2); //NOT WORKING
    
      
            priceElement.classList.add('blink');
            originalPriceElement.classList.add('blink');
    
         
            setTimeout(() => {
                priceElement.classList.remove('blink');
                originalPriceElement.classList.remove('blink');
            }, 1000); // Animasyon süresi 1 saniye (0.5s * 2)
        } else {

            priceElement.innerText = '{{ price }}';
            originalPriceElement.innerText = '{{ original_price }}';
        }
    }
    
    </script>

How to make Glide.js slider work on WordPress with Oxygen builder?

Please help me to figure out why I can’t get the slider to work. I’m using Oxygen builder and trying make a custom carousel slider using the Glide.js. I’ve added a Code Block on my page to build the structure and initialize slider, here’s the code:

<div class="glide">
  <div class="glide__track" data-glide-el="track">
    <ul class="glide__slides">
      <li class="glide__slide"><img class="abimg1" src="/wp-content/uploads/2025/01/blank.png"></li>
      <li class="glide__slide"><img class="abimg2" src="/wp-content/uploads/2025/01/blank.png"></li>
      <li class="glide__slide"><img class="abimg3" src="/wp-content/uploads/2025/01/blank.png"></li>
      <li class="glide__slide"><img class="abimg4" src="/wp-content/uploads/2025/01/blank.png"></li>
    </ul>
  </div>
  <div class="glide__arrows" data-glide-el="controls">
   <button class="glide__arrow glide__arrow--left" data-glide-dir="<">&lt;</button>
   <button class="glide__arrow glide__arrow--right" data-glide-dir=">">&gt;</button>
  </div>
</div>

<script>
new Glide('glide', {
  type: 'carousel',
  startAt: 0,
  autoplay: 4000,
  rewind: true,
  focusAt: 'center',
  perView: 1
})
</script>

I uploaded the CSS and JS files and used the WPcode plugin to link them (in header):

<link rel="stylesheet" type="text/css" href="/wp-content/uploads/glide/glide.core.css" />
<link rel="stylesheet" type="text/css" href="/wp-content/uploads/glide/glide.theme.css" />
<script src="/wp-content/uploads/glide/glide.js"></script>

A single image and left and right buttons appear on the page, the styles are got applied, but the slides don’t move (not at the press of a buttons, not by dragging). Actual images are added as background using CSS.

Screenshot

I think I did everything by the instruction from official glide.js site. I have of course tried the default settings for the “new Glide” script and all the styles, no result.

Given my total lack of html and javascript knowledge there is nothing else I figured out to do besides googling “how-to” for a two days, no result.

How to show message from API in next.js application?

Its my first week working with Next.js and i have very limited experience with React.
Scenario –

I am calling this method on basic sign up/ login form submission.

  const formSubmit = async (e, name) => {
    e.preventDefault();
    const url = `${url_prefix}/${formName}`

    try {
        const response = await fetch(url, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ user }),
        });
        console.log(response) // show message here
        if (response.ok) {
            router.push('/validateuser')
        } else if (response.status === 401) {
            msgFn({message: 'Invalid Credentials', type: 'F'})
            setTimeout(() => {
                msgFn({type: ''})
            }, 3000);
        }
      } catch (error) {
      }
  };

and my backend is in express.js and its something like

const createuser = async (req, res) => {
    try {
        console.log(req.body)
        const { username, email, password } = req.body.user;
        const userExist = await User.findOne({ email: email })

        if (userExist) {
            return res.status(401).send({message: 'User already exists.'})
        }
        const user = await User.create({ username, email, password })

        const new_user = await User.findOne({ email: email })
        const userId = new_user._id

        await LoggedUser.deleteMany({});
        const loggedUser = await LoggedUser.create({ username, email, userId })
        res.json({ message: 'User Created' })

    } catch (error) {
        console.error(error)
    }
}

If the User email is already in the db, i send ‘user already exists’ from the backend and in network tab of chrome, i can see it

enter image description here

but when i try to console ‘response’, i dont see the message in the reponse object.

enter image description here

I am specifically checking if error code is 01, but thats not a good approach as message can vary.

so how can i show the message coming from the BE?

rest of html code, if needed

enter image description here

Fix a weird looping bug

The below JavaScript code fetches the path from a svg image. The svg image is particularly complex, and looks like this.

function initializeAnimation() {
    fetch('assets/img.svg')
        .then(response => response.text())
        .then(svgContent => {
            const parser = new DOMParser();
            const svgDoc = parser.parseFromString(svgContent, 'image/svg+xml');
            const originalPath = svgDoc.querySelector('path');
            
            if (!originalPath) return;
            
            const animationSvg = document.querySelector('.border-line');
            const viewBox = svgDoc.querySelector('svg').getAttribute('viewBox');
            
            if (viewBox) {
                animationSvg.setAttribute('viewBox', viewBox);
            }
 
            const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
            path.setAttribute('d', originalPath.getAttribute('d'));
            animationSvg.appendChild(path);
            
            const pathLength = path.getTotalLength();
            let trailLength = pathLength * 0.01;
            let isComplete = false;
            
            function resetAnimation() {
                trailLength = pathLength * 0.01;
                path.style.strokeDasharray = `${trailLength} ${pathLength - trailLength}`;
                path.style.strokeDashoffset = 0;
                path.style.stroke = 'var(--on-surface)';
                path.style.strokeWidth = '5';
                isComplete = false;
                startTime = performance.now();
            }
            
            let startTime = performance.now();
            
            function animate(currentTime) {
                const elapsed = currentTime - startTime;
                
                if (!isComplete) {
                    trailLength = Math.min(pathLength * (0.01 + elapsed/50000), pathLength);
                    path.style.strokeDasharray = `${trailLength} ${pathLength - trailLength}`;
                    
                    if (trailLength >= pathLength) {
                        isComplete = true;
                        path.style.stroke = 'var(--on-primary-container)';
                        path.style.strokeWidth = '8';
                        setTimeout(resetAnimation, 20000);
                    }
                }
                
                const currentOffset = parseFloat(path.style.strokeDashoffset || 0);
                const newOffset = currentOffset - 1;
                
                if (Math.abs(newOffset) >= pathLength) {
                    path.style.strokeDashoffset = 0;
                } else {
                    path.style.strokeDashoffset = newOffset;
                }
                
                requestAnimationFrame(animate);
            }
            
            requestAnimationFrame(animate);
        })
        .catch(error => console.error('Error loading SVG:', error));
 } 

So the issue is that a perfect infinitely looping animation is not created. It just stops midway. And after that resumes its journey. I have tried debugging it, and it appears that some frames are not visible. With that said, I’m unaware of the root cause of the problem.

Screenshot of what actually happens.

For reference I have attached my CSS and HTML code.

<div class="profile-container">
    <div class="image-wrapper">
        <img src="assets/profile.jpg" alt="Eagle picture" class="profile-photo">
        <svg class="border-line" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet">
            <use href="#path"/>
        </svg>
    </div>
  .profile-container {
    display: flex;
    align-items: center;
    gap: 2rem;
    margin-bottom: 2rem;
}

.image-wrapper {
    position: relative;
    width: 250px;
    height: 250px;
}

.profile-photo {
    width: 250px;
    height: 250px;
    position: relative;
    object-fit: cover;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
    mask-image: url(assets/img.svg);
}

.border-line {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
}

.border-line path {
    fill: none;
    stroke: var(--on-surface);
    stroke-width: 5;
    vector-effect: non-scaling-stroke;
}

@media (max-width: 768px) {
    .profile-container {
        flex-direction: column;
        text-align: center;
    }

    .image-wrapper {
        width: 350px;
        height: 350px;
    }

    .profile-photo {
        width: 350px;
        height: 350px;
    }
}

Making layer-specific legends (hiding the legends of un-activated layers)

I am making a map that needs to have seven base layers on it. There are so many legends that they cannot all fit on the screen- which makes it necessary to add a feature of the map that makes it so that the legends only appear when their base layer is activated.

So far, using htmlwidgets, I have gotten all of my legends to disappear, but I can’t get the legend of the activated layer to become visible.

Here are the layer controls:

  addLayersControl(                                                #layer control 
    baseGroups = c("Parishes, plain",
                   "Unemployment rate", "Labor force participation rate", 
                   "FITAP, Parish","SNAP, Parish", "KCSP, Parish", 
                   "SNAP, zip"),
    overlayGroups = c("Community colleges", 
                      "Department of Corrections facilities", 
                      "Veterans Affairs Facilites"
    ),
    options = layersControlOptions(collapsed = FALSE)
  ) %>%
  showGroup("Parishes, plain")

I have tried using "hidegroup" for the legend groups, but I did not have luck with that.
So far, using htmlwidgets, I have gotten all of my legends to disappear, but I can’t get the legend of the activated layer to become visible.

Can I hint to VSCode that I want symbols in particular vanilla JS file imported as my_file_name.symbol?

I sometimes make files with a set of simple utility functions:

my_util.js

export function add(a,b) {
    return a+b;
}
export function modulo(a,b) {
    return a%b;
}

Obviously, this is a silly example but you get the point. Now when I type the symbol in another file, VS Code offers to import it:

image showes suggested import of add from my_util.js

Confirming the suggestion adds this to the top of the file:

import { add } from "./my_util.js";

But sometimes, I would prefer:

import * as my_util from "./my_util.js"
my_util.add(1, 2);

I was wondering what’s an elegant way to force the ide to do that instead of the default behavior.

Something like:

my_util.js

// @import-all-as my_util

export function add(a,b) {
    return a+b;
}
export function modulo(a,b) {
    return a%b;
}

Wait for function to finish before running it a second time

I have a function in my JavaScript application that gets called from various places. Sometimes, it gets called multiple times in quick succession. When this happens, it produces incorrect results because the first iteration hasn’t finished running when the second iteration starts.

For example:

function myFunction() {
    $("#myList").empty();
    //Do a bunch of stuff like maybe adding "x" and/or "y", to the list
    //API Call
    //success response = ["a", "b", "c"], response = ["d", "e", "f"]
    $.each(response, function(item) {
        $("#myList").append(`<li>${item}</li>`);
    }
}

myFunction();
myFunction();

This results in the list being emptied twice in a row. Then the API in the first call to myFunction returns and adds list items. Then the API in the second call to myFunction returns and adds more list items. This results in a longer list than expected. The expected result is something like:

<ul id="myList">
  <li>x</li> <!-- if second run results in adding x -->
  <li>d</li>
  <li>e</li>
  <li>f</li>
</ul>