Myers diff with a custom cost function

Myers diff algorithm treats insertion and removal equally at the same cost and treats equality at zero cost (free path).

I tried to alter this behavior with supplying a custom cost function which to begin with favours removal (with a cost of -1), then favours equality (with a cost of 0) and then favours insertion (with a cost of 1).

On running the following modified version and doing a diff on PQRSTUZ v/s PQTUARS, I get TUA as inserted and TUZ as removed.

        class Keep {
            constructor(line, coordinate, cost) {
                this.type = 'Keep';
                this.line = line;
                this.coordinate = coordinate;
                this.cost = cost;
            }
        }

        class Insert {
            constructor(line, coordinate, cost) {
                this.type = 'Insert';
                this.line = line;
                this.coordinate = coordinate;
                this.cost = cost;
            }
        }

        class Remove {
            constructor(line, coordinate, cost) {
                this.type = 'Remove';
                this.line = line;
                this.coordinate = coordinate;
                this.cost = cost;
            }
        }

        // Represents a point on the frontier with its history AND cost
        class Frontier {
            constructor(x, history, cost) {
                this.x = x; // x-coordinate in edit graph
                this.history = history; // sequence of operations to reach this point
                this.cost = cost; // Total cost to reach this point
            }
        }

        function visualizePath(history, oldSequence, newSequence) {
            const matrix = [];
            const costMatrix = [];
            const rows = newSequence.length + 1;
            const cols = oldSequence.length + 1;
            const firstRow = Array.from(` ${oldSequence.map(item => item.hashVal).join('')}`);

            matrix[0] = firstRow;
            costMatrix[0] = firstRow;

            for(let r = 1, c = 0; r < rows; r++) {
                matrix[r] = Array.from("·".repeat(cols))
                matrix[r][c] = newSequence[r-1].hashVal;

                costMatrix[r] = Array.from("·".repeat(cols))
                costMatrix[r][c] = newSequence[r-1].hashVal;
            }

            for(const item of history) {
                const {type, coordinate, cost} = item;
                let sign = null;
                switch(type) {
                    case 'Keep':
                        sign = '↘';
                        break;
                    case 'Insert':
                        sign = '↓';
                        break;
                    case 'Remove':
                        sign = '→';
                        break;
                }
                if(coordinate[0] === 0) {
                    coordinate[0] = 1;
                }
                matrix[coordinate[1]][coordinate[0]] = sign;
                costMatrix[coordinate[1]][coordinate[0]] = cost;
            }
            for(const row of matrix) {
                console.log(row.join(" "));
            }
            console.log("n")
            for(const row of costMatrix) {
                console.log(row.join(" "));
            }
        }

        function myersDiff(old, current, costFunction) {
            // Initialize the frontier with starting point.  Start with cost 0
            const frontier = { 1: new Frontier(0, [], 0) };

            // Convert from 1-based to 0-based indexing
            // Algorithm uses 1-based indexing, but JavaScript uses 0-based
            function one(idx) {
                return idx - 1;
            }

            const aMax = old.length; // horizontal size of edit graph
            const bMax = current.length; // vertical size of edit graph

            // Main loop: try increasing numbers of edits
            for (let d = 0; d <= aMax + bMax; d++) {  // Removed the + 1 because it was causing issues
                // For each value of D, try all possible diagonals
                for (let k = -d; k <= d; k += 2) {
                    // Determine whether to go down or right BASED ON COST
                    const goDown = (k === -d || // at left edge, must go down
                        (k !== d && frontier[k - 1] && frontier[k + 1] && frontier[k - 1].cost < frontier[k + 1].cost)); // compare COSTS. Added null checks

                    // Find starting point for this iteration
                    let oldX, history, currentCost;
                    if (goDown) {
                        // Copy from k+1 diagonal (going down)
                        ({ x: oldX, history, cost: currentCost } = frontier[k + 1]);
                        var x = oldX;
                    } else {
                        // Copy from k-1 diagonal and move right
                        ({ x: oldX, history, cost: currentCost } = frontier[k - 1]);
                        var x = oldX + 1;
                    }

                    // Clone history to avoid modifying previous paths
                    history = [...history];
                    let y = x - k; // Calculate y from x and k

                    let newCost = currentCost;  //Start newCost as the cost of where we came from

                    // Record the edit we made to get here AND UPDATE THE COST
                    if (y >= 1 && y <= bMax && goDown) {
                        // Insert from new sequence when going down
                        const insertCost = costFunction(null, current[one(y)]);  //Cost of inserting
                        history.push(new Insert(current[one(y)], [x,y], insertCost));
                        newCost += insertCost;  //Update the cost
                    } else if (x >= 1 && x <= aMax) {
                        // Remove from old sequence when going right
                        const removeCost = costFunction(old[one(x)], null);  //Cost of removing
                        history.push(new Remove(old[one(x)], [x,y], removeCost));
                        newCost += removeCost;  //Update the cost
                    }

                    // Follow the snake: match diagonal moves as far as possible
                    // This is key optimization - extend path along matches
                    while (x < aMax && y < bMax && costFunction(old[one(x + 1)], current[one(y + 1)]) === 0) {
                        x += 1;
                        y += 1;
                        history.push(new Keep(current[one(y)], [x,y], 0));
                    }

                    // Check if we've reached the end
                    if (x >= aMax && y >= bMax) {
                        visualizePath(history, old, current);
                        return history; // Found solution
                    } else {
                        // Save this point in the frontier.  Save the COST TOO.
                        frontier[k] = new Frontier(x, history, newCost);
                    }
                }
            }

            throw new Error('Could not find edit script');
        }

        // Example Usage:
        let text1 = "PQRSTUZ".split("").map(item => ({ hashVal: item, content: item }));
        let text2 = "PQTUARS".split("").map(item => ({ hashVal: item, content: item }));

        // Define a custom cost function
        function myCostFunction(oldElement, newElement) {
            if (oldElement === null) {
                // Cost for insertion
                return 1;
            }
            if (newElement === null) {
                // Cost for deletion
                return -1;
            }
            

            if (oldElement.hashVal === newElement.hashVal) {
                return 0; // No cost
            }
            return 1; // Default cost
        }

        const editScript = myersDiff(text1, text2, myCostFunction);

        let diff2 = editScript.map(operation => {
            const element = operation.line;
            if (operation instanceof Keep) {
                element.status = 'unchanged';
            } else if (operation instanceof Insert) {
                element.status = 'inserted';
            } else if (operation instanceof Remove) {
                element.status = 'removed';
            }
            return element;
        });

        console.log(diff2);
        console.log(diff2.length);

Here is also the path matrix for the path it chooses:

  P Q R S T U Z
P ↘ · · · · · ·
Q · ↘ · · · · ·
T · ↓ · · · · ·
U · ↓ · · · · ·
A · ↓ · · · · ·
R · · ↘ · · · ·
S · · · ↘ → → →

and the cost matrix:

  P Q R S T U Z
P 0 · · · · · ·
Q · 0 · · · · ·
T · 1 · · · · ·
U · 1 · · · · ·
A · 1 · · · · ·
R · · 0 · · · ·
S · · · 0 -1 -1 -1

My question is:

  • Is this the correct way to approach the cost function with Myers? In my case, I do not want to treat each insertion, removal, and matching equally. So a custom cost function will be helpful. How can this be improved?
  • The algorithm still prefers to minimize D by maximizing X. Should it still hold valid with the custom cost function in place?

react electron file drop can’t get filepath

I’m trying to build a React + Electron app that supports file drag and drop. The goal is for users to be able to drag files into a box, and for the app to retrieve the full file path from the user’s system. Right now, I’m able to capture and display the file names, but the path always ends up being null or an empty string.

Here’s the GitHub repo (main branch) with my code:
https://github.com/MartinBarker/electron-react-file-drop

When I drag a file, I can see something like this in my main.js logs:
1 File dropped: 11-shonuff_by_omid-cms.mp3 – undefined

enter image description here

Below are the relevant parts of my code. (Note: I’m including the import statements as well.)

import React, { useState } from 'react';
import './App.css';

function App() {
  const [files, setFiles] = useState([]);

  const handleDrop = (event) => {
    event.preventDefault();
    const droppedFiles = Array.from(event.dataTransfer.files);
    setFiles(droppedFiles);
    droppedFiles.forEach(file => {
      console.log(`File dropped: ${file.name} - ${file.path}`);
    });
    if (window.electron) {
      console.log('Sending files-dropped event to main process');
      window.electron.sendFiles(droppedFiles.map(file => ({ name: file.name, path: file.path })));
    }
  };

  const handleFileSelect = (event) => {
    const selectedFiles = Array.from(event.target.files);
    setFiles(selectedFiles);
    selectedFiles.forEach(file => {
      console.log(`File selected: ${file.name} - ${file.path}`);
    });
    if (window.electron) {
      console.log('Sending files-dropped event to main process');
      window.electron.sendFiles(selectedFiles.map(file => ({ name: file.name, path: file.path })));
    }
  };

  const handleDragOver = (event) => {
    event.preventDefault();
  };

  return (
    <div className="App">
      <div
        className="drop-zone"
        onDrop={handleDrop}
        onDragOver={handleDragOver}
      >
        <p>Drag and drop files here, or click to select files</p>
        <input type="file" multiple onChange={handleFileSelect} />
      </div>
      <ul>
        {files.map((file, index) => (
          <li key={index}>{file.name} - {file.path}</li>
        ))}
      </ul>
    </div>
  );
}

export default App;
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');

let mainWindow;

function createWindow() {
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true,
      preload: path.join(__dirname, 'preload.js')  // Add this line
    },
  });

  const isDev = !app.isPackaged; // Check if the app is in development mode
  const startUrl = isDev
    ? 'http://localhost:3000' // Load from React dev server
    : `file://${path.join(__dirname, 'build', 'index.html')}`;

  mainWindow.loadURL(startUrl);

  if (isDev) {
    mainWindow.webContents.openDevTools(); // Open DevTools in development mode
  }

  mainWindow.on('closed', () => {
    mainWindow = null;
  });
}

ipcMain.on('files-dropped', (event, files) => {
  console.log('Received files-dropped event');
  files.forEach(file => {
    console.log(`File dropped: ${file.name} - ${file.path}`);
  });
});

app.whenReady().then(() => {
  console.log('App is ready');
  createWindow();
});

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit();
});

app.on('activate', () => {
  if (mainWindow === null) createWindow();
});

What I’ve tried / Additional Info:

  • I’ve confirmed that I’m able to retrieve the file name from file.name.
  • However, file.path is always coming up undefined in both the renderer and the main process logs.
  • I tried enabling nodeIntegration, but I understand that’s not ideal for security reasons. Also, that didn’t fix the path issue.

Question:
How do I properly retrieve the full file path for each dropped file in a React + Electron setup? Is there something in my current setup preventing the path from being captured? Any tips or recommended changes to my preload scripts or webPreferences in BrowserWindow?

Thank you in advance for any guidance!

How can I use JS and CSS files from another directory?

I’m making a website, with my own widget. It looks like this (called roadstuff/index.html):
enter image description here
Here is the code on importing my widget:
JS:

$(function () {
    $("#nav-placeholder").load("server/nav.html");
});
$(function () {
    $("#shieldmaker-placeholder").load("server/shieldmaker.html");
});

HTML:

<html>
<head>
<title>Road Stuff - StickyChannel92</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
<link rel="icon" type="image/x-icon" href="files/images/favicon.ico">
<link rel="canonical" href="https://stickychannel-92.com/">
<link rel="stylesheet" href="server/default.css">
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
<script src="server/nav.js"></script>
<script src="server/shieldmaker.js"></script>
</head>
<body>
<div id="nav-placeholder">
</div>
<div id="shieldmaker-placeholder">
</div>
</body>
</html>

File directory:

htdocs (root)
 -index.html
 -404.html
 -server
  -nav.html
  -nav.js
  -shieldmaker.html
  -shieldmaker.js
 -roadstuff
  -index.html

HEAD HTML:

This whole entire setup works just fine when emulating it in NetBeans. When I copy and paste this entire setup on my InfinityFree setup, nothing happens, and just shows a blank page.

However, when I modify my code to include the JS code directly into my HTML’s , nothing shows up in NetBeans, but copying it all magically works on my actual website, albeit, the Logo text shows up in the default TNR font.

I even had several moments where my 404 page shows up twice on the html page, where the navbar and widget should go, and scripts running constantly, like this:
enter image description here

How can I link JS and CSS files to any site in a child directory, so that I have a navbar and the same CSS on EVERY single page of my website, while trying to fix the widget and making both setups work exactly the same?

Here is my website for investigation: stickychannel-92.com (replace htdocs with this URL if you need to look at the files above).

Expected:
Both NetBeans and the real server should show the exact same results and the navbar and widget should show up properly.

Actual:
Only one setup worked with either solution, cancelling the other setup. That is, NetBeans works just fine, but the website doesn’t, and vice versa.

Project Zip for deployment

Want to verify that my package.zip for my teams toolkit app contains the right files and is in the right structure.

Below is a screenshot of what is in my project.zip that I just deployed using the “az webapp deploy” command

I just did this deployment successfully, but my app is still unable to install in teams properly. I believe this may be the issue.

project.zip contents

Combining 2 addEventListeners which do the same thing into 1

I would like clicking div-1 and div-2 to do the same thing but please how can I combine the 2 eventlisteners functions into 1

var div_1 = document.getElementById("div-1");
var div_2 = document.getElementById("div-2");

div_1.addEventListener('click', function() {
 // clicking div_1 and div_2 does the same thing
});

div_2.addEventListener('click', function() {
 // clicking div_1 and div_2 does the same thing
});

Any help would be much appreciated!

How to disable code transforms by passing transform:{} (Jest and ECMAScripts)

Newbie!
I’m trying to implement Jest in a Node project, but I’m using ECMAScript (Import…) instead of CommonJS (require()).

Looking around the Jest documentation on the subject it states: “Ensure you either disable code transforms by passing transform: {} or otherwise configure your transformer to emit ESM rather than the default CommonJS (CJS)” https://jestjs.io/docs/ecmascript-modules

New to setting up Jest, so not sure what they mean by ‘disabling transforms’ – suspect it’s within either jest.config.js or package.json? what that would look like?

Within the .test.js

import { exec } from "child_process";
import { jest } from "@jest/globals";

Within package.json so far:

"scripts": {
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js"
 },

and trying this within package.json too:

"transform": {
   "^.+\.js$": "babel-jest"
}

Running npx jest results in:

Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.

Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration. By default “node_modules” folder is ignored by transformers.

Here’s what you can do:
If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.

How to import multiple text files from a folder into an html page?

I have a file uploader to submit a text file from folder “upload”.
This simple tag does work for a specific file.

<embed src="upload/whatever.txt"  />

However, what I am trying to accomplish is to stack multiple text files as *.txt (whatever their names are) and being arranged from recent date.
Is there any possibility to do that in only html and JavaScript? (No jQuery).

Indexing nested functions inside a javascript function?

Angular has effects and example is this:

effect(() => {
  console.log(`The current count is: ${count()}`);
});

And this causes the effect to fire whenever count is is changed.

So that means that the effect function knows how to index any signals that are contained inside it.

How does javascript know what functions / signals are being called inside another function?

Bootstrap 5 form validation for text area inputs fails if user enters newline character only (HTML/JavaScript)

I’m building a form using Bootstrap 5 custom form validation. The issue I’m having is that if a user clicks into a textarea input that requires a value, hits “enter” to create a new line, and then tries to submit the form, the form validator doesn’t stop the form submission. It thinks that the newline character is a valid value, when it is not. I can’t seem to find any documentation on how to handle this.

I did add a condition to my JavaScript to catch this, however, it’s confusing for the user since the bootstrap validation shows a green check mark on the input even though it’s not a valid entry. See screenshots as well as code below…here’s a codepen too.

enter image description here

// Initialize form validation
const initializeFormValidation = () => {
  "use strict";
  // Fetch all the forms we want to apply custom Bootstrap validation styles to
  var forms = document.querySelectorAll(".needs-validation");
  // Loop over them and prevent submission
  Array.prototype.slice.call(forms).forEach(function(form) {
    form.addEventListener(
      "submit",
      function(event) {
        if (!form.checkValidity()) {
          event.preventDefault();
          event.stopPropagation();
        }
        form.classList.add("was-validated");
      },
      false
    );
  });
};

initializeFormValidation();

// Reset form validation
$("#reset-button").on("click", () => {
  $("#test-form").removeClass("was-validated");
  $("#test-form").addClass("needs-validation");
});
/* Required Fields */

.required-field::after {
  content: "*";
  color: red;
  margin-left: 2px;
}

.required-field-margin-left::after {
  content: "*";
  color: red;
  margin-left: -2px;
}

form {
  padding-left: 10px;
  padding-top: 12px;
}

#help-text {
  width: 550px;
  margin-bottom: 1rem;
}
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>

<form id="test-form" class="needs-validation" novalidate>
  <div class="col-md-4">

    <div id="help-text">First, hit the submit form button to see the form validation stop form submission.

      <br><br>
    Then, click into the textarea box and hit enter.

      <br><br>

    You'll see the form validator say that the newline character is valid, when it is not.
    </div>

    <textarea type="textarea" class="form-control" id="textarea-input" placeholder="Enter a new line character only" required></textarea>
    <div id="validationServerUsernameFeedback" class="invalid-feedback">
      Please enter a value.
    </div>

  </div>
  <br>
  <div class="mb-3">
    <button class="btn btn-primary" type="submit">Submit form</button>
  </div>

  <div class="mb-3">
    <button id="reset-button" class="btn btn-secondary" type="button">Reset form</button>
  </div>

</form>

ThreeJS: Raycaster selecting old, wrong nodes

so i’ve made made an update on my GLB files

As you can see this is my chair in blender
enter image description here

And these are the child nodes that make up the figure of the chair
enter image description here

As you can see its only an one child node

But this happens, when i setup raycaster to select one object of my scene and paint it random colour
enter image description here

it doesnt paints the entire chair, it paints a part of the chair like if were more nodes to paint, i dont know

fun fact: in the past that was possible because the chair in blender was divided into various nodes, but i unified them, and overwrited the old .glb file. but it still happening like if it was reading an old .glb file. I restarted my project, and it doesnt worked

this is my raycaster code:

const raycaster = new three.Raycaster()

document.addEventListener('mousedown', onMouseDown)

function onMouseDown(event){
  const coords = new three.Vector2(
    (event.clientX / renderer.domElement.clientWidth) * 2 -1,
    -((event.clientY / renderer.domElement.clientHeight) * 2 -1)
  )

  raycaster.setFromCamera(coords, camera)

  const intersects = raycaster.intersectObjects(scene.children, true)
  if(intersects.length > 0){
    const selectedObject = intersects[0].object
    
    const color = new three.Color(Math.random(), Math.random(), Math.random())
    selectedObject.material.color = color
   
    console.log(`${selectedObject.name}`)
  }
}

trello authenticate user for token

async authenticateTrello() {
    const authUrl = `https://trello.com/1/authorize?expiration=1hour&name=TrelloPlanner&scope=read,write&response_type=token&key=${TRELLO_APP_KEY}`;

    const token = await new Promise((resolve) => {
        const popup = window.open(authUrl, 'Trello Auth', 'width=800,height=800');
        let tokenFound = false;

      
        const interval = setInterval(() => {
            try {
                if (popup.closed && !tokenFound) {
                    clearInterval(interval);
                    resolve(null);
                    return;
                }

                if (popup.location.href.includes('/token/approve')) {
                    const preElement = popup.document.querySelector('pre');
                    if (preElement && preElement.innerText) {
                        tokenFound = true;
                        const token = preElement.innerText.trim();
                        clearInterval(interval);
                        popup.close();
                        resolve(token);
                    }
                }
            } catch (error) {
              console.log(error)
            }
        }, 500);
    });

    if (token) {
        console.log('Token received:', token);
        this.trelloToken = token;
        sessionStorage.setItem('trelloToken', token);
        this.checkAuth();
    } else {
        console.error('Failed to authenticate with Trello');
    }
}

When I try to authenticate I see a token in the popup in a pre text which has the token. The pop up has the approve URL but the code doesn’t grab the token and I cannot figure out why.

I expect that the token is saved and stored to the local storage and the pop up is closed but the program doesn’t close the popup.

I tried to log some URL locations and the URL location is correct.

Printing datamatrix gives a blank page

Thank you for looking at my question,

Using this code set up I can generate a datmatrix code to the screen, html2pdf() fires and opens an instance of acrobat but the page is blank.

I have a similar set up from which I can print a standard 2D barcode quite easily.

Please can anybody tell what I’ve missed

<?php
error_reporting(E_ALL);
ini_set('display_errors', '1');
?>
<h2>DM Code Output Test</h2>
</br>
</br>

    <table width="100%" border="1">
        <tr>
            <td align="left" width="2%" rowspan="2">
                &nbsp;
            </td>
            <td align="left"width="20%"
                <font color="#17365D">Input Value: </font><input type="text" name="ip_source" id="ip_source" size="50"/>
            </td>
            <td align="left">
                      
                <div id="div_barcode" name="div_barcode" class="col-lg-8" align="center">
                    <svg style="display:none" name="barcode" id="barcode">
                    </svg>
                </div>
            </td>
        </tr>
        <tr>
            <td align="right">
                <button name="btn_dmcode" id="btn_dmcode">Press Me</button>
            </td>
                 <td align="left">
                      &nbsp;
            </td>
        </tr>
    </table>

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/JsBarcode.all.min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/qrcode/1.4.4/qrcode.js" integrity="sha512-oxrVyBhqnzQ0BzuM0A/6dEIk0alz0p4SpDRaWvtuUoarIc8rnL5lVniHG5Dp21MRFojcQcmKHjaskNXhSaUPPw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

<script src="datamatrix.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.min.js"></script> 

<script src="https://rawcdn.githack.com/GitHub30/dataMatrix.js/97edc524c04db3d30a3fdf00c1fd0988cfa82888/dist/dataMatrix.js"></script>
                
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.9.3/html2pdf.bundle.min.js"></script>

<script>
$(document).ready(function(){
    const cp = "u00a0";

    $("#btn_dmcode").click(function(){
        var source = $("#ip_source").val();
        var barcode = document.getElementById("barcode");

        dataMatrix(source)
            .then(barcode => document.body.appendChild(barcode))

        // Choose the element id which you want to export.
        var element = document.getElementById('div_barcode');
        element.style.width = '100px';
        element.style.height = '100px';
        var opt = {
            margin:      0.5,
            filename:    'mydmcode.pdf',
            image:       { type: 'png', quality: 1 },
            html2canvas: { scale: 1 },          
            jsPDF:       { unit: 'mm', format: [50,50], orientation: 'landscape', precision: '12' }         
         };

        // choose the element and pass it to html2pdf() function and call the save() on it to save as pdf.
        html2pdf().set(opt).from(element).save();
        
    });

});
</script>

This is the 2d barcode javascript that works

        var stemassno = document.getElementById("stemassno").textContent;
        var barcode = document.getElementById("barcode");

        JsBarcode(barcode, stemassno, {
            height: 20,
            width: 2
        });

        barcode.style.display = "inline";
        
        // Choose the element id which you want to export.
        var element = document.getElementById('div_barcode');
        element.style.width = '100px';
        element.style.height = '50px';
        var opt = {
            margin:      0.5,
            filename:    'myfile.pdf',
            image:       { type: 'jpeg', quality: 1 },
            html2canvas: { scale: 1 },          
            jsPDF:       { unit: 'mm', format: [60,22], orientation: 'landscape', precision: '12' }         
         };

        // choose the element and pass it to html2pdf() function and call the save() on it to save as pdf.
        html2pdf().set(opt).from(element).save();
        
    });

How to get svelte component’s children height?

I’m trying to create a component that will render it’s children when it comes into the viewport, here’s the code:

<script lang="ts">
    import type { Snippet } from 'svelte';
    import { viewport } from '$lib/actions/useViewportAction.svelte';

    let { children }: { children: Snippet } = $props();
    let animating = $state(false);

    function handleEnter() {
        console.log('Element entered the viewport');
        animating = true;
    }

    function handleLeave() {
        console.log('Element left the viewport');
        animating = false;
    }
</script>

<div use:viewport={{ onEnter: handleEnter, onLeave: handleLeave }}>
    {#if animating}
        {@render children()}
    {/if}
</div>

The outer div is the one that “detects” when the element enters the viewpor, and when that happens animating is set to true, which renders the children. This works but the problem is that before the user reaches the viewport the div is empty, so when you scroll to that point you can see the element apearing and displaising the elements bellow it.

I tryied fixing it several ways but I think the best solution would be to set the height of the reference div to the height of the children somehow. If this is not possible I would apreciate any alternative solutions.

Why there is reloading after saving image? [duplicate]

To save a picture placed in my html page with:

<canvas id="defaultCanvas0" class="p5Canvas" width="912" height="995" style="width: 912px; height: 995px;"></canvas>

At my html page I also have the next button:

<button id="downloadCanvas0">Download Image</button>

I use the next code to save the picture in this canvas element:

function saveCanvas2file(){
  let canvas = document.getElementById('defaultCanvas0');
  event.preventDefault();
  // let ctx = canvas.getContext('2d');
}

document.getElementById('downloadCanvas0').addEventListener('click', function(e) {
  // Convert our canvas to a data URL
  let canvasUrl = canvas.toDataURL();
  // Create an anchor, and set the href value to our data URL
  const createEl = document.createElement('a');
  createEl.href = canvasUrl;

  // This is the name of our downloaded file
  createEl.download = "download-this-canvas";

  // Click the download button, causing a download, and then remove it
  createEl.click();
  createEl.remove();
});

This is based on: https://fjolt.com/article/html-canvas-save-as-image

What I do not understand is why my form seems to reload loosing all the entered data.

Any suggestions?

Unable to navigate Javascript code in VSCode

I am unable to navigate to the function definitions / variable definitions of JavaScript in VS code. I have all the extensions installed that are needed for javascript (https://code.visualstudio.com/docs/nodejs/extensions).enter image description here

enter image description here

enter image description here

I added all the extensions. Still unable to navigate to the function / variable definitions in JS code. I tried different solutions provided in different stack overflow questions but of no use. Can some one please help me to figure out the issue.