Convert JavaScript Array to SQL Multirow Values List

Trying to load a JavaScript array into a SQL Server table. I convert the array to a string, however, its format does not immediately translate into something (I know of) to use as separate records to insert. So, I’m trying to convert the JavaScript array, to a string, and then that string into a multiple row, SQL values list.

JavaScript array:

const jsArray = [
    [1,'Cake','Special characters comma, left bracket ], right bracket ].'],
    [2,'Ice cream','Single 'quote' with "double" quote.'],
    [3,"Fudge Syrup","Double "quote" with 'single' quote."],
]
strArray = JSON.stringify(jsArray)
console.log(strArray)

JavaScript string result:

[
    [1,"Cake","Special characters comma, left bracket ], right bracket ]."],
    [2,"Ice cream","Single 'quote' with "double" quote."],
    [3,"Fudge Syrup","Double "quote" with 'single' quote."]
]

Desired SQL value list rows:

INSERT INTO [MYTABLE] (
    [FIELD1], [FIELD1], [FIELD3]
)
VALUES
    (1,'Cake','Special characters comma, left bracket ], right bracket ].'),
    (2,'Ice cream','Single ''quote'' with "double" quote.'),
    (3,'Fudge syrup','Double "quote" with ''single'' quote.')
;

As you can see for SQL, each array needs to be surrounded by parathesis, each text field needs single quotes, etc.

I’ve been using a blunt force approach of a number of “replace” steps, tried for loops, some RegEx, but each seemed the wrong or an over complicated method, or couldn’t quite get it right, or screwed up a valid instance of an entered special character (e.g. a double quote that needs to stay as a double quote).

Any ideas?

How to use msal-browser with dynamic import?

I’m trying to use msal-browser as documented here, but from a plain javascript file using a dynamic import, instead of using the static imports shown in the documentation. I’m not using React, Angular, or any other framework for this application, but Dojo is available because it’s used by other apps on the same site.

Following is my code. When the import call resolves, msal has a value, but apparently contains no properties or functions. Calling msal.createStandardPublicClientApplication produces “TypeError: msal.createStandardPublicClientApplication is not a function”. Logging msal produces “Module {Symbol(Symbol.toStringTag): ‘Module’}” in the browser console.

import('./msal-browser.js').then(function(msal) {
    console.log('Imported MSAL',msal);
    const msalObj=msal.createStandardPublicClientApplication({
        auth: {
            clientId: msClientId,
            authority: 'https://login.microsoftonline.com/'+msTenantId
        }
    });
});

I suspect it has something to do with the code at the top of the msal-browser.js file, which is as follows:

'use strict';
(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
    typeof define === 'function' && define.amd ? define(['exports'], factory) :
    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.msal = {}));
})(this, (function (exports) { 'use strict';

I’ve used the browser console to check the values of things in that code. exports is undefined, define is a function, and define.amd is defined. It therefore seems that define(['exports'], factory) would be called when the file is loaded.

How can I use the module’s exports?

React Component Takes Functional Parameter. No argument passed, but still works. Why?

I’m new to React and am trying to understand a code example. The component below takes a parameter { onEmployeeAdded } which appears to be a function that is called by handleSubmit()

In App.jsx at the bottom, is not called with any properties/arguments. So, on that basis, I’d assume that in handleSubmit(), onEmployeeAdded() would be undefined and would throw an error.

But when I run the code in a node.js environment, everything works fine and no error is thrown. Why is no error thrown?

AddEmployee.jsx

// src/components/AddEmployee.js
import React, { useState } from 'react';
import axios from 'axios';

const AddEmployee = ({ onEmployeeAdded }) => {
  const [name, setName] = useState('');
  const [department, setDepartment] = useState('');
  const [email, setEmail] = useState('');

  const handleSubmit = async (e) => {
    e.preventDefault();
    try {
      const newEmployee = { name, department, email };
      await axios.post('http://localhost:5000/api/employees', newEmployee);
      onEmployeeAdded();
      setName('');
      setDepartment('');
      setEmail('');
    } catch (error) {
      console.error('Error adding employee:', error);
    }
  };

  return (
    <div className="container mt-4">
      <h3>Add New Employee</h3>
      <form onSubmit={handleSubmit}>
        <div className="mb-3">
          <label htmlFor="name" className="form-label">Name</label>
          <input
            type="text"
            className="form-control"
            id="name"
            value={name}
            onChange={(e) => setName(e.target.value)}
            required
          />
        </div>
        <div className="mb-3">
          <label htmlFor="department" className="form-label">Department</label>
          <input
            type="text"
            className="form-control"
            id="department"
            value={department}
            onChange={(e) => setDepartment(e.target.value)}
            required
          />
        </div>
        <div className="mb-3">
          <label htmlFor="email" className="form-label">Email</label>
          <input
            type="email"
            className="form-control"
            id="email"
            value={email}
            onChange={(e) => setEmail(e.target.value)}
            required
          />
        </div>
        <button type="submit" className="btn btn-primary">Add Employee</button>
      </form>
    </div>
  );
};

export default AddEmployee;

App.jsx

function App() {
  return (
    <Router>
      <Routes>
        {/* Public Routes */}
        <Route path="/" element={<Login />} />
        <Route path="/signup" element={<Signup />} />
        
        {/* Protected Routes */}
        <Route path="/dashboard" element={<Layout />}>
          {/* Nested routes under /dashboard */}
          <Route index element={<Dashboard />} /> {/* Default route for /dashboard */}
          <Route path="orders/add" element={<AddOrder />} />
          <Route path="orders/view" element={<ViewOrders />} />
          <Route path="orders/manage" element={<ManageOrders />} />
          <Route path="suppliers/add" element={<AddSupplier />} />
          <Route path="suppliers/manage" element={<ManageSuppliers />} />
          <Route path="suppliers/edit/:id" element={<EditSupplier />} />
          <Route path="inventory/add" element={<AddInventoryItem />} />
          <Route path="inventory/add1" element={<ManageInventories />} />
          <Route path="sales/add" element={<AddSalesRecord />} />
          <Route path="sales/manage" element={<ManageSales />}/>
          <Route path="sales/report" element={<GenerateReport />}/>
          <Route path="Employees/add" element={<AddEmployee/>}/>
          <Route path="Employees/manage" element={<ManageEmployee/>}/>
          <Route path="settings" element={<Settings/>}/>
        </Route>
      </Routes>
    </Router>
  );
}

export default App;

Nav Menu dropdown does not work if canvas set to window size – Previous Solution does not work

To make sure the canvas performs on a responsive page, I set the canvas to the clientWidth.

    XSize = document.documentElement.clientWidth;

    YSize = document.documentElement.clientHeight;

    Y = document.getElementById("NavBarDiv").clientHeight;

    CancasXSize = XSize - 2;

    CancasYSize = YSize - Y - 2;


    c = document.getElementById("Time_CV");
    c.width = CancasXSize;
    c.height = CancasYSize;



   c = document.getElementById("Mouse_CV");
   c.width = CancasXSize;
   c.height = CancasYSize;

The page works perfectly as far as drawing on the canvas BUT when you hover the nav Menu button – the nav selection drops down but the disappears when the mouse moves off the nav bar to perform a link selection.

If I comment out

c = document.getElementById("Time_CV");
   // c.width = CancasXSize;
  //  c.height = CancasYSize;



   c = document.getElementById("Mouse_CV");
  // c.width = CancasXSize;
  // c.height = CancasYSize;

The nav Menu performs as expected BUT I can’t use the canvas.

I have included a test page to demonstrate the issue – see below.

As a side note – using Chrome development tool – in full screen mode – performs as described. Toggle screen to put display in 600 x 600 mode – the nav menu does NOT hover – but if you click on it, the dropdown appears and lets you select a link.

Any insight? Thanks

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />


<style>
body {
  font-family: Arial, Helvetica, sans-serif;
}

div.IEcontent 
{
   text-align: center;
}

.container {
  display: flex;
  justify-content: space-between;
  align-items:center;
  height: 7vmin;
  border-radius: 3vmin;
}


h2 {
  display: inline-block;
  font-size: 5vmin;
  padding-right: 3vmin;
  float: right;
}

.navbar {
  overflow: hidden;
  display: inline-block;
}

.navbar a {
  float: left;
  color: white;
  text-align: center;
  padding: 5vmin 5vmin;
  text-decoration: none;
}

.dropdown {
  float: left;
  overflow: hidden;
}


.dropdown .dropbtn {
  font-size: 4vmin;  
  border: none;
  outline: none;
  color: white;
  padding: 5vmin 7vmin;
  background-color: inherit;
  font-family: inherit;
  margin: 0;
  position: relative;
  z-index: 1;
}

.navbar a:hover, .dropdown:hover .dropbtn {
  background-color: red;
}




.dropdown-content {
  display: none;
  position: absolute;
  background-color: #f9f9f9;
  min-width: 200px;
  box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
  z-index: 1;
}

.dropdown-content a {
  float: none;
  color: black;
  padding: 2vmin 5vmin;
  text-decoration: none;
  display: block;
  text-align: left;
  font-size: 3vmin; 
 
}



.dropdown-content a:hover {
  background-color: #ddd;
}

.dropdown:hover .dropdown-content {
  display: block;
}


.dropdown-content_Mouse {
  display: none;
  position: absolute;
  background-color: #f9f9f9;
  min-width: 200px;
  box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
  z-index: 1;
}

.dropdown-content_Mouse a {
  float: none;
  color: black;
  padding: 2vmin 7vmin;
  text-decoration: none;
  display: block;
  text-align: left;
  font-size: 2vmin; 
}



.dropdown-content_Mouse a:hover {
  background-color: #ddd;
}

.dropdown:hover .dropdown-content_Mouse {
  display: block;
}



.Ibutton
{
  padding: 2vmin 2vmin;
  border-radius: 3vmin;
}

#canvas-container { position: relative; }
canvas { position: absolute; left: 0; top: 0; }

#Time_CV
{
    z-index: 0;
}

#Mouse_CV
{
    z-index: 1;
}



</style>

<script type="text/javascript">

var XSize;
var YSize;
var CancasXSize;
var CancasYSize;

window.onload = function() 
{
    var Y;

    XSize = document.documentElement.clientWidth;

    YSize = document.documentElement.clientHeight;

    Y = document.getElementById("NavBarDiv").clientHeight;

    CancasXSize = XSize - 2;

    CancasYSize = YSize - Y - 2;


    c = document.getElementById("Time_CV");
    c.width = CancasXSize;
    c.height = CancasYSize;



   c = document.getElementById("Mouse_CV");
   c.width = CancasXSize;
   c.height = CancasYSize;



}






</script>
</head>


<body id="MyPage" style ="background-color:#000000">


<div class="container" style ="color:#ffffff; background-color:#000080">
<div id="NavBarDiv" class="navbar">
       <div class="dropdown">
         <button class="dropbtn">  Menu </button>
         <div class="dropdown-content">
      <a href="RT_Text.html">Real Time Text</a>
      <a href="RT_Charting.html">Real Time Charting</a>
      <a href="History_Charting.html">History Charting</a>
      <a href="Config_Text.html">Config Text</a>
      <a href="Config_Charting.html">Config Charting</a>
      <a href="Config_SetPoints.html">RT Color SetPoints</a>
      <a href="Time.html">Adjust Time</a>
         </div>
       </div> 

       <div class="dropdown">
         <button class="dropbtn">  Mouse Actions </button>
         <div class="dropdown-content_Mouse">
        <a href="#" onclick="Mouse_Cancel()">Cancel</a>
        <a href="#" onclick="Mouse_Reset()">Reset to Original</a>
        <a href="#" onclick="Mouse_TimeData()">Time Data</a>
        <a href="#" onclick="Mouse_Box()">Box</a>
        <a href="#" onclick="Mouse_BoxZoom()">Box Zoom</a>
        <a href="#" onclick="Mouse_VLine()">Vertical Line</a>
        <a href="#" onclick="Mouse_ClipR()">Clip Vline Right</a>
        <a href="#" onclick="Mouse_ClipL()">Clip Vline Left</a>
        <a href="#" onclick="Mouse_HLine()">Horizontal Line</a>
        <a href="#" onclick="Mouse_ClipU()">Clip Hline Up</a>
        <a href="#" onclick="Mouse_ClipD()">Clip Hline Down</a>
        </div>
        </div> 

</div>
<h2>Time Charting</h2>
</div>
<div id="canvas-container"  class="IEcontent">
<canvas id="Time_CV" width="100%" height="100%" ></canvas>
<canvas id="Mouse_CV" width="100%" height="100%" ></canvas>
</div>
</body>
</html>

Google Cloud Function with Node.js 12 still running past Node.js decommission date

I have a Google Cloud Function (1st gen) running on Node.js 12. According to the warning message in the Google Cloud Console, Node.js 12 was supposed to be decommissioned on January 30, 2025:

Node.js 12 is deprecated as of Jan 30, 2024 and will be decommissioned
on Jan 30, 2025. Please update to the latest runtime version
available.

However, it’s now March 3, 2025 (over a month past the decommission date), and my function continues to operate normally. I haven’t made any changes to the function or received any additional notifications.

My questions are:

  • Why is my function still running despite being past the decommission date?

  • Is there a grace period that wasn’t announced?

  • What risks am I taking by continuing to use this runtime?

  • Has anyone else observed this with their Node.js 12 functions?

I’d prefer not to update the function immediately if possible since it’s working in production, but I want to understand the situation better before making any decisions.
Environment details:

  • Runtime: Node.js 12
  • Region: us-central1
  • Function continues to execute without errors

Any insights from the community would be greatly appreciated, especially from those who might have received official communication about this situation.

Many thanks in advance!

Firebase storage unit tests: Timeout when trying to upload files using emulator

When running the below test via npm test, I get the following output:

Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/Users/[myname]/development/Construct/construct/infra/test/storage.test.js)
      at listOnTimeout (node:internal/timers:564:17)
      at process.processTimers (node:internal/timers:507:7)

I have the storage emulator running, with output telling me it is running on 127.0.0.1:9199

You’ll notice I have a debug statement in storage.rules. This is consistently outputting a result, so the rules do appear to be getting run.

I can’t find definitive documentation on what env var I should be setting, but it seems like process.env.STORAGE_EMULATOR_HOST is probably the right one?

My colleague, running the same test on his machine, is finding it runs successfully. So it seems the problem is somehow connected to my local setup.

I also have tests that test firestore.rules as well as storage.rules (running against the Firestore emulator) and they run with no problem.

My environment

node -v: v18.0.0
npm -v: 8.6.0
firebase --version: 13.32.0
macOS 15.3.1 (24D70)

Related links

I came across this while searching for a solution: https://github.com/firebase/firebase-tools/issues/4908
I appear to have the same problem.

Steps to reproduce

Run the storage emulator, check the host and port match what’s being set in STORAGE_EMULATOR_HOST in storage.test.js, then run the test in storage.test.js via npm test.

Expected behavior

I expect to get feedback on whether my test has passed or failed, as I do for my firestore.rules tests, eg “PERMISSION_DENIED” when I expect permission to be denied, and a green tick when tests pass.

My code

storage.test.js:

import {
  assertFails,
  assertSucceeds,
  initializeTestEnvironment,
} from "@firebase/rules-unit-testing";
import { ref, uploadBytes } from "firebase/storage";
import { readFileSync } from "fs";
import { afterEach, describe, it } from "mocha";
import { v4 as uuid_v4 } from "uuid";

process.env.STORAGE_EMULATOR_HOST = "127.0.0.1:9199";
//process.env.DATASTORE_EMULATOR_HOST = "127.0.0.1:9199";
const projectId = "app-construct-firebase-storage-security-rules-test";
const firebaseStorage = {
  rules: readFileSync("./../storage.rules", "utf8"),
  host: "127.0.0.1",
  port: 9199,
};

const testEnv = await initializeTestEnvironment({
  projectId: projectId,
  storage: firebaseStorage,
});

describe("firebase storage security rules unit tests", () => {
  const userID = uuid_v4();
  const userEmail = "[email protected]";

  const tokenOptions = {
    email: userEmail,
  };

  function avatarPath(myUserID) {
    return `avatars/${myUserID}`;
  }

  describe("********** `avatars` storage **********", () => {
    it("users can only create avatars stored against their own user ID", async () => {
      const storage = testEnv
        .authenticatedContext(userID, tokenOptions)
        .storage();
      const image = readFileSync("./dummy-avatar.png");
      const storagePath = avatarPath(userID);

      const userImageRef = storage.ref(storagePath);
      await assertSucceeds(
        userImageRef.put(image, { contentType: "image/png" })
      );
    });
  });
});

storage.rules:

rules_version = '2';

service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read;
    }

    match /avatars/{userID} {
      allow write, delete: if debug(request.auth.uid) == debug(userID);
    }
  }
}

firebase.json:

{
  "hosting": {
    "public": "app/build/web",
    "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  },
  "firestore": {
    "rules": "infra/firestore.rules"
  },
  "storage": {
    "rules": "infra/storage.rules"
  },
  "emulators": {
    "auth": {
      "port": 9099
    },
    "firestore": {
      "port": 8080
    },
    "storage": {
      "port": 9199
    },
    "ui": {
      "enabled": true
    },
    "singleProjectMode": false
  },
  "functions": [
    {
      "source": "functions",
      "codebase": "default",
      "ignore": ["venv", ".git", "firebase-debug.log", "firebase-debug.*.log"]
    }
  ]
}

package.json:

{
  "name": "security-rules-tests",
  "version": "1.0.0",
  "main": "index.js",
  "type": "module",
  "scripts": {
    "test": "mocha "./storage.test.js" --exit"
  },
  "author": "",
  "license": "ISC",
  "description": "",
  "devDependencies": {
    "@firebase/rules-unit-testing": "^3.0.4",
    "firebase-admin": "^12.7.0",
    "firebase-tools": "^13.20.2",
    "mocha": "^10.7.3",
    "uuid": "^11.0.3"
  }
}

Debug info

npm test --debug gives the same output.

But if I check firestore-debug.log, I see this:

Mar 03, 2025 8:52:05 PM io.gapi.emulators.netty.HttpVersionRoutingHandler channelRead INFO: Detected non-HTTP/2 connection.

…and if I check firebase-debug.log, I see this:

[debug] [2025-03-03T20:55:36.909Z] >>> [apiv2][query] POST http://127.0.0.1:5001/functions/projects/app-construct-dv-428210/trigger_multicast [none] [debug] [2025-03-03T20:55:36.909Z] >>> [apiv2][body] POST http://127.0.0.1:5001/functions/projects/app-construct-dv-428210/trigger_multicast {"specversion":"1.0","id":"25e21402-0f42-4bf9-9197-7414f86c2eae","type":"google.cloud.storage.object.v1.finalized","source":"//storage.googleapis.com/projects/_/buckets/app-construct-firebase-storage-security-rules-test/objects/avatars/37d5ca50-211d-4d0c-993c-771c5668e0f8","time":"2025-03-03T20:55:36.888Z","data":{"kind":"storage#object","name":"avatars/37d5ca50-211d-4d0c-993c-771c5668e0f8","bucket":"app-construct-firebase-storage-security-rules-test","generation":"1741035336888","metageneration":"1","contentType":"image/png","timeCreated":"2025-03-03T20:55:36.888Z","updated":"2025-03-03T20:55:36.888Z","storageClass":"STANDARD","size":"561","md5Hash":"nWSYBL5eqqiZUZaMdncOqg==","etag":"3ZOhitoec/6YbVv42oz62nkv+BY","metadata":{"firebaseStorageDownloadTokens":"f5e7cfc7-8d49-43c5-b642-5345153f2748"},"crc32c":"16/Irg==","timeStorageClassUpdated":"2025-03-03T20:55:36.888Z","id":"app-construct-firebase-storage-security-rules-test/avatars/37d5ca50-211d-4d0c-993c-771c5668e0f8/1741035336888","selfLink":"http://127.0.0.1:9199/storage/v1/b/app-construct-firebase-storage-security-rules-test/o/avatars%2F37d5ca50-211d-4d0c-993c-771c5668e0f8","mediaLink":"http://127.0.0.1:9199/download/storage/v1/b/app-construct-firebase-storage-security-rules-test/o/avatars%2F37d5ca50-211d-4d0c-993c-771c5668e0f8?generation=1741035336888&alt=media"}} [debug] [2025-03-03T20:55:36.914Z] <<< [apiv2][status] POST http://127.0.0.1:5001/functions/projects/app-construct-dv-428210/trigger_multicast 200 [debug] [2025-03-03T20:55:36.914Z] <<< [apiv2][body] POST http://127.0.0.1:5001/functions/projects/app-construct-dv-428210/trigger_multicast {"status":"multicast_acknowledged"}

…and if I check database-debug.log, I see nothing recent.

(I’m not actually sure which of these files is the one relevant to storage rules?)

Force trackpad to horizontal scroll only in js/smooth scroll?

I have lenis scroll page that has a couple of overflow-y auto sections.

It works fine except the macbook trackpad, which makes it scroll both horizontally & vertically.

It seems lenis takes even the smallest fraction of vertical scroll and animates the page. And on trackpad you can’t really scroll straight horizontally.

Is there a way to prevent trackpad from scrolling vertically unless some ratio is met?

document.addEventListener('DOMContentLoaded', function () {
  const lenis = new Lenis({
        duration: 1
  })
});
.section {
height: 100vh;
margin: 40px 0;
border: 2px solid red;
}

.container {
overflow-y: auto;
}

.gallery {
background: blue;
width: 200vw;
height: 100px;
}


html.lenis {
  height: auto;
  scroll-behavior: auto !important;
}
.lenis.lenis-smooth {
  scroll-behavior: auto;
}
.lenis.lenis-smooth [data-lenis-prevent] {
  overscroll-behavior: contain;
}
.lenis.lenis-stopped {
  overflow: hidden;
}
<script src="https://unpkg.com/[email protected]/dist/lenis.min.js"></script>


<div class="section section-1">
<div class="container">
<div class="gallery"></div>
</div>
</div>

<div class="section">
<div class="container">
</div>
</div>

<div class="section section-2">
<div class="container">
<div class="gallery"></div>
</div>
</div>

AgGrid Empty RowGroups heading lost when exporting to excel

I’m using AgGrid React with row groupings. For entries that do not have a value for the Column I’m grouping by, it shows as ‘(Blanks)’ in the table which is fine, but exporting to excel loses that text and I can’t find an option to modify it.

The data underneath exports fine, just the title of the grouping is blank. I was hoping something like the following would help, but apparently AgGrid handles the empty row groups by default and overwrites in this case Empty Group with a blank cell

processRowGroupCallback: (params) => {
   if (!params.node.groupData) {
      return `Empty Group`
   }

   return params.node.key
}

Nav Menu dropdown does not work if canvas set to window size

To make sure the canvas performs on a responsive page, I set the canvas to the clientWidth.

    XSize = document.documentElement.clientWidth;

    YSize = document.documentElement.clientHeight;

    var Y = document.getElementById("NavBarDiv").clientHeight;

    CancasXSize = XSize - 2;

    CancasYSize = YSize - Y - 2;

    document.getElementById("MyCanvas").width = CancasXSize;
    document.getElementById("MyCanvas").height = CancasYSize;

The page works perfectly as far as drawing on the canvas BUT when you hover the nav Menu button – the nav selection drops down but the disappears when the mouse moves off the nav bar to perform a link selection.

If I comment out

    //document.getElementById("MyCanvas").width = CancasXSize;
    //document.getElementById("MyCanvas").height = CancasYSize;

The nav Menu performs as expected BUT I can’t use the canvas.

I have included a test page to demonstrate the issue – see below.

As a side note – using Chrome development tool – in full screen mode – performs as described. Toggle screen to put display in 600 x 600 mode – the nav menu does NOT hover – but if you click on it, the dropdown appears and lets you select a link.

Any insight? Thanks

var XSize;
var YSize;
var CancasXSize;
var CancasYSize;

window.onload = function() {

  XSize = document.documentElement.clientWidth;

  YSize = document.documentElement.clientHeight;

  var Y = document.getElementById("NavBarDiv").clientHeight;

  CancasXSize = XSize - 2;

  CancasYSize = YSize - Y - 2;

  document.getElementById("MyCanvas").width = CancasXSize;
  document.getElementById("MyCanvas").height = CancasYSize;

}
body {
  font-family: Arial, Helvetica, sans-serif;
}

.container {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 7vmin;
  border-radius: 3vmin;
}

h2 {
  display: inline-block;
  font-size: 5vmin;
  padding-right: 3vmin;
  float: right;
}

.navbar {
  overflow: hidden;
  display: inline-block;
}

.navbar a {
  float: left;
  color: white;
  text-align: center;
  padding: 5vmin 5vmin;
  text-decoration: none;
}

.dropdown {
  float: left;
  overflow: hidden;
}

.dropdown .dropbtn {
  font-size: 4vmin;
  border: none;
  outline: none;
  color: white;
  padding: 5vmin 10vmin;
  background-color: inherit;
  font-family: inherit;
  margin: 0;
}

.navbar a:hover,
.dropdown:hover .dropbtn {
  background-color: red;
}

.dropdown-content {
  display: none;
  position: absolute;
  background-color: #f9f9f9;
  min-width: 200px;
  box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
  z-index: 1;
}

.dropdown-content a {
  float: none;
  color: black;
  padding: 2vmin 10vmin;
  text-decoration: none;
  display: block;
  text-align: left;
  font-size: 3vmin;
}

.dropdown-content a:hover {
  background-color: #ddd;
}

.dropdown:hover .dropdown-content {
  display: block;
}

.Ibutton {
  padding: 2vmin 2vmin;
  border-radius: 3vmin;
}

#canvas-container {
  position: relative;
}

canvas {
  position: absolute;
  left: 0;
  top: 0;
}
<body id="MyPage" style="background-color:#000000">

  <div class="container" style="color:#ffffff; background-color:#000080">
    <div id="NavBarDiv" class="navbar">
      <div class="dropdown">
        <button class="dropbtn">Menu</button>
        <div class="dropdown-content">
          <a href="RT_Text.html">Real Time Text</a>
          <a href="RT_Charting.html">Real Time Charting</a>
          <a href="History_Charting.html">History Charting</a>
          <a href="Config_Text.html">Config Text</a>
          <a href="Config_Charting.html">Config Charting</a>
          <a href="Config_SetPoints.html">RT Color SetPoints</a>
          <a href="Time.html">Adjust Time</a>
        </div>
      </div>

    </div>
    <h2>Real Time Charting</h2>
  </div>
  <div id="canvas-container">
    <canvas id="MyCanvas" width="100%" height="100%" ></canvas>
  </div>

How to convert all date inputs into a single format

here’s what I’m trying to do.

I have this js script I’m using with Obisidian that allows me to input a date:

const watched = await QuickAdd.quickAddApi.inputPrompt ("When did you watch this movie?");
if (!watched) {
    notice("No date entered.");
    throw new Error("No date entered.");
}

This opens up an input prompt that allows me to write any text I want, although in this case I’m alway going to input a date.

What I want to accomplish is the following: I want every date that I input to be converted into the same format (YY/MM/DD), regardless of whether I write 03/03/2025, 03/03/25, or even 3/3/25.

How to return the sum of the two previous numbers?

I want to write a function that returns a number based on the fibonacci rule where each new number returned is based on the sum of the two previous numbers 1, 1, 2, 3, 5, etc. So if the user inputs 4, the output should be 3. And it should work with any number such as 10, 12, 45, etc.

I tried using for loop to create an array but didn’t get the results as I had expected. When i++ >= 3 I get NaN instead of 3.

const fibonacci = function(num) {
  for (let i = 2; i < num; i++) {

    let arr = [0, 1, 1];
    let num1 = arr[i];
    let num2 = arr[i - 1];
    let push;

    push = arr.push(num1 + num2);
    console.log(arr);
  }
};

fibonacci(4);

need to specify x and Y on screen according to present x,y and move in a square shape where i cover all possible x,y

i have a 1000 X 1000 board.
my present x,y is 1,1 need to move to 1000,1 THEN to 1000,1000, then to 1,1000, then to 1,1 again
next round will be 2,2 then 999,2 then 999,999 then back to 2,2 and so on until every pixle is covered.

i thought of deviding board(screen) to 4 parts

part#1 both x and y less then 500 that would be north west
part#2 x MORE THAN 500 & y LESS THAN 500 that would be north east
part#3 both x and y are MORE THAN 500 that would be south east
part#4 x less than 500 & y more than 500 that would be south west

where i can use

var oldx=newx;oldy=newy;
if (newx< 500 && newy < 500 ){ newx = (1000 - oldx) && (newy = oldy  } ; else
if (newx> 500 && newy < 500 ){ newx = (1000 - oldx) && (newy = oldy  } ;

so on.
problem is i cannot get it to work 🙂
any ideas ?

tried the above, and expecting movement to be in order :

(1,1) then (1000,1)then (1000,1000) then (1,1000) then (1,1)
(2,2) then (999,2) then (999,999) then (2,999) then (2,2)
(3,3) then (998,3) then (998,998) then (3,998) then (3,3)
and so on until it is (500,500)

How to Draw a Solid 3-Band Waveform Like Rekordbox Using Canvas in JavaScript?

I’m trying to replicate Rekordbox’s 3-band waveform display (low, mid, high frequencies as solid, color-coded shapes) in JavaScript using canvas. I’ve already created a Python script that extracts waveform data from audio files and splits it into 4 bands (low, low_mid, mid, high), saving min/max sample pairs per band into a JSON file. My challenge is drawing these bands as solid, filled shapes like Rekordbox, where each band’s envelope is a smooth, continuous block rather than a squiggly line.
Here’s a snippet of my current WaveformRenderer class in JavaScript, focusing on the renderClubStyle method I’m using to draw the waveform:

class WaveformRenderer {
  constructor(canvasId) {
    this.canvas = document.getElementById(canvasId);
    this.ctx = this.canvas.getContext("2d");
    this.waveformData = null;
    this.zoom = 1;
    this.offset = 0;
    this.selectedBands = new Set();
    this.displayMode = "stacked";
    this.bandColors = { low: "#0055e2", low_mid: "#aa6d28", mid: "#f2aa3c", high: "#ffffff" };
    this.renderStyle = "club";
  }

  async loadData(data) {
    this.waveformData = await this.decodeWaveformData(data);
    this.selectedBands = new Set(this.waveformData.data.multiband.bands.map(b => b.name));
    this.render();
  }

  // ... (other methods like decodeWaveformData, render, etc.)

  renderClubStyle(samples, visibleStart, visibleEnd, height, centerY, color) {
    const ctx = this.ctx;
    const scaleFactor = (height / 2) * 0.95;

    ctx.beginPath();
    ctx.moveTo((visibleStart - this.offset) * this.zoom, centerY);
    for (let i = visibleStart; i < visibleEnd; i++) {
      const x = (i - this.offset) * this.zoom;
      const maxY = samples[i * 2 + 1]; // Upper peak
      const yMax = centerY - (maxY / 32768) * scaleFactor;
      ctx.lineTo(x, yMax);
    }
    for (let i = visibleEnd - 1; i >= visibleStart; i--) {
      const x = (i - this.offset) * this.zoom;
      const minY = samples[i * 2]; // Lower peak
      const yMin = centerY - (minY / 32768) * scaleFactor;
      ctx.lineTo(x, yMin);
    }
    ctx.closePath();
    ctx.fillStyle = color;
    ctx.fill();
  }
}

My Python script outputs a JSON file like this:

{
  "type": "multiband",
  "sample_rate": 44100,
  "samples_per_pixel": 256,
  "data": {
    "multiband": {
      "bands": [
        { "name": "low", "samples": ["base64 encoded min/max pairs"] },
        { "name": "low_mid", "samples": ["base64 encoded min/max pairs"] },
        { "name": "mid", "samples": ["base64 encoded min/max pairs"] },
        { "name": "high", "samples": ["base64 encoded min/max pairs"] }
      ]
    }
  }
}

What I’ve Done:

  • My Python script uses filters to split the audio into bands, then
    computes min/max amplitudes per pixel (similar to waveform analysis
    tools).
  • In JavaScript, I decode the base64 data into arrays of min/max pairs
    and render them on a canvas. The above renderClubStyle draws a filled
    shape using raw min/max values.

The Problem:
Rekordbox’s 3-band waveform looks smoother and more polished—solid shapes with reduced noise, not just raw peaks. My current rendering shows too much detail (jagged edges) and doesn’t fully capture that clean, envelope-like style.

What I Need Help With:

  • How can I modify renderClubStyle to draw each band as a solid shape
    like Rekordbox? Specifically: What techniques should I use to simplify the min/max data into a clean
    envelope?

  • How do I apply these per band (e.g., less detail for low, more for
    high)?

  • Any tips on matching Rekordbox’s aesthetic (e.g., outline, fill
    opacity)?

I’d prefer a pure JavaScript solution without external libraries if possible. Full code is available here https://github.com/GabrielJuliao/wavypy . Thanks for any guidance or code examples!

This is how it look like vs. what is supposed to look like:
My javascript

Rekordbox

How to reference a common folder in a monorepo

I’ve got a bunch of repos set up in a monorepo. Now I want to create a /lib directory at the top for some common stuff. I’ve got both js and python code in here and in either case I know I can essentially do the following locally

import ../../lib/<whatever>

monorepo:

  • my_repo1/
    • src
      • my_code
  • my_repo2/
    • src
      • my_other_code
  • lib/
    • my_common_stuff

But I know that in the build environment the ‘src’ directory gets flattened away, so this won’t work in both local and the build environment.

How are other folks navigating this? Is there a best practice?

Infinite Loop Carousel Function “Rewind” Issue on duplicate carousels

I’ve written this javascript function to create multiple “infinite loop” style carousels on a webpage I’m developing.
The first carousel that I implement with the function works fine, and as expected, but when I add more carousels to the page, those new carousels exibit behaviour where they “rewind” instead of seamlessly looping around to the first item again the index arrives at a certain point, both forwards and backwards.
I expect it’s something to do with the scoping in the code, but I’ve been working for hours and can’t find the issue.
Need a set of fresh eyes here!

Code is:

document.addEventListener("DOMContentLoaded", () => {
  //Call Function for each new carousel instance and define markup classes
  createCarousel({
    container: ".team-carousel",
    cardSelector: ".carousel-card",
    navSelector: ".team-carousel-controls span",
  });
});

function createCarousel({
  container,
  cardSelector,
  navSelector
}) {
  const carousel = document.querySelector(container);
  if (!carousel) return;

  const navBtns = carousel.parentElement.querySelectorAll(navSelector);
  let cards = Array.from(carousel.querySelectorAll(cardSelector));

  if (cards.length === 0) return;

  let isDragging = false,
    startX = 0,
    startScrollLeft = 0;

  const firstCardWidth = cards[0].offsetWidth;
  const cardPerView = Math.round(carousel.offsetWidth / firstCardWidth);
  const carouselChildren = Array.from(carousel.children);

  // Assign unique dataset index to original cards
  cards.forEach((card, index) => (card.dataset.originalIndex = index));

  // Function to clone and insert cards
  function cloneCards(sliceStart, sliceEnd, insertPosition) {
    carouselChildren.slice(sliceStart, sliceEnd).forEach((card, i) => {
      const clone = card.cloneNode(true);
      clone.dataset.originalIndex = (sliceStart === 0 ? i : cards.length - cardPerView + i);
      carousel.insertAdjacentElement(insertPosition, clone);
    });
  }

  // Insert card copies at the beginning and end
  cloneCards(-cardPerView, undefined, "afterbegin");
  cloneCards(0, -cardPerView, "beforeend");

  // Update cards list after cloning
  cards = Array.from(carousel.querySelectorAll(cardSelector));

  // Navigation Button Clicks
  navBtns.forEach((btn) =>
    btn.addEventListener("click", () => {
      carousel.scrollLeft += btn.dataset.direction === "left" ? -firstCardWidth : firstCardWidth;
      requestAnimationFrame(highlightCenterCard);
    })
  );

  // Dragging Handlers
  function handleDrag(e, action) {
    if (action === "start") {
      isDragging = true;
      carousel.classList.add("dragging");
      startX = e.pageX;
      startScrollLeft = carousel.scrollLeft;
    } else if (action === "move" && isDragging) {
      carousel.scrollLeft = startScrollLeft - (e.pageX - startX);
    } else if (action === "end") {
      isDragging = false;
      carousel.classList.remove("dragging");
      requestAnimationFrame(highlightCenterCard);
    }
  }

  carousel.addEventListener("mousedown", (e) => handleDrag(e, "start"));
  document.addEventListener("mousemove", (e) => handleDrag(e, "move"));
  document.addEventListener("mouseup", () => handleDrag(null, "end"));

  // Infinite Scroll
  function infiniteScroll() {
    if (carousel.scrollLeft <= 0) {
      carousel.classList.add("no-transition");
      carousel.scrollLeft = carousel.scrollWidth - (2 * carousel.offsetWidth);
      carousel.classList.remove("no-transition");
    } else if (Math.ceil(carousel.scrollLeft) >= carousel.scrollWidth - carousel.offsetWidth) {
      carousel.classList.add("no-transition");
      carousel.scrollLeft = carousel.offsetWidth;
      carousel.classList.remove("no-transition");
    }
  }

  carousel.addEventListener("scroll", () => {
    requestAnimationFrame(() => {
      infiniteScroll();
      highlightCenterCard();
    });
  });

  // Function to detect the most centered card
  function highlightCenterCard() {
    const carouselRect = carousel.getBoundingClientRect();
    const carouselCenter = carouselRect.left + carouselRect.width / 2;
    let closestCard = cards.reduce((closest, card) => {
      const cardRect = card.getBoundingClientRect();
      const distance = Math.abs(carouselCenter - (cardRect.left + cardRect.width / 2));
      return distance < closest.distance ? {
        card,
        distance
      } : closest;
    }, {
      card: null,
      distance: Infinity
    }).card;

    if (closestCard) {
      const originalIndex = closestCard.dataset.originalIndex;
      const matchingCards = cards.filter(card => card.dataset.originalIndex === originalIndex);

      cards.forEach(card => card.classList.remove("active-card", "card-blur"));
      matchingCards.forEach(card => card.classList.add("active-card"));
      cards.forEach(card => !matchingCards.includes(card) && card.classList.add("card-blur"));
    }
  }

  // Adjust shift amounts dynamically
  function updateShiftAmounts() {
    carousel.querySelectorAll(cardSelector).forEach((el) => {
      el.style.setProperty("--shift-amount", `calc(50% - ${el.offsetWidth / 2}px)`);
    });
  }

  highlightCenterCard();
  updateShiftAmounts();
  window.addEventListener("resize", updateShiftAmounts);
}