AdvancedMarkerElement: making drag behaviour more like legacy Marker

With the legacy Marker, when dragging a marker there is a nice little crosshair to give the impression of a precise positioning movement, and this crosshair disappears automatically at the end of the drag… see this example.

Relevant code:

async function initMap() {
  const { Map } = await google.maps.importLibrary("maps");
    const { Marker } = await google.maps.importLibrary("marker");

    const myLatLng = {
    lat: -34.397,
    lng: 150.644
  };

    const map = new Map(document.getElementById("map"), {
    center: myLatLng,
    zoom: 8
  });
  
  const marker = new Marker({
    map,
    position: myLatLng,
    draggable: true
  });

  google.maps.event.addListener(marker, 'dragend', function() {
    const position = marker.getPosition();
    alert('dragend at ' + position);
  });
}

initMap();

Compare this to the new AdvancedMarkerElement… no crosshair, and instead some bounding box that IMHO is unnecessary and looks plain ugly… see this example.

Not only that, but the bounding box remains after the end of the drag… at the very least how so we ensure that focus is removed from the marker at the end of the drag?

Relevant code:

async function initMap() {
  const { Map } = await google.maps.importLibrary("maps");
    const { AdvancedMarkerElement } = await google.maps.importLibrary("marker");

    const myLatLng = {
    lat: -34.397,
    lng: 150.644
  };

    const map = new Map(document.getElementById("map"), {
    center: myLatLng,
    zoom: 8,
    mapId: "DEMO_MAP_ID", // Map ID is required for advanced markers.
  });
  
  const marker = new AdvancedMarkerElement({
    map,
    position: myLatLng,
    gmpDraggable: true
  });

  marker.addListener('dragend', function(event) {
    const position = marker.position;
    alert(`dragend at (${position.lat}, ${position.lng})`);
  });
}

initMap();

React Testing Library Hook testing: userEvent.selectOptions not firing onChange event handler

userEvent.selectOptions actually selects the value i set but its not firing the event listener that updates a hook

this is the component

onChangeSelectHandler = (e: React.ChangeEvent<HTMLSelectElement>): void => {
  setSinger({
    ...singer,
    voiceType: VoiceType[Number(e.currentTarget.value)],
  });
},
VoiceTypeList = () => (
  <select
    ref={selectRef}
    onChange={onChangeSelectHandler}
    value={VoiceType[singer.voiceType as keyof typeof VoiceType]}
  >
    {Object.keys(VoiceType).map((element, id) => {
      if (isNaN(Number(element))) {
        return (
          <option
            key={id}
            value={VoiceType[element as keyof typeof VoiceType]}
          >
            {element}
          </option>
        );
      }
    })}
  </select>
);

Here the test

test("Add singer to the list when form is filled", async () => {
const { result } = renderHook(
    () => useSelector((state: RootState) => state.crud),
    {
      wrapper: ({ children }) => (
        <Provider store={store}>{children}</Provider>
      ),
    }
  ),
  singerNameInput = screen.getByPlaceholderText("Singer name"),
  singerBandInput = screen.getByPlaceholderText("Singer band"),
  singerVoiceTypeSelect = screen.getByRole("combobox") as HTMLOptionElement,
  addSingerBtn = screen.getByText("Add");

await userEvent.type(singerNameInput, "Hansel");
await userEvent.type(singerBandInput, "Hansel");
await userEvent.selectOptions(singerVoiceTypeSelect, "2");

fireEvent(
  addSingerBtn,
  new MouseEvent("click", {
    bubbles: true,
    cancelable: true,
  })
);
expect(singerVoiceTypeSelect.querySelectorAll("option")[2].selected).toBe(
  true
);
expect(result.current[0].name).toBe("Hansel");
expect(result.current[0].band).toBe("Hansel");
expect("Baritone").toBe(VoiceType[2]);
expect(result.current[0].voiceType).toBe(VoiceType[2]);});

The console show me this
enter image description here

As you can see the test doesnt fails when I assure that element with value of “2” is selected. Its actually select but the hook doesnt update when I submit.

i want to make a program which count all the words in the string

Here i am trying to create a program which counts all the words that are there in a string, but it’s giving me an incorrect answer. Please have a look at this:

let text = "Hello world  ";
const mystring = text.split(" "); // output = "Hello", "world", " ", " "

console.log(mystring);

var countwords = 0

mystring.forEach((element) => {
    if(element != " "){
        countwords = countwords + 1
    }
    
})

console.log(countwords);

I was trying to create a program in js which would count all the words that are there in the string, but it’s giving me incorrect answer. Shouldn’t the output be 2, but instead of that it’s showing 4.

Deploying my web application and cannot get the submit button to post back and query my database

I’m building a book recommendation engine. I have a homepage, quiz page, and a recommendation page. I have deployed this code to an AWS S3 bucket but cannot get the quiz submit button to actually work correctly. I have a postgres database and am looking to query the database to get a random book recommendation based on the genreid mapping from the values of the questions.

I am getting a “method not allowed” error when I click the submit button, despite trying to have the server.js code to handle the submit post method. I’m not sure where to go from here.

This is my quiz.js code:

`const { Client } = require('pg');

const dbConfig = {
    user: 'username',
    host: 'host',
    database: 'postgres',
    password: 'password',
    port: 5432, 
    ssl: {
        rejectUnauthorized: false 
    }
};

const cors = require('cors');
app.use(cors());

const client = new Client(dbConfig);


client.connect()
    .then(() => {
        console.log('Connected to the database');
        startQuiz();
    })
    .catch(error => {
        console.error('Error connecting to the database:', error);
    });

process.on('exit', () => {
    client.end();
});

const genreIdMapping = {
    7: 3,
    8: 3,
    9: 6,
    10: 6,
    11: 8,
    12: 8,
    13: 7,
    14: 4,
    15: 1,
    16: 9,
    17: 9,
    18: 10,
    19: 10,
    20: 2,
    21: 5
};

function startQuiz() {
    console.log('Quiz form loaded');
    const quizForm = document.getElementById('quiz-form');

    quizForm.addEventListener('submit', (event) => {
        event.preventDefault();
        console.log('Quiz form submitted');

        let totalScore = 0;
        const userScores = {};

        for (let i = 1; i <= 7; i++) {
            const selectedAnswerIndex = parseInt(document.querySelector(`input[name="answer${i}"]:checked`).value);
            totalScore += questions[i - 1].answers[selectedAnswerIndex].score;
            userScores[i - 1] = questions[i - 1].answers[selectedAnswerIndex].score;
        }

        const genreId = genreIdMapping[totalScore];
        if (genreId) {
            fetch('https://mhtwcqy8pd.execute-api.us-east-2.amazonaws.com/BookWizard', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({ genreId })
            })
            
            .then(response => response.json())
            .then(data => {
                let resultText = '';
                if (data.title) {
                    resultText = `
                        <h2>Based on your answers, we recommend the following book:</h2>
                        <p>${data.title} by ${data.author}</p>
                    `;
                } else {
                    resultText = "No book recommendation found for your score.";
                }
                const resultContainer = document.getElementById('result-container');
                resultContainer.innerHTML = resultText;
            })
            .catch(error => {
                console.error('Error fetching book recommendation:', error);
                const resultContainer = document.getElementById('result-container');
                resultContainer.innerHTML = "Error fetching book recommendation.";
            });
        } else {
            console.log("No genre ID mapping found for your score.");
            const resultContainer = document.getElementById('result-container');
            resultContainer.innerHTML = "No genre ID mapping found for your score.";
        }
    });
}

document.addEventListener('DOMContentLoaded', () => {
    console.log('Document loaded');
    startQuiz();
});`

Here is my server.js code:

`import { Client } from 'pg';
import express from 'express';
import { urlencoded, json } from 'body-parser';

const app = express();
const port = 3000;
const cors = require('cors');
app.use(cors());

const dbConfig = {
    user: 'postgres',
    host: 'host',
    database: 'database',
    password: 'password',
    port: 5432, 
    ssl: {
        rejectUnauthorized: false 
    }
};

const client = new Client(dbConfig);

client.connect()
    .then(() => {
        console.log('Connected to the database');
    })
    .catch(error => {
        console.error('Error connecting to the database:', error);
    });

app.use(urlencoded({ extended: false }));
app.use(json());
app.use(express.static('public'));

app.post('/recommendation', async (req, res) => {
    try {
        const { genreId } = req.body;

        const query = 'SELECT title, author, description, imgurl FROM books WHERE genreId = $1 ORDER BY RANDOM() LIMIT 1';
        const { rows } = await client.query(query, [genreId]);

        if (rows.length > 0) {
            const recommendation = {
                title: rows[0].title,
                author: rows[0].author
                description: rows[0].description
                imgurl: rows[0].imgurl

            };
            res.json(recommendation);
        } else {
            res.json({ message: 'No book recommendation found for this genre' });
        }
    } catch (error) {
        console.error('Error fetching book recommendation:', error);
        res.status(500).json({ message: 'Error fetching book recommendation' });
    }
});

app.listen(port, () => {
    console.log(`Server running at http://localhost:${port}`);
});`

I have tried the code above and attempted to get results when I clicked on the submit button. What actually resulted was a method not allowed error.

Toast function cannot find its div

Hello I have this error where the toast alert is not showing on the page when I log in but it is when I sign out, any idea why it does this? I tried multiple things like logging the toastLiveExample and the toastBody but it always returns null when I sign in showToast("text-bg-success", ${username}, you have successfully signed in! Check out your <a href="/profile/${username}">profile</a>!);

TypeError: Cannot read properties of null (reading ‘classList’)
at showToast (toast.js:6:20)
at HTMLDocument. (sign-in?id=…)

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  <title>GildNovel</title>
  <link rel="icon" type="icon" href="/images/icon.jpg" />

  <meta property="og:site_name" content="GildNovel" />
  <meta property="og:title" content="Novel and Manga Community" />
  <meta property="og:description"
    content="GildNovel is a platform where you can find a variety of books and novels up to your taste, specially made for manga-lovers and action lovers." />
  <meta property="og:image" content="/images/icon.jpg" />
  <meta property="og:image:type" content="image/png">
  <meta property="og:image:width" content="250">
  <meta property="og:image:height" content="250">

  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
  <link rel="stylesheet" href="https://site-assets.fontawesome.com/releases/v6.1.1/css/all.css" />

  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Bebas+Neue&display=swap" rel="stylesheet">

  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />

  <link rel="stylesheet" href="/gnCss" />
</head>
<style>
  /*Buttons*/
  .flex {
    display: flex;
    justify-content: center;
    flex-direction: column;
    align-items: center;
  }

  button {
    text-align: center;
    font-weight: bold;
    text-decoration: none;
    font-family: "Roboto", sans-serif;
    display: inline-block;
    border: none;
    border-radius: 16px;
    background-color: #2196f3;
    cursor: pointer;
    padding: 20px;
    font-size: 30px;
    color: white;
    margin: 0 auto;
    margin-bottom: 10px;
  }

  .discordButton {
    background-color: #7289da;
    color: #ffffff;
    border: none;
    border-radius: 15px;
    font-size: 25px;
    padding: 15px;
    cursor: pointer;
    transition: background-color 0.3s ease;
  }

  .discordButton:hover {
    background-color: #677bc4;
  }

  .googleButton {
    background-color: #fff;
    color: #000;
    border: none;
    border-radius: 15px;
    font-size: 25px;
    padding: 15px;
    cursor: pointer;
    transition: background-color 0.3s ease;
  }

  .googleButton:hover {
    background-color: #b7b7b7;
  }
</style>

<body>
  <div id="alert"></div>

  <div class="navbar">
    <a style="margin-left: 25px;" href="/home" class="navbar-text">Home</a>

    <form name="search" class="box" action="/explore" method="GET">
      <input type="text" name="search" style="width: 40vw;" placeholder="Explore..." />
      <i class="fas fa-search"></i>
    </form>

    <div class="nav-right">
      <a style="margin-right: 25px;" href="/premium" class="navbar-text">Premium</a>
      <a style="margin-right: 25px;" id="toggle" href="#" class="navbar-text"><i class="fa fa-sign-out"
          aria-hidden="true"></i></a>
      <a style="margin-right: 25px;" id="account" href="#" class="navbar-text"><i class="fas fa-user"></i></a>
    </div>
  </div>

  <script>
    if (typeof Storage !== "undefined") {
      if (localStorage.user) {
        let data = JSON.parse(localStorage.user);
        document.getElementById("account").href = `/profile/${data.username}`;
      } else {
        document.getElementById("toggle").innerHTML = '<i class="fa fa-sign-in" aria-hidden="true"></i>';
        document.getElementById("toggle").href = "/sign-in";
      }
    }

    document.getElementById("toggle").addEventListener("click", async (e) => {
      if (e.target.classList.contains('fa-sign-out')) {
        showToast("text-bg-success", "Signing you out.");
        localStorage.removeItem("user");
        await fetch('/logout', { method: 'POST', credentials: 'same-origin' })
        setTimeout(() => {
          window.location.reload();
        }, 3000);
      }
    });
  </script>

  <div class="header">
    <h1 class="bebas-neue-regular" style="font-size:15vw;">GILDNOVEL</h1>
    <p>Experience the full potential of our community by joining or signing in with Discord or Google!</p>
  </div>

  <div style="margin-top:50px;" class="flex">
    <button id="discordSignUp" class="discordButton">
      <i class="fa-brands fa-discord"></i> Sign in with Discord
    </button>
    <button id="googleSignIn" class="googleButton">
      <i class="fa-brands fa-google"></i> Sign in with Google
    </button>
  </div>

  <div class="header-no-image">
    <p>By signing in you agree to follow our <a href="/tos">Terms of Service</a></p>
  </div>

  <!--bootstrap code-->
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"></script>
  <!--alert code-->
  <script type="text/javascript" src="//code.jquery.com/jquery-1.11.0.min.js"></script>

  <script>
    $("#alert").load("/staticHtml/toast.html");
  </script>
  <!-- toast function -->
  <script src="/js/toast.js"></script>

  <script>
    const discordSignUpBtn = document.getElementById("discordSignUp");
    discordSignUpBtn.addEventListener("click", () => {
      const clientID = "1100495054063284354";
      const redirectURI = encodeURIComponent("https://novels-production.up.railway.app/auth/discord/callback");
      const scopes = encodeURIComponent("email identify");
      const url = `https://discord.com/oauth2/authorize?client_id=${clientID}&redirect_uri=${redirectURI}&response_type=code&scope=${scopes}`;
      window.location.href = url;
    });

    const googleSignUpBtn = document.getElementById("googleSignIn");
    googleSignUpBtn.addEventListener("click", () => {
      window.location.href = "https://novels-production.up.railway.app/auth/google";
    });
  </script>

  <script>
    document.addEventListener('DOMContentLoaded', async () => {
      try {
        const queryString = window.location.search;
        const urlParams = new URLSearchParams(queryString);
        const token = urlParams.get("token");

        if (token) {
          const id = urlParams.get("id");
          const username = urlParams.get("username");

          let params = {
            _id: id,
            username,
            token,
          };

          showToast("text-bg-success", `${username}, you have successfully signed in! Check out your <a href="/profile/${username}">profile</a>!`);
          localStorage.setItem("user", JSON.stringify(params));
        }
      } catch (err) {
        console.log(err)
        showToast("text-bg-danger", "Something went wrong");
      }
    });
  </script>
</body>

</html>
function showToast(toastType, message) {
  const toastLiveExample = document.getElementById("liveToast");
  const toastBody = document.getElementById("toastBody");
  const toastBootstrap = bootstrap.Toast.getOrCreateInstance(toastLiveExample);

  toastLiveExample.classList.add(toastType);
  toastBody.innerHTML = message;
  toastBootstrap.show();
}
<div class="toast-container position-fixed bottom-0 end-0 p-3">
  <div id="liveToast" class="toast align-items-center" role="alert" aria-live="assertive" aria-atomic="true">
    <div class="d-flex">
      <div class="toast-body" id="toastBody">Hello, world! This is a toast message.</div>
      <i class="fa fa-times me-2 m-auto" data-bs-dismiss="toast" aria-hidden="true"></i>
    </div>
  </div>
</div>

Typescript not reading mapbox declaration file

Any assistance would greatly be appreciated.

Do you guys know how to solve this error?

import Geocoding from ‘@mapbox/mapbox-sdk/services/geocoding’;

it directs to the declaration file: declare module “@mapbox/mapbox-sdk/services/geocoding” {
}

Error: Did you mean to import “@mapbox/mapbox-sdk/services/geocoding.js”?

I already installed types for mapbox: @types/mapbox__mapbox-sdk

I already installed types for mapbox: @types/mapbox__mapbox-sdk

I tried to change the declaration file in the node_modules for my development and add .js extension to my /geocoding path but it does not work in production because I can’t edit the node_modules there.

FFMPEG Command to convert images to svg

Users are trying to convert images to SVG image on my website, Below I’ve given a link to the site, more detail on error and code that handles the conversion of media files.

You can check out the live site Here.

Steps to reproduce the error.

  1. Upload the png file,
  2. Select SVG as output file
  3. Click convert.

It is throwing error.

Below is the code for that converts users input and gives input based on user preference.

// imports

import { createCanvas, loadImage } from "canvas";

import { Action } from "@/types";
import { FFmpeg } from "@ffmpeg/ffmpeg";
import { fetchFile } from "@ffmpeg/util";

function getFileExtension(file_name: string) {
  const regex = /(?:.([^.]+))?$/; // Matches the last dot and everything after it
  const match = regex.exec(file_name);
  if (match && match[1]) {
    return match[1];
  }
  return ""; // No file extension found
}

function removeFileExtension(file_name: string) {
  const lastDotIndex = file_name.lastIndexOf(".");
  if (lastDotIndex !== -1) {
    return file_name.slice(0, lastDotIndex);
  }
  return file_name; // No file extension found
}

export default async function convert(
  ffmpeg: FFmpeg,
  action: Action
): Promise<any> {
  const { file, to, file_name, file_type } = action;
  const input = getFileExtension(file_name);
  const output = removeFileExtension(file_name) + "." + to;
  ffmpeg.writeFile(input, await fetchFile(file));

  // FFMPEG COMMANDS
  let ffmpeg_cmd: any = [];

  if (to === "svg") {
    ffmpeg_cmd = [
      "-i",
      input,
      "-vf",
      "scale=trunc(iw/2)*2:trunc(ih/2)*2",
      "-c:v",
      "libvpx-vp9",
      "-crf",
      "30",
      "-b:v",
      "1M",
      "-c:a",
      "libopus",
      "-b:a",
      "128k",
      output,
    ];
  } else if (to === "3gp") {
    ffmpeg_cmd = [
      "-i",
      input,
      "-r",
      "20",
      "-s",
      "352x288",
      "-vb",
      "400k",
      "-acodec",
      "aac",
      "-strict",
      "experimental",
      "-ac",
      "1",
      "-ar",
      "8000",
      "-ab",
      "24k",
      output,
    ];
  } else {
    ffmpeg_cmd = ["-i", input, output];
  }

  // execute cmd
  await ffmpeg.exec(ffmpeg_cmd);

  const data = (await ffmpeg.readFile(output)) as any;
  const blob = new Blob([data], { type: file_type.split("/")[0] });
  const url = URL.createObjectURL(blob);
  return { url, output };
}

Help appreciated, Thank You

Error: Objects are not valid as a React child (found: [object Promise]). in MDX remote

I’m trying to use next.js to get all of the blogs on a mongodb backend, and converting all of the blog strings stored in blog.mdx into an array of objects wrapped in

  • wrappers. However, the code below gives me the error that:
    Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.
    I’m not really sure what’s the fix to this. I’ve followed this stackoverflow question for help but it hasn’t fixed my issue

    import Head from "next/head";
    import clientPromise from "../lib/mongodb";
    import type { InferGetServerSidePropsType, GetServerSideProps } from "next";
    import {useEffect, useState} from "react";
    import {MDXRemote} from "next-mdx-remote/rsc";
    import { serialize } from 'next-mdx-remote/serialize'
    import React from "react";
    
    type ConnectionStatus = {
        isConnected: boolean;
    };
    
    export const getServerSideProps: GetServerSideProps<
        ConnectionStatus
    > = async () => {
        try {
            await clientPromise;
            // `await clientPromise` will use the default database passed in the MONGODB_URI
            // However you can use another database (e.g. myDatabase) by replacing the `await clientPromise` with the following code:
            //
            // `const client = await clientPromise`
            // `const db = client.db("myDatabase")`
            //
            // Then you can execute queries against your database like so:
            // db.find({}) or any of the MongoDB Node Driver commands
    
            return {
                props: { isConnected: true },
            };
        } catch (e) {
            console.error(e);
            return {
                props: { isConnected: false },
            };
        }
    };
    
    const Home = ({ isConnected }: InferGetServerSidePropsType<typeof getServerSideProps>) => {
        const [blogs, setBlogs] = useState([]);
        useEffect(() => {
            async function fetchAllBlogs() {
                const response = await fetch("http://localhost:3000/api/getAllBlogs");
                const blogs = await response.json();
                const blogMDX = await Promise.all(blogs.map(async (blog) => (
                    <li key={blog._id}>
                        <MDXRemote {...(await serialize(blog.mdx))} />
                    </li>
                )))
                console.log("blogs ", blogs);
                console.log("blogsMDX ", blogMDX);
                setBlogs(blogMDX);
            }
            fetchAllBlogs();
        }, []);
    
    
        return (
            <div className="container">
                <Head>
                    <title>Create Next App</title>
                    <link rel="icon" href="/favicon.ico"/>
                </Head>
    
                <main>
                    <div>
                        {isConnected ? (
                            <h2 className="subtitle">You are connected to MongoDB</h2>
                        ) : (
                            <h2 className="subtitle">
                                You are NOT connected to MongoDB. Check the <code>README.md</code>{" "}
                                for instructions.
                            </h2>
                        )}
                    </div>
                    <div>
                        {
                            blogs == null ? (
                                <div></div>
                            ) :(
                                blogs.length > 0 ? (
                                    <ul>
                                        {blogs}
                                    </ul>
                                ) : (
                                    <p>Loading...</p>
                                )
                            )
                        }
                    </div>
                    <div>
    
                    </div>
                </main>
    
    
            </div>
        );
    }
    
    export default Home;
    

    I’ve tried converting my

    
    <ul>
        {blogs}
    </ul>
    

    to

    blogs.map( (blog:any, index) => (
                                        <React.Fragment key={index}>
                                            {blog}
                                        </React.Fragment>
                                    ))
    ```,
    but while this gets rid of the error, the MDXRemote no longer shows up.
    
    The console.logs print out this:
    
    

    blogs
    Array [ {…} ]

    0: Object { _id: “66358b465fb668714ea217b3”, mdx: “—ntitle: Example Postnpublished: 2021-02-13ndescription: This is some descriptionn—nnnnHere’s a neat demon:” }

    length: 1

    : Array []
    index.tsx:50:20
    blogsMDX
    Array [ {…} ]

    0: Object { “$$typeof”: Symbol(“react.element”), type: “li”, key: “66358b465fb668714ea217b3”, … }

    length: 1

    : Array []

  • Get “prompt()” input from a web worker and return it from function?

    I’m working with the pyodide library and i’ve ran into an issue, I need to add a handler for stdin, however I’m running pyodide in a web worker and I don’t have access to the window or any sort of prompt.

    pyodide.setStdin({ stdin: () => { 
        // code here
    }})
    

    I have tried using the postMessage() function to ask the page for input and send it back, but since I am returning this from a function I am unable to receive the input before I have to return. I have also tried using SharedArrayBuffer and Atomics to freeze the web worker until the page responds, but I was unable to figure out a solution with those, however I think it’s a good starting point. Most solutions I’ve seen so far have just been to restructure code, but since pyodide is an external library I am forced to return from the function I set in pyodide.setStdin

    How do I create a ticket with multiple attachment using freshservice api?

    exports.app = onRequest({cors: true}, (req, res) => {
      const form = formidable({ multiples: true, maxFileSize: 15 * 1024 * 1024 });
      form.parse(req, (err, fields, files) => {
        if (err) {
          logger.error(err);
          res.status(500).send({ error: 'Failed to parse form' });
        } else {      
          const dataSourceString = fields['dataSource[]'];
          var dataSourceList = JSON.parse(dataSourceString);
          
          const fileList = files['attachment[]'];
          
          fileList.forEach((file, index) => {
            // Modify filename as needed
            const parts = file.name.split('.');
            const name = parts[0]; // Filename without extension
            const extension = parts.slice(1).join('.'); // File extension
    
            var fileName = dataSourceList[index].docType;
            fileName = fileName.replace(///g, " ");
            file.name = `${fileName}.${extension}`;
         });
    
          const ticketData = {
                subject: 'Test',
                description: fields.description,
                priority: 1,
                status: 2,
                email: fields.email,
            };
          
            function formatDate(date) {
              return new Date(date).toISOString();
          }
    
          const formData = new FormData();
    
          formData.append('subject', ticketData.subject);
          formData.append('description', ticketData.description);
          formData.append('priority', ticketData.priority);
          formData.append('status', ticketData.status);
          formData.append('email', ticketData.email);
    
    
          fileList.forEach((file) => {
            const stream = fs.createReadStream(file.path);
            const blob = new Blob([stream], { type: file.type });
        
            formData.append('attachments[]', blob, {
                filename: file.name,
                contentType: file.type,
            });
        });
    
          const configData = {
            method: 'post',
            url: config.fsURL + '/api/v2/tickets',
            headers: {
              'Authorization': 'Basic ' + Buffer.from(config.fsAPIKey + ':x').toString('base64'),
              'Content-Type': 'multipart/form-data'
            },
            data : formData
          };
    
          axios(configData)
            .then(function (response) {
                console.log(response.data);
                res.status(200).json(response.data);
            })
            .catch(function (error) {
                console.log('Error:', error.toJSON());
            });
        }
      });
    });
    

    I have code as above and it seems to work fine for all fields. However there seems to be some problem when I try to upload multiple attachments. It doesn’t seem to be inserting files correctly as I am getting attachments as [[Object], [Object]] when return after create ticket.

    Details can be shown as below. Anyone have any idea how this can be done?

    enter image description here

    Javascript emulate CSS snap scroll with pointer-events

    I have the following code which can swipe child element left and right. This works well.

    Is there a way I could implement snap effect with this somehow with pointermove? So it behaves like CSS snap scroll (you drag slightly and you can see next / previous item entering, before swipe actually happens).

    I dont want to use CSS snap scroll because I cannot detect scrollend event (on Safari for start) so I cannot detect on which child I am currenty (I need this so I can show / hide previous / next buttons, numbering etc)

    var wrap = document.querySelector('.wrap'),
      touchstartX,
      touchendX
    
    
    wrap.addEventListener('pointerdown', startHorizSwipeDirection);
    document.addEventListener('pointerup', endHorizSwipeDirection);
    
    function startHorizSwipeDirection(e) {
      touchstartX = e.clientX;
    }
    
    function endHorizSwipeDirection(e) {
      touchendX = e.clientX;
      checkHorizSwipeDirection()
    }
    
    function checkHorizSwipeDirection() {
    
      if (touchendX < touchstartX - 100) {
        //left
        nextHorizMedia();
      }
      if (touchendX > touchstartX + 100) {
        //right
        previousHorizMedia();
      }
    }
    
    function nextHorizMedia() {
    
      var active_id = parseInt(wrap.getAttribute('data-active-id'), 10),
        len = wrap.querySelectorAll('.child').length
    
      if (active_id >= len - 1) {
        console.log('end')
        return false;
      }
    
      var width = wrap.querySelector('.child').offsetWidth
    
      var transform = wrap.style.transform.replace(/[^-?d.]/g, '')
      var value
      if (transform) value = parseInt(transform, 10)
      else value = 0;
    
      value -= width;
      active_id++;
    
      wrap.setAttribute('data-active-id', active_id)
    
      wrap.style.transform = "translateX(" + value + "px)";
    
    
    
    }
    
    function previousHorizMedia() {
    
      var active_id = parseInt(wrap.getAttribute('data-active-id'), 10),
        len = wrap.querySelectorAll('.child').length
     
      if (active_id <= 0) {
        return false;
      }
    
      var width = wrap.querySelector('.child').offsetWidth
    
      var transform = wrap.style.transform.replace(/[^-?d.]/g, '')
      var value
      if (transform) value = parseInt(transform, 10)
      else value = 0;
    
      value += width;
      active_id--;
    
      wrap.setAttribute('data-active-id', active_id)
    
      wrap.style.transform = "translateX(" + value + "px)";
    
    
    }
    .parent {
      width: 300px;
      height: 100px;
      overflow: hidden;
    }
    
    .wrap {
      display: flex;
      flex-direction: row;
      flex-wrap: nowrap;
      transition: transform 0.3s;
    }
    
    .child {
      width: 300px;
      height: 100px;
      font-size: 30px;
      color: #fff;
      background: #ccc;
      flex-shrink: 0;
      text-align: center;
      user-select: none;
    }
    
    .child[data-id="0"] {
      background: red;
    }
    
    .child[data-id="1"] {
      background: blue;
    }
    
    .child[data-id="2"] {
      background: green;
    }
    
    .child[data-id="3"] {
      background: #ccc;
    }
    <div class="parent">
      <div class="wrap" data-active-id="0">
        <div class="child" data-id="0">0</div>
        <div class="child" data-id="1">1</div>
        <div class="child" data-id="2">2</div>
        <div class="child" data-id="3">3</div>
      </div>
    </div>

    How to edit and update on React JS?

    So i have UserList.jsx component which displays the all user data in a table. enter image description here When i click on edit button it goes to http://localhost:3000/user/id. I have created a form in there to update the user details. The problem is the form is not displaying the specific user data from id. How do i do that? And how to update as well? My UserList.jsx goes like this

    import "./userList.css";
    import { DataGrid } from '@mui/x-data-grid';
    import {DeleteOutline, Block} from '@mui/icons-material';
    // import { userRows, trainerRows } from "../../../dummyData";
    import { Link } from 'react-router-dom';
    import { useState, useEffect } from "react";
    
    
    export default function UserList() {
        const [data, setData] = useState([]);
        const [selectedRole, setSelectedRole] = useState('');
        const [filteredData, setFilteredData] = useState([]);
        // const [sessionID, setSessionID] = useState('');
    
        useEffect(() => {
          // Login as admin to get session ID
          fetch('http://localhost:3001/login', {
              method: 'POST',
              headers: {
                  'Content-Type': 'application/json',
              },
              body: JSON.stringify({
                  email: '[email protected]',
                  password: 'password123',
              }),
          })
          .then(response => response.json())
          .then(data => {
              // Store the session ID in localStorage
              localStorage.setItem('sessionID', data.session);
              // Filter the data based on user_type
              
              
              // Fetch initial user data
              // const url = selectedRole === 'All_User'
              //     ? 'http://localhost:3001/register_detail/recieve'
              //     : 'http://localhost:3001/register_detail/recieve';
              // Function to get the stored session ID
              const sessionId = localStorage.getItem('sessionID');
              
              console.log(sessionId);
              
              fetch('http://localhost:3001/profile/allusers', {
                  method: 'GET',
                  headers: {
                    'session': `${sessionId}`,
                  },
              })
              .then(response => response.json())
              .then(data => {
                
                  // Ensure data is an array of objects
                  if (Array.isArray(data)) {
                      setData(data);
                      setFilteredData(data);
                  } else {
                      console.error('Received data is not an array:', data);
                  }
              })
              .catch(error => console.error('Error fetching users:', error));
                
          })
          .catch(error => console.error('Error logging in:', error));
      }, []);
      
    
     
    
        const handleDelete = (id) => {
            setData(data.filter(item=>item.id!==id))
        }
        const handleRoleChange = (event) => {
          console.log(event.target.value);
          setSelectedRole(event.target.value);
          filterData(event.target.value);
        };
    
        const filterData = (role) => {
          let filtered = [];
          if (role === 'All_User') {
              filtered = data;
              
          } else {
            // data.filter(item => item.user_type === 'trainer'
              filtered = data.filter(item => item.user_type.toLowerCase() === role.toLowerCase());
              console.log(filtered); //gives data according to filterd event
          }
          setFilteredData(filtered);
      };
      
        
        
        const columns = [
          
            { field: 'user_id', headerName: 'User_ID', width: 70 },
            { field: 'first_name', headerName: 'First Name', width: 150,
                // renderCell: (params) => {
                //     return (
                //         <div className="userListUser">
                //             <img className="userListImage" src={params.row.profile_image} alt="Profile" srcset="" />
                //             {params.row.username}
                //         </div>
                //     )
                // }
            },
            { field: 'last_name', headerName: 'Last Name', width: 150 },
            // {
            //   field: 'email',
            //   headerName: 'Email',
            //   width: 200,
            // },
            // {
            //   field: 'user_type',
            //   headerName: 'User Type',
            //   width: 150,
    
            // },
            { field: 'contact', headerName: 'Contact', width: 150 },
            { field: 'address', headerName: 'Address', width: 150 },
            {
                field:'action',
                headerName:'Action',
                width:150,
                renderCell: (params) => {
                    return (
                        <div className="userListAction">
                            <Link to = {"/user/" + params.row.user_id}>
                              
                                <button className="userListEdit">Edit</button>
                            </Link>
                            
                            <DeleteOutline className="userListDelete" onClick={() => handleDelete(params.row.id)}/>
                            <Block className="userListBlock"/>
                        </div>
                        
                    )
                }
            },
          ];
         
        return (
       
        <div className="userList">
           <div className="userDropdown">
            <select className= "userDropdownicon" value={selectedRole} onChange={handleRoleChange}>
              <option value="All_User">All User</option>
              <option value="Trainer">Trainer</option>
              <option value="Customer">Customer</option>
            </select>
          </div>
            <DataGrid
            rows={filteredData} // Use filteredData instead of data
            columns={columns}
            getRowId={(row) => row.user_id}
            initialState={{
              pagination: {
                paginationModel: { page: 0, pageSize: 8 },
              },
            }}
            pageSizeOptions={[5, 10]}
            checkboxSelection
            disableRowSelectionOnClick
          />
        </div>
      )
    }
    
    

    and my User.jsx goes like this

    import "./user.css";
    // import axios from 'axios';
    import { Link, useParams } from 'react-router-dom';
    import { useEffect, useState } from 'react';
    import {CalendarToday, LocationSearching, MailLockOutlined, PermIdentity, PhoneAndroid, Publish} from '@mui/icons-material';
    export default function User() {
        const {userId} = useParams();
        console.log(userId);
      useEffect(() => {
        fetch('http://localhost:3001/profile/allusers/' +userId)
        .then(res => res.json()) // Convert the response to JSON
        .then(data=> console.log(data)) //Log the data
        .catch(err=>console.log(err));
      }, [userId]);  
      return (
        <div className="user">
            <div className="userTitleContainer">
                <h1 className="userTitle">Edit User</h1>
                <Link to="/newUser">
                    <button className="userAddButton">Create</button>
                </Link>
                
            </div>
            <div className="userContainer">
                <div className="userShow">
                    <div className="userShowTop">
                        <img src={process.env.PUBLIC_URL + "/images/admin.jpeg"} alt="" className="userShowImg" />
                        <div className="userShowTopTitle">
                            <span className="userShowUsername">Robert Kiyosaki</span>
                            <span className="userShowUserTitle">Investor</span>
                        </div>
                    </div>
                    <div className="userShowBottom">
                        <span className="userShowTitle">Account Details</span>
                        <div className="userShowInfo">
                            <PermIdentity className="userShowIcon"/>
                            <span className="userShowInfoTitle">robert99</span>
                        </div>
                        <div className="userShowInfo">
                            <CalendarToday className="userShowIcon"/>
                            <span className="userShowInfoTitle">02.01.1998</span>
                        </div>
                        <span className="userShowTitle">Contact Details</span>
                        <div className="userShowInfo">
                            <PhoneAndroid className="userShowIcon"/>
                            <span className="userShowInfoTitle">0406687956</span>
                        </div>
                        <div className="userShowInfo">
                            <MailLockOutlined className="userShowIcon"/>
                            <span className="userShowInfoTitle">[email protected]</span>
                        </div>
                        <div className="userShowInfo">
                            <LocationSearching className="userShowIcon"/>
                            <span className="userShowInfoTitle">Keswick, Adelaide</span>
                        </div>
                        
                    </div>
                </div>
                <div className="userUpdate">
                    <span className="userUpdateTitle">Edit</span>
                    <form action="" className="userUpdateForm">
                        <div className="userUpdateLeft">
                            <div className="userUpdateItem">
                                <label>First Name</label>
                                <input type="text" placeholder="robert99" className="userUpdateInput" />
                            </div>
                            <div className="userUpdateItem">
                                <label>Last Name</label>
                                <input type="text" placeholder="Robert Kiyosaki" className="userUpdateInput" />
                            </div>
                            <div className="userUpdateItem">
                                <label>Email</label>
                                <input type="text" placeholder="[email protected]" className="userUpdateInput" />
                            </div>
                            <div className="userUpdateItem">
                                <label>Phone</label>
                                <input type="text" placeholder="0406687956" className="userUpdateInput" />
                            </div>
                            <div className="userUpdateItem">
                                <label>Address</label>
                                <input type="text" placeholder="Keswick, Adelaide" className="userUpdateInput" />
                            </div>
                        </div>
                        <div className="userUpdateRight">
                            <div className="userUpdateUpload">
                                <img src={process.env.PUBLIC_URL + "/images/admin.jpeg"} alt="userimg" className="userUpdateImg" />
                                {/* htmlFor Associates this label with an input element using the 'htmlFor' attribute */}
                                <label htmlFor="file"><Publish className="userUpdateIcon"/></label>
                                <input type="file" name="" id="file" style={{display:"none"}} />
                            </div>
                            <button className="userUpdateButton">Update</button>
                        </div>
                    </form>
                </div>
            </div>
        </div>
      )
    }
    
    

    The logic i was trying to use is to append the userId at the endpoint of an API /profile/allusers. But it didn’t gave me any data

    Navbar collapse using javascript

    I have created a navbar with HTML and selected all of the headers, saving them in a navEl object. After that, I created a function called showNav. This function takes one of the navEl properties as its parameter and shows the content of that navEl element to the user. It also hides it when the user removes their mouse from it.

    The problem I am facing is with the last event listener of the function. When I added a mouseleave to the item, it works perfectly when I hover over it the first time. However, the moment I change my navEl to another one, when one is already showing, it stays for 100ms and then disappears again.

    I have tried modifying the code slightly and put a clearTimeout function on the item when I am changing the navEl. But the problem, I think, was that my navEl properties and the content are not nested within each other or separated.

    Is there any way I could fix this?

    HTML code

    <header class="navbar navbar-expand-lg d-lg-block d-none ">
                <div class="container-fluid">
                    <ul class="navbar-nav me-auto mb-2 mb-lg-0 d-flex flex-wrap">
                        <li class="nav-item nav-item-1" id="photo-books">
                            <a class="nav-link active" href="#">Photo Books</a>
                        </li>
                        <li class="nav-item nav-item-1" id="Cards-Stationery">
                            <a class="nav-link active" href="#">Cards & Stationery</a>
                        </li>
                        <li class="nav-item nav-item-1" id="Gifts">
                            <a class="nav-link active" href="#">Gifts</a>
                        </li>
                        <li class="nav-item nav-item-1" id="Wall-Art">
                            <a class="nav-link active" href="#">Wall Art</a>
                        </li>
                        <li class="nav-item nav-item-1" id="Prints">
                            <a class="nav-link active" href="#">Prints</a>
                        </li>
                        <li class="nav-item nav-item-1" id="Home-Decor">
                            <a class="nav-link active" href="#">Home Decor</a>
                        </li>
                        <li class="nav-item nav-item-1" id="Graduation">
                            <a class="nav-link active" href="#">Graduation</a>
                        </li>
                        <li class="nav-item nav-item-1" id="Wedding">
                            <a class="nav-link active d-xl-block d-none" href="#">Wedding</a>
                        </li>
                        <li class="nav-item nav-item-1" id="Calendars">
                            <a class="nav-link active d-xxl-block d-none" href="#">Calendars</a>
                        </li>
                        <li class="nav-item nav-item-1" id="Deals">
                            <a class="nav-link active" href="#" style="color: #a81719;">Deals</a>
                        </li>
                        <li class="nav-item nav-item-1">
                            <a class="nav-link active d-xxl-block d-none" id="nav-tinyprints" href="#">Tinyprints</a>
                        </li>
                        <li class="nav-item nav-item-1 dropdown d-xxl-none d-xl-block">
                            <a class="nav-link " href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
                                More +
                            </a>
                            <ul class="dropdown-menu" aria-labelledby="navbarDropdown">
                                <li>
                                    <a class="dropdown-item d-xl-none d-block" href="#" id="Wedding2">Wedding</a>
                                </li>
                                <li>
                                    <a class="dropdown-item" href="#" id="Calendars2">Calendars</a>
                                </li>
                                <li>
                                    <a class="dropdown-item" id="nav-tinyprints" href="#">Tinyprints</a>
                                </li>
                            </ul>
                        </li>
                    </ul>
                    <div class="d-xl-none d-block"><i class="fas fa-search"></i></div>
                    <div class="search-container d-flex align-items-center d-xl-block d-none">
                        <input class="search-input p-1" type="search" placeholder="Search" aria-label="Search">
                        <button class="search-button" type="submit" title="search">
                            <i class="fas fa-search"></i>
                        </button>
                    </div>              
                </div>
            </header>   
            <!-- Start of the Nav Content -->
            <div class="nav-content w-100 row">
                <div class="col-12 nav-content-header">Photo Books</div>
                <div class="col-md-15">
                    <ul class="navbar-nav me-auto d-flex flex-wrap column-1">
                        <!-- Column 1 will be added using javascript -->
                    </ul>
                </div>
                <div class="col-md-15">
                    <ul class="navbar-nav me-auto d-flex flex-wrap column-2">
                        <!-- Column 2 will be added using javascript -->
                    </ul>
                </div>
                <div class="col-md-15">
                    <ul class="navbar-nav me-auto d-flex flex-wrap column-3">
                        <!-- Column 3 will be added using javascript -->
                    </ul>
                </div>
                <div class="col-md-15">
                    <ul class="navbar-nav me-auto d-flex flex-wrap column-4">
                        <!-- Column 4 will be added using javascript -->
                    </ul>
                </div>
                <div class="col-md-15">
                    <ul class="navbar-nav me-auto d-flex flex-wrap column-5">
                        <!-- Column 5 will be added using javascript -->
                    </ul>
                </div>
                <div class="d-flex align-items-center justify-content-center gap-5" style="background-color: #fafafb;">
                    <a class="nav-link" id="nav-tinyprints" href="#">Tinyprints</a>
                    <a href="#"><img src="./Images/SpoonFlower-logo.png" alt="This is SpoonFlower-logo" width="100px" height="40px"></a>
                </div>
            </div>
            <!-- End of the Nav Content -->
    

    JavaScript code

    let navEl = {
        'Photo Books' : document.querySelector('#photo-books'),
        'Cards & Stationery' : document.querySelector('#Cards-Stationery'),
        'Gifts' : document.querySelector('#Gifts'),
        'Wall Art' : document.querySelector('#Wall-Art'),
        'Prints' : document.querySelector('#Prints'),
        'Home Decor' : document.querySelector('#Home-Decor'),
        'Graduation' : document.querySelector('#Graduation'),
        'Wedding' : document.querySelector('#Wedding'),
        'Wedding2' : document.querySelector('#Wedding2'),
        'Calendars' : document.querySelector('#Calendars'),
        'Calendars2' : document.querySelector('#Calendars2'),
        'Deals' : document.querySelector('#Deals'),
    }
    
    function showNav(item) {
        // Get the corresponding nav-content for each navigation item
        let navContent = document.querySelector(".nav-content");
        let timeoutId;
    
        item.addEventListener('mouseover', function() {
            // Clear any existing timeout
            clearTimeout(timeoutId);
            // Show the nav-content when mouseover the navigation item
            navContent.style.display = "block";
        });
    
        navContent.addEventListener('mouseover', function() {
            clearTimeout(timeoutId); // Clear the timeout if the mouse moves over the items
            const mediumScreenSize = 992;
            if (window.innerWidth <= mediumScreenSize) {
                navContent.style.display = "none";
            } else {
                navContent.style.display = "block"; // Keep the items visible
            }
        });
    
        navContent.addEventListener('mouseout', function() {
            // Start a timeout
            timeoutId = setTimeout(function() {
                // Hide the nav-content when mouseout of the nav-content
                navContent.style.display = "none";
            }, 100); // Add a small delay before hiding the nav-content
        });
    
    item.addEventListener('mouseleave', function(e) {
            // Start a timeout
            timeoutId = setTimeout(function() {
                // Get the mouse position
                let x = e.clientX, y = e.clientY;
                // Get the bounding rectangle of the current nav-content
                let rect = navContent.getBoundingClientRect();
                // Check if the mouse is outside the current nav-content
                if (x < rect.left || x > rect.right || y < rect.top || y > rect.bottom) {
                    // If the mouse is outside the current nav-content, hide it
                    console.log('');
                }
            }, 100); // Same delay as the mouseover event
        });
    
    }
    
    Object.keys(navEl).forEach(function(key) {
        showNav(navEl[key]);
    });