How can I make my red cells repell of blue cells?

How can i achive this, without changing behaviour in the code, rather the forces array. i want them to move, and not just fight in 1 place.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Magnet Sprites</title>
    <style>
        .sprite {
            width: 5px;
            height: 5px;
            position: absolute;
            border-radius: 50%;
        }
    </style>
</head>
<body>

    <div id="game-container"></div>

    <script>

        class Sprite {
            constructor(posX, posY) {
                this.posX = posX;
                this.posY = posY;
                this.vx = 0;
                this.vy = 0;
                this.element = document.createElement("div");
                this.element.classList.add("sprite");
                document.getElementById("game-container").appendChild(this.element);
                this.element.style.backgroundColor = colors[Math.floor(Math.random()*colors.length)];
            }

            updatePosition() {
                this.posX += this.vx;
                this.posY += this.vy;
                this.element.style.left = `${this.posX}px`;
                this.element.style.top = `${this.posY}px`;
            }
        }


        let sprites = [];

        const colors = ['red', 'blue']
        const forces = [
            [0.1, -1],
            [1.2, 0.1]
        ];
        //


        console.log(forces)

        const attractionStrength = 0.2
        const minDist = 5;
        const maxDist = 300;
        const damping = 0.9;

        for (let step = 0; step < 500; step++) {
            sprites.push(new Sprite(Math.random() * window.innerWidth, Math.random() * window.innerHeight));
        }

        function updateSprites() {
            for (let i = 0; i < sprites.length; i++) {
                let sprite = sprites[i];

                for (let j = i + 1; j < sprites.length; j++) {
                    let target = sprites[j];

                    let dx = target.posX - sprite.posX;
                    let dy = target.posY - sprite.posY;
                    let dist = Math.sqrt(dx * dx + dy * dy) + 1e-6;

                    if (dist < maxDist) { 
                        let spriteColorIndex = colors.indexOf(sprite.element.style.backgroundColor);
                        let targetColorIndex = colors.indexOf(target.element.style.backgroundColor);

                        if (spriteColorIndex !== -1 && targetColorIndex !== -1) {
                            let force = forces[spriteColorIndex][targetColorIndex] / dist * attractionStrength;

                            let fx = (dx / dist) * force;
                            let fy = (dy / dist) * force;

                            sprite.vx += fx;
                            sprite.vy += fy;
                            target.vx -= fx; 
                            target.vy -= fy;
                        }
                    }
                    if (dist < minDist) {
                        sprite.posX -= (dx / dist) * (minDist - dist);
                        sprite.posY -= (dy / dist) * (minDist - dist);
                    }
                }

                sprite.vx *= damping;
                sprite.vy *= damping;

                sprite.posX += sprite.vx;
                sprite.posY += sprite.vy;

                if (sprite.posX < 0) sprite.posX += window.innerWidth;
                if (sprite.posX > window.innerWidth) sprite.posX -= window.innerWidth;
                if (sprite.posY < 0) sprite.posY += window.innerHeight;
                if (sprite.posY > window.innerHeight) sprite.posY -= window.innerHeight;

                sprite.updatePosition();
            }

            requestAnimationFrame(updateSprites);
        }


        updateSprites();
    </script>

</body>
</html>

in this array:

const forces = [
            [0.1, -1],
            [1.0, 0.1]
        ];

i try this, but they just fight in 1 place, instead of moving smoothly across the screen like i want them to. I have messed with the repulsion, values and other functions in the code, but nothing seems to work like other simulations i have seen on the internet.

An html code with JS works well in online html viewer, but doesn’t work in blogger. Why is it so? [closed]

I have generated an html code for emi calculator using AI. Then I checked the code in online html viewer and is working well. But when I pasted it in the blogger post, no charts are shown, sliders doesn’t change the inputs, output is not updated when numbers are modified manually (as sliders are not working). What’s the problem with blogger, is it because there is external js or something else? Here is the entire code. Kindly anyone help with solution.

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Flat vs Reducing Rate Calculator</title>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 20px;
            background-color: #f4f6f9;
            min-height: 100vh; /* Ensure body takes full viewport height */
            display: flex;
            flex-direction: column;
        }

        .container {
            max-width: 900px;
            margin: 0 auto;
            background: white;
            border-radius: 10px;
            padding: 20px; /* Reduced padding for compactness */
            box-shadow: 0 4px 6px rgba(0,0,0,0.1);
            flex: 1; /* Allow container to grow and fill available space */
        }

        h1 {
            color: #2c3e50;
            text-align: center;
            margin-bottom: 20px; /* Reduced margin */
            font-size: 24px; /* Slightly smaller heading */
        }

        .input-section {
            display: grid;
            gap: 15px; /* Reduced gap */
            margin-bottom: 15px; /* Reduced margin */
        }

        .input-group {
            display: flex;
            flex-direction: column;
            gap: 5px; /* Reduced gap */
        }

        label {
            color: #34495e;
            font-weight: 500;
            font-size: 14px; /* Smaller label text */
        }

        .slider-container {
            display: flex;
            align-items: center;
            gap: 10px; /* Reduced gap */
        }

        input[type="range"] {
            flex: 1;
            -webkit-appearance: none;
            height: 6px; /* Thinner slider */
            background: #ddd;
            border-radius: 5px;
            outline: none;
        }

        input[type="range"]::-webkit-slider-thumb {
            -webkit-appearance: none;
            width: 16px; /* Smaller thumb */
            height: 16px;
            background: #3498db;
            border-radius: 50%;
            cursor: pointer;
        }

        input[type="number"] {
            width: 80px; /* Reduced width */
            padding: 6px; /* Reduced padding */
            border: 1px solid #ddd;
            border-radius: 4px;
            font-size: 14px; /* Smaller text */
        }

        .results {
            display: grid;
            grid-template-columns: 1fr;
            gap: 15px; /* Reduced gap */
            margin-top: 15px; /* Reduced margin */
        }

        .result-box {
            padding: 15px; /* Reduced padding */
            border-radius: 5px;
            background-color: #f8f9fa;
            border: 2px solid;
            overflow: hidden;
        }

        .flat-rate {
            border-color: #e74c3c;
        }

        .reducing-rate {
            border-color: #2ecc71;
        }

        .chart-container {
            position: relative;
            width: 100%;
            max-width: 200px; /* Reduced max-width */
            height: 200px; /* Reduced height */
            margin: 0 auto 10px; /* Reduced margin */
        }

        .details {
            text-align: center;
        }

        .details p {
            margin: 5px 0; /* Reduced margin */
            color: #34495e;
            font-size: 14px; /* Smaller text */
        }

        .details p span {
            font-weight: bold;
            color: #2c3e50;
        }

        .legend {
            display: flex;
            justify-content: center;
            gap: 10px; /* Reduced gap */
            margin-top: 5px; /* Reduced margin */
            flex-wrap: wrap;
        }

        .legend-item {
            display: flex;
            align-items: center;
            gap: 5px;
        }

        .legend-dot {
            width: 10px; /* Smaller dot */
            height: 10px;
            border-radius: 50%;
        }

        .legend-dot.loan {
            background-color: #d6e4ff;
        }

        .legend-dot.interest {
            background-color: #3366cc;
        }

        @media (min-width: 600px) {
            .results {
                grid-template-columns: 1fr 1fr;
            }

            .chart-container {
                max-width: 250px; /* Slightly larger on desktop */
                height: 250px;
            }

            .input-section {
                gap: 20px;
            }

            .details p {
                font-size: 16px;
            }

            h1 {
                font-size: 28px;
            }
        }

        @media (max-width: 599px) {
            .chart-container {
                max-width: 150px; /* Even smaller on mobile */
                height: 150px;
            }

            .details p {
                font-size: 12px; /* Smaller text on mobile */
            }

            .legend {
                gap: 8px;
            }

            .input[type="number"] {
                width: 70px;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>Flat vs Reducing Rate Calculator</h1>
        <div class="input-section">
            <div class="input-group">
                <label>Loan Amount (₹)</label>
                <div class="slider-container">
                    <input type="range" id="principalRange" min="10000" max="10000000" value="100000">
                    <input type="number" id="principal" min="10000" max="10000000" value="100000">
                </div>
            </div>
            <div class="input-group">
                <label>Interest Rate (%)</label>
                <div class="slider-container">
                    <input type="range" id="rateRange" min="1" max="20" step="0.1" value="10">
                    <input type="number" id="rate" min="1" max="20" step="0.1" value="10">
                </div>
            </div>
            <div class="input-group">
                <label>Loan Tenure (Years)</label>
                <div class="slider-container">
                    <input type="range" id="tenureRange" min="1" max="30" value="5">
                    <input type="number" id="tenure" min="1" max="30" value="5">
                </div>
            </div>
        </div>
        <div class="results" id="results">
            <div class="result-box flat-rate">
                <h3 style="text-align: center; margin: 0 0 10px;">Flat Rate</h3>
                <div class="chart-container">
                    <canvas id="flatChart"></canvas>
                </div>
                <div class="details">
                    <p>EMI Amount: ₹<span id="flatEMI">0</span></p>
                    <p>Amount To Be Paid: ₹<span id="flatTotal">0</span></p>
                </div>
                <div class="legend">
                    <div class="legend-item">
                        <span class="legend-dot loan"></span>
                        <p>Loan Amount: ₹<span id="flatPrincipal">0</span></p>
                    </div>
                    <div class="legend-item">
                        <span class="legend-dot interest"></span>
                        <p>Interest Amount: ₹<span id="flatInterest">0</span></p>
                    </div>
                </div>
            </div>
            <div class="result-box reducing-rate">
                <h3 style="text-align: center; margin: 0 0 10px;">Reducing Rate</h3>
                <div class="chart-container">
                    <canvas id="reducingChart"></canvas>
                </div>
                <div class="details">
                    <p>EMI Amount: ₹<span id="reducingEMI">0</span></p>
                    <p>Amount To Be Paid: ₹<span id="reducingTotal">0</span></p>
                </div>
                <div class="legend">
                    <div class="legend-item">
                        <span class="legend-dot loan"></span>
                        <p>Loan Amount: ₹<span id="reducingPrincipal">0</span></p>
                    </div>
                    <div class="legend-item">
                        <span class="legend-dot interest"></span>
                        <p>Interest Amount: ₹<span id="reducingInterest">0</span></p>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script>
      
        // Get all input elements
        const principalRange = document.getElementById('principalRange');
        const principalInput = document.getElementById('principal');
        const rateRange = document.getElementById('rateRange');
        const rateInput = document.getElementById('rate');
        const tenureRange = document.getElementById('tenureRange');
        const tenureInput = document.getElementById('tenure');

        // Initialize charts
        const flatChartCtx = document.getElementById('flatChart').getContext('2d');
        const reducingChartCtx = document.getElementById('reducingChart').getContext('2d');

        const flatChart = new Chart(flatChartCtx, {
            type: 'doughnut',
            data: {
                labels: ['Loan Amount', 'Interest Amount'],
                datasets: [{
                    data: [100000, 0],
                    backgroundColor: ['#d6e4ff', '#3366cc'],
                    borderWidth: 0
                }]
            },
            options: {
                responsive: true,
                maintainAspectRatio: false,
                cutout: '70%',
                plugins: {
                    legend: { display: false },
                    tooltip: {
                        enabled: true,
                        callbacks: {
                            label: function(context) {
                                let label = context.label || '';
                                if (label) {
                                    label += ': ₹';
                                }
                                label += context.raw.toLocaleString('en-IN');
                                return label;
                            }
                        }
                    }
                }
            }
        });

        const reducingChart = new Chart(reducingChartCtx, {
            type: 'doughnut',
            data: {
                labels: ['Loan Amount', 'Interest Amount'],
                datasets: [{
                    data: [100000, 0],
                    backgroundColor: ['#d6e4ff', '#3366cc'],
                    borderWidth: 0
                }]
            },
            options: {
                responsive: true,
                maintainAspectRatio: false,
                cutout: '70%',
                plugins: {
                    legend: { display: false },
                    tooltip: {
                        enabled: true,
                        callbacks: {
                            label: function(context) {
                                let label = context.label || '';
                                if (label) {
                                    label += ': ₹';
                                }
                                label += context.raw.toLocaleString('en-IN');
                                return label;
                            }
                        }
                    }
                }
            }
        });

        // Sync slider and number input
        function syncInputs(range, input) {
            range.addEventListener('input', () => {
                input.value = range.value;
                calculateEMI();
            });
            input.addEventListener('input', () => {
                if (input.value >= range.min && input.value <= range.max) {
                    range.value = input.value;
                    calculateEMI();
                }
            });
        }

        syncInputs(principalRange, principalInput);
        syncInputs(rateRange, rateInput);
        syncInputs(tenureRange, tenureInput);

        function calculateEMI() {
            const principal = parseFloat(principalInput.value);
            const rate = parseFloat(rateInput.value);
            const tenureYears = parseInt(tenureInput.value);
            const tenureMonths = tenureYears * 12;

            // Flat Rate Calculation
            const flatYearlyInterest = (principal * rate * tenureYears) / 100;
            const flatTotalInterest = flatYearlyInterest;
            const flatTotalAmount = principal + flatTotalInterest;
            const flatEMI = flatTotalAmount / tenureMonths;

            // Reducing Rate Calculation
            const monthlyRate = rate / (12 * 100);
            const reducingEMI = principal * monthlyRate * Math.pow(1 + monthlyRate, tenureMonths) / 
                              (Math.pow(1 + monthlyRate, tenureMonths) - 1);
            const reducingTotalAmount = reducingEMI * tenureMonths;
            const reducingTotalInterest = reducingTotalAmount - principal;

            // Update text results
            document.getElementById('flatEMI').textContent = flatEMI.toFixed(2).toLocaleString('en-IN');
            document.getElementById('flatInterest').textContent = flatTotalInterest.toFixed(2).toLocaleString('en-IN');
            document.getElementById('flatTotal').textContent = flatTotalAmount.toFixed(2).toLocaleString('en-IN');
            document.getElementById('flatPrincipal').textContent = principal.toFixed(2).toLocaleString('en-IN');

            document.getElementById('reducingEMI').textContent = reducingEMI.toFixed(2).toLocaleString('en-IN');
            document.getElementById('reducingInterest').textContent = reducingTotalInterest.toFixed(2).toLocaleString('en-IN');
            document.getElementById('reducingTotal').textContent = reducingTotalAmount.toFixed(2).toLocaleString('en-IN');
            document.getElementById('reducingPrincipal').textContent = principal.toFixed(2).toLocaleString('en-IN');

            // Update charts
            flatChart.data.datasets[0].data = [principal, flatTotalInterest];
            flatChart.update();

            reducingChart.data.datasets[0].data = [principal, reducingTotalInterest];
            reducingChart.update();
        }

        // Initial calculation
        calculateEMI();
  </script>

  
  </body>
</html>

What causes this Laravel and JavaScript article tags bug?

I am working on a blogging application in Laravel 8.

I have put together a way to add and edit tags to articles.

enter image description here

I ran into a bug whose cause and solution I have been unable to find: updating the article’s list of tags fails after one or more (but not all) tags are deleted. By contrast, if I only select new tags, the update operation works fine.

In the ArticleController controller, I have the below methods for editing and updating an article:

public function edit($id)
  {
    $article = Article::find($id);
    $attached_tags = $article->tags()->get()->pluck('id')->toArray();
    
    return view(
      'dashboard/edit-article',
      [
        'categories' => $this->categories(),
        'tags' => $this->tags(),
        'attached_tags' => $attached_tags,
        'article' => $article
      ]
    );
  }

  public function update(Request $request, $id)
  {
    $validator = Validator::make($request->all(), $this->rules, $this->messages);

    if ($validator->fails()) {
      return redirect()->back()->withErrors($validator->errors())->withInput();
    }

    $fields = $validator->validated();
    $article = Article::find($id);

    // If a new image is uploaded, set it as the article image
    // Otherwise, set the old image...
    if (isset($request->image)) {
      $imageName = md5(time()) . Auth::user()->id . '.' . $request->image->extension();
      $request->image->move(public_path('images/articles'), $imageName);
    } else {
      $imageName = $article->image;
    }

    $article->title = $request->get('title');
    $article->short_description = $request->get('short_description');
    $article->category_id = $request->get('category_id');
    $article->featured = $request->has('featured');
    $article->image = $request->get('image') == 'default.jpg' ? 'default.jpg' : $imageName;
    $article->content = $request->get('content');
    // Save changes to the article
    $article->save();

    //Attach tags to article
    if ($request->has('tags')) {
      $article->tags()->sync($request->tags);
    } else {
        $article->tags()->sync([]);
    }

    return redirect()->route('dashboard.articles')->with('success', 'The article titled "' . $article->title . '" was updated');
  } 

In viewsdashboardedit-article.blade.php I have this code got the pat of the interface that deals with the tags:

<div class="row mb-2">
  <label for="tags" class="col-md-12">{{ __('Tags') }}</label>

  <div class="position-relative">
      <span id="tagSelectorToggler" class="tag-toggler" onclick="toggleTagSelector(event)">
          <i class="fas fa-chevron-up"></i>
      </span>
      <ul id="tagsList" class="form-control tags-list mb-1" onclick="toggleTagSelector(event)">
          <li class="text-muted">
              Use [Ctrl] + [Click] to select one or more tags from the list
          </li>
      </ul>
  </div>

  <div id="tagActions" class="tag-actions">
      <input oninput="filterTags(event)" type="search" class="form-control mb-1"
          placeholder="Filter available tags" />

      @php $selectedTags = old('tags', $attached_tags) @endphp

      <select name="tags[]" id="tags" class="form-control tag-select" multiple>
          @foreach ($tags as $tag)
              <option value="{{ $tag->id }}"
                  {{ in_array($tag->id, $selectedTags) ? 'selected' : '' }}>
                  {{ $tag->name }}
              </option>
          @endforeach
      </select>
  </div>
</div>

In resourcesjstags.js, I have:

const tagsList = document.querySelector(".tags-list")
const tagActions = document.getElementById("tagActions")
const tagSelector = document.getElementById("tags")
const tagToggler = document.getElementById("tagSelectorToggler")
if (tagSelector) {
  var preSelectedTags = Array.from(tagSelector.options)
    .filter((option) => option.selected)
    .map((option) => option.text)
  var selectedTags = new Set()
}

window.filterTags = (event) => {
  var query = event.target.value
  var availableTags = Array.from(tagSelector.options)

  availableTags.forEach(function (option) {
    if (!option.text.toLowerCase().includes(query.toLowerCase())) {
      option.classList.add("d-none")
    } else {
      option.classList.remove("d-none")
    }
  })
}

window.toggleTagSelector = (event) => {
  let tagActionsVisibility = tagActions.checkVisibility()
  if (event.target.tagName !== "BUTTON" && event.target.tagName !== "SPAN") {
    if (tagActionsVisibility) {
      tagActions.style.display = "none"
      tagToggler.classList.add("active")
    } else {
      tagActions.style.display = "block"
      tagToggler.classList.remove("active")
    }
  }
}

window.renderTags = () => {
  tagsList.innerHTML =
    [...selectedTags]
      .sort()
      .map(
        (tag) =>
          `<li class="tag"
            ><span class="value">${tag}</span>
            <button>&times;</button>
         </li>`,
      )
      .join("") ||
    `<li class="text-muted">Use [Ctrl] + [Click] to select one or more tags from the list</li>`
  for (const option of tagSelector.options) {
    option.selected = selectedTags.has(option.textContent)
  }
}

if (preSelectedTags) {
  window.addPreselectedTags = () => {
    preSelectedTags.forEach(selectedTags.add.bind(selectedTags))
    renderTags()
  }
}

if (tagsList) {
  tagsList.addEventListener("click", function (event) {
    if (event.target.tagName !== "BUTTON") return
    let tagToRemove = event.target.closest("LI").children[0].textContent
    let optionToDeselect = Array.from(tagSelector.options).find((option) => {
      return option.innerText == tagToRemove
    })
    optionToDeselect.removeAttribute('selected')
    selectedTags.delete(tagToRemove)
    console.log(selectedTags);  
    renderTags()
  })
}

if (tagSelector) {
  tagSelector.addEventListener("change", function () {
    selectedTags = new Set(
      Array.from(tagSelector.options)
        .filter((option) => option.selected)
        .map((option) => option.textContent),
    )
    renderTags()
    console.log(selectedTags);
  })
}

if (tagSelector) {
  window.addPreselectedTags();
}

If I click a tag’s close button and then update the article, it loses all the tags (not only the deleted one).

Where is my mistake?

My own Vue 3 Library can’t work properly when inported in another project

I’m developing a Vue 3 component library using Vite and TypeScript, and when I import and use my library in another Vue 3 app, I get the following error:

runtime-core.esm.js:38 [Vue warn]: Missing ref owner context. ref cannot be used on hoisted vnodes. A vnode with ref must be created inside the render function.

After some research, I found that this issue often occurs due to multiple Vue instances being bundled together. However, I’m already using external: [“vue”] in my vite.config.ts, so I don’t understand why this is happening.

This is my vite.config.ts

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import typescript2 from "rollup-plugin-typescript2";
import { resolve } from "path";
import cssInjectedByJsPlugin from "vite-plugin-css-injected-by-js";

// https://vitejs.dev/config/
export default defineConfig({
    plugins: [
        vue(),
        typescript2({
            check: false,
            include: ["src/**/*.vue", "src/**/*.ts"],
            tsconfigOverride: {
                compilerOptions: {
                    outDir: "dist",
                    sourceMap: true,
                    declaration: true,
                    declarationMap: true
                }
            },
            exclude: ["vite.config.ts"]
        }),
        cssInjectedByJsPlugin()
    ],
    build: {
        cssCodeSplit: false,
        sourcemap: false,
        lib: {
            entry: "./src/main.ts",
            formats: ["es", "cjs"],
            name: "RuntimeCore",
            fileName: format => `runtime-core.${format}.js`
        },
        rollupOptions: {
            external: ["vue"],
            output: {
                exports: "named",
                globals: {
                    vue: "Vue"
                }
            }
        }
    },
    resolve: {
        alias: {
            "@": resolve(__dirname, "src")
        }
    }
});

I build module and dependency using

vite build && vue-tsc --emitDeclarationOnly

In my package json i have the following entries

 "main": "dist/tk3d_hotspots.cjs.js",
 "module": "dist/tk3d_hotspots.es.js",
 "typings": "dist/main.d.ts",
 "type": "module",

Has anyone else experienced this issue with a Vue 3 + Vite library?

TypeError: mode must be int32 or null/undefined in Node JS issue when connecting to mongodb

Below is the Node JS project

api
   swagger.yaml - having visual representation of the API and its documentation
controllers
   entityApi.js file - APIs - create,delete,list,patch api
service
   entityService.js - API implementation
utils
   mongoUtils.js
index.js file
.... and other files

Below is the code in index.js file n


'use strict';

const fs = require('fs'),
      path = require('path'),
      http = require('http'),
      mongoUtils = require('./utils/mongoUtils'),
      swaggerUtils = require('./utils/swaggerUtils');

const {error, errorEnum, sendError} = require('./utils/errorUtils');

const app = require('connect')();
const swaggerTools = require('swagger-tools');

const serverPort = 8080;

//error is coming here
fs.copyFileSync(path.join(__dirname, './index.html_replacement'), 
        path.join(__dirname, './node_modules/swagger-ui-dist/index.html'), (err) => {
  if(err) {
    console.log('Unable to replace swagger-ui-dist/index.html file - something wrong with the installation ??');
    process.exit(1);
  }
})

// swaggerRouter configuration
const options = {
  swaggerUi: path.join(__dirname, '/swagger.json'),
  controllers: path.join(__dirname, './controllers'),
  useStubs: process.env.NODE_ENV === 'development' // Conditionally turn on stubs (mock mode)
};

const swaggerDoc = swaggerUtils.getSwaggerDoc();

swaggerTools.initializeMiddleware(swaggerDoc, function (middleware) {

  app.use(middleware.swaggerMetadata());

  // Validate Swagger requests
  app.use(middleware.swaggerValidator({
        validateResponse: false
  }));

  // Error handling for validation
  app.use(errorHandler);

  // Route validated requests to appropriate controller
  app.use(middleware.swaggerRouter(options));

  // Serve the Swagger documents and Swagger UI
  // using the more up-to-date swagger-ui-dist - not the default app.use(middleware.swaggerUi())
  app.use(middleware.swaggerUi({ swaggerUiDir: path.join(__dirname, 'node_modules', 'swagger-ui-dist') }));

  // Start the server
  http.createServer(app).listen(serverPort, function () {
    console.log('Your server is listening on port %d (http://localhost:%d)', serverPort, serverPort);
    console.log('Swagger-ui is available on http://localhost:%d/docs', serverPort);
  });

});

// handles timed out requests
function haltOnTimedout(req, res, next) {
    if (!req.timedout) {
        next();
    } else {
        debug("nrequest timed out!n");
        next("the request timed out", null, null, null, 504);
    }
}

function errorHandler (err, req, res, next) {
  if(err) {
    if(err.failedValidation) {
      const message = err.results.errors.map(item => item.message).join(", ");
      
      const error = new Error(ErrorEnum.INVALID_BODY, message);
      sendError(res,error);

    } else {
      const error = new Error(ErrorEnum.INVALID_BODY, "Invalid request");
      sendError(res,error);

    }

  } else {
    next(err,req,res);
  }
};

and mongoUtils.js contents below n


'use strict';

const util = require('util')
const assert = require('assert');

const queryToMongo = require('query-to-mongo');
const querystring = require('querystring');

const MongoClient = require('mongodb').MongoClient;

const {getResponseType, getPayloadType, getTypeDefinition} = require('./swaggerUtils');

var mongodb = null; 

function connectHelper(callback) {
  var config = require('../config.json');

  var argv = require('minimist')(process.argv);
  var dbhost = argv.dbhost ? argv.dbhost: config.db_host;
  const mongourl = process.env.MONGO_URL || (config.db_prot + "://" + dbhost + ":" + config.db_port + "/" + config.db_name);
 
  MongoClient.connect(mongourl, { useNewUrlParser: true }, function (err, db) {

      if (err) {
        mongodb = null;
        callback(err,null);
      } else {
        mongodb = db.db("mydatabase");
        callback(null,mongodb);
      }
    }
  );
};


function getMongoQuery(req) {
  var res;
  if(req instanceof Object) {
    res = queryToMongo(req._parsedUrl.query);
  } else {
    res = queryToMongo(querystring.parse(req));
  }

  if(res!==undefined && res.options!==undefined && res.options.fields!==undefined) {
    res.options.fields.href = true;
    res.options.fields.id = true;
  }

  try {
    const requestType = getPayloadType(req);
    const properties = Object.keys(res.criteria);

    var typeDefinition = getTypeDefinition(requestType);
    if(typeDefinition.properties!==undefined) {
      typeDefinition = typeDefinition.properties;
    }

    properties.forEach(prop => {
      var paramDef = typeDefinition[prop];
      if(paramDef!==undefined && paramDef.type === "string" && paramDef.format === "date-time") {
        const propVal = res.criteria[prop];
        // equality test if not the value is an object
        if(!(propVal instanceof Object)) {
          if(!isNaN(Date.parse(propVal))) {
            res.criteria[prop] = {$regex: '^' + propVal + '.*' };
          }
        }
      }
    });
  }
  catch(err) {
    // ignore for now
  }

  res.options.projection = res.options.fields;
  delete res.options.fields;

  return(res);

};

function quotedString(s) {
  return s;
};

function connectDb(callback) {
  if(mongodb) {
      mongodb.stats(function(err, stats) {
        if(stats != null) {
          callback(null,mongodb);
        } else {
          connectHelper(callback);
        }
      });
  } else {
    connectHelper(callback);
  }
};

function connect() {
  return new Promise(function(resolve,reject) {
      connectDb(function(err,db) {
        if(err!=null || db==null) {
          reject(err);
        } else {
          resolve(db);
        };
      });
    });
};

function sendDoc(res,code,doc) {
  // delete internal mongo _id from all documents
  if(Array.isArray(doc)) {
    // remove _id from all documents
    doc.forEach(x => {
      delete x._id;
    });
  } else {
    delete doc._id;
  }

  if(doc.href) {
    res.setHeader('Location',  doc.href);
  }

  res.statusCode = code;
  res.setHeader('Content-Type', 'application/json');
  res.end(JSON.stringify(doc));
}


module.exports = { connect, connectDb, getMongoQuery, sendDoc };

the npm install is fine
where as node index.js gives below error

binding.copyFile(
**          ^
TypeError: mode must be int32 or null/undefined 
    at Object.copyFileSync (node:fs:3086:11) 
    at Object. (C:Usersshivashankar.g02>index.js:18:4) at Module._compile (node:internal/modules/cjs/loader:1562:14) 
**
    at Object..js (node:internal/modules/cjs/loader:1699:10) 
    at Module.load (node:internal/modules/cjs/loader:1313:32) 
    at Function._load (node:internal/modules/cjs/loader:1123:12) 
    at TracingChannel.traceSync (node:diagnostics_channel:322:14) 
    at wrapModuleLoad (node:internal/modules/cjs/loader:217:24) 
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:170:5) 
    at node:internal/main/run_main_module:36:49 { 
  code: 'ERR_INVALID_ARG_TYPE' 

Any pointers/directions on why it’s coming?. Kindly assist in resolving the issue. Thanks

How to isolate the execution of JS code, such that each script is executed within a “container”? Tried shadowDOM and IIFE, does not do the job

I have 2 js files – dashboard.js and statuspanel.js. They render React components inside the div that has the name of the script as it’s id. For example, in my JSF application.

<composite:implementation>
    <div id="#{cc.attrs.name}"></div>
    <script src="http://localhost:8900/microfrontends/#{cc.attrs.name}/#{cc.attrs.name}.js" type="text/javascript"></script>
    <link rel="stylesheet" type="text/css" href="http://localhost:8900/microfrontends/#{cc.attrs.name}/#{cc.attrs.name}.css"/>
</composite:implementation>

When there is one component per page, there are no issues at all. But if I have more than one component, then there is a collision in the variable names. So If I do this

                    <div class="ui-g-12 ui-g-nopad">
                        <ic:microfrontend name="statuspanel"/>
                        <ic:microfrontend name="dashboard"/>
                    </div>

I get this error

dashboard.js:1 Uncaught SyntaxError: Identifier 'Wc' has already been declared (at dashboard.js:1:1)

I searched the internet and found 2 ways to possibly solve the problem. First approach is using the shadowDOM.

<composite:implementation>
    <div id="#{cc.attrs.name}_host"></div>
    <div id="#{cc.attrs.name}"></div>
    <script type="text/javascript">
        (function () {
            const shadowHost = document.getElementById("#{cc.attrs.name}_host");
            const shadowRoot = shadowHost.attachShadow({mode: 'open'});

            const div = document.createElement('div');
            div.id = "#{cc.attrs.name}";
            shadowRoot.appendChild(div);

            const script = document.createElement("script");
            script.src = `http://localhost:8900/microfrontends/#{cc.attrs.name}/#{cc.attrs.name}.js`;
            shadowRoot.appendChild(script);

            const link = document.createElement("link");
            link.rel = 'stylesheet';
            link.href = `http://localhost:8900/microfrontends/#{cc.attrs.name}/#{cc.attrs.name}.css`;
            shadowRoot.appendChild(link);
        })();
    </script>
</composite:implementation>

But I still get the same error. Also, script only finds the div outside the shadowDOM, it does not see the one inside (I did remove the div above the shadowDOM beforehand).

Uncaught SyntaxError: Identifier 'Wc' has already been declared (at dashboard.js:1:1)

enter image description here

So I tried a second approach – wrapping my script with a function to make global variables function scoped.

<composite:implementation>
    <div id="#{cc.attrs.name}"></div>
    <script type="text/javascript">
        (function () {
            var script = document.createElement('script');
            script.src = 'http://localhost:8900/microfrontends/#{cc.attrs.name}/#{cc.attrs.name}.js';
            document.head.appendChild(script);
        })();
    </script>
    <link rel="stylesheet" type="text/css" href="http://localhost:8900/microfrontends/#{cc.attrs.name}/#{cc.attrs.name}.css"/>
</composite:implementation>

However, I still get the same error.

Uncaught SyntaxError: Identifier 'Wc' has already been declared (at dashboard.js:1:1)

enter image description here

I have also tried to change the auto-generated js files (dashboard and statuspanel), where I replaced var with let, but this breaks the scripts. So that is not an option.

Question: How to isolate the execution of JS code, such that each script is executed within a “container”? Using iframe is not an option.

how to Add/Remove an item to dropdown list in JavaScript

I would like to add an item to the dropdown list when the “Yes” radio button is selected, and remove the item when the “No” radio button is selected. Additionally, I want the modified values to be retained even after the page is reloaded. How can I accomplish this?

<div class="ABForm" id="credit<%= i %>" style="display:block">
<label for='<%= "persTaxcredit.persList[" + i + "].featureFilmEnhancedCredit" %>'><spring:message code="fct25"/></label>
<span onchange="checkYesNo(this, <%= i %>);">
    <ss:radiobutton path='<%= "persTaxcredit.persList[" + i + "].featureFilmEnhancedCredit" %>' id="idYesNo" value="true"/>
    <ss:radiobutton path='<%= "persTaxcredit.persList[" + i + "].featureFilmEnhancedCredit" %>' id="idYesNo" value="false"/>
</span>
<div class="ABForm" id="taxPercent<%= i %>">
<label for='<%= "persTaxcredit.persList[" + i + "].taxCredit" %>'></label>
<ss:select path='<%= "persTaxcredit.persList[" + i + "].taxCredit" %>' >
  <form:option value=""></form:option>    
  <form:option value="10%"></form:option>
  <form:option value="20%"></form:option>
</ss:select>
function checkYesNo(val, index) {
var selectedValue = isRadioButtonSelected(val, index);
if(selectedValue === "true"){
    //Wanted to add a new tax credit 30% to the dropdown list, modified dropdown values should be retained on page load
    
}
else if(selectedValue === "false"){
    //Wanted to remove the newly added tax credit 30%, modified dropdown values should be retained on page load
}

}

How do I turn a div that contains a pdf file into a button on a small screen?

I am trying to turn my pdf into a button when viewed on a mobile device. I want the pdf to be fully displayed on a larger screen then turn into a button on smaller ones. How do I accomplish this?

Here is my code:

HTML

<body>
    <h1 class="about-h1">Overview Of Me!</h1>
    <div class="container-about">
      <div class="resume">
        <object class="pdf" data="pictures/Resume2025.pdf"></object>
      </div>
    </div>

    <script
      src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
      integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
      crossorigin="anonymous"
      src="index.js"
    ></script>

Javascript

function makeResumeBtn() {
  const button = document.createElement("button");
  button.id = "resumeBtn";
  button.textContent = "Resume";

  const container = document.getElementById(".container-about");
  container.appendChild(button);
}

let widthMatch = window.matchMedia("(max-width: 767px)");

widthMatch.addEventListener("change", function (makeResumeBtn) {
  if (makeResumeBtn.matches) {
    document.body.addEventListener("change");
  } else {
  }
});

.ics file is not getting detected by Google Calendar

The .ics file user is receiving is not blocking the calendar and not even detectable by Google. Even in the organiser’s calendar it is not showing. The .ics file is getting generated programatically using SES, Nodemailer.

const transporter = nodemailer.createTransport({ SES: { ses, aws } });

const res = await transporter.sendMail(mailData);
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Your App//EN
CALSCALE:GREGORIAN
METHOD:REQUEST
BEGIN:VTIMEZONE
TZID:UTC
BEGIN:STANDARD
DTSTART:16010101T000000
TZOFFSETFROM:+0000
TZOFFSETTO:+0000
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
UID:[email protected]
DTSTAMP:20240101T120000Z
DTSTART;TZID=UTC:20240915T140000
DTEND;TZID=UTC:20240915T150000
ORGANIZER;CN=John Doe:mailto:[email protected]
ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED:mailto: [email protected]
ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=Jane:mailto:[email protected]
SUMMARY:Team Sync
DESCRIPTION:Project status update
LOCATION:Google Meet
TRANSP:OPAQUE
STATUS:CONFIRMED
SEQUENCE:0
X-MICROSOFT-CDO-BUSYSTATUS:BUSY
BEGIN:VALARM
TRIGGER:-PT15M
ACTION:DISPLAY
DESCRIPTION:Reminder
END:VALARM
END:VEVENT
END:VCALENDAR

enter image description here

I want to know what param to be modified/added in the .ics file to make it work . My question is not how to generate it programmatically .

Need help building a playlist-based radio station that syncs playback across users [closed]

I have an idea for a page that is basically a fake radio station, kind of live but not really I guess?

My idea is a page that plays through a playlist of music 24/7 so any time someone visits the page it will be playing a song from the playlist. Any device/connection that accesses the page will be playing the same song, at the same playback time (or close at least), in the same order like a real radio station. I think this is definitely possible but I can’t find much help with this online because it is a pretty specific idea. I am not the best at HTML/js/css coding but I know a bit and make it work, I am good at working off of/modifying stuff but not the best at figuring out more complex stuff like this from scratch. I’m good at reverse engineering I suppose.

I am not sure how to approach this, I know a real live audio feed would be the easiest/simplest probably but I also feel like my way might be easier if I can figure out how to get it to start playing at the same point across devices/connections. That is the part I really need help with, I can figure out some way to get a playlist of music playing I’m sure but having it start playback at a specific place and making sure every connection does this around the same place is the unknown. Is there a way to do this? I feel like it is a very specific thing I’m trying to do but I know there’s gotta be a way. I just need it to feel like streaming a radio station without actually being one.

To clarify; I just need some ideas on how to sync playback of a playlist across users and start playback (onclick) at that point.

Ant Design Tree checkboxes not updating when clearing corresponding badge until manually unchecked first

I have an Ant Design Tree component, along with badges that correspond to items in the Tree component. When I “clear a badge” then it should uncheck the corresponding box for that item in the tree. But it doesn’t do that even though the checkedKeys state that gets passed into Tree component DOES update correctly. It’s only after I uncheck a box FIRST and then clear other badges that the Tree component actually updates and the corresponding boxes get unchecked.

import { useRef, useEffect, useMemo, useState } from "react";
import { Tree } from "antd";
import type { TreeDataNode, TreeProps } from "antd";
import { Badge } from "@/components/ui/badge";
import { X } from "lucide-react";
import { filterBrand } from "@/app/(dashboard)/custom-audiences/brands-tree-utils";

type BrandsTreeProps = {
  treeData: TreeDataNode[];
  checkedKeys: TreeProps["checkedKeys"];
  onChecked: (checkedKeys: string[]) => void;
};

export default function BrandsTree({
  treeData,
  checkedKeys,
  onChecked,
  brandCharacteristics,
  handleBadgeClear,
}: BrandsTreeProps) {
  const [selectedNodes, setSelectedNodes] = useState<string[]>([]);

  useEffect(() => {
    const finalArr = Object.values(brandCharacteristics).flat();
    setSelectedNodes(finalArr);
  }, [brandCharacteristics]);

  const onCheck = (checkedKeysValue: TreeProps["checkedKeys"]) => {
    if (checkedKeysValue === undefined) {
      return;
    }

    let checkedKeysArray: string[];

    if (Array.isArray(checkedKeysValue)) {
      checkedKeysArray = checkedKeysValue.map(String);
    } else {
      checkedKeysArray = checkedKeysValue.checked.map(String);
    }

    onChecked(checkedKeysArray);
  };

  return (
    <div>
      <p className="mb-2 text-base font-medium">Brands</p>
      <div className="mb-2">
        {selectedNodes.length > 0 &&
          selectedNodes.map((item, index) => {
            return (
              <div key={index}>
                <Badge>
                  <span className="mr-1 mt-0.5">{item}</span>
                  <button
                    className="ring-offset-background focus:ring-ring ml-1 items-center rounded-full outline-none focus:ring-2 focus:ring-offset-2"
                    onClick={() => {
                      handleBadgeClear(item);
                    }}
                  >
                    <X className="text-muted-foreground hover:text-foreground h-4 w-4" />
                  </button>
                </Badge>
              </div>
            );
          })}
      </div>
      {!!treeData.length && (
        <Tree
          checkable
          treeData={treeData}
          onCheck={onCheck}
          checkedKeys={checkedKeys}
        />
      )}
    </div>
  );
}

 function onChecked(checkedKeys: CheckedKeys) {
    if (!Array.isArray(checkedKeys)) {
      return;
    }
    const keys = checkedKeys.map(String);
    form.setValue("brand_ids", convertBrandHierarchyToIds(brands, keys));
    setCheckedKeys(keys);

    setIsSizeRefreshRequired(true);
  }

  function handleBadgeClear(brandName: string) {
    const updatedBrandKeywordCheckedKeys = filterBrand(
      brandKeywordCheckedKeys,
      brandTreeData,
      brandName,
    );

    onChecked(updatedBrandKeywordCheckedKeys);
  }

Cannot get 3 tier collapsible structure in html – Is my JavaScript code the issue?

I’m brand new to HTML/JavaScript/CSS and trying to make a website. I want to create my resume in a page and there be collapsible options where it goes:

About Me (1)

  • Example text (2)

Certifications & Skillsets (1)

Example Text (2)

Experience (1)

  • Example 1 Job (2)

  • Description (3)

  • Example 2 Job (2)

  • Description (3)

Education (1)

Example Text (2)

The issue is mostly under ‘Experience’ the text after ‘Example 1’ and ‘Example 2’ won’t display after I’ve selected it. I have Copiloted/AI’d this to death and cannot figure out why the collapsible buttons aren’t working. Appreciate any help!

I tried changing display:block but then it shows up every time, I changed the variables in the JavaScript to coll2 because originally it was the same code just with collapsible2 changed.

var coll = document.getElementsByClassName("collapsible");
var i;

for (i = 0; i < coll.length; i++) {
  coll[i].addEventListener("click", function() {
    this.classList.toggle("active");
    var content = this.nextElementSibling;
    if (content.style.display === "block") {
      content.style.display = "none";
    } else {
      content.style.display = "block";
    }
  });
}

var coll2 = document.getElementsByClassName("collapsible2");
var j;

for (j = 0; j < coll2.length; j++) {
  coll2[j].addEventListener("click", function() {
    this.classList.toggle("active");
    var content2 = this.nextElementsibling;
    if (content2.style.display === "block") {
      content2.style.display = "none";
    } else {
      content2.style.display = "block";
    }
  });
} 
body {
  font-family: Arial, Helvetica, sans-serif;
  background-color: whitesmoke
}

p {
  color: black
}

.topnav {
  overflow: hidden;
  background-color: lavender;
  display: flex;
  position: sticky;
  align-items: center;
  justify-content: space-evenly;
  background-blend-mode: darken;
  background-size: cover;
  text-decoration: none;
  text-align: center;
  height: 75px;
  border-radius: 10px;
}

.topnav a {
  float: left;
  color: black;
  text-align: center;
  padding: 16px 16px;
  font-size: 18px;
  font-weight: bold;
  margin-right: 25px;
  border-radius: 10px;
  transition: color .3s ease-in-out;
}

.topnav a:hover {
  background-color: white;
  color: black;
  border-radius: 10px;
}

.topnav a.active {
  background-color: slateblue;
  color: white;
  border-color: black;
  border-width: 5px;
}

.topnav a.email-me {
  align-items: right;
  background-color: rgb(77, 65, 151);
  color: white;

}

.topnav a.email-me:hover {
  background-color: rgb(63, 53, 128);
  color: white;
  transition: color .3s ease-in-out;
}

.collapsible {
  color: black;
  background-color: lightgrey;
  cursor: pointer;
  padding: 10px;
  width: 100%;
  height: 100px;
  border: none;
  text-align: left;
  outline: none;
  font-size: 18px;
}

.active,
.collapsible:hover {
  background-color: darkgrey;
}

.content {
  padding: 0 18px;
  display: none;
  overflow: hidden;
  background-color: whitesmoke;
}

.collapsible2 {
  color: white;
  background-color: slateblue;
  cursor: pointer;
  padding: 10px;
  width: 100%;
  height: 50px;
  border: none;
  text-align: left;
  outline: none;
  font-size: 14px;
}

.active,
.collapsible2:hover {
  background-color: rgb(63, 53, 128);
}

.content2 {
  padding: 0 18px;
  display: none;
  overflow: hidden;
  background-color: whitesmoke;
}
<html>

<head>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script type="module" src="https://unpkg.com/[email protected]/dist/ionicons/ionicons.esm.js"></script>
  <script nomodule src="https://unpkg.com/[email protected]/dist/ionicons/ionicons.js"></script>

</head>

<title> XXX Life & Experiences
</title>

<body>
  <nav class="topnav">
    <a href="main website code.html">About Me</a>
    <a class="active" href="Resume.html">Resume</a>
    <a href="Current Projects.html">Current Projects</a>
    <a href="mailto:[email protected]" class="email-me">Email Me</a>
  </nav>
  <div style="padding-left:16px">
    <p> Check out my LinkedIn for more details: <a href="https://www.linkedin.com/in/XXX/">LinkedIn Profile.</a></p> <br><br>

    <button class="collapsible"><h3>ABOUT ME</h3></button>
    <div class="content">
      <ul>
        <li>Senior consultant with a strong background in project management and leading technical teams. Effective at managing teams and clients, working with Agile principles, and supporting business requirements</li>
      </ul>
    </div>

    <button class="collapsible"><h3>CERTIFICATIONS & SKILLSETS</h3></button>
    <div class="content">
      <ul>
        <li>Project Management Professional (PMP) Certified: 2023 </li>
        <li>Salesforce Business Analyst Certified: 2023</li>
        <li>Skills: PowerPoint, Salesforce, Excel, Word, Visio, Mural, Qualtrics, and Jira</li>
      </ul>
    </div>

    <button class="collapsible"><h3>EXPERIENCE</p></h3></button>
    <div class="content">
      <button class ="collapsible2"><h4>EXAMPLE1 </h4></button>
      <br><br>
      <div class="content2">
        <h4>Development of New Salesforce Feature: AAA</h4>
        <ul>
          <li>XYZ</li>
        </ul>
        <h4>Development of New Salesforce Feature: BBB</h4>
        <ul>
          <li>XYZ/li>
        </ul>
      </div>

      <button class="collapsible2"><h4>EXAMPLE 2</h4></button>
      <br><br>
      <div class="content2">
        <ul>
          <li>XYZ</li>
        </ul>
      </div>
    </div>
    <button class="collapsible"><h3>EDUCATION </h3></button>
    <div class="content">
      <h4>XXX – B.B.A | Economics – Honors </h4>
      <ul>
        <li>GPA: 3.91</li>
      </ul>
    </div>
    <br><br>
    </p>
  </div>
</body>

</html>

Cannot get 3 tier collapsible structure in html – Need help figuring out if Javascript is the issue

I’m brand new to HTML/JavaScript/CSS and trying to make a website. I want to create my resume in a page and there be collapsible options where it goes:

About Me (1)

Example text (2)

Certifications & Skillsets (1)

Example Text (2)

Experience (1)

  • Example 1 Job (2)
    Description (3)

  • Example 2 Job (2)
    Description (3)

Education (1)

Example Text (2)

I have Copiloted/AI’d this to death and cannot figure out why the collapsible buttons aren’t working. Appreciate any help!

My code is below:

<!doctype html>
<html>
<head>
    <meta name="keywords" content ="XXX">
    <meta name="author" content="XXX">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script type="module" src="https://unpkg.com/[email protected]/dist/ionicons/ionicons.esm.js"></script>
    <script nomodule src="https://unpkg.com/[email protected]/dist/ionicons/ionicons.js"></script>
    <style>
    body {font-family:Arial, Helvetica, sans-serif;
    background-color:whitesmoke
    }
    p { color:black
    }
    .topnav {
        overflow:hidden;
        background-color:lavender;
        display:flex;
        position:sticky;
        align-items:center;
        justify-content:space-evenly;
        background-blend-mode:darken;
        background-size:cover;
        text-decoration:none;
        text-align:center;
        height:75px;
        border-radius:10px;
    }
    .topnav a{
        float:left;
        color:black;
        text-align:center;
        padding: 16px 16px;
        font-size:18px;
        font-weight:bold;
        margin-right: 25px;
        border-radius:10px;
        transition:color .3s ease-in-out;
    }
    .topnav a:hover {
        background-color:white;
        color:black;
        border-radius:10px;
    }
    .topnav a.active{
        background-color:slateblue;
        color:white;
        border-color:black;
        border-width:5px;
    }
    .topnav a.email-me {
        align-items:right;
        background-color: rgb(77, 65, 151);
        color:white;

    }
    .topnav a.email-me:hover {
        background-color:rgb(63, 53, 128);
        color:white;
        transition:color .3s ease-in-out;
    }
    .collapsible{
        color:black;
        background-color:lightgrey;
        cursor:pointer;
        padding:10px;
        width:100%;
        height:100px;
        border:none;
        text-align:left;
        outline:none;
        font-size:18px;
    }
    .active, .collapsible:hover{
        background-color:darkgrey;
    }
    .content{
        padding:0 18px;
        display:none;
        overflow:hidden;
        background-color:whitesmoke;
    }
    .collapsible2{
        color:white;
        background-color:slateblue;
        cursor:pointer;
        padding:10px;
        width:100%;
        height:50px;
        border:none;
        text-align:left;
        outline:none;
        font-size:14px;
    }
    .active, .collapsible2:hover{
        background-color:rgb(63, 53, 128);
    }
    .content2{
        padding:0 18px;
        display:none;
        overflow:hidden;
        background-color:whitesmoke;
    }

    </style>
    </head>

<title> XXX Life & Experiences
    </title>

<body>
    <nav class="topnav">
        <a href="main website code.html">About Me</a>
        <a class="active" href="Resume.html">Resume</a>
        <a href="Current Projects.html">Current Projects</a>
        <a href="mailto:[email protected]" class="email-me">Email Me <ion-icon name="mail-outline"></ion-icon></a>
    </nav>
    <div style="padding-left:16px">
        <p> Check out my LinkedIn <ion-icon name="logo-linkedin"></ion-icon> for more details: <a href="https://www.linkedin.com/in/XXX/">LinkedIn Profile.</a> <br><br>
            
            <button class="collapsible"><img src="icons/me icon.png"><h3>ABOUT ME</h3></button>
            <div class ="content">
                <ul>
                    <li>Senior consultant with a strong background in project management and leading technical teams. Effective at managing teams and clients, working with Agile principles, and supporting business requirements</li>
                </ul>
            </div>

            <button class="collapsible"><img src="icons/skills icon.png"><h3>CERTIFICATIONS & SKILLSETS</h3></button>
            <div class ="content">
                <ul>
                    <li>Project Management Professional (PMP) Certified: 2023 </li>
                    <li>Salesforce Business Analyst Certified: 2023</li>
                    <li>Skills: PowerPoint, Salesforce, Excel, Word, Visio, Mural, Qualtrics, and Jira</li>
                </ul>
            </div>
            <img src="icons/icons8-salesforce-48 (1).png">
            <img src="icons/jira icon.png">
            <img src="icons/powerpoint icon.png">
            <img src="icons/visio icon.png">


            <button class="collapsible"><img src="icons/work icon.png"><h3>EXPERIENCE</p></h3></button>
            <div class ="content">
            <button class ="collapsible2"><h4>EXAMPLE1 </h4></button>
            <br><br>
            <div class="content2">
            <h4>Development of New Salesforce Feature: AAA</h4>
            <ul>
                <li>XYZ</li>
            </ul>
            <h4>Development of New Salesforce Feature: BBB</h4>
            <ul>
                <li>XYZ/li>
            </ul>
            </div>
        
            <button class="collapsible2"><h4>EXAMPLE 2</h4></button>
            <br><br>
            <div class="content2">
            <ul>
                <li>XYZ</li>
            </ul>
            </div>
            </div>
             <button class="collapsible"><img src="icons/education icon.png"><h3>EDUCATION </h3></button>
             <div class ="content"> <h4>XXX – B.B.A | Economics – Honors </h4>
            <ul>
                <li>GPA: 3.91</li>
            </ul>
            </div>
            <br><br>
            <small>Icons by <a href="https://icons8.com">Icons8. </a></small>
        </p>
    </div>

    <script>
        var coll = document.getElementsByClassName("collapsible");
        var i;

        for (i = 0; i < coll.length; i++) {
            coll[i].addEventListener("click", function() {
                this.classList.toggle("active");
                var content = this.nextElementSibling;
                if (content.style.display === "block") {
                    content.style.display = "none";
                } else {
                    content.style.display = "block";
                }
            });
        }

        var coll2 = document.getElementsByClassName("collapsible2");
        var j;

        for (j = 0; j < coll2.length; j++) {
            coll2[j].addEventListener("click", function() {
                this.classList.toggle("active");
                var content2 = this.nextElementsibling;
                if (content2.style.display === "block") {
                    content2.style.display = "none";
                } else {
                    content2.style.display = "block";
                }
            });
        }
    </script>
    </body>

</html>

I tried changing display:block but then it shows up every time, I changed the variables in the JavaScript to coll2 because originally it was the same code just with collapsible2 changed.

Create and delete events in a Google Calendar from a Firebase function

I am building a app with Firebase Functions as a backend. The app schedules events for a small sports club but those events must also be synced to a Google Calendar for public usage. I would like to keep the Google Calendar updated via a function, and thus far I have this code:

async function updateCalendarOnTimesChange(timeId: string, data: DocumentData | null) {
    const authClient = await getAuthClient();
    google.options({ auth: #SOMETHING# });

    // Remove event from calendar to start with
    await calendar.events.delete({
        calendarId: calendarId,
        eventId: timeId,
    });

    if (!data) {
        return;
    }

    const eventTime = data.dateAndTime as Timestamp;
    const dateStart = eventTime.toDate();
    dateStart.setHours(data.timeStartHour);
    dateStart.setMinutes(data.timeStartMinutes);
    const dateEnd = eventTime.toDate();
    dateEnd.setHours(data.timeEndHour);
    dateEnd.setMinutes(data.timeEndMinutes);

    const event = {
        summary: data.description,
        start: {
            dateTime: dateStart,
            //timeZone: 'America/Los_Angeles',
        },
        end: {
            dateTime: dateEnd,
            //timeZone: 'America/Los_Angeles',
        },
    };

    // Create new event
    const response = await calendar.events.insert({
        calendarId: calendarId,
        requestBody: event,
    });
}

I do not know what to give the auth parameter? As it is a function that runs automaticly and not tied to the actual user creating the event, but tied to the sports club Google Calendar, how do I authenticate with the Google Calendar?

Am I on the right track here?

Thank you
Søren