classList.add method doesn’t work and component is rerendered when clicking file input in Svelte

I want to make the image upload box open and close. In my code, the opening function works, but for some reason, the closing function doesn’t work. Additionally, when I use console.log in the functions responsible for opening and closing, the console.log in the closing function runs twice. I also tried using another approach variable = !variable, but this approach has problem when the file input button is clicked, it causes the page to rerender, which resets the state variable to false, causing the box to close again. Does anyone know how to fix this?

<script>
    let article = {}
    
    let base64Image
    
    let articleViewer
    
    let imageUploadBox
    
    function showImageUpload(){
        if (imageUploadBox.classList.contains("hidden")){
            imageUploadBox.classList.remove("hidden")
            console.log(imageUploadBox.classList)
        }
    }
    
    function closeImageUpload(){
        if (!imageUploadBox.classList.contains("hidden")){
            imageUploadBox.classList.add("hidden")
            console.log(imageUploadBox.classList)
        }
    }
    
    function processImage(e){
        const image = e.target.files[0]
        const imageReader = new FileReader()
        imageReader.onload = (e) => {
            base64Image = e.target.result
        }
        imageReader.readAsDataURL(image)
    }
    
    function insertImage(image){
        let selection = window.getSelection()
        let range = selection.getRangeAt(0)
        
        if (articleViewer.contains(range.commonAncestorContainer)){
            let imgTag = document.createElement("img")
            imgTag.src = image
            imgTag.className = "w-[50%] m-auto rounded-lg"
            
            range.deleteContents()
            range.insertNode(imgTag)
            
            range.setStartAfter(imgTag)
            range.collapse(true)
            selection.removeAllRanges()
            selection.addRange(range)
            
            base64Image = ""
        }
        else {
            alert("Images can only be inserted in the article content")
        }
    }
    
    function updateArticle(){}
</script>

<div class="flex flex-col gap-4 p-8 h-screen">
    <input type="text" class="bg-emerald-500 text-white p-4 rounded-lg focus:border-none focus:outline-none" bind:value={article["title"]} />
    <div class="relative">
        <button on:click={() => showImageUpload()} >
            <svg viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg" height="40px" width="40px"><path fill="white" d="M13.3 34.15h21.45q.5 0 .7-.4.2-.4-.1-.8l-5.85-7.8q-.25-.3-.6-.3t-.6.3l-6 7.75-4.05-5.55q-.25-.3-.6-.3t-.6.3l-4.3 5.6q-.25.4-.075.8t.625.4ZM9 42q-1.2 0-2.1-.9Q6 40.2 6 39V9q0-1.2.9-2.1Q7.8 6 9 6h30q1.2 0 2.1.9.9.9.9 2.1v30q0 1.2-.9 2.1-.9.9-2.1.9Zm0-3h30V9H9v30ZM9 9v30V9Z"/></svg>
            <!--{#if imageUploadBox}-->
                <div class="hidden bg-emerald-500 p-8 rounded-lg flex justify-center items-center flex-col gap-8 absolute top-[110%] relative" bind:this={imageUploadBox}>
                    <input type="file" accept="images/*" on:change={processImage} class="rounded-lg text-emerald-100 text-xs font-semibold bg-emerald-950 p-4" />
                    {#if base64Image}
                        <img src={base64Image} class="rounded-lg w-[50%]" />
                        <button on:click={insertImage(base64Image)} class="bg-emerald-950 text-emerald-100 p-4 text-xs font-semibold rounded-lg" >Add</button>
                    {/if}
                    <button on:click={closeImageUpload} class="p-4 rounded-full absolute bottom-[100%] right-[100%] bg-emerald-950" >
                        <svg viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg" height="1.5em" width="1.5em"><path fill="white" d="M24 26.1 13.5 36.6q-.45.45-1.05.45-.6 0-1.05-.45-.45-.45-.45-1.05 0-.6.45-1.05L21.9 24 11.4 13.5q-.45-.45-.45-1.05 0-.6.45-1.05.45-.45 1.05-.45.6 0 1.05.45L24 21.9l10.5-10.5q.45-.45 1.05-.45.6 0 1.05.45.45.45.45 1.05 0 .6-.45 1.05L26.1 24l10.5 10.5q.45.45.45 1.05 0 .6-.45 1.05-.45.45-1.05.45-.6 0-1.05-.45Z"/></svg>
                    </button>
                </div>
            <!--{/if}-->
        </button>
    </div>
    <div id="articleViewer" class="bg-emerald-500 text-white p-4 rounded-lg focus:border-none focus:outline-none" bind:innerHTML={article["content"]} contenteditable="true" bind:this={articleViewer}>hello</div>
</div>

<style>
    input:active {
        border: 0;
        outline: 0;
    }
    
    .hidden {
        display: none;
    }
</style>

The other approach that caused rerender, the rerender happens when I click the <input type="file" /> :

<script>
    let article = {}
    
    let base64Image
    
    let articleViewer
    
    let imageUploadBox = false
    
    function showImageUpload(){
        imageUploadBox = !imageUploadBox
    }
    
    function closeImageUpload(){
        imageUploadBox = !imageUploadBox
    }
    
    function processImage(e){
        const image = e.target.files[0]
        const imageReader = new FileReader()
        imageReader.onload = (e) => {
            base64Image = e.target.result
        }
        imageReader.readAsDataURL(image)
    }
    
    function insertImage(image){
        let selection = window.getSelection()
        let range = selection.getRangeAt(0)
        
        if (articleViewer.contains(range.commonAncestorContainer)){
            let imgTag = document.createElement("img")
            imgTag.src = image
            imgTag.className = "w-[50%] m-auto rounded-lg"
            
            range.deleteContents()
            range.insertNode(imgTag)
            
            range.setStartAfter(imgTag)
            range.collapse(true)
            selection.removeAllRanges()
            selection.addRange(range)
            
            base64Image = ""
        }
        else {
            alert("Images can only be inserted in the article content")
        }
    }
    
    function updateArticle(){}
</script>

<div class="flex flex-col gap-4 p-8 h-screen">
    <input type="text" class="bg-emerald-500 text-white p-4 rounded-lg focus:border-none focus:outline-none" bind:value={article["title"]} />
    <div class="relative">
        <button type="button" on:click={() => showImageUpload()} >
            <svg viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg" height="40px" width="40px"><path fill="white" d="M13.3 34.15h21.45q.5 0 .7-.4.2-.4-.1-.8l-5.85-7.8q-.25-.3-.6-.3t-.6.3l-6 7.75-4.05-5.55q-.25-.3-.6-.3t-.6.3l-4.3 5.6q-.25.4-.075.8t.625.4ZM9 42q-1.2 0-2.1-.9Q6 40.2 6 39V9q0-1.2.9-2.1Q7.8 6 9 6h30q1.2 0 2.1.9.9.9.9 2.1v30q0 1.2-.9 2.1-.9.9-2.1.9Zm0-3h30V9H9v30ZM9 9v30V9Z"/></svg>
            {#if imageUploadBox}
                <div class="bg-emerald-500 p-8 rounded-lg flex justify-center items-center flex-col gap-8 absolute top-[110%] relative">
                    <input type="file" accept="images/*" on:change={processImage} class="rounded-lg text-emerald-100 text-xs font-semibold bg-emerald-950 p-4" />
                    {#if base64Image}
                        <img src={base64Image} class="rounded-lg w-[50%]" />
                        <button type="button" on:click={() => insertImage(base64Image)} class="bg-emerald-950 text-emerald-100 p-4 text-xs font-semibold rounded-lg" >Add</button>
                    {/if}
                    <button type="button" on:click={closeImageUpload} class="p-4 rounded-full absolute bottom-[100%] right-[100%] bg-emerald-950" >
                        <svg viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg" height="1.5em" width="1.5em"><path fill="white" d="M24 26.1 13.5 36.6q-.45.45-1.05.45-.6 0-1.05-.45-.45-.45-.45-1.05 0-.6.45-1.05L21.9 24 11.4 13.5q-.45-.45-.45-1.05 0-.6.45-1.05.45-.45 1.05-.45.6 0 1.05.45L24 21.9l10.5-10.5q.45-.45 1.05-.45.6 0 1.05.45.45.45.45 1.05 0 .6-.45 1.05L26.1 24l10.5 10.5q.45.45.45 1.05 0 .6-.45 1.05-.45.45-1.05.45-.6 0-1.05-.45Z"/></svg>
                    </button>
                </div>
            {/if}
        </button>
    </div>
    <div id="articleViewer" class="bg-emerald-500 text-white p-4 rounded-lg focus:border-none focus:outline-none" bind:innerHTML={article["content"]} contenteditable="true" bind:this={articleViewer}>hello</div>
</div>

<style>
    input:active {
        border: 0;
        outline: 0;
    }
    
    .hidden {
        display: none;
    }
</style>

Array of Promises running on Declaration

It appears that the promises are running as soon as declared in the array and not when promise.all is called.

    p1 = new Promise(function (resolve, reject) {
        console.log('running geek1');
        const date = Date.now();
        let currentDate = null;
        do {
            currentDate = Date.now();
        } while (currentDate - date < 2000);
        resolve('timeout geek1');
    });

    p3 = new Promise(function (resolve, reject) {
        console.log('running geek3');
        const date = Date.now();
        let currentDate = null;
        do {
            currentDate = Date.now();
        } while (currentDate - date < 2000);
        resolve('geek3');
    });
    p4 = function () {
        return new Promise(function (resolve, reject) {
            console.log('running geek4');
            resolve('geek4');
        });
    }
    p5 = new Promise(function (resolve, reject) {
        console.log('running geek5');
        resolve('geek5');
    });

When you run it notice the delay I put it pauses the execution of the javascript. Which means to me this is running the code inside the promise as soon as I declare it.

results are:

running geek1
running geek3
running geek5

notice it doesn’t run p4 cause I returned the promise so it wouldn’t execute immediately.

But if I add

Promise.all([p1, p4, p5, p3]).then(function (values) {
    console.log(values);
});

I get the following out

running geek1
running geek3
running geek5
['timeout geek1', [Function: p4], 'geek5', 'geek3']

Notice that p4 did not run under promise.all and returned the value as a function.

How do I create a dynamic array of promises to run them under Promise.all?

I find conflicting examples on technique. It doesn’t make sense why I need to do return new promise to make sure it doesn’t run on declaration. It is a constructor and I am passing in a function definition. So why is it running?

If I did the following:

    class SampleClass {
        constructor(testFunc, value) {
            this.testFunc = testFunc;
            this.value = value;
        }
        writeIt(){
            console.log(this.testFunc(this.value));
        }
    }

    console.log("declare");

    let sc = new SampleClass((value) => { console.log(value); value++; console.log(value); return "added value" }, 453);
    console.log("between");
    sc.writeIt();

it works as I expect it the values don’t get written until I call writeIt()
this is what it returns.

declare
between
453
454
added value

Help is greatly appreciated.

telegram bot, cannot figure out the problem

I been struggling to deploy my bot. Im getting an error message. Im also having trouble with Jest.
These are const on my .env file/ or variables I dont know exactly what its called. If someone can please guide me and let me know how to fix this.

const Web3 = require('web3');
const TelegramBot = require('node-telegram-bot-api');
require('dotenv').config();

// Load environment variables
const token = process.env.TELEGRAM_BOT_TOKEN;
const infuraEndpoint = process.env.INFURA_OR_ALCHEMY_ENDPOINT;
const contractAddress = process.env.CONTRACT_ADDRESS;
const privateKey = process.env.PRIVATE_KEY;
const chatId = process.env.TELEGRAM_CHAT_ID;

const bot = new TelegramBot(token, { polling: true });
const web3 = new Web3(infuraEndpoint);

// Replace with your contract's ABI
const abi = [
    {
        "inputs": [],
        "name": "get",
        "outputs": [
            {
                "internalType": "uint256",
                "name": "",
                "type": "uint256"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "uint256",
                "name": "value",
                "type": "uint256"
            }
        ],
        "name": "set",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    }
];
const account = web3.eth.accounts.privateKeyToAccount(privateKey);
web3.eth.accounts.wallet.add(account);
web3.eth.defaultAccount = account.address;

const contract = new web3.eth.Contract(abi, contractAddress);

// Function to handle trade confirmation
async function handleTradeConfirmation(chatId, token, amountIn, minAmountOut) {
    const message = `Do you want to trade ${web3.utils.fromWei(amountIn, 'ether')} ETH for ${token}? Minimum tokens expected: ${web3.utils.fromWei(minAmountOut, 'ether')}`;

    // Send confirmation message
    const sentMessage = await bot.sendMessage(chatId, message, {
        reply_markup: {
            inline_keyboard: [
                [{ text: 'Confirm', callback_data: 'confirm' }],
                [{ text: 'Cancel', callback_data: 'cancel' }]
            ]
        }
    });

    // Listen for user's response
    const callbackListener = async (callbackQuery) => {
        const data = callbackQuery.data;
        const messageId = callbackQuery.message.message_id;

        if (data === 'confirm') {
            // Execute the trade
            try {
                await contract.methods.confirmTrade(token, amountIn, minAmountOut)
                    .send({ from: account.address, gas: 200000 });
                bot.sendMessage(chatId, 'Trade executed successfully.');
            } catch (error) {
                bot.sendMessage(chatId, 'Error executing trade: ' + error.message);
            }
        } else {
            bot.sendMessage(chatId, 'Trade canceled.');
        }

        // Remove the inline buttons
        bot.editMessageReplyMarkup({}, { chat_id: chatId, message_id: messageId });
        bot.removeListener('callback_query', callbackListener);
    };

    bot.on('callback_query', callbackListener);
}

// Listen for TradeDetails event
contract.events.TradeDetails()
    .on('data', async (event) => {
        const { token, amountIn, minAmountOut } = event.returnValues;
        await handleTradeConfirmation(chatId, token, amountIn, minAmountOut);
    })
    .on('error', (error) => {
        console.error('Error listening to TradeDetails event:', error);
    });

console.log('Bot is running...');

THIS IS A ERROR MESSAGE I GOT TRYING TO RUN IT:

/Users/j/MyTelegramBot/index.js:46
const account = web3.eth.accounts.privateKeyToAccount(privateKey);
^^^^^

SyntaxError: Unexpected token ‘const’
at wrapSafe (node:internal/modules/cjs/loader:1281:20)
at Module._compile (node:internal/modules/cjs/loader:1321:27)
at Module._extensions..js (node:internal/modules/cjs/loader:1416:10)
at Module.load (node:internal/modules/cjs/loader:1208:32)
at Module._load (node:internal/modules/cjs/loader:1024:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:174:12)
at node:internal/main/run_main_module:28:49

THIS IS MY .ENV FILE

 TELEGRAM_BOT_TOKEN=
    INFURA_OR_ALCHEMY_ENDPOINT=
    CONTRACT_ADDRESS=
    PRIVATE_KEY=
    TELEGRAM_CHAT_ID=

——————————————————————–THIS IS THE TEST CODE THAT I USED TO TEST THE BOT.

test('basic arithmetic', () => {
  expect(1 + 2).toBe(3);
});

Is it possible to see a complete list of const or let variables?

I’m writing a piece of JavaScript code which will be used on any Instagram POSTS page (the landing page of an Instagram user). After pasting my code into the console and hitting Enter, the code needs to get all posts that have been loaded.

I noticed that, after scrolling down the page for some distance, the previously loaded posts disappear from DOM. And after scrolling back up, those posts re-appear in DOM. I think the data of those posts are most likely stored in a variable for quick access because I have seen a similar social media doing that.

I checked the window global variable and didn’t find any such variable under it. The variable (if there is one) must have been a const or let variable then. Is there a way to see a complete list of const or let variables so that I can try to dig out the data of posts from them?

Call javascript function from Swift in Capacitor

I completed the capacitor iOS example by packaging a web game (Phaser). It runs fine but I would like to know how to call into a javascript function in the game from native Swift code. I see an extended WKWebView in the capacitor pod but I don’t see how it’s used in the app. I need to do the same in android but I’ll do that in another post.

Any thoughts?

How to retrieve and display text from AJAX Response in SweetAlert using JavaScript and PHP

In the SweetAlert located in “kardex.js”, I am receiving this for some reason on the server:

[]{"justification":"Hello"} 

And I want to receive only the text that corresponds to “justification”, which in this case is “Hello”, and display it on this part:

text: 'Justification: ' + response,

Please consider that I am not very proficient in JavaScript. Thank you in advance.

I have four segments of 4 files that are related to each other.

First, here is “kardex.js”:

if(info.event.title === "OMISSION")
{
  getJustification(info.event.id, function(response)
  {
    Swal.fire(
    {
      title: 'Delete omission event?',
      text: 'Justification: ' + response,
      icon: 'warning',
      showCancelButton: true,
      confirmButtonText: 'Yes, delete',
      cancelButtonText: 'Cancel'
    }).then((result) => 
    {
      if (result.isConfirmed)
      {
        delete(info.event.id);
      }
    });
  });
}

Next is “omission.ajax.js”:

function getJustification(eventId, callback) 
{
  $.ajax(
  {
    type: 'POST',
    url: 'controller/omission.controller.php',
    data: 
    {
      accion: 'justification',
      eventId: eventId
    },
    success: function(response) 
    {
      callback(response);
    }
  });
}

Then “omission.controller.php”:

<?php

require_once "../model/omission.model.php";

class Controller
{
    public static function manageRequest()
    {
        $response= array();

        if ($_SERVER["REQUEST_METHOD"] == "POST") 
        {
            $table= "omission";
                           
            if (isset($_POST["action"]) && $_POST["action"] == "justification") 
            {
                $eventId = $_POST["eventId"];
                
                $response= Model::getJustification($table, $eventId);
            }
        }

        echo json_encode($response);
    }
}

Controller::manageRequest();
?>

Finally, “omission.model.php”:

<?php
require_once "db.php";

class Model
{
  public static function getJustification($table, $eventId)
  {
    $conn = connection::connect();

    // Get justification
    $stmt = $conn->prepare("SELECT justification FROM $table WHERE id = :id");
    $stmt->bindParam(":id", $eventId, PDO::PARAM_INT);
    $stmt->execute();
    
    $responose = $stmt->fetch(PDO::FETCH_ASSOC);
    
    return $response; 
  }
}
?>

What am I doing wrong? I have tried changing “response” to “response.justification”, but that gives me an error.

Cant find the error in my tictactoe (javascript) code

So far I’ve only been trying to create the functions for the players turn, the computers turn, and to display the tic tac toe board before the game starts.

I’m not done yet and the functions are working fine, but the issue comes up when I execute compTurn() after playerTurn() with the while loop in the compTurn() function. The window freezes and I cant do anything except rerun the entire code.

I cant find the issue with the whileloop.

HTML file

<!DOCTYPE html>
<html>
<head>
  <title>Basic Web Page</title>
  <meta name="viewport" content="width=device-width,initial-scale=1" >
  <link href="style.css" rel="stylesheet">
</head>
<body>
  <h1>Hello World!</h1>
  <p>This is your space to practice, get creative, and build your own projects from scratch.</p>
<button onclick="displayTable()">Display Tic Tac Toe Boe</button>
<button onclick="playerTurn()">Player Turn</button>
<button onclick="compTurn()">Comp Turn</button>

  <script src="script.js"></script>
</body>
</html>

javascript file

//tic tac toe

const playerUser = 'X'
const playerComp = 'O'
let rowTop = [1, 2, 3]
let rowMid = [4, 5, 6]
let rowLow = [7, 8, 9]

function displayTable(){
  console.log(rowTop)
  console.log(rowMid)
  console.log(rowLow)
}

function playerTurn(){
    console.log(`----------------------`)

  let change = window.prompt(`Please choose a spot`)
  change = Number(change);

  /*while(change === NaN){
    window.alert('not a number')
    change = window.prompt(`Please choose a spot`)
    change = Number(change);
  }*/

  for(let i = 0; i < 3; i++){
    if(rowTop[i] === change){
      rowTop[i] = playerUser
    }
    else if(rowMid[i] === change){
      rowMid[i] = playerUser
    }
    else if(rowLow[i] === change){
      rowLow[i] = playerUser
    }
  
  }
  displayTable()
  console.log(`----------------------`)

}


function compTurn(){
    console.log(`----------------------`)

  let compChange = Math.floor(Math.random() * 9) + 1;
  for(let a = 0; a < 3; a++){
    /*while(rowTop[a] === playerUser ||  rowMid[a] === playerUser || rowLow[a] === playerUser){
     compChange = Math.floor(Math.random() * 9) + 1;
    }*/
    /*while(rowTop[a] === 'X' ||  rowMid[a] === 'X' || rowLow[a] === 'X' || rowTop[a] === 'O' ||  rowMid[a] === 'O' || rowLow[a] === 'O'){
     compChange = Math.floor(Math.random() * 9) + 1;
    }*/
      if(rowTop[a] === compChange){
      rowTop[a] = playerComp
      }
      else if(rowMid[a] === compChange){
      rowMid[a] = playerComp
      }
      else if(rowLow[a] === compChange){
      rowLow[a] = playerComp
      }
  }
   displayTable()
  console.log(`----------------------`)

}


      

I tried rewriting the while loops but still had the same problem

    /*while(rowTop[a] === playerUser ||  rowMid[a] === playerUser || rowLow[a] === playerUser){
     compChange = Math.floor(Math.random() * 9) + 1;
    }*/

    /*while(rowTop[a] === 'X' ||  rowMid[a] === 'X' || rowLow[a] === 'X' || rowTop[a] === 'O' ||  rowMid[a] === 'O' || rowLow[a] === 'O'){
     compChange = Math.floor(Math.random() * 9) + 1;
    }*/

How to find this type of values in Javascript? [duplicate]

I have an object that is like this:

let obj = {
  links: {},
  data: [
    {
      type: "type",
      id: "id",
      attributes: {
        name: "some-name",
      },
    },
    {
      type: "type",
      id: "id",
      attributes: {
        name: "some-other-name",
      },
    },
  ],
};
let array = obj.data;

So I have an object with key and value that is another object, that is in another object that is in array, and that array is in object.
I want to know how to find the exact value, for example I want to find value “some-other-name”, how can I do that. I tried with

for (let i in array)
if(array[i].attributes.name === "some-other-name") {
return array[i];

but it seems like it’s not working.
Can someone help?

How can i write to a specific cell in a Google sheets range?

I am creating a discord bot and would like to write to a specific cell in Google sheets. With this code i am able to post the userInput into the embed when the command is executed on discord.

However the code is returning an error : Missing range, and is not writing in google sheets.

Essentially i want the user to use the command “/checkbl steamidhere”. “steamidhere” would be whatever the userInput is. Write that user input into the Google sheets cell H1.

This is my code I am currently using:

async function readBlacklist() {
    const spreadsheetId = "myspreadsheetID";
    const sheetName = "BOTDATA";
    const cells = ["H1"];
    const valueInputOption = 'USER_ENTERED';
    const ranges = cells.map((c) => `'${sheetName}'!${c}`);
    const sheets = google.sheets({ version: "v4", auth });
    try {
      const response = await sheets.spreadsheets.values.update({ spreadsheetId, ranges, valueInputOption });
     const rows = response.data.valueRanges.reduce((o, { values = [[""]] }, i) => ((o[cells[i]] = values[0][0]), o), {});
      return rows;
    } catch (error) {
        console.log(`There was an error: ${error}`)
    }
  }

  (async()=>{
const write = await readBlacklist(['test']);
console.log(write);
if (interaction.commandName === 'checkbl') {
    const userInput = interaction.options.get('steamid').value;
    const bl = new EmbedBuilder()
    .setTitle('Blacklist Checker')
    .setDescription(`${userInput}`)
    .setColor('Red')
    .setThumbnail('https://i.imgur.com/9GKhYQf.png')
    .setFooter({text: 'DroneOS', iconURL: 'https://i.imgur.com/9GKhYQf.png'})
    .setTimestamp()

    interaction.reply({ embeds: [bl]});

}

})()

Is it good practice to use a POST request instead of PATCH to update data in a CRUD application?

I’m making a CRUD application and I’m making an update comment function. Normally, there is a patch request that is used for updating or modifying objects. However, while working on forms, I saw that the html forms only respond to GET and POST requests. This got me thinking for the UPDATE application of the CRUD, and I thought I could simply use a POST request to create the application.

html:

<form action="http://localhost:3000/update" id='POST' method="post">
    <label for="username">Username: </label>`  
    <input type="text" name='username' id='username'>
    <label for="comment">Comment:</label>
    <input type="text" name="comment" id="comment">
    <button>UPDATE</button>
</form>

Javascript:

app.post('/update', (req, res) => {

    console.log(req.body);
    const { username, comment } = req.body;
    const ind = comments.findIndex((element) => element.username === username)
    comments[ind].comment = comment;
    console.log('Comment updated!');
    res.redirect('/comments');

})

The code works as expected on my end, it updates the person’s comment and then redirects to /comments, which is a page that displays all comments, but I’m not sure if it’s good practice to do it like this.

i am trying to get the information from my movies.js file to be display on the player page based on the param

here is my progress so far on the code

    const playBtn = document.querySelector('.playBtn');
    const pauseBtn = document.querySelector('.pauseBtn');
    const forwardBtn = document.querySelector('.forwardBtn');
    const prevBtn = document.querySelector('.prevBtn');
    const vid = document.getElementById("movieDisplay");
    const { name } = useParams();
    const [movie, setMovie] = useState()

    useEffect(() => {
        // Find the movie data that matches the URL parameter
        const matchedMovie = movies.find((movie) => movie.title === name);
        setMovie(matchedMovie);
        
      }, [name]); // Re-run the effect when the URL parameter changes
      console.log(movie)

this code responded with no error just an blank screen

HTML, JavaScript, CSS, fade-in troubleshooting

I am trying to add a fade in and slide up feature to some of the content in the middle of my HTML page as I scroll down. Currently I am having issues with the fade in. I am trying to apply the fade-in to a paragraph and button tag and both of them have two classes. Their own class for styling and then a .fade-in class which applies the styles for the fade in. I am implementing the fade-in through JavaScript. At the moment though, after I applied the .fade-in styles, the content isn’t showing up on the page anymore because I set the fade-in to opacity 0. While I scroll down, the content should fade in due to the fade-in.appear class which has opacity 1 but still the content is not visible.

To do some troubleshooting, I swapped opacity transitions from .fade-in {} from 0 to 1 and from .fade-in.appear {} from 1 to 0. With this change, now content never fades out. So I have come to the conclusion that the animation never gets triggered. Also please note that I have checked the browser console for JavaScript errors and ran the files through the W3C validator for HTML files and found no errors.

Here is also the code from HTML, CSS, and JS files:

HTML:

<div class="first-section">
  <p class="our-story-text fade-in">
    We customize sneakers with a focus on timeless designs, local production, and responsibly sourced products.
  </p>
  <button onclick="navigateToAbout()" class="story-button fade-in">Our Story</button>
</div>

CSS:


.our-story-text {
  font-family: 'Montserrat', sans-serif;
  display: block;
  font-size: 14px;
  text-align: center;
  padding: 50px;
  margin-top: 70px;
  background-color: rgb(242,239,227);
  width: 100%;
  max-width: 550px;
}

.story-button {
  font-family: 'Montserrat', sans-serif;
  background-color: rgb(242,239,227);
  display: block;
  color: black;
  height: 66px;
  width: 200px;
  border-width: 2px;
  border-color: black;
  font-weight: 550;
  margin-top: -28px;
}

.story-button:hover {
  cursor: pointer;
  color: rgb(242,239,227);
  background-color: black;
}

.fade-in {
  opacity: 0;
  transition: opacity 250ms ease-in;
}

.fade-in.appear {
  opacity: 1;
}

@media (max-width: 600px) {
  .our-story-text {
    background-color: rgb(242,239,227);
    margin-top: -10px;
    max-width: 85%;
  }

  .story-button {
    margin-top: 0px;
    height: 59px;
    width: 300px;
  }
}

JavaScript:

function navigateToAbout() {
  window.location.href = 'about.html';
}

const faders = document.querySelectorAll(".fade-in");

const appearOptions = {
  threshold: 1,
  rootMargin: "0px 0px -100px 0px"
};

const appearOnScroll = new IntersectionObserver(function(entries, appearOnScroll) {
  entries.forEach(entry => {
    if (!entry.isIntersecting) {
      return;
    } else {
      entry.target.classList.add("appear");
      appearOnScroll.unobserve(entry.target);
    }
  });
}, appearOptions);

faders.forEach(fader => {
  appearOnScroll.observe(fader);
});

“Region is missing” error for Amazon S3 PutObjectCommand even though region is specified

I’m working on project where I need to upload an image file (e.g., .png) to an Amazon S3 bucket. I’ve been through many examples, and as far as I can tell, I’ve been following everything the same. I finally progressed to a point where the error I am getting is “Error: Region is missing”. However, I have specified the region, and I have double-checked it is the same region specified on my bucket in the correct format (e.g., “us-west-1”). I’m just not sure any other direction to proceed in, so any direction would be helpful. Note that the file I am trying to upload is of format:

Main photo file: [
{
fieldname: ‘mainPhoto’,
originalname: ‘mainPhoto.png’,
encoding: ‘7bit’,
mimetype: ‘image/png’,
buffer: <Buffer 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 07 ac 00 00 03 28 08 06 00 00 00 7b c3 1e 08 00 00 0c 3f 69 43 43 50 49 43 43 20 50 72 6f 66 69 … 2666634 more bytes>,
size: 2666684
}
]

Here is the code (React). The image I am trying to upload is mainPhotoFile.

require('dotenv').config();
const express = require('express');
const multer = require('multer');
const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3');
// const { getSignedURL } = require('@aws-sdk/s3-rquest-presigner')
const { Pool } = require('pg');
const cors = require('cors');
const fs = require('fs');

const app = express();
app.use(cors());

const REGION = process.env.AWS_REGION;
const BUCKET = process.env.S3_BUCKET_NAME;
// Configure AWS SDK
const s3Client = new S3Client({
  region: REGION
  credentials: {
    accessKeyId: process.env.AWS_ACCESS_KEY_ID,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
  },
});
const pool = new Pool({
  user: 'postgres',
  host: 'localhost',
  database: 'databaseName',
  password: '********',
  port: 5432,
});
app.get('/api/projects', async(req, res) => {
  const { offset = 0, limit = 10 } = req.query;
  const rows = await pool.query('SELECT * FROM portfolio LIMIT $1 OFFSET $2', [limit, offset]);
  res.json(rows);
})

const upload = multer();

app.post('/upload', upload.fields([{ name: 'mainPhoto', maxCount: 1 }, { name: 'auxPhoto1', maxCount: 1 }]), async (req, res) => {
  try {
    const files = req.files;
    const mainPhotoFile = files.mainPhoto ? files.mainPhoto : null;
    const auxPhotoFile = files.auxPhoto1 ? files.auxPhoto1 : null;

    let mainPhotoURL = null;
    let auxPhotoURL = null;

    console.log('Main photo file:', mainPhotoFile);
    console.log('Aux photo file:', auxPhotoFile);

    if (mainPhotoFile) {
      const mainPhotoParams = {
        Bucket: BUCKET,
        Key: mainPhotoFile.originalname,
        Body: mainPhotoFile,
        ContentType: mainPhotoFile.mimetype,
      };
      const mainPhotoCommand = new PutObjectCommand(mainPhotoParams);
      const mainPhotoData = await s3Client.send(mainPhotoCommand);
      mainPhotoURL = `https://${mainPhotoParams.Bucket}.s3.${REGION}.amazonaws.com/${mainPhotoParams.Key}`;
    }

    // if (auxPhotoFile) {
    //   const auxPhotoParams = {
    //     Bucket: 'your-bucket-name',
    //     Key: auxPhotoFile.originalname,
    //     Body: fs.createReadStream(auxPhotoFile.path),
    //     ContentType: auxPhotoFile.mimetype,
    //   };
    //   const auxPhotoCommand = new PutObjectCommand(auxPhotoParams);
    //   const auxPhotoData = await s3.send(auxPhotoCommand);
    //   auxPhotoURL = `https://${auxPhotoParams.Bucket}.s3.${process.env.AWS_REGION}.amazonaws.com/${auxPhotoParams.Key}`;
    // }

    const { clientName, clientTag1, clientTag2, clientTag3, clientDesc, clientNeeds, companySolution } = req.body;

    const query = `
      INSERT INTO portfolio (
        clientname,
        clienttag1,
        clienttag2,
        clienttag3,
        clientdesc,
        clientneeds,
        companysolution,
        mainphotourl,
        auxphoto1url
      ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
    `;

    const values = [
      clientName,
      clientTag1,
      clientTag2,
      clientTag3,
      clientDesc,
      clientNeeds,
      companySolution,
      mainPhotoURL,
      auxPhotoURL
    ];

    await pool.query(query, values);
    res.send('Data uploaded and inserted successfully.');
  } catch (err) {
    console.error(err);
    res.status(500).send('Error uploading data and files.');
  }
});


const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});

Bootstrap smooth card collapse on dynamic DOM

I’m trying to create a card collapse following this page here.
https://getbootstrap.com/docs/4.0/components/collapse/#accordion-example
I’m creating the elements dynamically. Two things I noticed was:
A: Dynamically added elements do not collapse/show on their own
B: They do not do smooth collapsing/showing

So in my case to get around problem A , I added a button click event to the button which added and removed the “show” “collapse” class for the card.

export const ToggleCard = ((dom) => {
    let collapsed = dom.lastChild;
    if(collapsed.classList.contains("show")){
        collapsed.classList.add("collapsed");
        collapsed.classList.remove("show");
    }else{
        collapsed.classList.add("show");
        collapsed.classList.remove("collapsed");
    }
});

This works but it’s not smooth toggling/collapsing like the demo on the page.
When I click, it just pops in and out. Is there any way to resolve this?

Best way to learn JavaScript? [closed]

I find Youtube videos are one of the best sources for me learning so far, with HTML, CSS and PHP however most of them are either too long with lots of repetition or too short with not enough detail.

However along with those I used a few free websites to help me learn, i would like to start learning JavaScript without YouTube tutorials.

Any websites, links etc that could help kickstart learning and progress me through the ‘beginner stage’ would be greatly appreciated!

Thank you.

Also, apologies if this isnt the type of question to send here, ive used it countless times for questions others have asked before, ive just never actually typed one out.