Draggable items with out of bound drag zone in Vuejs using HTML5 canvas

The problem is that the drag zone of the rectangle shape is somewhere around and outside the rectangle shape whether partially or completely instead of being within the range of the rectangle itself completely.

The part responsible for creating shape is drawshape function and the one responsible for the shape movement is mousemove function.

This is my code:

<template>
  <v-app>
    <v-main>
      <v-app-bar color="red"></v-app-bar>

        <canvas ref="canvas"></canvas>
    </v-main>
  </v-app>
</template>

<script>
export default{
  data(){
    return{
      shapes:[],
      current_shape_index: null,
      is_drag:false,
      startX: null, 
      startY: null,
    }
  },
  mounted(){
    const canvas=this.$refs.canvas;
    console.log(canvas);
    const context= canvas.getContext("2d");
    canvas.width = window.innerWidth-35;
    canvas.height = window.innerHeight-85;
    canvas.style.border= '10px solid blue';

    this.shapes.push({ type: 'rectangle', x: 100, y: 100, width: 100, height: 100,color:'red', initZoneColor: 'green'});
    this.shapes.push({ type: 'rectangle', x: 100, y: 100, width: 200, height: 50,color:'orange', initZoneColor: 'green'});
    this.shapes.push({ type: 'rectangle', x: 100, y: 100, width: 200, height: 5,color:'green', initZoneColor: 'green'});
    this.drawShape(context);
    canvas.onmousedown=this.mousedown;
    canvas.onmouseup=this.mouseup;
    canvas.onmouseout=this.mouseout;
    canvas.onmousemove=this.mousemove;
  },
  methods:{
    drawShape(context){
      context.clearRect(0, 0, context.canvas.width, context.canvas.height);
      // Draw each shape
      this.shapes.forEach(shape => {
        context.fillStyle = shape.color;
        if (shape.type === 'rectangle') {
          context.fillRect(shape.x, shape.y, shape.width, shape.height);
        } else if (shape.type === 'circle') {
          context.beginPath();
          context.arc(shape.x, shape.y, shape.radius, 0, Math.PI * 2);
          context.fill();
        }
        // Draw text if available
        if (shape.text) {
          context.fillStyle = 'black';
          context.font = '14px Arial';
          context.fillText(shape.text, shape.x, shape.y);
        }
      })
    },
    is_shape(x,y,shape){
      const sl=shape.x;
      const sr=shape.x + shape.width;
      const st=shape.y;
      const sb=shape.y+shape.height;

      if(x>sl && x<sr && y>st && y<sb){
        return true;
      }
      return false;
    },
    mousedown(event){
      event.preventDefault(); 
      this.startX=parseInt(event.clientX);
      this.startY=parseInt(event.clientY); 
      let index=0;
      for (let shape of this.shapes){
        if(this.is_shape(this.startX,this.startY,shape)){
          console.log("INIT");
          this.current_shape_index=index;
          this.is_drag=true;
          return;
        }else{
          console.log("No");
        }
        index++
      }
    },
    mouseup(event){
      if(!this.is_drag){
        console.log("Not moving")
        return;
      }
      event.preventDefault();
      this.is_drag=false;
    },
    mouseout(event){
      if(!this.is_drag){
        console.log("Out of Bound")
        return;
      }
      event.preventDefault();
      this.is_drag=false;
    },
    mousemove(event){
      if(!this.is_drag){
        return;
      }else if(this.is_drag){

        event.preventDefault();
        let mouseX=parseInt(event.clientX);
        let mouseY=parseInt(event.clientY);

        let dx=mouseX-this.startX;
        let dy=mouseY-this.startY;
        console.log(dx,dy);

        let current_shape=this.shapes[this.current_shape_index];
        console.log(current_shape);
        current_shape.x+=dx;
        current_shape.y+=dy;

        const canvas = this.$refs.canvas;
        const context = canvas.getContext("2d");
        this.drawShape(context);
        this.startX=mouseX;
        this.startY=mouseY;
      }
    },
  }
}
</script>

PHP and 403 issue

So I have a SPA with 4 simple buttons. The site is actually just my digital resume. I have two buttons at the top:
One opens a Download modal window with a captcha in it. They complete the captcha the download button gets enabled and it should download a pdf file using a download handler php script to protect the file from bots etc. The other button opens a contact form that works much the same way, a captcha that allows the send button to enable, and the form to actually send. That contact part works flawlessly, sends the message etc.

The download is where I am getting issues. It is giving me a 403 error and from my troubleshooting it seems to be that captcha isn’t recorded but it has to be or the button wouldn’t have enabled and wouldn’t be clickable. The contact form portion is working without issue and sending the message, just the download isn’t working.

I tried everything I can think of, and even tried to do some troubleshooting with ChatGPT, but am currently going in circles. I am not a dev, but know just enough to be dangerous. Can anyone offer some guidance?

Here are the two main files with redactions:

form-handler.js:

document.addEventListener('DOMContentLoaded', function() {
    var contactModal = document.getElementById('contactModal');
    var downloadModal = document.getElementById('downloadModal');
    var notificationPopup = document.getElementById('notificationPopup');

    document.getElementById('contactBtn').addEventListener('click', function() {
        setupCaptcha('contactModal', 'contactCaptcha', 'RECAPTCHA_SITE_KEY', enableSubmitBtn, 'submitBtn');
    });

    document.getElementById('downloadBtn').addEventListener('click', function() {
        setupCaptcha('downloadModal', 'downloadCaptcha', 'RECAPTCHA_SITE_KEY', enableDownloadBtn, 'downloadLinkBtn');
    });

    document.getElementById('contactForm').addEventListener('submit', function(event) {
        event.preventDefault();
        submitForm(this);
    });

    document.getElementById('downloadLinkBtn').addEventListener('click', initiateDownload);
});

function setupCaptcha(modalId, widgetId, siteKey, callback, buttonId) {
    var modal = document.getElementById(modalId);
    var container = document.createElement('div');
    container.id = widgetId;
    container.className = 'g-recaptcha captcha-padding';
    container.style.textAlign = 'center';
    container.style.display = 'flex';
    container.style.justifyContent = 'center';
    container.style.padding = '10px 0';

    var button = modal.querySelector('#' + buttonId);
    button.parentNode.insertBefore(container, button);
    window[widgetId] = grecaptcha.render(container, {
        'sitekey': siteKey,
        'callback': callback
    });
}

function enableSubmitBtn() {
    document.getElementById("submitBtn").disabled = false;
}

function enableDownloadBtn() {
    document.getElementById("downloadLinkBtn").disabled = false;
}

function submitForm(form) {
    var recaptchaResponse = grecaptcha.getResponse(window.contactWidgetId);
    if (!recaptchaResponse) {
        alert("Please complete the CAPTCHA.");
        return;
    }
    var formData = new FormData(form);
    formData.append('g-recaptcha-response', recaptchaResponse);
    fetch('scripts/phpmailer.php', {
        method: 'POST',
        body: formData,
    })
    .then(response => response.json())
    .then(data => {
        if (data.success) {
            alert("Your message has been successfully received. Thank you!");
            form.reset();
        } else {
            alert("There was an error processing your request. Please try again.");
        }
    })
    .catch(error => {
        alert("There was an error processing your request. Please try again.");
    });
}

function initiateDownload() {
    var recaptchaResponse = grecaptcha.getResponse(window.downloadWidgetId);
    if (!recaptchaResponse) {
        showNotification("Please complete the CAPTCHA.", false);
        return;
    }
    fetch('scripts/download-handler.php', {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify({captcha: recaptchaResponse}),
        credentials: 'include'
    })
    .then(response => {
        if (response.ok) return response.blob();
        return response.text().then(text => { throw new Error(text || 'Download failed'); });
    })
    .then(blob => {
        const url = window.URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = 'SampleFile.pdf'; // Adjust filename as needed
        document.body.appendChild(a);
        a.click();
        window.URL.revokeObjectURL(url);
    })
    .catch(error => {
        console.error("Error initiating download:", error);
        showNotification(error.message, false);
    });
}

download-handler.php:

<?php
session_start();

// Log session variables for debugging
error_log("Session CAPTCHA completed: " . var_export($_SESSION['captcha_completed'], true));

// Decode JSON input for PHP processing
$_POST = json_decode(file_get_contents("php://input"), true);

if (!isset($_SESSION['captcha_completed']) || $_SESSION['captcha_completed'] !== true) {
    http_response_code(403);
    echo "CAPTCHA verification failed or session expired.";
    exit;
}

$file = '/path/to/your/file.pdf';
if (file_exists($file)) {
    header('Content-Description: File Transfer');
    header('Content-Type: application/pdf');
    header('Content-Disposition: attachment; filename="' . basename($file) . '"');
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    readfile($file);
    exit;
} else {
    http_response_code(404);
    echo "Requested file not available.";
    exit;
}
?>

Here is the console output in the browser if it helps:

POST https://example.com/scripts/download-handler.php 403 (Forbidden)
initiateDownload @ form-handler.js?ver=1.5.4:80
form-handler.js?ver=1.5.4:100 Error initiating download: Error: CAPTCHA verification failed or session expired.
    at form-handler.js?ver=1.5.4:88:53
(anonymous) @ form-handler.js?ver=1.5.4:100
Promise.catch (async)
initiateDownload @ form-handler.js?ver=1.5.4:99
form-handler.js?ver=1.5.4:101 Uncaught (in promise) ReferenceError: showNotification is not defined
    at form-handler.js?ver=1.5.4:101:9

Any help is greatly appreciated. I am not an expert as you will quickly be able to tell lol

How to reference highlighter.js within lit element?

How do we use highlight.js inside a lit element web component if we are importing highlight.js in a index.html file.

So for example in the head element of index.html we may have this:

    <link
      rel="stylesheet"
      href="https://unpkg.com/@highlightjs/[email protected]/styles/default.min.css"
    />
    <script type="module">
      import hljs from 'https://unpkg.com/@highlightjs/[email protected]/es/highlight.min.js';
      //  and it's easy to individually load & register additional languages
      import go from 'https://unpkg.com/@highlightjs/[email protected]/es/languages/go.min.js';
      hljs.registerLanguage('go', go);
    </script>

Which makes hljs available, but if we try to use it inside the connectedCallback function of the web component like this:

this._code = hljs.highlightElement(this.innerHTML);

The linting creates the error:

Cannot find name 'hljs'.(2304)
any

So how should we go about referencing hljs within the web component?

Next14 project deployed in Vercel with “notfound” page infinitely reloading

This happens only in production. What can it be?

The only import I have in the notfound page is:

import Link from "next/link";

And this is my nextconfig file:

/** @type {import('next').NextConfig} */
const nextConfig = {
    typescript: {
        ignoreBuildErrors: true,
     },
};

export default nextConfig;

I’ve already looked up answers here on StackOverFlow, but they just say that this only happens when it’s not in production.

Getting Started with protocol/configuration file builder

I have built an application which delivers a series of “tasks” each written in psychJS (javascript). Each task has a name and a large series of parameters. The platform delivers all of the tasks with the appropriate parameters based on a config file.

I would like to create a browser-based interface where an end-user (non-programmer) can creates this config file. I would there to be an “add task” button which is a pull-down menu where the options are dynamically loaded up from a mySQL call/result. Then the user clicks the added task and a new window opens up where all the parameters are displayed and the end-user makes selections. The parameters will be booleans, pulldowns, or number entry. The required parameters for each task are loaded from a JS file.

The end result is/are config file(s) that the main “task” platform delivers.

I have included examples of the end resultant config files below.

I am asking for direction on how to get started on this. Where to start, what to read, etc. I am comfortable with JS and have a rudementary knowledge of ReactJS. I am thinking this would be a good project for me to learn ReactJS.
Thank you.

var List = []
List.push({Task: 'Screening', Parameters: 'BriefScreening', Instructions: '', IconName: 'Screening'})
List.push({Task: 'Intake Form', Parameters: 'IntakeForm_EN', Instructions: 'Default', IconName: 'Intake'})
List.push({Task: 'Word Recall', Parameters: 'RAVLT_Spoken_Immediate', Instructions: 'Default', IconName: 'Immediate'})
List.push({Task: 'Card Sort', Parameters: 'CardSort_001', Instructions: 'Default', IconName: 'Card Sort'})
List.push({Task: 'Pattern Comparison', Parameters: 'PatternComparison_001', Instructions: 'Default', IconName: 'Patt Comparison'})
List.push({Task: 'Spetial DMS', Parameters: 'SpatialDMS_Adaptive', Instructions: 'Default', IconName: 'Dots'})

BatteryList.push({index: 16, 
    name:'Demo', 
    description: 'Test',
    BatteryInstructions: '<p class="Instructions">Neural Cognitive Mapping Laboratory - <b>Cognitive Evaluation</b>',
    Language:'EN',
    RunAudioTest: true,
    Footer: '©NCMLab 2024',
    TaskList: List,
})

And the parameter file for a single task is:

var RAVLT_Spoken_Delayed = {
    FolderName: 'RAVLT_en_US-Neural2-F_Speed100/',
    WordList: 'RAVLT',
    FileExtension: '.wav',
    NBlocks: 1,
    BListFlag: false, // Check to see if there is a second set of words
    RecallType: 'Spoken',
    RecallDuration: 60, // seconds
    DelayBeforeShowingDoneButton: 10,
    TimePerWord: 1500, // milliseconds
    DelayedRecallFlag: true,
    ShowWelcome: false,
    ShowThankYou: false,
    ShowInstructions: true,
    AskForNotes: false,
}

Microsoft Edge gap mouseout issue

In Microsoft Edge, there is a gap between the <select> menu and its options when you expand the menu, like this:

enter image description here

This can lead to issues with the mouseout event since the behavior is not consistent with Chrome. Consider this minimal example:

const menu = document.getElementById('menu');

menu.addEventListener('mouseout', (e) => {
  // The line below fixes the glitch in Firefox, but not Edge
  if (e.relatedTarget === null) return;
  document.body.classList.toggle('red');
});
.red {
  background: red;
}
<select id="menu">
  <option>One</option>
  <option>Two</option>
  <option>Three</option>
</select>

In Edge and only in Edge, when you move the mouse cursor between the menu and its expanded options, it triggers the mouseout event. How do you prevent this behavior in Edge?

Set auto-width for embedded facebook posts

I am working on a simple HTML/CSS/Javascript + jQuery app that displays embedded facebook posts based on data returned by an API. Everything is working nicely, except I’m having a hard time setting the width + height for the posts themselves. I’m wanting to set the width/height to auto or fit-content so that the frame will stretch to fit the content, but those styling rules are having no effect. If I set a specific width/height in pixels, I see changes, but that means that I have to set the width per the widest post, and then the posts with smaller images have tons of whitespace around them. Same goes for the height.

It’s always tricky to handle styling when there is a ton of boilerplate code that I didn’t write myself…but I’m wondering why I’m able to change the width/height in pixels, but not able to use a rule like auto. I’d love to understand this better if anyone has any ideas what’s happening.

Here is a codepen, and see below for code as well. You will find that if you set the width to 700px and the height to 800px, you’re able to see the full content, but then there is way too much whitespace, and the posts are too big in general.

facebookArr = [{
    post_id: "959689765514464",
    post_type: "FB"
  },
  {
    post_id: "959696358847138",
    post_type: "FB"
  },
  {
    post_id: "959720495511391",
    post_type: "FB"
  },
  {
    post_id: "959725872177520",
    post_type: "FB"
  },
  {
    post_id: "959763208840453",
    post_type: "FB"
  },
  {
    post_id: "960116688805105",
    post_type: "FB"
  },
  {
    post_id: "960201025463338",
    post_type: "FB"
  },
  {
    post_id: "960245285458912",
    post_type: "FB"
  },
  {
    post_id: "960383525445088",
    post_type: "FB"
  },
  {
    post_id: "960441922105915",
    post_type: "FB"
  },
  {
    post_id: "960785228738251",
    post_type: "FB"
  },
  {
    post_id: "960845102065597",
    post_type: "FB"
  }
];

// Store container in variable
let facebookContainer = document.getElementById("facebook-feed-container");

facebookArr.forEach((post) => {
  const postId = post.post_id;

  const postContainer = document.createElement("div");
  facebookContainer.append(postContainer);
  postContainer.classList.add("post");

  $(".post--title").hide();

  // Append relative container to DOM parent container
  const postFrame = document.createElement("iframe");
  postContainer.append(postFrame);
  postFrame.classList.add("facebook-post-frame");
  postFrame.id = `fb-post__${postId}`;
  postFrame.src = `https://www.facebook.com/plugins/post.php?href=https%3A%2F%2Fwww.facebook.com%2FIconicCool%2Fposts%2F${postId}&show_text=true`;
  postFrame.frameborder = "0";
  postFrame.allowfullscreen = "true";
  postFrame.allow =
    "autoplay; clipboard-write; encrypted-media; picture-in-picture; web-share";
});
#facebook-feed-container {
  display: flex;
  flex-direction: row;
  row-gap: 1rem;
  column-gap: 3rem;
  padding: 1rem;
  flex-wrap: wrap;
}

.facebook-post-frame {
  width: fit-content; //does not work, must set px
  height: fit-content; //does not work, must set px
}
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<div id="facebook-feed-container">

</div>

Do you need an overall “entity” class for actors in NodeJS canvas game?

I was wondering whether you should have a super class that all the other actor classes extend, or do each actor class individually. For example, should I have an entity class which the player and enemy class extend, or should I code the player and enemy individually?

I have mainly just coded the classes individually, and it worked, however I see other people using an overall “actor” class. Should I do that?

how to change titles in UploadThing

I’m using the library UploadThing. And I want to change these names to my own:

enter image description here

This is my code

"use client";

import toast from "react-hot-toast";

import { UploadDropzone } from "@/lib/uploadthing";
import { ourFileRouter } from "@/app/api/uploadthing/core";

interface FileUploadProps {
  onChange: (url?: string) => void;
  endpoint: keyof typeof ourFileRouter;

};

export const FileUpload = ({
  onChange,
  endpoint,
}: FileUploadProps) => {
  return (
    <UploadDropzone
      endpoint={endpoint}
      onClientUploadComplete={(res) => {
        onChange(res?.[0].url);
      }}
      onUploadError={(error: Error) => {
        toast.error(`${error?.message}`);
      }}
    />
  )
}

I would like to get this result. I was able to do this through the element code:

enter image description here

How to import all google variable fonts at once in NextJS project?

I am trying to get all google variable fonts in a text editor app that let user change font family of the text they are inserting, how can I import all google variable fonts at once.

I downloaded all google variable fonts from font-source github repo, but I can’t import them in the project at once. enter image description here
enter image description here

Also tried to use font-source but it also requires installing fonts one by on.
enter image description here

How do you change document style in functional react component

I’m learning react and clearly missing something.. I’m just trying to set the backgroundImage after a functional component is loaded.

    const root = ReactDOM.createRoot(
      document.getElementById('root') as HTMLElement
    );
    root.render(
      <React.StrictMode>
          <App />
      </React.StrictMode>
    );

Changing the backgroundImage outside of App() works fine.

When I move the code into App() it does not work.

    // This works!
    // document.body.style.backgroundImage = `linear-gradient(to right, #ffffff, #111111)`;

    function App() {
    
      const t = (new Date().getTime() & 0x0fffffff).toString(16);

      // Does not work!
      useEffect(() => {
          document.body.style.backgroundImage =
            `linear-gradient(to right, #ffffff, #${t})`;
      }, [t]);
    
      return (
        <div className="App">hello</div>
      );
    }

How does Wasm code run in browsers and how does it interact with JavaScript

I’m curious about how WebAssembly (Wasm) code operates in the browser. I understand that JavaScript code in the browser is executed by the JavaScript engine, but I’m unsure about who executes the Wasm binary. Is it also the JavaScript engine?

Additionally, I’d like to understand how asynchronous JavaScript functions interact with Wasm. When we load a Wasm binary through JavaScript and call an exported Wasm function, it’s added to the JavaScript call stack. But what happens if the Wasm function calls an asynchronous JavaScript function inside its body? Is the callback of the asynchronous function added to the JS queue stack? Do JS and Wasm share the same call stack and event queue, or do they each have their own? If they each have their own stacks and queues, how do they coordinate execution?

twilio function to get call status

I’m using a simple but effective javascript function to make calls depending on working hours and days. It works ok but i need to evaluate the call state (busy, no-answer, etc). The script goes like this.

const joe = "+123456";
const curly = "+1231321";
const moe = "+12313";

exports.handler = function (context, event, callback) {
  const twiml = new Twilio.twiml.VoiceResponse();

  console.log(event);

  let moment = require("moment-timezone");
  let timezone = event.timezone || "America/Argentina/Buenos_Aires";

  console.log("+ timezone: " + timezone);

  const hour = moment().tz(timezone).format("H");
  const dayOfWeek = moment().tz(timezone).format("d");

  console.log("Hora: " + hour);
  console.log("Dia: " + dayOfWeek);
    
  if (hour >= 9 && hour <= 24 && dayOfWeek == 1) {
    //response = "1";
  } else if (hour >= 9 && hour <= 24 && dayOfWeek == 2) {
    //response = "2";
    twiml.dial(joe); 
// THIS IS THE PART I NEED TO EVALUATE IF JOE HAS "NO-ANSWER" OR "BUSY". THEN CALL CURLY.
    twiml.dial(curly);
    //si se corta la llamada de juan se activa juli, si se atiende la de juan se llama a juli. Hay que poner una condicion para eso. ver como.
  } else if (hour >= 9 && hour <= 24 && dayOfWeek == 3) {
    //response = "3";
    twiml.dial(juan);
  } else if (hour >= 9 && hour <= 24 && dayOfWeek == 4) {
    //response = "4";
    twiml.dial(juan);
  } else if (hour >= 9 && hour <= 24 && dayOfWeek == 5) {
    //response = "5";
    twiml.dial(juan);
  } else if (hour >= 9 && hour <= 24 && dayOfWeek == 6) {
    //response = "6";
    twiml.dial(juan);
  } else if (hour >= 9 && hour <= 24 && dayOfWeek == 7) {
    //response = "7";
    twiml.dial(juan);
  }
  return callback(null, twiml);
};

Thanks a lot in advance!.

Regards!