preventDefault() doesn’t function as documented

The MDN documentation says

The preventDefault() method of the Event interface tells the user agent that if the event does not get explicitly handled, its default action should not be taken as it normally would be.

But, even if I add a listener and thereby explicitly handle the event, preventDefault() still prevents the default handling, even though the documentation specifically says it prevents the default if the event isn’t handled.

It appears it prevents the default handling regardless of whether the event is explicitly handled.

Google Maps Autocomplete started giving “This page can’t load Google Maps correctly” Error

I have a React + Typescript application that displays an address text input and a map. I have connected Autocomplete to the input element and everything was working fine. I built it and deployed it to AWS S3 as a static site and it’s fine. As I was doing some more editing of my local code, the local version started giving me the above error (I stupidly did not save the code yet). I’m running locally using vite.

The MyMap component is wrapped using the @googlemaps/react-wrapper:

   <TextField required id="location-id" label="Enter address" variant="standard" />

    :

   <Wrapper apiKey={API_KEY} render={render} libraries={["places"]}>
       <MyMap coords={coords}
              center={center}
              style={{width: "calc(65vw-5)", height: "calc(70vh)"}}
              setPoint={setCenter}
       />
   </Wrapper>

MyMap.tsx:

const options = {
    bounds: <the bounds of my area>,
    componentRestrictions: {country: 'us', state: 'va'},
    strictBounds: false,
    fields: ["address_components", "geometry"],
    types: ["address", "routes", "locality", "intersection"],
};

export default function MyMap(props: propsType){

   :
            setMap(new window.google.maps.Map(ref.current, {
                center: {lat: DEFAULT_LAT, lng: DEFAULT_LNG},
                zoom: DEFAULT_ZOOM,
            }));

        }

      :
       // Set up the autocomplete feature
       const input = document.getElementById('location-id') as HTMLInputElement;
       console.log('found input element: ', input);
       const autocomplete = new window.google.maps.places.Autocomplete(input, options);

I get no errors or warnings in the console log. My places API is enabled and works when running the version I deployed two days ago. Is there any way to debug the Autocomplete feature? I see the network calls being made, and they are responding with javascript, e.g. “/**/xdc._66hdg9 && xdc._66hdg9( [4] )”

This is what I’m getting now:

enter image description here

This is what I see on my AWS S3 site:
enter image description here

puppeteer nodejs, cant take the value outside of the evaluate scope

I have a puppeteer program, which i get the element of a div, and then process its children.
When I try to log with console.log(), I can inspect and see the value on browser. Yet on node js, console, I can’t see the value that was supposed to be pushed to the array.

This is a longer program, but i just post the code of the function where my problem is related. What is the reason to this ? I also checked How can I pass variable into an evaluate function? to interact outside scope variables with .evaluate()..
if the console.log() gives the correct value, that means the value is obtained, but the push method fails. And I dont see a warning or a error on both browser or program log. What is the reason ?

async function observer(){
    await page.waitForFunction("document.querySelectorAll("div[id='myid']").length > 1")
    var arrayOfMailNames = []
    await page.evaluate((arrayOfMailNames) => {
        var parentDiv = document.querySelectorAll("div[id='myid']");
        for(var t = 0; t < parentDiv.length; t++){
                if(parentDiv[t].getAttribute('id') !=null){
                    console.log(` ${parentDiv[t].split(";")[0]}`); //returns correct values on the browser's console. 
                    arrayOfMailNames.push(parentDiv[t].split(";")[0]); //apparently doesnt work
                }
        }
    }, arrayOfMailNames)
    console.log(`${arrayOfMailNames.length}`); //logs 0 on nodejs terminal.. which is not correct because I used push above
}

Using Selection API to distinguish between start of line and end of line positions for the same index

The Selection API can be used to detect the cursor’s position in a contenteditable container. However, if a cursor is placed at the very end of a line, or at the very beginning, I can not find a way to detect the difference as the index is the same. Even if I use the getBoundingClientRect() method on the range, it still returns the call bounding box for the two separate locations.

I have two screenshots showing the cursor in both positions and the details showing the same information

Showing cursor at end of line

Showing cursor at the start of the line

The snippet below can also demonstrate this

const updateRange = () => {
  const range = document.getSelection()?.getRangeAt(0);
  const rect = range.getBoundingClientRect();
  let res = {
    startOffset: range.startOffset,
    endOffset: range.endOffset,
    top: rect.top,
    bottom: rect.bottom,
    left: rect.left,
    right: rect.right,
  };
  
  document.querySelector('code').textContent = JSON.stringify(res, null, 2);
};

const div = document.querySelector('div');

div.addEventListener('click', updateRange);
div.addEventListener('keyup', updateRange);
main {
  display: grid;
  grid-template-columns: 1fr 1fr;
}
div {
  font-family: monospace;
  font-size: 4rem;
  width: 200px;
  padding: 1rem;
  word-wrap: break-word;
}

code {
  white-space: pre;
  float: right;
}
<main>
  <div contenteditable>CONTENT</div>
  <code></code>
</main>

I’m implementing a method to remove the entire visual line (deleteEntireSoftLine from here). Obviously this should behave differently depending on these two different scenarios.

I’ve tested this both on Brave/Chromium and Firefox. Both had the same functionality. Using getClientRects() performed the same as getBoundingClientRect().

I did notice that if I set the div to display: inline-block, I can no longer forcefully place the cursor at the clear end of the line, however I want the user to be able to place the cursor at the end of the line.

display button into html form failed with initialize

My script doesn’t work well.
When the button “b5” clicked with ouside <form …> … element, the buttons b5 and b4 deseapper and the buttons b1,b2,b3 appear. This work normaly when my code about button is not inside the <form …> … element…
When i put inside and i press or click the button b5, it reverses. It means i still get the buttons b4 and b5. Please help.

<form action="" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="row">
<div class="col-md">
<div class="card card-body" >
<h5>Informations</h5>
<hr>
<p>Nom:</p>
<fieldset>
<input name="LibELE_GROUPE" type="text" id="LibELE_GROUPE" value="{{groupe.LibELE_GROUPE}}" size="35"
placeholder="Nom du groupe" tabindex="1" required>*
</fieldset>

            </div>   
        </div>
    
        <div class="col-md">
            <div class="card card-body" style="width:300px; margin-left:40%;">
                <h5>Total des Utilisateurs</h5>
                <hr>
                <h1 style="text-align: center;padding: 10px"></h1>
            </div>
        </div>
    
    
        <div class="col-md">
            <div class="card card-body" style="width:200px; margin-left:50%;">
                <!--<h5>Client:</h5>-->
    
                <hr>
    
                {% if sEtat == "crea" %}
                <a class="btn btn-outline-success  btn-sm btn-block" href=""
                   style="font-size: 10px; ">Ajouter</a>
                <a class="btn btn-outline-info  btn-sm btn-block" href="" style="font-size: 10px;">Quitter</a>
                {% elif sEtat == "modif" %}
                <button class="b3  btn-outline-warning  btn-sm btn-block " href=""
                        style="font-size: 10px;display:None;">
                    Modifier
                </button>
                <button class="b2  btn-outline-danger  btn-sm btn-block " href=""
                        style="font-size: 10px; display:None;">
                    Supprimer
                </button>
                <button class="b1  btn-outline-secondary  btn-sm btn-block " href=""
                        style="font-size: 10px; display:None;">
                    Annuler
                </button>
                <button class="b4 btn-outline-success  btn-sm btn-block" id="AJ" name="Ajouter" type="submit"
                        value="Submit"
                        style="font-size: 10px; ">Ajouter
                </button>
                <button class="b5 btn-outline-info  btn-sm btn-block" id="QT" href="" style="font-size: 10px; ">Quitter
                </button>
    
                {% else %}
                <a class="btn btn-outline-success  btn-sm btn-block" href=""
                   style="font-size: 10px; ">Ajouter...</a>
                <a class="btn btn-outline-info  btn-sm btn-block" href="" style="font-size: 10px;">Quitter</a>
                {% endif %}
    
            </div>
    
        </div>
    
    </div>
    <script>
                                const buttons = document.getElementsByTagName("button");
    
                                var clicked = false
                                var b1 = document.querySelector(".b1")
                                var b2 = document.querySelector(".b2")
                                var b3 = document.querySelector(".b3")
                                var b5 = document.querySelector(".b5")
    
                                function hideButtons( button1, button2, button3) {
                                    clicked = false
                                    for (button of buttons) {
                                        button.style.display = "inline";
                                    }
                                    button1.style.display = (clicked ? "inline" : "none")
                                    button2.style.display = (clicked ? "inline" : "none")
                                    button3.style.display = (clicked ? "inline" : "none")
                                    clicked = !clicked
                                }
                                b1.addEventListener("click", () => {hideButtons(b2, b3, b1)})
    
                                function hideButtons1( button1, button2, button3) {
                                    clicked = false
                                    for (button of buttons) {
                                        button.style.display = "none";
                                    }
                                    button1.style.display = "inline";
                                    button2.style.display = "inline";
                                    button3.style.display = "inline";
                                    clicked = !clicked
                        }
    
    
                                b5.addEventListener("click", () => {hideButtons1(b1, b2, b3)})
    
    </script>

</form>

Tippy tooltip not working in server side datatable render function

I am creating an index on posts using Blade and I am having a problem in my code: tippy tooltip is not working on render function of datatable serve-side.

I am not getting any errors; every time I hover over the column where the tooltip is defined (description (body) column) I cannot see it.

Where am I going wrong?

FILE BLADE:

<x-layout>
    <h3>List posts</h3>
    <table id="example" class="display" style="width:100%">
        <thead>
            <tr>
              <th>ID</th>
              <th>TITLE</th>
              <th>DESCRIPTION</th>
              <th>PUBLISH</th>
            </tr>
        </thead>
    </table>

    <script src="https://unpkg.com/@popperjs/core@2"></script>
    <script src="https://unpkg.com/tippy.js@6"></script>
    <script>
        new DataTable('#example', {
            ajax: "{{ route('retrieveposts') }}",
            processing: true,
            serverSide: true,
            columns: [{
                    data: 'id',
                    name: 'id'
                },
                {
                    data: 'title',
                    name: 'title',
                    render: function(data, type, row) {
                        return `
                            <strong id="title_${row.id}" class="title"> ${data} </strong>                    
                        `;
                    }
                },
                {
                    data: 'body',
                    name: 'body',
                    render: function(data, type, row) {
                        return `
                        <div data-tippy-content="Tooltip">
                            <span id="value_description_${row.id}"> ${data}</span>
                         </div>
                         `;
                    }
                },
                {
                    data: 'is_publish',
                    name: 'is_publish',
                    render: function(data, type, row) {
                        return `
                        <span> ${data} </span>                         
                        `;
                    }
                },
            ]
        });
        
        tippy('[data-tippy-content]')

    </script>

</x-layout>

Uploading a file to Azure File Storage

I have a url with a SAS token to upload a file. I have a base64 string of a previously defined content type that I need to upload.

import { FileUploadStreamOptions, ShareFileClient } from "@azure/storage-file-share";
import { Readable } from "readable-stream";

async submitData(context: ComponentFramework.Context<IInputs>, fileName: string, ext: string, base64: string, contentType: string, classification: string, upload: any) : Promise<boolean> {
   const buffer = Buffer.from(base64, 'base64');

   let client = new ShareFileClient(upload.url);
   let readable = Readable.from(buffer);

   const options = {
       fileHttpHeaders: { 
          fileContentType: contentType,
       },
   };

   await client.uploadStream(readable, buffer.length, 4 * 1024 * 1024, 5, options);
   console.log("Upload successful");
   
   // more logic
   return true;
}

I’m having two problems with this code:

  1. The await client.uploadStream(readable, buffer.length, 4 * 1024 * 1024, 5, options); is not being awaited and the method is escaped.

  2. The uploaded file is corrupted. When downloaded, the content comes back as:

{"$content-type":"application/pdf","$content":"AAAAAAAAAAAAAA...AAAAA"}
  1. I have tried not awaiting the call and that seems to work for the most part although it really should be awaited.

  2. I tried adding encoding to the stream but that didn’t seem to work either.

Dynamically Moving A Submit Button on a pre-existing site

I work a lot of my projects with this platform and often override a lot of the pre-existing customizations to make them my own for me and my clients.

I’m having trouble creating a JS code that will allow me to move this wherever I want on the page. For example, I want the ‘Submit & Next’ button to be between the ‘Please Confirm Our Start Date’ and ‘Thank you for choosing…’ text.

I’m pretty new to Javascript, but assuming this should be easy I still don’t know how to do this. Any help would be appreciated!

Click here to view form

Using OpenAI’s real-time api with server-vad mode

I’m trying to setup the real-time api, but I’m a little confused on how the audio to audio events are suppose to work in server_vad mode.

Currently I do the following:

  1. setup the real-time client
const client = new RealtimeClient({ apiKey: process.env.OPENAI_API_KEY });
  1. set the client session:
  instructions: "be nice and helpful",
  input_audio_transcription: { model: 'whisper-1' },
  turn_detection: { type: "server_vad" },
});
  1. listen for events:
  console.log("Realtime Event: ", event);
});
  1. connect:
client.connect()
  1. send some audio:
  client.appendInputAudio(data)

However, I never receive any events other than the input_audio_append.event. Is there another step I need to take to ensure I receive a response?

Drag and Drop Image that can be Cropable

I have the following js code below which allows the user to drag and drop an image into a container. Within the container, it uses a circle mask to preview only the image content falling inside the circle. CSS for the image uses object-fit: cover to peserve the aspect ratio.

It also allows the user to drag the image to adjust what gets shown in the circular preview container. The code works as expected if the user does not adjust the images after dragging it into the container. The aspect ratio is perserved.

However, if the user shifts the container, for images where aspectRatioNatural > aspectRatioMask, the offsetX is in correctly computed. For aspectRatioNatural > aspectRatioMask, offsetY is incorrectly computed. I’ve tried to adjust the offset using the aspect ratio, but this different solve the issue. The context.drawImage is applying scaling that I can’t seem to figure out.

// Select the drop area and file input elements
let image = document.getElementById('draggableImage');
let isDragging = false;
let startX, startY, initialX, initialY;

let dropArea = document.getElementById('drop-area');
let fileInput = document.getElementById('fileElem');
let uploadForm = document.getElementsByClassName('upload-form')[0];
let deleteBtn = document.getElementsByClassName('delete')[0];
let circleMask = document.getElementById('circle-mask');
let saveImage = document.getElementById('save-image');
let canvas = document.createElement('canvas');

// Prevent default browser behavior for drag and drop
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
  dropArea.addEventListener(eventName, preventDefaults, false);
});

function preventDefaults(e) {
  e.preventDefault();
  e.stopPropagation();
}

// Handle dropped files (uses Drag and Drop API)
dropArea.addEventListener('drop', (e) => {
  let dt = e.dataTransfer;
  let files = dt.files;
  handleFiles(files);
}, false);

// Fallback to file input
document.getElementById('fileSelect').onclick = function() {
  fileInput.click();
};

circleMask.addEventListener('mousedown', function (e) {
  isDragging = true;
  startX = e.clientX;
  startY = e.clientY;
  initialX = image.offsetLeft;
  initialY = image.offsetTop;
  image.style.cursor = 'grabbing';  // Change the cursor to indicate the image is being dragged
});

document.addEventListener('mousemove', function(e) {
  if (isDragging) {
    let dx = e.clientX - startX;
    let dy = e.clientY - startY;

    // Adjust the position of the image
    image.style.left = `${initialX + dx}px`;
    image.style.top = `${initialY + dy}px`;
    image.style.cursor = 'grab';  // Reset the cursor
  }
});

document.addEventListener('mouseup', function() {
  isDragging = false;
});

// Make sure this is an image file (file type) and if valid show inside div/hide form
function handleFiles(files) {
  const file = files[0];
  if (file && file.type.startsWith('image/')) {
    previewFile(file);
    deleteBtn.classList.remove('hidden');
    uploadForm.classList.add('hidden');
  } else {
    alert('Please upload a valid image file.');
  }
}

// Preview file, enable image adjustments via dragging, and show delete button.
function previewFile(file) {
  showPreview();
  let reader = new FileReader();
  reader.readAsDataURL(file);
  reader.onloadend = function () {
    circleMask.innerHTML = ''; // Remove any existing image in the circle mask

    image = document.createElement('img');
    image.src = reader.result;

    // Apply necessary styles to the image
    image.style.position = 'absolute';
    image.style.left = '0px';
    image.style.top = '0px';
    image.style.width = '100%';
    image.style.height = '100%';

    circleMask.appendChild(image);
    document.getElementById('save-image').classList.remove('hidden');
  };
}

function showPreview() {
  dropArea.classList.remove('highlight');
  deleteBtn.classList.remove('hidden');
  circleMask.classList.remove('hidden');
  uploadForm.classList.add('hidden');
}

// Function to save only the masked image in the preview
saveImage.addEventListener('click', function () {
  let canvas = document.createElement('canvas');
  let context = canvas.getContext('2d');

  // Set canvas dimensions to match the mask's size
  const maskWidth = circleMask.offsetWidth;
  const maskHeight = circleMask.offsetHeight;
  canvas.width = maskWidth;
  canvas.height = maskHeight;

  // Get the natural dimensions of the image
  const naturalImageWidth = image.naturalWidth;
  const naturalImageHeight = image.naturalHeight;

  // Get the current image position offsets (adjustments made by dragging)
  const leftOffset = parseInt(image.style.left, 10) || 0;
  const topOffset = parseInt(image.style.top, 10) || 0;

  // Calculate aspect ratios
  const aspectRatioNatural = naturalImageWidth / naturalImageHeight;
  const aspectRatioMask = maskWidth / maskHeight;

  // Variables to store final drawing dimensions
  let drawWidth, drawHeight, offsetX, offsetY;

  // Match the behavior of `object-fit: cover`
  if (aspectRatioNatural > aspectRatioMask) {
    drawHeight = maskHeight;
    drawWidth = naturalImageWidth * (maskHeight / naturalImageHeight);

    // Adjust the X-axis calculation for drag and centering
    offsetX = (maskWidth - drawWidth) / 2 + leftOffset;
    offsetY = topOffset;  // Y-axis is fine
  } else {
    drawWidth = maskWidth;
    drawHeight = naturalImageHeight * (maskWidth / naturalImageWidth);

    offsetX = leftOffset;
    offsetY = topOffset + (maskHeight - drawHeight) / 2;
  }

  // Clear the canvas before drawing
  context.clearRect(0, 0, canvas.width, canvas.height);

  // Clip the context to the circular mask
  context.save();
  context.beginPath();
  const radius = maskWidth / 2;
  context.arc(maskWidth / 2, maskHeight / 2, radius, 0, Math.PI * 2);
  context.clip();

  // Draw the image onto the canvas with object-fit: cover behavior, adjusted for dragging
  context.drawImage(
    image,
    offsetX,  // X position adjusted for drag and object-fit scaling
    offsetY,  // Y position adjusted for drag and object-fit scaling
    drawWidth,  // Width after scaling
    drawHeight  // Height after scaling
  );

  context.restore();  // Restore after clipping

  // Convert the canvas content to a downloadable image
  const croppedImage = canvas.toDataURL('image/png');

  // Trigger the download
  const link = document.createElement('a');
  link.href = croppedImage;
  link.download = 'cropped-image.png';
  link.click();
});

I was expecting the saved image file to be identical to what is shown in the preview file. It does when I don’t move the image once inside the preview container (circle-mask).

Disable “Changes that you made may not be saved.” confirm dialog in PDF.JS viewer

Is there a way to disable the confirmation dialog Changes that you made may not be saved in the PDF.JS viewer?

When an annotation (i.e. text, line drawing, text highlighting) is added to an open document in the PDF.js viewer and an attempt is made to close the document, the viewer displays the confirmation dialog Changes that you made may not be saved. Can this be switched off?

PDF.js viewer confirmation dialog

How to add script src dynamically with getElementById?

Go easy on me – I don’t spend a lot of time in javascript. 😀

I am trying to write a script that will build a JS call based on a URL query, but cannot get the script src to update.

For example, if someone visits https://example.com/page?aid=ABC123, I want to create a script call that would function akin to:
<script type='text/javascript' src='https://example.com/script.js?aid=ABC123'></script>
But I need that call to be dynamically built based on the “aid” variable in the URL.

My “page” code looks like this:

<script type='text/javascript' src='' id='hwContent'></script>
<script type='text/javascript'>
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
const artid = urlParams.get('aid');
var url = "https://example.com/js.php?aid=";
document.getElementById('hwContent').src = url + artid;
</script>

For the moment while I’m testing, the “script.js” code is just a basic “success!” message using document.write – I haven’t even gotten to seeing if the “aid” makes it through to the script file.

If I go direct to the script URL, it works.
If I hard code the script URL into the script src field, it works.
But as soon as I leave the src field empty and rely on getElementById to insert the url into the src field, nothing happens – the area that should display the “success!” message is just blank. Chrome inspector shows no JS errors.

Carousel as a background in my hero section

How do I use a carousel as a background in my website using html and css? I also want to have texts overlaying the carousel..

I have trying using the url option in adding the background but i can’t link the carousel
I would really appreciate your assistance on this. Thank you

Azure Function App – No HTTP triggers found (works fine locally)

I’m looking to create a relatively simple javascript app that runs on node as an azure function app and will eventually return a generated png. I installed the Azure Function extension to get me going with a really simple hello world app. I published this to azure and it works fine.

The issue is – I want to use canvas to create png images but when i modify my code and publish i get No HTTP triggers found and no functions are listed on the azure portal.

I have greatly reduced the code just to show how little code actually breaks it.

httpTrigger1.js

const { app } = require('@azure/functions');
const { createCanvas } = require('canvas');  // ***

app.http('httpTrigger1', {
    methods: ['GET', 'POST'],
    authLevel: 'anonymous',
    handler: async (request, context) => {
        context.log(`Http function processed request for url "${request.url}"`);

        const name = request.query.get('name') || await request.text() || 'world';

        const canvas = createCanvas(600, 600); // ***

        return { body: `Hello, ${name}!` };
    }
});

When removing the lines commented with *** and publish to azure function app the trigger shows and the app returns the body fine.

packages.json

{
  "name": "accelerate.ai.chart_v3",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "start": "func start",
    "test": "echo "No tests yet...""
  },
  "dependencies": {
    "@azure/functions": "^4.5.1",
    "canvas": "^2.11.2"
  },
  "main": "src/{index.js,functions/*.js}"
}

Azure function app settings:
Stack = Node.js
Node.js Version: Node.js 20 LTS

Using Azure Functions Extension 1.15.4

Thanks

What is the difference of TypeScript vs TypeScript + SWC when creating a Vite project?

I’m working on a project using Vite, and I want to understand the difference between using TypeScript alone and TypeScript with SWC. I’ve searched online but couldn’t find a clear explanation. I believe it would be helpful to get answers from experienced developers, which is why I’m asking here. Could someone explain the differences and when it’s better to use one over the other?

enter image description here