How to keep canvas in bounds?

I have been struggling with an issue for a few days now. I have an editor made with CanvasJS, and I need to add ruler support and responsiveness. To achieve this, I made the canvas responsive, and it zooms out when the window is resized. However, my canvas has panning and zooming enabled, and when the maximum zoom-out is set to 20%, you can zoom in and pan from left to right.

The issue arises with my keepCanvasInBounds function, which handles the panning bounds incorrectly when I zoom in. If the initial zoom-out is below 100%, the canvas won’t pan all the way from left to right. Specifically, when zoomed in, the panning stops before reaching the far-left (30cm on the ruler), which is the expected behavior.

Here are the steps to reproduce the issue:

Access the link.
Zoom in and try to pan from left to right.
The expected outcome is that you should be able to pan all the way to the left (30cm on the ruler), but it stops prematurely. Can anyone help me out with this? Here is a link to a sandbox https://codesandbox.io/p/devbox/9969p6

Inject a script in iframe

I am trying to inject a script in a page loaded in iframe (loading a website of different origin).
I get the same origin policy error.
I tried to disable it by launching chrome with –disable-web-security flag but it seems to not work anymore.
Extensions did not work for me as well.
Is there any work around for chrome? Is there a different browser that disables web security?
Note: I don’t want to use postMessage solution as I am not going to add any scripts for the other website.
Thanks in advance

I tried the suggested solution i found for different browsers chrome, edge and brave –disable-web-security but that didn’t solve the problem. All answers I found are outdated.

How to get the result of the HTTPrequest in advance and process the result of the request after a certain condition?

Let the HTTPrequest be executed in advance. After moving the mouse to an element on the page, if the request is completed, process the result and open the link in the returned result.

Consider a delay of 1500ms for the time being, wait for the request to be completed, and process the link in the return result.

Can you judge that the HTTPrequest has been completed when opening the request result link without delay?

Request function, get a link to the returned result, and execute the request immediately.

    var jhref;
    function getWebsite(s) {
        let xhrResult = '';
        jhref = 'http://aaa.com';
            GM_xmlhttpRequest({
                method: 'GET',
                url: jhref,
                onload: function (result) {
                    xhrResult = result.status;
                    let domNew = new DOMParser().parseFromString(result.responseText, 'text/html');
                    let linkElement = domNew.querySelectorAll('.item>a')[0];
                    if(linkElement != undefined) {
                        jhref = linkElement.href;
                    } else {
                        xhrResult = 404;
                    }
                },
                onerror: function (result) {
                    console.log(result);
                },
            });
    }
          
    getWebsite(text);

Move the mouse to an element to execute the link in the return result, which must be executed after the GET request is completed.

window.open(jhref)

vue 3 both helper and comosable functions return “is not a function”

Template Code:

<template>
  <p ref="paragraphRef">i am a paragraph</p>
  <button @click="paragraphClick">click</button>
</template>

<script>
  import { ref } from 'vue'
  import helperFunction from '@/utils/helperFunction'
  
  export default {
    props: {
      paragraphText: {
        type: String,
        default: 'i am the paragraph text'
      }
    },
    setup(props) {
      const paragraphRef = ref(null)
      const paragraphClick = () => {
        helperFunction(paragraphRef, props.paragraphText, 0)
      }

      return { paragraphRef, paragraphClick }
    }
  }
</script>

Helper Function Code:

const helperFunction = (element, text, index) => {
  if (index === 0) {
    element.innerHTML = ''
  }
  
  element.innerHTML += text[index]

  if (index === text.length - 1) {
    return
  }

  setTimeout(() => helperFunction(index + 1), 100)
}

export default { helperFunction }

Problem:
Uncaught TypeError: helperFunction is not a function at Proxy.paragraphClick

I have tried a Composable Function using “watchEffect” and “unref” to track the paragraph element, but the same error occur

How do you add non-text parts to a multiturn chat with Gemini / Vertex AI?

Overview

After reviewing the documentation, it looks like multi-turn chat is only optimized for receiving a text prompt, but clearly this is something that is implemented across many AI products–Gemini, Claude, ChatGPT, and more.

So, what am I missing here? What’s the right approach to managing / supporting a multi-turn, multi-modal conversation with Vertex / Gemini 1.5?

Desired Behavior

  • Use the startChat method to start a multiturn chat.
  • Generate text (non-streaming) with multimodal input as seen in the code block below
 // To generate text output, call generateContent with the text and image
  const result = await model.generateContent([prompt, imagePart]);

Stack

  • Javascript
  • vertexai-preview library (part of the "firebase": "^10.12.2",) package

Efficient dev and debug setup for building Chrome Extensions?

What are some tips for a productive dev setup for building and debugging Chrome extensions? I use Chrome Dev Tools but the issues below still make it extremely inefficient for me to build and debug my extension.

1 – There is no way to hot reload the popup without manually launching the extension. This means that every time I make a code change, I have to manually close and reopen the popup to get to the same place.

2 – If there is an error on one of my clicks, the popup closes and so does the Chrome Dev Tools window. I can find the error on the Extension page, but I lose all the context. How can I see the full stack trace and debug this better?

3 – What is the proper way to trigger service workers for debugging? Again, having to do this from my popup makes it very time consuming.

Feel free to point me to other answers, but I couldn’t find a good guide that covers the dev productivity aspect. Thanks in advance!

Trigger download in firefox without creating history entry

I want to trigger a download from a website using window.location or other similar means while not adding a history entry. In Chrome, using window.location.replace() works and doesn’t append the history, but on Firefox, any method I’ve tried did. The URL for the download contains a token, which I’d prefer not to have stored in the browsers history.

Here are the methods I’ve tried so far, but all created a history entry:

  • window.location.replace()
  • create an tag and click it
  • create an iframe with the url set to the download location
  • use window.location and history.replaceState – only appends another entry

Are there any other options that I could try here? Note that the download path and frontend code are hosted on the same domain, so it’s not a domain mismatch

Is it possible to include tts voice in the recording in the browser?

Using the react library in the Chrome browser, we implemented a function to read text displayed on the screen using the TTS function and record the screen.
When I run the source below, the screen and microphone voice are recorded, but the voice reading the text through TTS is not included in the recording.
Can you tell me how to include tts audio in the recording?

  // Modify voice reading function
  const readSelectedTexts = (selectedTexts: string[]) => {
    if (selectedTexts.length > 0 && typeof window !== 'undefined' && window.speechSynthesis) {
      const textToRead = selectedTexts.join(', ');
      const utterance = new SpeechSynthesisUtterance(textToRead);
      utterance.lang = 'en-US'; // Set to English
      utterance.rate = 1.0;
      utterance.pitch = 1.0;
      window.speechSynthesis.speak(utterance);
    }
  };

  const startRecording = async () => {
    try {
      const displayStream = await navigator.mediaDevices.getDisplayMedia({ video: true });
      const audioStream = await navigator.mediaDevices.getUserMedia({ audio: true });
      const combinedStream = new MediaStream([
        ...displayStream.getVideoTracks(),
        ...audioStream.getAudioTracks()
      ]);
      
      mediaRecorderRef.current = new MediaRecorder(combinedStream);

      const chunks: BlobPart[] = [];
      mediaRecorderRef.current.ondataavailable = (event) => {
        if (event.data.size > 0) {
          chunks.push(event.data);
        }
      };

      mediaRecorderRef.current.onstop = () => {
        const blob = new Blob(chunks, { type: 'video/webm' });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = 'study_rec.webm';
        a.click();
        URL.revokeObjectURL(url);
        
        displayStream.getTracks().forEach(track => track.stop());
        audioStream.getTracks().forEach(track => track.stop());
        setIsRecording(false);
      };

      mediaRecorderRef.current.start();
      setIsRecording(true);
    } catch (error) {
      console.error('Failed to start screen and audio recording:', error);
    }
  };

  const stopRecording = () => {
    if (mediaRecorderRef.current) {
      mediaRecorderRef.current.stop();
      setIsRecording(false); // Status change when recording ends
    }
  };

Merging URLSearchParams back into URL object

I have recently started using the URL object to modify URLs in javascript. I am struggling to find any documentation on the procedure I am currently trying to complete though, which is modifying a query string using a URLSearchParams object and then merging that back into the URL object

    if (~url.toLowerCase().indexOf("page=")) {
        var cleanseUrl = new URL(newUrl);
        var params = new URLSearchParams(cleanseUrl.search);
        params.delete("page");
        cleanseUrl.searchParams.set(params);
        redirectUrl = cleanseUrl.href;
    }

    window.location.replace(redirectUrl)

This is currently throwing an obvious error on the cleanseUrl.searchParams.set(params) line since this function requires two parameters and is for setting individual parameters

Failed to execute ‘fetch’ on ‘Window’: The provided value is not of type ‘RequestInit’

Can not fetch data,and the error what I have seen is first time

I am testing it on laptop ,so I am using window.location.origin to fetch data

  let jsonObject = await JSON.stringify({
        name,
        description,
        cetegory,
        thumb,
        images,
        selling_price_canada: sellingStyle === 'per_price' ?selling_price_canada : 'none',
        selling_price_india: sellingStyle === 'per_price' ?selling_price_india : 'none',
        selling_Amount: sellingStyle === 'per_price' ? selling_Amount : 'none',
        selling_style,
        selling_country,
        size_and_price,
        delivery_charge_in_canada,
        delivery_charge_in_india
    })
 let fetchOptions = {
        method:'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: jsonObject
    }
    uploadTheProductBtn.style.opacity = .7;
    uploadingStatus = true;
    let url = window.location.origin + '/api/api_s/upload-product';
    
    fetch(url, jsonObject)
      .then(res => res.json())
      .then(({error, success}) => {
        if (error) return alert(error)
        if (success) return alert('success');
      })
      .catch(e => console.log(e))
      .finally(e => {
        uploadTheProductBtn.style.opacity = 1;
        uploadingStatus = false;
    })

And I found This error –

TypeError: Failed to execute ‘fetch’ on ‘Window’: The provided value is not of type ‘RequestInit’

I was expecting to post data on the server

php hash_file equivalent to javascript

has anyone encountered the issue where the value generated using the hash_file function in PHP with “sha256” does not match the one from CryptoJS.createHash(“sha256”, …)?
This is my php code:
hash_file("sha256", $filePath)

this is javascript code:
const hash = crypto.SHA256(crypto.lib.WordArray.create(buffer)); const hexHash = hash.toString(crypto.enc.Hex);

How can this be handled so that both values are the same?

Next.js automatically resets tsconfig.json ‘jsx’ option, causing React import warnings in VS Code

I am working on a Next.Js-TypeScript project. Everything was fine. Suddenly I get a VS Code warning that I have to write import React from “react” in the .tsx files where I have used Fragment (<></>) of React. But everything was fine until yesterday. I suddenly saw this situation today. Then, I searched the internet and found that the “tsconfig.json” file contains (“jsx”:”preserve”) by default, but if I change it to (“jsx”:”react-jsx”) all the problems are solved. . But there is another problem here. When I start localhost or restart, immediately a message comes in the terminal, that We detected TypeScript in your project and reconfigured your tsconfig.json file for you. Strict-mode is set to false by default. The following mandatory changes were made to your tsconfig.json: - jsx was set to preserve (next.js implements its own optimized jsx transform). After that, the tsconfig.json file is reset as before.

This is my dependencies and devDependencies:

 "dependencies": {
    "@reduxjs/toolkit": "^2.2.7",
    "bcryptjs": "^2.4.3",
    "mongoose": "^8.7.0",
    "next": "^14.2.13",
    "next-auth": "^5.0.0-beta.20",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "react-hook-form": "^7.53.0",
    "react-icons": "^5.3.0",
    "react-player": "^2.16.0",
    "react-redux": "^9.1.2",
    "react-simple-star-rating": "^5.1.7",
    "react-toastify": "^10.0.5",
    "redux-persist": "^6.0.0",
    "sass": "^1.79.4"
  },
  "devDependencies": {
    "@tailwindcss/aspect-ratio": "^0.4.2",
    "@types/bcryptjs": "^2.4.6",
    "@types/node": "^20.16.10",
    "@types/react": "^18.3.10",
    "@types/react-dom": "^18",
    "@types/redux-persist": "^4.0.0",
    "daisyui": "^4.12.10",
    "eslint": "^8",
    "eslint-config-next": "^14.2.13",
    "postcss": "^8.4.47",
    "tailwindcss": "^3.4.13",
    "typescript": "^5.6.2"
  }

Notifications sent from browser API doesn’t work on iOS [duplicate]

This is NOT about push notifications. It’s about standard HTML5 browser api notifications (https://developer.mozilla.org/en-US/docs/Web/API/Notification)

Prerequisite:

  • App which is a vueJS SPA app was installed on iOS home screen.
  • Notification.permission === “granted” was obtained

This is in the context of a Javascript VueJS non native app.
Code used to send notifications:

const sendnotification = () => {
  try {
    new Notification(`Alert title`, {
      body: `alert body`
    });
    flashMessageStore.setMessage("Notification was sent", 'info');

    console.log("Notification sent");
  } catch (error) {
    alert("sendnotification: ", error);
  }
};

No error is shown, it’s as if nothing happens: notification just don’t appear.
It works perfectly on dekstop browser. Not on Chrome mobile (haven’t tested other mobile browsers).

  • I didn’t installed specifically a web service worker. Should I ?
  • What could be the problem ?

Can’t read clipboard in Telegram WebApp: Permissions policy blocking Clipboard API

I’m developing a web application inside Telegram’s WebApp (Mini App), and I’m trying to read or write text to the clipboard using the Clipboard API. However, when I try to execute navigator.clipboard.writeText() or navigator.clipboard.readText(), I receive the following error:

NotAllowedError: Failed to execute 'writeText' on 'Clipboard': The Clipboard API has been blocked because of a permissions policy applied to the current document.

Is here another way to read content from clipboard?

  1. Checked for Clipboard API availability:
    I verified that navigator.clipboard is available in the environment. The Clipboard API exists, so it should theoretically work.

  2. Triggered clipboard operations through user interaction:
    To meet security requirements, I made sure that both clipboard read and write operations were triggered via a user action, such as clicking a button. Here’s an example of the code I used:

  3. Tried both reading and writing text:
    I tried both navigator.clipboard.writeText() for writing to the clipboard and navigator.clipboard.readText() for reading from the clipboard. Both operations throw a NotAllowedError with a message saying the clipboard has been blocked due to a permissions policy.

  4. Tested in different environments:

In Chrome: The clipboard functionality works as expected in a standard Chrome browser (both desktop and mobile). I can successfully read and write to the clipboard after user interaction.

In Telegram WebApp: The same code throws the NotAllowedError when run inside Telegram’s WebApp (Mini App). This suggests the WebView in Telegram is applying stricter security policies or permissions that block access to the Clipboard API.

Phaser object not Draggable

This code does not allow the rectangle w/topbar to be draggable. What do I need to change? I created a scrollabel Phaser scene and can get the ‘box’ to draw but it is not draggable. When the user selects the topbar I want to be able to move the box in any direction within the phaser container.

This code creates the phaser scene and the scene is scrollabel x and y but the box crateed can not be selected or dragged.

let currentScene; // Global variable to store the current scene
let mainRect, topBar; // Global variables to store the main rectangle and top bar
let isDragging = false; // Variable to track if dragging is in progress

function preload() {
  console.log("Preload function called"); // Log when preload is called
  // Load assets here if needed
}

function create() {
  console.log("Create function called"); // Log when create is called
  // Assign the created scene to currentScene
  currentScene = this;

  // Log the current scene
  console.log("Current Scene:", currentScene);

  // Enable camera controls for scrolling
  this.cameras.main.setBounds(0, 0, 5000, 300); // Set the bounds of the camera
  this.cameras.main.setScroll(0, 0); // Initialize the camera position

  // Add event listener to handle two-finger scrolling within the Phaser canvas
  this.input.on('wheel', (pointer, gameObjects, deltaX, deltaY, deltaZ) => {
    if (!isDragging) {
      this.cameras.main.scrollX += deltaX;
      this.cameras.main.scrollY += deltaY;
    }
  });

  // Add touch event listeners to handle touch-based scrolling within the Phaser canvas
  this.input.on('pointerdown', (pointer) => {
    if (pointer.isDown && !isDragging) {
      this.input.dragStartX = pointer.x;
      this.input.dragStartY = pointer.y;
      this.input.cameraStartX = this.cameras.main.scrollX;
      this.input.cameraStartY = this.cameras.main.scrollY;
    }
  });

  this.input.on('pointermove', (pointer) => {
    if (pointer.isDown && !isDragging) {
      const deltaX = pointer.x - this.input.dragStartX;
      const deltaY = pointer.y - this.input.dragStartY;
      this.cameras.main.scrollX = this.input.cameraStartX - deltaX;
      this.cameras.main.scrollY = this.input.cameraStartY - deltaY;
    }
  });

  // Expose createActivityObject to the global scope for button click
  window.createActivityObject = () => createActivityObjectInternal(currentScene);
}

function update() {
  // Log the positions of the main rectangle and top bar during the update
  if (mainRect && topBar) {
    console.log(`Update - mainRect: (${mainRect.x}, ${mainRect.y}), topBar: (${topBar.x}, ${topBar.y})`);
  }
}

const config = {
  type: Phaser.AUTO,
  width: 5000, // Set the width of the visible area
  height: 300, // Set the height of the visible area
  parent: "phaser-container",
  backgroundColor: 'rgb(200, 249, 251)', // Set the background color of the Phaser scene
  scene: {
    preload: preload,
    create: create,
    update: update,
  },
  render: {
    pixelArt: true, // Enable pixel art rendering for sharper edges
    antialias: false, // Disable antialiasing for sharper edges
  },
};

document.addEventListener("DOMContentLoaded", () => {
  console.log("DOMContentLoaded event fired"); // Log when DOMContentLoaded event fires
  let game = new Phaser.Game(config);
  console.log("Game:", game); // Log the game object

  // Add event listener to the button to create the draggable object
  document.getElementById("create-activity-button").addEventListener("click", () => {
    if (currentScene) {
      createActivityObjectInternal(currentScene);
    }
  });
});

// Internal function to create a draggable rectangle with a top bar
function createActivityObjectInternal(scene) {
  console.log("Creating activity object"); // Log the function call
  console.log("The scene is: ", scene); // Log the scene object

  if (!scene) {
    console.error("Scene is not defined");
    return;
  }

  const scale = 0.15; // Scale factor to reduce size to 15%
  const rectWidth = 400 * scale * 1.5; // Increase width by 50%
  const rectHeight = 100 * scale; // Keep height the same
  const topBarHeight = 12 * scale;
  const rectX = 100;
  const rectY = 100;

  // Create the main rectangle
  mainRect = scene.add.rectangle(rectX, rectY + topBarHeight, rectWidth, rectHeight - topBarHeight, 0xffffff).setOrigin(0);
  mainRect.setStrokeStyle(2 * scale, 0x000000);
  mainRect.setDepth(1); // Ensure the main rectangle is on top
  console.log("Main rectangle created:", mainRect); // Log the main rectangle creation

  // Create the top bar
  topBar = scene.add.rectangle(rectX, rectY, rectWidth, topBarHeight, 0xffa500).setOrigin(0);
  topBar.setStrokeStyle(2 * scale, 0xffa500);
  topBar.setDepth(2); // Ensure the top bar is on top
  console.log("Top bar created:", topBar); // Log the top bar creation

  // Ensure the topBar is created before making it draggable
  if (topBar) {
    console.log("Top bar is not null or undefined"); // Log the top bar check

    // Check if input plugin is available
    if (scene.input) {
      console.log("Input plugin is available"); // Log input plugin availability

      // Add the top bar to the input system
      topBar.setInteractive();
      scene.input.setDraggable(topBar);
      console.log("Top bar added to input system and set as draggable"); // Log input system addition and draggable setting

      // Handle dragging
      scene.input.on("dragstart", (pointer, gameObject) => {
        console.log("Drag start:", gameObject); // Log drag start
        isDragging = true; // Disable scrolling
      });

      scene.input.on("drag", (pointer, gameObject, dragX, dragY) => {
        if (gameObject === topBar) {
          mainRect.x = dragX;
          mainRect.y = dragY + topBarHeight;
          topBar.x = dragX;
          topBar.y = dragY;
          console.log("Dragging:", { dragX, dragY }); // Log dragging coordinates
        }
      });

      scene.input.on("dragend", (pointer, gameObject) => {
        console.log("Drag end:", gameObject); // Log drag end
        isDragging = false; // Re-enable scrolling
      });
    } else {
      console.error("Input plugin is not available");
    }
  } else {
    console.error("Failed to create topBar");
  }
}