A way to get element id on click while using it as eventhandler

I programmed a a download progress bar. On click of the element it starts the download and shows the download progress. Sadly I cannot get it to work for multiple buttons and I am at a loss for options.

In detail what i am looking for: on click it gets the calling elements ID and the file supposed to be downloaded when pressing button {num}. Then use the id for the eventhandler and download the file.

First post on here so tell me what i should do differently.

Thanks in advance.

My Html

<html class="no-js" lang="">

<head>
  <script src="js/app.js" defer></script>
</head>

<body>
<div class="button-and-progress-div">
  <a class="download-start-button" id="startDownload"  data-file-to-download="img/jdk-22_windows-x64_bin.exe">Download</a>

  <div class="download-progress-bar__container" id="progbardiv">
    <div class="download-progress-bar__progress"></div>
  </div>
</div>
</body>
</html>

My Css:

html {
  height: 100%;
}
body {
  height: 100%;
}

#startDownload {
  background: #c50408;
  color: honeydew;
  padding: 10px;
}

#startDownload:disabled {
  background-color: rgb(39, 92, 74);
}

.button-and-progress-div {
  display: flex;
  flex-flow: nowrap column;
  align-items: center;
  justify-content: center;
  height: 100%;
}

.download-progress-bar__container {
  margin: 20px 0;
  width: 400px;
  height: 40px;
  border-radius: 10px;
}

.download-progress-bar__progress {
  background: linear-gradient(to right, rgba(255, 0, 0, 0), rgb(255, 0, 0));
  border-radius: 10px;
  color: honeydew;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 0;
  height: 100%;
}

.download-progress-bar__progress.error {
  background: linear-gradient(to right, rgba(138, 0, 226, 0), rgb(138, 0, 226, 1));
}

and finally my Javascript:

const fileToDownload = 'img/jdk-22_windows-x64_bin.exe';

const startDownloadElem = document.getElementById('startDownload');

  const downloadProgressElem = document.querySelector(
    '.download-progress-bar__progress'
  );

console.log('Initially ' + (window.navigator.onLine ? 'on' : 'off') + 'line');

window.addEventListener('online', () => console.log('Became online'));
window.addEventListener('offline', () => console.log('Became offline'));

//document.getElementById('statusCheck').addEventListener('click', () => console.log('window.navigator.onLine is ' + window.navigator.onLine));


  startDownloadElem.addEventListener('click', () => {
//    downloadProgressElem.style.background = 'linear-gradient(to right, rgba(255, 0, 0, 0), rgb(255, 0, 0))';
    console.log('Download Started');
    startDownloadElem.setAttribute('disabled', 'true');
    const dataChunks = [];
      fetch(`/${fileToDownload}`)
        .then(response => {
          const reader = response.body.getReader();
          const totalSize = Number(
            response.headers.get('content-length')
          );
          let totalSizeDownloaded = 0;
          downloadProgressElem.classList.remove('error');
          function readData() {
            return reader.read().then(result => {
              if (result.value) {
                dataChunks.push(result.value);
                totalSizeDownloaded += result.value.length;
                const percentage = Math.floor(
                  (totalSizeDownloaded / totalSize) * 100
                );

                console.log(
                  `${totalSizeDownloaded}/${totalSize} (${percentage}%)`
                );
                downloadProgressElem.textContent = `${percentage}%`;
                downloadProgressElem.style.width = `${percentage}%`;
              }

              if (!result.done) {
                return readData();
              }
            });
          }

          return readData();
        })
        .then(() => {
          console.log('Download finished');
          const downloadAnchor = document.createElement('a');
          const blob = new Blob(dataChunks);
          downloadAnchor.href = URL.createObjectURL(blob);
          downloadAnchor.download = fileToDownload;
          document.body.appendChild(downloadAnchor);
          downloadAnchor.click();
          document.body.removeChild(downloadAnchor);
        })
        .catch( () => {
          downloadProgressElem.textContent = 'Download error';
          downloadProgressElem.classList.add('error');
        })
        .finally(() => {
          startDownloadElem.removeAttribute('disabled');
        })
  })

Conflict between webpack OptimizePlugin and bootstrap 5 components (tooltip, tab)

I try to set up webpack configuration with separate downloads for modern and legacy browsers according to this principle

<script src="modern.main.js" type="module"></script>
<script src="legacy.main.js" nomodule defer></script>

For this purpose, on the recommendation from Google Wiki, I added to the configuration Optimize Plugin for Webpack but when loading the page and interacting with bootstrap elements, I get errors in the console that signal a conflict in the resulting build.

const { merge } = require('webpack-merge');
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const webpack = require('webpack');
const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
//const HtmlWebpackEsmodulesPlugin = require('webpack-module-nomodule-plugin');
//const TerserPlugin = require('terser-webpack-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const OptimizePlugin = require('optimize-plugin');

require('default-passive-events');
require('dotenv').config();

// Common configuration
const commonConfig = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    clean: true,
    publicPath: process.env.PUBLIC_PATH || path.join('/', path.relative(process.cwd(), path.resolve(__dirname, 'dist'))),
    assetModuleFilename: 'assets/[name][ext]',
  },
  module: {
    rules: [
      /*
      {
        test: /.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              [
                '@babel/preset-env',
                {
                  useBuiltIns: 'usage',
                  corejs: 3, // Use core-js@3
                },
              ],
            ],
          },
        },
      },
      */
      {
        test: /.(sa|sc|c)ss$/,
        exclude: [/font-awesome.min.css$/, /sow-slider.css$/],
        use: [
          MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: {
              sourceMap: true,
              url: false,
            },
          },
          {
            loader: 'postcss-loader', // Add postcss-loader
            options: {
              postcssOptions: {
                plugins: [
                  require('autoprefixer')
                ],
              },
            },
          },
          'sass-loader',
        ],
      },
      {
        test: /(font-awesome.min.css|sow-slider.css)$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
        ],
      },
      {
        test: /.(woff|woff2|eot|ttf|otf|svg)$/i,
        type: 'asset/resource',
        generator: {
          filename: 'fonts/[name][ext][query]'
        }
      },
      {
        test: /.(png|svg|jpg|jpeg|gif)$/i,
        type: 'asset/resource',
        generator: {
          filename: 'images/[name][ext]'
        }
      },
      {
        test: /modernizr-config.json$/,
        use: [
          'modernizr-loader',
          'json-loader'
        ],
      }
    ],
  },
  resolve: {
    alias: {
      modernizr$: path.resolve(__dirname, ".modernizrrc"),
    },
    fallback: {
      "assert": require.resolve("assert/"),
      "path": require.resolve("path-browserify"),
      "fs": false,
    },
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].css',
    }),
    new webpack.ProvidePlugin({
      ItcSlider: path.resolve(__dirname, 'src/js/vendor/itc-slider.min.js')
    }),
    new WebpackManifestPlugin({
      fileName: 'asset-manifest.json',
    }),
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: './src/index.html',
      inject: 'body',
    }),
    new OptimizePlugin({
      exclude: [
        /node_modules/bootstrap/
      ]
    }),
  ],
  stats: {
    errorDetails: true
  },
  mode: 'production',
};

module.exports = commonConfig;

Errors occur in this fragment of the script.js with tooltips and tabs. If the tabs are switched despite the error, then the tooltips don’t appear at all. Otherwise the assembly works properly.

import { Tooltip, Tab } from 'bootstrap';

document.addEventListener("DOMContentLoaded", function() {

    var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
    var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
        if (tooltipTriggerEl.closest('.vertical-slider-left')) {
            var options = { boundary: tooltipTriggerEl.closest('.vertical-slider-left') };
            return new Tooltip(tooltipTriggerEl, options);
        } else {
            return new Tooltip(tooltipTriggerEl); // Default options if closest() fails
        }
    });

    var tabTriggerList = [].slice.call(document.querySelectorAll('#v-pills-tab button[data-bs-toggle="pill"]'));
    var tabList = tabTriggerList.map(function (tabTriggerEl) {
        tabTriggerEl.addEventListener('shown.bs.tab', function (event) {
            for (var i = 0; i < tabTriggerList.length; i++) {
              if(tabTriggerList[i].classList.contains('prev')) {
                tabTriggerList[i].classList.remove('prev');
              }
            }
            if(event.relatedTarget.id<event.target.id) {
                document.getElementById(event.relatedTarget.id).classList.add("prev");
            }
        });
    });

});

If I connect scripts and all libraries separately without webpack build, then everything works properly. npm, bootstrap and other libraries and plugins are installed latest versions. I tried to achieve similar functionality with babel-loader, but without success and even Chat GPT didn’t help me here. What can you advise me?

How to create a transparent color overlay with texture blending effect using CSS and JavaScript?

I’m working on a project where I need to dynamically apply a transparent color overlay to an image that contains a subtle texture. The goal is to blend the selected color with the texture of the image, similar to how paint colors are displayed on a textured surface.

The functionality involves:

Displaying an image (e.g., a textured wall or paint sample).
Allowing users to select a color from a palette.
Dynamically applying the selected color as a semi-transparent overlay on top of the image while preserving the visible texture beneath the color.

The best result I got:

image

What I would like to achieve:

image

I have tried using the following:

CSS pseudo-elements with ::after for the overlay.
background-blend-mode: multiply; to combine the overlay color with the texture.
JavaScript to dynamically set the overlay color using inline styles and a rgba() value.

Here’s an example of my current CSS for the overlay:

.template-image-container {
    position: relative;
    width: 100%;
    height: auto;
    overflow: hidden;
}

.template-image-container img {
    display: block;
    width: 100%;
    height: auto;
}

.template-image-container::after {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: transparent; /* Default state is transparent */
    background-blend-mode: multiply;
    pointer-events: none;
    z-index: 1;
    transition: background-color 0.3s ease;
}

.template-image-container[data-color-overlay="true"]::after {
    background-color: var(--overlay-color, transparent);
}

I also use JavaScript to update the overlay color dynamically:

function applyOverlayColor(colorCode) {
    const imageContainer = document.getElementById("pattern-image");

    if (colorCode) {
        const transparentColor = hexToRgba(colorCode, 0.5); // Adjust transparency
        imageContainer.style.setProperty("--overlay-color", transparentColor);
        imageContainer.setAttribute("data-color-overlay", "true"); // Enable overlay
    } else {
        imageContainer.style.setProperty("--overlay-color", "transparent");
        imageContainer.removeAttribute("data-color-overlay"); // Disable overlay
    }
}

function hexToRgba(hex, alpha) {
    const r = parseInt(hex.slice(1, 3), 16);
    const g = parseInt(hex.slice(3, 5), 16);
    const b = parseInt(hex.slice(5, 7), 16);
    return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}

The Problem:
While this approach is working, the texture visibility is not as prominent as i want it to be. You can faintly see the texture through the color overlay (see the attached screenshot), but it’s not as clear or vivid as what Novacolor achieves on their site.

What might I be missing?
Are there better techniques in CSS or JavaScript for achieving a more pronounced texture visibility while maintaining a semi-transparent color overlay?
What I’ve Tried:
Adjusting background-blend-mode values:

Based on their site, they seem to use precise blending techniques and possibly manipulate their textures differently.
Attached Screenshot:
Current Implementation: Semi-transparent color applied, texture faintly visible.
Desired Effect: Texture remains more prominent, similar to the effect on Novacolor’s site.
What adjustments should I make to improve this, or is there a better method to achieve this type of overlay effect? Any guidance would be greatly appreciated!

What I’ve Tried:
Adjusting background-blend-mode values:

I’ve tried multiply, overlay, and screen. Multiply works best but still doesn’t achieve the vivid texture I’m aiming for.
Experimenting with transparency:

Lowering the alpha value in rgba increases texture visibility but reduces the color’s presence.
Using pseudo-elements:

Ensuring the texture and color overlay are properly stacked using a ::after pseudo-element.

Leave PopoverPanel after Link Clicked

In my Vue Project ive a Navbar Component with a Dashboard (Popover), how can i fadeout the PopoverPanel when i click a link inside of it:
ive tried using bool and v-if but its confusing and im seaarching for a more simpler answer.

        <Popover class="relative">
          <PopoverButton class="flex items-center gap-x-1 text-sm/6 font-semibold text-[#E0D8DE] hover:text-[#949D6A]"
          >
            Dashboard
            <ChevronDownIcon class="size-5 flex-none text-gray-400" aria-hidden="true" />
          </PopoverButton>

          <transition
            @after-leave="isOpen = false"
            enter-active-class="transition ease-out duration-200" 
            enter-from-class="opacity-0 translate-y-1" 
            enter-to-class="opacity-100 translate-y-0" 
            leave-active-class="transition ease-in duration-150" 
            leave-from-class="opacity-100 translate-y-0" 
            leave-to-class="opacity-0 translate-y-1"
            >
          <PopoverPanel class="absolute -left-8 top-full z-10 mt-3 w-screen max-w-md overflow-hidden rounded-3xl bg-[#1a1a1a] shadow-lg ring-1 ring-gray-900/5">
            <div class="p-4">
              <div v-for="item in products" :key="item.name" class="group relative flex items-center gap-x-6 rounded-lg p-4 text-sm/6 hover:bg-[#423E37]">
                <div class="flex size-11 flex-none items-center justify-center rounded-lg bg-gray-50 group-hover:bg-white">
                  <component :is="item.icon" class="size-6 text-gray-600 group-hover:text-indigo-600" aria-hidden="true" />
                </div>
                <div class="flex-auto">
                  <router-link 
                    v-if="item.href" 
                    :to="item.href" 
                    class="block font-semibold text-[#949D6A]"               
                    >
                    {{ item.name }}
                  </router-link>
                  <p class="mt-1 text-[#E0D8DE]">{{ item.description }}</p>
                </div>
               </div>
              </div>
              <div class="grid grid-cols-2 divide-x divide-gray-900/5 bg-gray-50">
                <a v-for="item in callsToAction" :key="item.name" :href="item.href" class="flex items-center justify-center gap-x-2.5 p-3 text-sm/6 font-semibold text-gray-900 hover:bg-gray-100">
                  <component :is="item.icon" class="size-5 flex-none text-gray-400" aria-hidden="true" />
                  {{ item.name }}
                </a>
              </div>
            </PopoverPanel>
          </transition>
        </Popover>
      </PopoverGroup>

resize video using ffmpeg.wasm, getting invalid URL

I am trying to compress and resize a video in my vue application, but have run into a few headaches, where I am getting errors I cant quite any documentation on (Error compress video: TypeError: Failed to construct ‘URL’: Invalid URL).

I am using this package: https://github.com/ffmpegwasm/ffmpeg.wasm

import { FFmpeg } from '@ffmpeg/ffmpeg';
import { fetchFile } from '@ffmpeg/util';

const _ffmpeg = ref(new FFmpeg());

const compressVideo = async (file: File) => {
  const fileName = file.name;
  const fileData = await fetchFile(file);

  await _ffmpeg.value.load();

  _ffmpeg.value.writeFile(fileName, fileData);

  try {
    await _ffmpeg.value.exec([
      '-i',
      fileName,
      '-vf',
      'scale=720:-1',
      '-b:v',
      '1000k',
      '-c:v',
      'libx264',
      '-crf',
      '23',
      '-preset',
      'medium',
      'output.mp4',
    ]);

    // Read the compressed file
    const data = await _ffmpeg.value.readFile('output.mp4');

    // Create a Blob from the compressed file data
    const compressedBlob = new Blob([data], { type: 'video/mp4' });

    // Optional: Create a downloadable link
    const url = URL.createObjectURL(compressedBlob);
    const link = document.createElement('a');
    link.href = url;
    link.download = 'compressed_' + fileName;
    link.click();

    // Clean up
    URL.revokeObjectURL(url);

    console.log('Video compressed successfully');
  } catch (error) {
    console.error('Compression failed:', error);
  }
};

I am using it like so when the user selects a video file using an input file element:

const target = e.target as HTMLInputElement;
const newFile = target.files[0];
    try {
      const test = await compressVideo(file);
      console.log('the resized file', newFile)
    } catch (error) {
      console.log('Error compress video:', error);
    }

The error I am getting is: Error compress video: TypeError: Failed to construct ‘URL’: Invalid URL

Chrome extension content script stops execution at first function call and does not throw errors

I made the first line of my content script a console.log(); statement because it appeared not to get loaded. The content script will run the first line, then does nothing else after that. No errors are thrown, none of the other console.log(); statements are processed, setting watch statements in Chrome DevTools Sources tab for the variables in the first function all are never set to any value; I’m at a loss for what is going on. I wrote the extension in vscode so it would tell me if I’d made any syntax errors, or something I was trying to do wasn’t working, like the message passing to/from my background.service_worker. I’m not trying to import anything into the content script. I’m very much hoping the problem seems to be glaring to someone that reads my code so I can get some help. I am wasting too much time spinning wheels and not making any headway.

The extension is supposed to do two things—

One: search the text of the document.body of the DOM for matches of a set of regexes and replace any matches found with a hyperlink. The HTML code snippet is a test file that should have most of the text after the bullet points hyperlinked.

Two: add a context menu entry that shows up when selected text is right-clicked that allows the user to jump to a ServiceNow form or run a ServiceNow search.

The context menu functionality works without any problem, and like I said there are no errors thrown that I’ve found during my testing so far, so the background.service_worker code is solid and the imports have to all be correct and working right, too. The issue must be with the content script.

manifest.json

{
  "name": "SearchNow",
  "description": "Search ServiceNow",
  "manifest_version": 3,
  "version": "0.9",
  "background": {
    "service_worker": "background-simplified.js",
    "type": "module"
  },
  "icons": {
    "16": "icons/SNow16.png",
    "24": "icons/SNow24.png",
    "32": "icons/SNow32.png",
    "48": "icons/SNow48.png",
    "128": "icons/SNow128.png"
  },
  "action": {
    "default_icon": {
      "16": "icons/SNow16.png",
      "24": "icons/SNow24.png",
      "32": "icons/SNow32.png"
    },
    "default_title": "Click for advanced search options",
    "default_popup": "popup.html"
  },
  "content_scripts": [
    {
      "matches": ["http://*/*", "https://*/*", "file:///*/*"],
      "css": ["styles.css"],
      "js": ["content-script-hyperlinker.js"],
      "run_at": "document_end"
    }
  ],
  "options_ui": {
    "page": "options.html",
    "open_in_tab": true
  },
  "permissions": [
    "activeTab",
    "alarms",
    "tabs",
    "scripting",
    "storage",
    "contextMenus"
  ],
  "host_permissions": [
    "<all_urls>"
  ],
  "commands": {
    "autoSearch": {
      "suggested_key": {
        "default": "Ctrl+Shift+1"
      },
      "description": "AutoSearch selected text"
    },
    "autoNav": {
      "suggested_key": {
        "default": "Ctrl+Shift+2"
      },
      "description": "Automatically navigate to selected record"
    }
  }
}

content-script-hyperlinker.js

console.log('Content script loaded.');

function hyperlinkMatches(node, regexPatterns) {
    if (node.nodeType === Node.TEXT_NODE) {
        let text = node.nodeValue;
        let replacedText = text;

        console.log('Original text:', text);

        for (const [patternName, regex] of Object.entries(regexPatterns)) {
            replacedText = replacedText.replace(new RegExp(regex), (match) => {
                chrome.runtime.sendMessage(
                    {
                        action: 'constructUrl',
                        base: 'https://servicenowinstancename.com',
                        path: '/nav_to.do',
                        query: match
                    },
                    (response) => {
                        const url = response.url;
                        console.log(`Match found: ${match}, URL: ${url}`);
                        return `<a href="${url}" target="_blank">${match}</a>`;
                    }
                );
            });
        }

        if (replacedText !== text) {
            console.log('Replaced text:', replacedText);
            const span = document.createElement('span');
            span.innerHTML = replacedText;
            node.parentNode.replaceChild(span, node);
        }
    } else if (node.nodeType === Node.ELEMENT_NODE && node.nodeName !== 'SCRIPT' && node.nodeName !== 'STYLE') {
        for (let child = node.firstChild; child; child = child.nextSibling) {
            hyperlinkMatches(child, regexPatterns);
        }
    }
}

function runner () {
    console.log('Document loaded, starting hyperlinking process.');
    chrome.runtime.sendMessage({ action: 'getRegexPatterns' }, (response) => {
        const regexPatterns = response.regexPatterns;
        hyperlinkMatches(document.body, regexPatterns);
    });
}

document.addEventListener('DOMContentLoaded', runner);

background-simplified.js

import { autoNav } from './handlers/autoNav.js';
import { autoSearch } from './handlers/autoSearch.js';
import { constructUrl } from './utils/urlConstructor.js';
import * as eventListeners from './eventListeners.js';
import * as regexPatterns from './utils/regexPatterns.js';

/* jshint esversion: 6*/

// Initialize event listeners
eventListeners.setupEventListeners();

// Create context menu entries
chrome.runtime.onInstalled.addListener(() => {
    chrome.contextMenus.create({
        id: 'autoNav',
        title: 'Open "%s"',
        contexts: ['selection']
    });

    chrome.contextMenus.create({
        id: 'autoSearch',
        title: 'Search ServiceNow for "%s"',
        contexts: ['selection']
    });
});

// Handle message passing with content script
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
    if (request.action === 'getRegexPatterns') {
        sendResponse({ regexPatterns });
    } else if (request.action === 'constructUrl') {
        const url = constructUrl(request.base, request.path, request.query);
        sendResponse({ url });
    }
});

// Handle context menu item clicks
chrome.contextMenus.onClicked.addListener((info, tab) => {
    if (info.menuItemId === 'autoNav') {
        autoNav(info, tab);
    } else if (info.menuItemId === 'autoSearch') {
        autoSearch(info, tab);
    }
});

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Test Page for Content Script</title>
</head>
<body>
    <h1>Test Page for Content Script</h1>
    <p>Here are some test cases for the regex patterns:</p>
    <ul>
        <li>KB1234567</li>
        <li>INC1234567</li>
        <li>RITM1234567</li>
        <li>STASK1234567</li>
        <li>REQ1234567</li>
        <li>CALL1234567</li>
        <li>PRB1234567</li>
        <li>CHG1234567</li>
        <li>SEC1234567</li>
        <li>CHAT1234567</li>
        <li>192.168.1.1</li>
        <li>[email protected]</li>
        <li>CO0102A-12345678</li>
        <li>(123) 456-7890</li>
        <li>AB123456789</li>
    </ul>
</body>
</html>

discord.js – Bot fetches an ancient version of a message

I’m requesting for some help because I’m stuck since too much time on this bug

Here’s a quick explanation of what I want to do

  1. The previous message

message v1

Keep in mind the 2nd field value : <t:1761343200:D>

Now I edit the message by clicking on Démarrer les inscriptions

  1. the edited message

new embed

The 2 embeds are different messages, I just sent them in the same channel for the example

Until here, everything is fine.

  1. the bug

When I click on S’inscrire I fetch the first embed to edit Nombre d’inscrits value, but when I fetch the message, I get as value of the embeds[0].fields[1].value, this : <t:1761343200:D>

I tracked with console.log values of the embed at different timings

1, fetch { value: '<t:1761343200:D>', name: 'Date', inline: true } // When *Démarrer les inscriptions* is clicked
2, edit { name: "Nombre d'inscrits", value: '0', inline: true } // When the message is edited
3, fetch { value: '<t:1761343200:D>', name: 'Date', inline: true } // When I fetch *Nombre d'inscrits*

Now, the code

1.

const panelChannel = interaction.guild.channels.cache.get(inhouse[0].panel_channel);
const message = await panelChannel.messages.fetch(inhouse[0].panel_message);

console.log("1, fetch", message.embeds[0].fields[1]);
const a = await message.edit({
    embeds: [sessionEmbed],
    components: [row]
});

console.log("2, edit", a.embeds[0].fields[1]);
const panelChannel = interaction.guild.channels.cache.get(inhouse[0].panel_channel);
const panelMessage = await panelChannel.messages.fetch(inhouse[0].panel_message);
const panelEmbed = panelMessage.embeds[0];
const panelButtons = panelMessage.components[0];

console.log("3, fetch", panelEmbed.fields[1]);

Can someone tell me what is wrong ?

amchart map is not updating fill colors

I am trying to update the fill color of certain countries. The map shows with all the countries but the background color for some of the countries is not changing.

am5.ready(function () {

  const amcolors = [
    0x4C787E, 0x5E7D7E, 0x307D7E, 0x348781, 0x438D80, 0x4E8975, 0x1F6357, 0x306754, 0x006A4E,
    0x2E8B57, 0x1B8A6B, 0x31906E, 0x00A36C, 0x34A56F, 0x1AA260, 0x50C878, 0x3EB489, 0x3CB371,
    ... snip ...
    0xE2A76F, 0xC19A6B, 0xE6BF83, 0xDEB887, 0xD2B48C, 0xC8AD7F, 0xC2B280, 0xBCB88A, 0xC8B560
  ];

  // Create root element
  // https://www.amcharts.com/docs/v5/getting-started/#Root_element
  let root = am5.Root.new("my-collection-map-chartdiv");

  // Set themes
  // https://www.amcharts.com/docs/v5/concepts/themes/
  root.setThemes([
    am5themes_Animated.new(root)
  ]);

  // Create the map chart
  // https://www.amcharts.com/docs/v5/charts/map-chart/
  let chart = root.container.children.push(am5map.MapChart.new(root, {
    panX: "translateX",
    panY: "translateY",
    projection: am5map.geoMercator()
  }));

  // Create main polygon series for countries
  // https://www.amcharts.com/docs/v5/charts/map-chart/map-polygon-series/
  const polygonSeries = chart.series.push(am5map.MapPolygonSeries.new(root, {
    geoJSON: am5geodata_worldLow,
    exclude: ["AQ"]
  }));

  polygonSeries.mapPolygons.template.setAll({
    tooltipText: "{name}",
    toggleKey: "active",
    interactive: true
  });

  const seriesInfo = Object.keys(countryInfos).map((code, index) => {
    const country = countryInfos[code];
    const count = country.count ? country.count : '0';
    const fillcolor = am5.color(amcolors[index]);
    return {
      id: code,
      polygonSettings: {
        fill: fillcolor,
        tooltipHTML: `${country.name}<br/>Count: ${count}`,
      },
    };
  });


// `seriesInfo` data:
// {id: 'US', polygonSettings: {…}, geometry: {…}, geometryType: 'MultiPolygon', name: 'United States'}
// {id: 'DE', polygonSettings: {…}, geometry: {…}, geometryType: 'Polygon', name: 'Germany'}
// {id: 'AT', polygonSettings: {…}, geometry: {…}, geometryType: 'Polygon', name: 'Austria'}
// --SNIP--
// {id: 'PT', polygonSettings: {…}, geometry: {…}, geometryType: 'Polygon', name: 'Portugal'}

  console.log(seriesInfo); // <== I see all 38 items I want to color.
  polygonSeries.data.setAll(seriesInfo);

  // Make things animate on load
  chart.appear(1000, 100);

}); // end am5.ready()

I verified that the seriesInfo holds the data I want to show. Any idea why this doesn’t work?

Thanks.

Javascript “Uncaught type error: pixel() is not a function”

I’m creating a really simple webpage that makes you draw a 50×50 pixel two-colors image you can export (I didn’t implemented the function to do that yet) that I will use for a next project I called “nork”. Here’s the full HTML and JS code:

<html>
    <head>
        <title>nork Image Format Converter</title>
        <script>
            var width, height;
            var tableDiv;
            var table;
            
            let i, j;
            
            function pixel(id, color)
            {
                pixel = document.getElementById(id);
                
                if (color==0)
                {
                    pixel.src = "pixelBlack.png";
                } if (color==1) {
                    pixel.src = "pixelWhite.png";
                } else {
                    window.alert("Error in color argument passed to pixel() function. Not recognized color code. Avaiable colors are: 0(black), 1(white).")
                }
            }
            
            function createImageTable()
            {   
                width = 50;
                height = 50;
                
                tableDiv = document.getElementById("image");
                
                table = "";
                for (i = 0; i<height; i++)
                {
                    for (j = 0; j<width; j++)
                    {
                        table += "<img src="pixelBlack.png" id="" + i.toString() + j.toString() + "" onClick = "pixel('" + i.toString() + j.toString() + "', 1);" onDblClick = "pixel('" + i.toString() + j.toString() + "', 0);">";
                        console.log(i.toString(), j.toString(), i, j);
                    }
                    table += "<br>"
                }
                
                tableDiv.innerHTML = table;
            }
        </script>
    <head>
    <body>
        <button onClick="createImageTable()">Create image table</button>
        </div>
        <br>
        <div id="draw-image">
            <h3>Draw image</h3>
            <p>To draw single-click a pixel to colour it white, to colour it black - so to erease it - double-click the pixel.</p>
            
            <div id="image"></div>
        </div>
    <body>
</html>

There is a button at the top to create the 50×50 table (and this works. Function createImageTable()). Next the user created the table it can be used to draw anything a person wants: clicking a single time the pixel becomes white, clicking two times (double-click) the pixel becomes black. This is the pixel() function’s work. In theory, ’cause it works only for the first pixel I click, but after I click the first time, the other times, any pixel I hit, it says:

Uncaught TypeError: pixel is not a function
    at HTMLImageElement.onclick (main.html:1:1)

What’s the problem here?
Thank you very much!

Square API integration

I’m trying to build a Square app that, when installed by the Square user, reads out available store data to another platform. This other platform will use the store data to make recommendations, etc.

I have never used Square’s API before and I am running in circles trying to get something basic running in the sandbox on localhost.

Most recently, I keep getting this error in the console:

GET https://squareupsandbox.com/oauth2/authorize?client_id=sandbox-XXXXXX-XXXXXXXXXXXXX&scope=MERCHANT_PROFILE_READ&state=9a0ahl&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fapi%2Fsquare%2Fcallback 400 (Bad Request)

This is my .env

NEXT_PUBLIC_SQUARE_APPLICATION_ID=sandbox-XXXXX-XXXXXXXXXXXXX
SQUARE_ACCESS_TOKEN=XXXXXXXXXXXXXXXXXXXXX
SQUARE_REDIRECT_URL=http://localhost:3000/api/square/callback

Here is /lib/squareClient.js:

const { Client } = require('square');

const squareClient = new Client({
  environment: 'sandbox', // or 'production' for live apps
  accessToken: process.env.SQUARE_ACCESS_TOKEN,
});

module.exports = squareClient;

here is /api/square.js

import { NextApiRequest, NextApiResponse } from 'next';
const squareClient = require('../lib/squareClient');

export default async function handler(req = NextApiRequest, res = NextApiResponse) {
  const { method } = req;

  switch (method) {
    case 'GET':
      // Example: Fetch merchant data
      try {
        const merchantsApi = squareClient.merchantsApi;
        const response = await merchantsApi.listMerchants();
        res.status(200).json(response.result);
      } catch (error) {
        res.status(500).json({ error: error.message });
      }
      break;

    default:
      res.setHeader('Allow', ['GET']);
      res.status(405).end(`Method ${method} Not Allowed`);
  }
}

here is /pages/api/square/callback.js

import { NextApiRequest, NextApiResponse } from 'next';

export default async function handler(req = NextApiRequest, res = NextApiResponse) {
  // Log all query parameters for debugging
  console.log('Callback received with query params:', req.query);

  const { code, state, error } = req.query;

  if (error) {
    console.error('Square OAuth error:', error);
    return res.redirect(`/?error=${encodeURIComponent(error)}`);
  }

  if (!code) {
    return res.redirect('/?error=No authorization code received');
  }

  try {
    // Log success and redirect
    console.log('Successfully received authorization code');
    res.redirect('/?success=true');
  } catch (err) {
    console.error('Callback error:', err);
    res.redirect(`/?error=${encodeURIComponent(err.message)}`);
  }
}

and here is /pages/index.js

import React, { useState } from 'react';
import Head from 'next/head';

export default function Home() {
  const [error, setError] = useState(null);

  const connectSquare = () => {
    try {
      const state = Math.random().toString(36).substring(7);
      
      // Build OAuth URL with minimal required parameters
      const authParams = new URLSearchParams({
        'client_id': process.env.NEXT_PUBLIC_SQUARE_APPLICATION_ID,
        'scope': 'MERCHANT_PROFILE_READ',
        'state': state,
        'response_type': 'code',
        'redirect_uri': `${window.location.origin}/api/square/callback`
      });

      const authUrl = `https://squareupsandbox.com/oauth2/authorize?${authParams.toString()}`;
      
      // Log the URL for debugging
      console.log('Redirecting to:', authUrl);
      
      // Redirect to Square's OAuth page
      window.location.href = authUrl;
    } catch (err) {
      setError(err.message);
      console.error('Error during Square connection:', err);
    }
  };

  return (
    <div>
      <Head>
        <title>Square Integration App</title>
        <meta name="description" content="Connect your Square account" />
      </Head>

      <main style={{ padding: '20px', maxWidth: '800px', margin: '0 auto' }}>
        <h1 style={{ marginBottom: '20px' }}>Square Integration App</h1>
        
        {error && (
          <div style={{ 
            padding: '10px', 
            marginBottom: '20px', 
            backgroundColor: '#fee', 
            border: '1px solid #f00',
            borderRadius: '4px'
          }}>
            Error: {error}
          </div>
        )}

        <div style={{ marginBottom: '20px' }}>
          <p>Click the button below to connect your Square account.</p>
          <p style={{ fontSize: '14px', color: '#666' }}>
            This will redirect you to Square's secure login page.
          </p>
        </div>

        <button 
          onClick={connectSquare}
          style={{
            padding: '10px 20px',
            fontSize: '16px',
            backgroundColor: '#006aff',
            color: 'white',
            border: 'none',
            borderRadius: '4px',
            cursor: 'pointer'
          }}
        >
          Connect Your Square Account
        </button>
      </main>
    </div>
  );
}

When I click the “Connect Your Square Account” button, I get the error at the top of the post.

Not sure where I’m going wrong.

How can I memoize a JavaScript function that accepts multiple arguments, including objects?

I’m trying to improve the performance of a computationally expensive JavaScript function by memoizing it. The function accepts multiple arguments, including objects. Here’s an example:

function expensiveCalculation(a, b, options) {
    // Simulating an expensive operation
    return a + b + options.value;
}

const options = { value: 10 };
console.log(expensiveCalculation(5, 3, options)); // 18
console.log(expensiveCalculation(5, 3, options)); // Should use the cached result

memoizedCalculation(5, 3, options);

How to Prevent Flickering When Moving a Mesh with Autodesk.Viewing.ModelBuilder?

I am using the Autodesk.Viewing.ModelBuilder to add a custom mesh to the Forge Viewer. I want to move the mesh dynamically using a slider by updating its position matrix and calling Builder.updateMesh().

My code updates the mesh’s matrix and then calls Builder.updateMesh() each time the slider value changes. This successfully moves the mesh, but it causes the viewer to flicker with each update:

this.EditMesh.mesh.position.x += 1; 
this.EditMesh.mesh.updateMatrix();
this.EditMesh.mesh.updateMatrixWorld(true);
this._ModelBuilder.updateMesh(this.EditMesh.mesh, false, false);

If I do not call Builder.updateMesh(), the mesh does not move, but the viewer does not flicker.

The highlight functionality (used for selection) and the explode feature of Autodesk Viewer move objects smoothly without flickering, suggesting there might be a way to achieve smooth movement without the flicker.

Is there a way to move a mesh smoothly without calling Builder.updateMesh() on every slider change?
Alternatively, is there a way to prevent the flickering when using Builder.updateMesh()?

Draw a diagonal line in PowerPoint using Office.Js API

I hope you are well. I am facing a strange issue in Office.JS API for PowerPoint. My purpose is simple, I want to draw a diagonal line (front up), but I cannot. In the below pic, you can see it’s top-up line, and in the Shape documentation, I can’t find anything either.

This is the result which I want to achieve

I fiddled with the code below but still had no success. Any help is really appreciated.

  // This function gets the collection of shapes on the first slide,
  // and adds a line to the collection, while specifying its
  // start and end points. Then it names the shape.
  await PowerPoint.run(async (context) => {
    const shapes: PowerPoint.ShapeCollection = context.presentation.slides.getItemAt(0).shapes;

    // For a line, left and top are the coordinates of the start point,
    // while height and width are the coordinates of the end point.
    const line: PowerPoint.Shape = shapes.addLine(PowerPoint.ConnectorType.straight, {
      left: 400,
      top: 200,
      height: 20,
      width: 150
    });
    line.name = "StraightLine";

    await context.sync();
  });
}```



Properly integrating JSDoc and type definitions for Deno and JSR

I’m working on a JavaScript codebase designed for both Deno and browsers. We’re adding documentation and types to publish it on JSR, but I’ve hit some roadblocks.

  1. JSDoc

    Using JSDoc for @param and @returns doesn’t work with deno doc or JSR – they ignore the types, likely because they rely on .d.ts files for type information. This seems limiting for *.js files but might be a technical constraint (my educated guess is, it’s not really JSDoc but TSDoc, which makes sense).

  2. .d.ts Files

    I tried using .d.ts files following https://docs.deno.com/runtime/fundamentals/typescript/, however:

    • Comments in the source and .d.ts seem mutually exclusive in deno doc, forcing me to move all comments in .d.ts, leaving the source undocumented.
    • While the editor’s language server recognizes the .d.ts types for imports (a main.js, but still fails on add.js), deno check fails on both main.js and add.js with errors like: error: TS7006 [ERROR]: Parameter 'a' implicitly has an 'any' type. (same for b).

Questions:

  1. How can I make deno check work with @ts-self-types for both the source (add.js) and the importer (main.js)?
  2. Is there any way to make JSDoc types work directly with deno doc and JSR without .d.ts files?

How to Create a Line Chart with Area Fills for Production-Consumption Balance in ECharts?

I want to create the above chart using ECharts, but I’m running into some difficulties. The chart displays the energy production and consumption balance across the days of the week. The data is represented with two separate lines (production and consumption) and additionally highlights energy given to and taken from the grid with colored areas.

Here are the chart’s features:

Line Chart:
“Production (kWh)” and “Consumption (kWh)” are shown as two different lines.
Area Fill:
Energy given to the grid is shown in blue, and energy taken from the grid is shown in beige.
Labels and Tooltip:
The x-axis shows the days of the week.
The y-axis shows energy values (kWh).
A tooltip displays details on hover.
How can I configure this chart in ECharts? How should I structure the series data? How can I properly define colors, area fills, and line styles (like dashed lines)?

Specifically, I need help with:

Creating the line charts.
Adding area fills (e.g., energy given to and taken from the grid).
Configuring colors and tooltips correctly.
Can anyone guide me?

How to Create a Line Chart with Area Fills for Production-Consumption Balance in ECharts?