Encrypt and decrypt files with JavaScript (Error in characters codification)

I’m doing a small software in JavaScript for encrypting and decrypting files directly on the browser. All right but when I try to decrypt files… it’s impossible. I think it’s all related to codification of text, but I don’t know, I need a good coder for review this code

<!DOCTYPE html>
<html>
<head>
  <title>Formulario de cifrado y descifrado de archivos</title>
  <meta charset="utf-8">
  <link rel="stylesheet" href="resetcss.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
</head>
<body>
    <h1> Cifrado y descifrado de ficheros </h1>
    <hr>
    <h2>CIFRADO DE FICHERO</h2>
    <div>
        <table>
            <tr>
                <th>Fichero</th>
                <th>Semilla aleatoria</th>
            </tr>
            <tr>
                <td><input type="file" id="filetocypher" placeholder="Fichero" /></td>
                <td><input type="text" id="cypherpass" placeholder="Semilla aleatoria"></td>
            </tr>
            <tr>
                <td><button id="efi" disabled>Encriptar fichero</button></td>
                <td></td>
            </tr>
        </table>
        
        
        <div id="resultado_cif"></div>
    </div>


    <br />
    <h2>DES-CIFRADO DE FICHERO</h2>
    <div>
        <table>
            <tr>
                <th>Fichero</th>
                <th>KEY</th>
                <th>IV</th>
                <th>SALT</th>
            </tr>
            <tr>
                <td><input type="file" id="filetodescypher" placeholder="Fichero" /></td>
                <td><input type="text" id="key" placeholder="Pegue aquí la KEY" value=""></td>
                <td><input type="text" id="iv" placeholder="Pegue aquí la IV" value=""></td>
                <td><input type="text" id="salt" placeholder="Pegue aquí la SALT" value=""></td>
            </tr>
            <tr>
                <td><button id="defi" disabled>Descifrar fichero</button></td>
                <td></td>
                <td></td>
                <td></td>
            </tr>
        </table>
        
        
        <div id="resultado_dcif"></div>
    </div>


    <script type="text/javascript">
        const mode = CryptoJS.mode.CBC;
        var Password={_pattern:/[a-zA-Z0-9_-+.]/,_getRandomByte:function(){if(window.crypto&&window.crypto.getRandomValues){var t=new Uint8Array(1);return window.crypto.getRandomValues(t),t[0]}if(!window.msCrypto||!window.msCrypto.getRandomValues)return Math.floor(256*Math.random());var t=new Uint8Array(1);return window.msCrypto.getRandomValues(t),t[0]},generate:function(t){return Array.apply(null,{length:t}).map(function(){for(var t;;)if(t=String.fromCharCode(this._getRandomByte()),this._pattern.test(t))return t},this).join("")}};


        $( document ).ready(function() {

            $("#filetocypher").on("change", function(e) {
                $("#efi").removeAttr("disabled")
            });

            $("#filetodescypher").on("change", function(e) {
                $("#defi").removeAttr("disabled")
            });

            const leerFichero = (f) =>
            new Promise(resolve => Object.assign(new FileReader(), {onload(){
                resolve(this.result)}}).readAsText(f));
            $("#cypherpass").val(Password.generate(16));




            $("#efi").on("click", function(e) {
                $("#resultado_cif").html("Procesando ...");
                leerFichero(document.querySelector('#filetocypher').files[0])
                .then(function(contenido) { 
                    var fichero = document.querySelector('#filetocypher').files[0];
                    var fichero_p_array = [fichero.name,fichero.type,contenido];
                    var fichero_p_json = JSON.stringify(fichero_p_array);
                    var encrypted = CryptoJS.AES.encrypt(fichero_p_json, $("#cypherpass").val(), {mode:mode});
                    var blob = new Blob([encrypted], { type: 'text/plain' });

                    var urlCBlob = URL.createObjectURL(blob);
                    $("#resultado_cif").html('Su fichero seguro ha sido generado, no es necesario recordar la semilla aleatoria, se usó para generar las credenciales, por favor guarde en un lugar seguro las siguientes credenciales generadas, las necesitará para volver a desencriptar su fichero: <br /><br/> KEY: ' + $("#cypherpass").val() + '<br />IV: ' + encrypted.iv + '<br />SALT: ' + encrypted.salt + '<br/><br/>Descarga del fichero: <a href="'+urlCBlob+'" download="'+fichero.name+'.crypto">Descargar</a>');
                });
            });


            $("#defi").on("click", function(e) {
                $("#resultado_dcif").html("Procesando ...");
                leerFichero(document.querySelector('#filetodescypher').files[0])
                .then(function(contenido) { 
                    var fichero = document.querySelector('#filetodescypher').files[0];

                    var ckey = $("#key").val();
                    var civ = $("#iv").val();
                    var csalt = $("#salt").val();
                    var des = CryptoJS.AES.decrypt(contenido, ckey, { iv: civ, mode: mode, salt: csalt });
                    var dcontenido = des.toString(CryptoJS.enc.Utf8); //json
                    var dcontenido_array = JSON.parse(dcontenido); //array
                    var blob = new Blob([dcontenido_array[2]], { type: dcontenido_array[1] });
                    var urlDBlob = URL.createObjectURL(blob);
                    $("#resultado_dcif").html('Descarga del fichero original: <a href="'+urlDBlob+'" download="'+dcontenido_array[0]+'">Descargar</a>');
                });
            });


        });

    </script>


</body>
</html>

Please, I need a possible solution!

I can do it with PHP, but I would love do it with JavaScript.

Why the game isn’t restart when space key is pressed in determined position?

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="marioCSS/style.css">
    <script src="marioJS/script.js" defer></script>
    <title>Mario Jump</title>
</head>
<body>
    <div class="container">
        <img src="./marioImages/logo.png" alt="logo" class="logo">
    <div class="game-board">
        <h2 id="score">SCORE: 0</h2>
        <img src="./marioImages/control.png" alt="press-space" class="press-space">
        <img src="marioImages/clouds.png" class="clouds">
        <img src="marioImages/mario.gif" class="mario">
        <img src="marioImages/pipe.png" class="pipe">
    </div>
    <audio src="./marioAudios/Theme song.mp3" class="theme-song" controls></audio>
    <audio src="./marioAudios/Jump.mp3" class="jump-sound"></audio>
    <audio src="./marioAudios/Death.mp3" class="death-sound"></audio>
    </div>
</body>
</html>

CSS:

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

html,
body {
    height: 100%;
}

body {
    padding-top: 20vh;
    background-image: url(../marioImages/wallpaper.jpg);
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    overflow-y: hidden;
}

.theme-song {
    display: none;
}

.container {
    height: 100%;
}

.logo {
    position: absolute;
    padding-left: 41vw;
    bottom: 75vh;
    width: 60%;
    z-index: 1;
}

.press-space {
    position: absolute;
    bottom: 160px;
    padding-left: 400px;
    z-index: 2;
    animation: press-space-animation 1s infinite;
}

.game-board {
    position: relative;
    width: 80%;
    height: 500px;
    border-bottom: 15px solid rgb(35, 160, 35);
    margin: 0 auto;
    overflow: hidden;
    background: linear-gradient(#87ceeb, #e0f6ff);
}

#score {
    font-family: "Super Mario 256";
    margin: 10px;
    z-index: 4;
}

.pipe {
    position: absolute;
    bottom: 0;
    width: 80px;
    animation: pipe-animation 1.5s infinite linear;
}

.mario {
    position: absolute;
    width: 150px;
    bottom: 0;
    z-index: 3;
}

.jump {
    animation: jump 500ms ease-out;
}

.clouds {
    position: absolute;
    width: 500px;
    animation: clouds-animation 4s infinite linear;
    z-index: 1;
}

@keyframes pipe-animation {
    from {
        right: -80px;
    }

    to {
        right: 100%;
    }
}

@keyframes jump {
    0% {
        bottom: 0;
    }

    40% {
        bottom: 180px;
    }

    50% {
        bottom: 180px;
    }

    60% {
        bottom: 180px;
    }

    100% {
        bottom: 0;
    }
}

@keyframes clouds-animation {
    from {
        right: -500px;
    }

    to {
        right: 100%;
    }
}

@keyframes press-space-animation {
    0% {
        opacity: 1;
    }
    50% {
        opacity: 0;
    }
    100% {
        opacity: 1;
    }
}

@font-face {
    font-family: "Super Mario 256";
    src: url(/marioFont/SuperMario256.ttf);
}

Javascript:

// Declaring required variables
const mario = document.querySelector(".mario");
const pipe = document.querySelector(".pipe");
const control = document.querySelector(".press-space");

const themeSong = document.querySelector(".theme-song");
const jumpSound = document.querySelector(".jump-sound");
const deathSound = document.querySelector(".death-sound");

let spaceKeyPressed = false;

let score = 0;
let scoreSet = false;

// Setting how Mario's jump works
const jump = () => {
    mario.classList.add("jump");
    setTimeout(() => {
        mario.classList.remove("jump");
    }, 500);

    scoreSet = false;
};

// Setting space key control and game music
document.addEventListener("keydown", (event) => {
    if (event.code === "Space") {
        jump();
        control.style.display = "none";
        spaceKeyPressed = true;
        if (themeSong.paused) {
            themeSong.play();
        } else {
            jumpSound.play();
        }
    }
});

// Setting player score
function scoreCount() {
    if (!scoreSet) {
        score++;
        scoreSet = true;
    }

    document.querySelector("#score").innerHTML = `SCORE: ${score}`;
}

// Restart game functions (DOESN'T WORKING)
const restartGame = () => {
    score = 0;
    scoreSet = false;
    pipe.style.animation = "pipe-animation 1.5s infinite linear";
    mario.src = "marioImages/mario.gif";
    mario.style.width = "150px";
    mario.style.margin = "0";
    mario.style.bottom = "0";
    control.style.display = "block";
    spaceKeyPressed = false;
    themeSong.currentTime = 0;
    jumpSound.currentTime = 0;
};

const restartSpace = (event) => {
    if (
        pipePosition <= 120 &&
        pipePosition > 0 &&
        marioPosition < 80 &&
        event.code === "Space"
    ) {
        pipe.style.right = "-80px";
        restartGame();
    }
};

// Setting game mechanics
const loop = setInterval(() => {
    if (spaceKeyPressed) {
        const pipePosition = pipe.offsetLeft;
        const marioPosition = +window
            .getComputedStyle(mario)
            .bottom.replace("px", "");

        if (pipePosition < 0 && marioPosition >= 60) {
            scoreCount();
        }

        if (pipePosition <= 120 && pipePosition > 0 && marioPosition < 80) {
            pipe.style.animation = "none";
            pipe.style.left = `${pipePosition}px`;
            mario.style.animation = "none";
            mario.style.bottom = `${marioPosition}px`;
            mario.src = "./marioImages/game-over.png";
            mario.style.width = "75px";
            mario.style.margin = "50px";
            clearInterval(loop);

            themeSong.pause();
            themeSong.currentTime = 0;
            jumpSound.pause();
            jumpSound.currentTime = 0;

            deathSound.play();
        }
    }
}, 10);

I’m trying to restart the game when the user press space after Mario touch the pipe.

I attempted to create a ‘restartGame’ function to make Mario and the pipe go to their respective initial position.

And them I call that function to another function called ‘restartSpace’. This function only call ‘restartGame’ when Mario touch the pipe and the user press space, to initiate a new round.

But even so, the pipe isn’t restart in your inital position and Mario can’t jump.

How restart the game correctly?

Exported Whatsapp Client Object NOT Updated When Imported [duplicate]

I’m using whatsapp-web.js to create a bot. I want to use the client in different files so I’m trying to export it but I cant get the updated client value on the files where I import it. I tried making a global variable as an object so then its value can be updated ones it goes through the function.

const { Client, RemoteAuth } = require('whatsapp-web.js');

var client = {}
// Require database
mongoose.connect(DATABASE_URL).then(async () => {
    const store = new MongoStore({ mongoose: mongoose });

    client = new Client({
        authStrategy: new RemoteAuth({
            store: store,
            backupSyncIntervalMs: 300000
        }),
        headless: false,
        puppeteer: {
            args: [
                '--no-sandbox',
                '--disable-setuid-sandbox',
                '--disable-dev-shm-usage',
                '--disable-accelerated-2d-canvas',
                '--no-first-run',
                '--no-zygote',
                '--disable-gpu'
            ],
        },
    });

    client.on('authenticated', async () => {
        console.log('Client is authenticated!');
    });
    client.on('qr', async qr => {
        qrcode.generate(qr, { small: true });
    });
    client.on('ready', async () => {
        console.log('Client is ready!');
    });

    client.on('remote_session_saved', () => {
        console.log('Client is saved!');
    });
    client.initialize();
});

exports.client = client

The files where I’m importing it gives me ‘client = {}’ I thought that by declaring it as an object I get a reference space which allows to change the variable value later. This was working for me before I use RemoteAuth() and have to update the variable inside a function.

This is how I import it:

var client = require('../app').client;

//Funcion para que se envie correo de minimo de productos
async function correoAgotados(agotados) {
    console.log('inicia proceso de envio de correo')
    var mensaje = "Saludos desde " + agotados[0].planta + ", <br>";
    for (var i = 0; i < agotados.length; i++)
        mensaje = mensaje + "<p>El producto: " + agotados[i].producto + " ha llegado a su minimo.</p>" + "<p>Cantidad en Existencia: " + agotados[i].cantidad + " " + agotados[i].unidadCosteo + "</p><p>Minimo Registrado: " + agotados[i].min + " " + agotados[i].unidadCosteo + "</p> <br>"

    var mailOptions = {
        from: '--',
        to: '--',
        subject: 'Falta de Materiales',
        html: mensaje
    };
    try {
        var contacts = ['--']
        if (agotados[0].planta == 'Hadrok')
            contacts.push('--')
        mensaje = mensaje
        for (var i = 0; i < contacts.length; i++) {
            await client.sendMessage('521' + contacts[i] + '@c.us', mensaje.replace(/<br>|<p>/g, 'n').replace(/</p>/g, ''))
        }
    } catch {
        console.log('error de bot')
        console.log(client)
    }
}

Textarea is not working in safari after using javascript

I’m trying to create a custom made form in my website. I’ve got the desired result in chrome but when I open my website in safari the textarea is not working, I’m unable to type anything.

Here is my code, you can check out my website also https://www.thebranvetica.com

<footer>
            <form action="https://api.web3forms.com/submit" method="POST" id="form">
                <input type="hidden" name="access_key" value="8a33718e-6751-4330-a4ef-ccc9d5de1d36"/>
                <input type="hidden" name="subject" value="New Submission: The Branvetica" />
                <input type="hidden" name="name" value="NA" />
                <input type="hidden" name="phone" value="NA" />
                <input type="checkbox" name="botcheck" id="" style="display: none;" />
                <div class="textarea-send-main">
                    <div class="textarea-foot">
                        <textarea onclick="textAreaClick()" name="message" id="message" aria-label="Enter your message"></textarea>
                        <textarea onclick="emailAreaClick()" name="email" id="email" aria-label="Enter your email"></textarea>
                    </div>
                    <div class="button-foot">
                        <button type="button" id="sendText" onclick="emailButton()">SE<br>ND</button>
                    </div>
                </div>
            </form>
        </footer>
<script>
            document.addEventListener('DOMContentLoaded', function(){
              var infoTextArea = document.getElementById('message');
              infoTextArea.value = 'I Want ';
        
              infoTextArea.addEventListener('input', function() {
                var inputValue = infoTextArea.value;
                var desiredText = 'I Want ';
        
                if (!inputValue.startsWith(desiredText)) {
                  infoTextArea.value = desiredText;
                }
              });
            });
        </script>

         
        <script>
            document.addEventListener('DOMContentLoaded', function() {
            var infoTextArea = document.getElementById('email');
            infoTextArea.value = 'Email: ';

            infoTextArea.addEventListener('input', function() {
                var inputValue = infoTextArea.value;
                var desiredText = 'Email: ';

                if (!inputValue.startsWith(desiredText)) {
                infoTextArea.value = desiredText;
                }
            });
            });
        </script>

        <script>
            document.addEventListener('DOMContentLoaded', function() {
            var infoTextArea = document.getElementById('message');
            var desiredText = 'I Want ';
            
            infoTextArea.addEventListener('focus', function() {
                if (infoTextArea.value.length < desiredText.length) {
                infoTextArea.value = desiredText;
                }
            });

            infoTextArea.addEventListener('mouseup', function(event) {
                if (infoTextArea.selectionStart < desiredText.length) {
                infoTextArea.setSelectionRange(desiredText.length, desiredText.length);
                event.preventDefault();
                }
            });
            });
        </script>

        <script>
            document.addEventListener('DOMContentLoaded', function() {
            var infoTextArea = document.getElementById('email');
            var desiredText = 'Email: ';
            
            infoTextArea.addEventListener('focus', function() {
                if (infoTextArea.value.length < desiredText.length) {
                infoTextArea.value = desiredText;
                }
            });

            infoTextArea.addEventListener('mouseup', function(event) {
                if (infoTextArea.selectionStart < desiredText.length) {
                infoTextArea.setSelectionRange(desiredText.length, desiredText.length);
                event.preventDefault();
                }
            });
            });
        </script>



        <script>
            document.addEventListener('DOMContentLoaded', function() {
            var infoTextArea = document.getElementById('message');
            var sendButton = document.getElementById('sendText');

            infoTextArea.addEventListener('keydown', function(event) {
                if (event.keyCode === 13 && !event.shiftKey) { // Enter key without Shift
                event.preventDefault(); // Prevent the default behavior of the Enter key
                sendButton.click(); // Trigger the button click event
                }
            });
            });
        </script>

        <script>
            document.addEventListener('DOMContentLoaded', function() {
            var infoTextArea = document.getElementById('email');
            var sendButton = document.getElementById('sendText');

            infoTextArea.addEventListener('keydown', function(event) {
                if (event.keyCode === 13 && !event.shiftKey) { // Enter key without Shift
                event.preventDefault(); // Prevent the default behavior of the Enter key
                sendButton.click(); // Trigger the button click event
                }
            });
            });
        </script>

I’m new to web development, I’ve tried manupalating javascript code but I’m very bad at it. Please help.your text

how to check why an API fill a variable

I have been trying to get the data from this API to display in the console based off of the name of the college I input, but variables aren’t working and aren’t getting any data from the API to store.

What I have so far:

// Function to retrieve school information
function getSchoolInformation() {
  var schoolName = document.getElementById("schoolName").value;
  fetch('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2020/2020-03-10/tuition_cost.csv')
    .then(response => response.text())
    .then(csvData => {
      var schoolInfo = findSchoolInformation(schoolName, csvData);
      displaySchoolInformation(schoolInfo);
    })
    .catch(error => {
      console.error('Error:', error);
    });
}

// Function to find school information based on school name
function findSchoolInformation(schoolName, csvData) {
  var parsedData = Papa.parse(csvData, {
    header: true,
    skipEmptyLines: true
  }).data;
  var schoolInfo = [];

  parsedData.forEach(function(row) {
    var collegeName = row["INSTNM"];
    var degreeLength = row["CURROPER"];
    var tuitionCost = row["TUITIONFEE_IN"];

    if (collegeName && collegeName.toLowerCase() === schoolName.toLowerCase()) {
      collegeName = collegeName.toLowerCase();
      degreeLength = parseInt(degreeLength);
      tuitionCost = parseFloat(tuitionCost);

      if (!isNaN(degreeLength) && !isNaN(tuitionCost)) {
        schoolInfo.push({
          collegeName: collegeName,
          degreeLength: degreeLength,
          tuitionCost: tuitionCost
        });
      }
    }
  });
  return schoolInfo;
}

// Function to display school information in the console
function displaySchoolInformation(schoolInfo) {
  for (var i = 0; i < schoolInfo.length; i++) { //never runs
    var collegeName = schoolInfo[i].collegeName;
    var degreeLength = schoolInfo[i].degreeLength;
    var tuitionCost = schoolInfo[i].tuitionCost;

    console.log("College Name: " + collegeName);
    console.log("Degree Length: " + degreeLength);
    console.log("Tuition Cost: $" + tuitionCost.toFixed(2));
    console.log("------------------------------");
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.3.0/papaparse.min.js"></script>

<label for="schoolName">Enter School Name:</label>
<input type="text" id="schoolName" />
<button onclick="getSchoolInformation()">Get Information</button>

I have tried so many variations of my code but none seem to work and it is slowly turning more into spaghetti code.

Express.Js response.download not reacting to client-side abort

When aborting a request to an express.js application, that is currently responding with response.download, the express.js application waits for a timeout rather than canceling the request (or throwing an error, or doing anything).

The provided callback function is also not called until this timeout is reached.

Client Code

const abortController = new AbortController();
const request = axios.get('/file', {
  signal: controller.signal,
  responseType: 'arraybuffer'
});
abortController.abort();

Express.js

const app = Express();
app.get('/file', (req, res) => {
  res.download(path, name, (err) => {
    if (err) {
      res.status(500).send();
    }
  });
});

Browser Differences

In Firefox, resending the request from the client will result in a wait until the aborted request timed out. If the file is above a certain threshold in size, the request gets canceled immediately and no wait time before the next request starts (this is the desired behaviour).

In Chrome, resending the request will continue the previous aborted request.
This also holds true for Opera and seems to be a Chromium feature.

I don’t want any of this behaviour. I want the request to be canceled immediately, and after requesting again to be started from the beginning.

I know, that the above code will error, because res.status(500).send() cannot resend headers. But my concern is the timeout / not immediate cancel of requests.

map() JSON and return data [duplicate]

I might need your help..
I am fetching from apiUrl some JSON data. The code below delivers the result that all “name” from liste.json are returned.
But I would like to add an addtitional requirement, where only “name” will be returned, when “categorie” === “Tool”

Thanks, Konstantin

test.js

import { useState, useEffect } from "react";

export default function ExampleCheckbox() {
  const [showPosts, setshowPosts] = useState();
  const apiUrl = "/api/liste";
  let displayData;

  function pullJson() {
    fetch(apiUrl)
      .then((response) => response.json())
      .then((responseData) => {
        displayData = responseData.map(function (liste) {
          return <p key={liste.id}>{liste.name}</p>;
        });
      });
  }

  useEffect(() => {
    pullJson();
  }, []);


  return (
      <div>
        <main>
          <p>Test</p>
          {showPosts}
        </main>
      </div>
  );
}

liste.json

  {
    "name": "Werkzeugkoffer",
    "categorie": "Tool",
    "dauer": "Woche",
    "verkehrsmittel": "Auto",
    "region": "Italien",
    "gruppengre": "groß",
    "unterkunft": "Fewo",
    "radmitnahme": "Ja"
  },
  {
    "name": "Multitool",
    "categorie": "Car",
    "dauer": "Kurztrip",
    "verkehrsmittel": "Flugzeug",
    "region": "Italien",
    "gruppengre": "klein",
    "unterkunft": "Hotel",
    "radmitnahme": "Nein"
  }

Apps Script, Using jquery DataTables With Additional Script

I am attempting to write a script that pulls data from a google sheet and posts to an html table. If I strictly do the code.gs with the required doGet function, and only add html/javascript via a scriplet (i.e., ) for the table ONLY, it works fine. However, if I try to add any additional functions it stops working. However, I wanted to add some additional functions. I was trying to add a function that adds the current month and day at the top of the page. I’ve tested this code for the month/day completely separate from the the table, and it too works fine. But when I try to add it to the Javascript file in combination with the code for the table, I get this error:

**
SyntaxError: Unexpected token ‘=’ (line 2, file “Code”)**

I thought perhaps it was a problem with which code was loading first, and that the it was calling for the necessary files before they loaded. I attempted “document.ready” and window.onload, but neither fixed.

I think the problem is with the scriplet and when it tries to include the Javascript. I’ve tried moving the scriplet in the code as well, but that hasn’t solved the problem.

Here is the code. I appreciate any help in advance.

**code.gs**
   function doGet(){
   return HtmlService.createTemplateFromFile('Index').evaluate();
  }
 
   function getData(){
      
      var spreadSheetId = "1-CkmSe_dDNZJNWTTz6EfqOiFjSkP7ZdiLT3XeyBSH60"; 
      var dataRange = "Data!A2:C";
      var range = Sheets.Spreadsheets.Values.get(spreadSheetId,dataRange);
      var values = range.values;
      return values;
   }

   function include(filename) {
   return HtmlService.createHtmlOutputFromFile(filename).getContent();
   }

**Index.html**
    <!DOCTYPE html>
    <html>
    <head>
    <base target="_top">
  
    <script src="https://code.jquery.com/jquery-3.5.1.js"></script>
    <script src="https://cdn.datatables.net/1.10.23/js/jquery.dataTables.min.js"></script>
    <script src="https://cdn.datatables.net/1.10.23/js/dataTables.bootstrap4.min.js"></script>
    <link rel="stylesheet" type="text/css"    
     href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.2/css/bootstrap.css">
    <link rel="stylesheet" type="text/css"   
     href="https://cdn.datatables.net/1.10.23/css/dataTables.bootstrap4.min.css">
  
    <?!= include('StyleSheet'); ?>

     </head>
 
 <body>
  <div class="wrapper">
   
    <div class="datetime">
      <div class="date">
        Entry For:  
        <span id="dayname">Day</span>,
        <span id="month">Month</span>
        <span id="daynum">00</span>,
        <span id="year">Year</span>
      </div>
          </div>
    <div class="container">
      
      <br>
      <div class="row">
        <table id="data-table" class="table table-striped table-sm table-hover table-bordered">
        </table>

      </div>
    </div>  

  </body>
    <?! = include('JavaScript'); ?>
  </html>
  
**JavaScript.html**
<script>
    
  google.script.run.withSuccessHandler(showData).getData();
 
  function showData(dataArray){
    $(document).ready(function(){
      $('#data-table').DataTable({
        data: dataArray,
  
          columns: [
          {"title":"Date "},
          {"title":"Year"},
          {"title":"Event"},
      ]
      });
    });
  }

  $(document).ready(function(){
  function updateClock(){
      var now = new Date();
      var dname = now.getDay(),
          mo = now.getMonth(),
          dnum = now.getDate(),
          yr = now.getFullYear(),
          hou = now.getHours(),
          min = now.getMinutes(),
          sec = now.getSeconds(),
          pe = "AM";

          if(hou >= 12){
            pe = "PM";
          }
          if(hou == 0){
            hou = 12;
          }
          if(hou > 12){
            hou = hou - 12;
          }

          Number.prototype.pad = function(digits){
            for(var n = this.toString(); n.length < digits; n = 0 + n);
            return n;
          }

          var months = ["January", "February", "March", "April", "May", "June", "July",     
          "August", "September", "October", "November", "December"];
          
          var week = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", 
          "Saturday"];
          
           var ids = ["dayname", "month", "daynum", "year", "hour", "minutes", "seconds", 
           "period"];
          
           var values = [week[dname], months[mo], dnum.pad(2), yr, hou.pad(2), min.pad(2),  
           sec.pad(2), pe];
          
           for(var i = 0; i < ids.length; i++)
           document.getElementById(ids[i]).firstChild.nodeValue = values[i];
    }
  
    $(document).ready(function(){
       function initClock(){
       updateClock();
       window.setInterval("updateClock()", 1);
      }
     });
  });
`
</script>

Supabase Email Redirect

How can I make dynamic redirect link in confirmation email after user create account?

For example:

If some user gets to the web site using link www.website.com/project/1 or /project/2 etc.
And it doesn’t have account and needs to make one. After sign up, user needs to confirm account via email, after confirmation user gets redirected to www.website.com/ in a new tab.

How can I setup email dynamic redirect link to redirect the user to specific nested route?

How to Prevent Links from Showing Absolute URL in Document Title

I’ve been trying to stop the window title from flashing the absolute URL of links when clicked.

Here is the link.

enter image description here

At the top of the main index I’m setting the title. I’m using a timeout to set the full page title one second after $(document).ready() with a timeout.

enter image description here

Whenever I click the link it flashes the full URL for the link. In the video I click the link multiple times to show the behavior.

Streamable Video Showing Behavior

How to access two fields inside a subcollection inside EACH userID document in Firestore Firebase [duplicate]

I am trying to access the fields lat: “” and lng: “” that are saved inside a subcollection “userLocations” inside that userID document in the main collection “locations”. Here is a screenshot of what it looks like.

As you can see I have a userID that saves lats and lngs.
enter image description here

enter image description here

I CAN access all lat, and lng of each document inside userLocation collection but for ONE USER ONLY if and only if I copy and paste that userID.

Here is the code that I used to access only one user’s lat and lng:

useEffect(() => {
    const fetch = async () => {
      try {
        const mainCollectionLocations = collection(db, "locations");
        const userDocRef = doc(
          mainCollectionLocations,
          "LhCNVWJt5bdI0slgBPnbmESrwJh1" //PROBLEM I need to go through all documents available
        );
        const userLocationSubCollection = collection(
          userDocRef,
          "userLocation"
        );

        onSnapshot(userLocationSubCollection, (querySnapshot) => {
          let loc = querySnapshot.docs.map((doc) => ({
            lat: doc.data().lat,
            lng: doc.data().lng,
          }));
          setLocations(loc);
        });
      } catch (error) {
        console.log(error);
      }
    };
    fetch();
  }, []);

BUT I CANNOT iterate over EACH user getting each user’s lat and lng. Here is the current code I’m using in order to try to accomplish this:

useEffect(() => {
    const fetch = async () => {
      try {
        const mainCollectionLocations = collection(db, "locations");
        const querySnapshot = await getDocs(mainCollectionLocations);

        let allLocations = [];

        querySnapshot.forEach(async (doc) => {
          console.log("start for loop");
          console.log("doc-ref:", doc.ref);
          const userLocationSubCollection = collection(doc.ref, "userLocation");
          console.log("userLocationSubCollection: ", userLocationSubCollection);
          // const subQuerySnapshot = await getDocs(userLocationSubCollection);

          onSnapshot(userLocationSubCollection, (querySnapshot) => {
            console.log("querySnapShot: ", querySnapshot);

            let loc = querySnapshot.docs.filter((doc) => ({
              lat: doc.data().lat,
              lng: doc.data().lng,
            }));
            console.log("locationsLOc: ", loc);
            allLocations = [...allLocations, ...loc];
            setLocations(allLocations);
          });
        });
      } catch (error) {
        console.log(error);
      }
    };

    fetch();
  }, [])

PLEASE HELP; I’ve been stuck for a week already trying to get this data.

TypeScript type error when using generic callbacks for different event types

I’m trying to make some kind of a generic event handler, I want to be able to specify the event key like “pointermove” and typescript to infer the event type in this case PointerEvent, but I get an error when using more than one event.

here’s a minimal repoducible example

export type ContainedEvent< K extends keyof HTMLElementEventMap> = {
    eventName: K;
    callback: ContainedEventCallback< K>;
  
};
export type ContainedEventCallback< K extends keyof HTMLElementEventMap> = (
    event: HTMLElementEventMap[K],

) => void;
export default function useContainedMultiplePhaseEvent<
    K extends keyof HTMLElementEventMap = keyof HTMLElementEventMap
>(
    el: HTMLElement ,
    events: ContainedEvent<K>[],
) {
    
  for (const e of events) {
      el.addEventListener(e.eventName, (ev) => e.callback(ev));
  }     
}
const div = document.createElement("div");
 const doA: ContainedEventCallback<"pointerdown"> = (
        e,
    ) => {
      console.log("A")
    };
 const doB: ContainedEventCallback<"pointermove"> = (
        e,
    ) => {
      console.log("B")
    };

useContainedMultiplePhaseEvent(div,
        [
            {
                eventName: "pointerdown",
                callback: doA,
            },
            {
                eventName: "pointermove",
                callback: doB,
            }
        ]
    );

React filtering object from an array not working, better options available?

Beginner here. I’m trying to make a character builder, where you have two lists of good and bad traits you can click on and move into a list of selected traits. My overall goal is that when I click on a trait, the trait is removed from it’s initial list and moved to the selected list. From there, you can click on the trait in the selected list to return it back to it’s initial list in it’s initial index. From the selected list, I use data from those objects and display it, for example a ‘points’ counter to track how many traits you can still choose.

So far I can click on a trait and move it to the selected state array, and click on it in the selected list to remove it by filter. However this way currently the trait is not removed from it’s initial list, allowing it to be selected multiple times which is not what I want. And from the selected list, all it does is filter it out of the array, not return it to it’s original array in it’s original index which it will have to be able to do when I successfully remove it from the initial list. I’m not sure the best way to go about this. I tried to use the same function that I used to remove the object from the selected list, but it’s not working and I’m not sure why.

If you’d like to see what I have so far: GH Pages Preview

And here’s my code:

  // initializing selected traits as empty
  const [selectedTraits, setSelectedTraits] = useState([])

  // List of selected traits
  const selectedlist = selectedTraits.map((item) => {
    return  <div key={item.name} onClick={() => handleChosenClick(item)} className={`selected-item ${item.value > 0 ? 'red' : 'green'}`}>
    <div className="selected-item-icon"><img src={item.icon} alt="" /></div>
    <div className="selected-item-name">{item.name}</div>
    <div className="selected-item-points">{`${item.value > 0 ? "+" : ""}`}{item.value}</div>
  </div>
  })

 // Mapping over three data sheets for the traits values/names/etc.
  const jobs = occupationsData.map((item) => {
    return <Occupation key={item.name}{...item} onClick={() => handleJobChange(item)} className={`occupation-item ${active == item && 'highlight'}` }/>;
  });

  const [goodtraits, setGoodTraits] = useState(goodtraitsData.map((item) => {
    return <Goodtrait key={item.name} {...item} onClick={() => handleTraitClickGood(item)} />;
  }));

  const [badtraits, setBadTraits] = useState(badtraitsData.map((item) => {
    return <Badtrait key={item.name} {...item} onClick={() => handleTraitClickBad(item)} />;
  }));

  //This you can ignore, for job selection which is working as intended.
  const handleJobChange = (item) => {
    setStartValue(item.value)
    setActive(item)
  }


  //function that moves whatever object is clicked into the selected traits
  const handleTraitClickGood = (item) => {
    setSelectedTraits(prevState => [...prevState, item ] )

    // This function isn't working as intended, not removing.
    setGoodTraits(prevTraits => {
      return prevTraits.filter(prev => prev !== item)
    })
  }
  const handleTraitClickBad = (item) => {
    setSelectedTraits(prevState => [...prevState, item ] )
  }



  //Function that removes an object on click in the selected list
  const handleChosenClick = (item) => {
    setSelectedTraits(prevTraits => {
      return prevTraits.filter(prev => prev !== item)
    })
  }

If this doesn’t show enough, I apologize and here’s a link to the GH repo just in case but hopefully you don’t have to view this: GH Repo

I tried using the same exact function that removes an object from the selected list:

  const handleChosenClick = (item) => {
    setSelectedTraits(prevTraits => {
      return prevTraits.filter(prev => prev !== item)
    })
  }

In my function that moves the object to the selected list like this:

  const handleTraitClickGood = (item) => {
    setSelectedTraits(prevState => [...prevState, item ] )
    setGoodTraits(prevTraits => {
      return prevTraits.filter(prev => prev !== item)
    })
  }

However that doesn’t work. Any reason why this isn’t working or are there just better options to meet my goal? Feeling a little overwhelmed by this one as I’m pretty new. Eventually I want to try to make it that some traits are mutually exclusive, for example cannot take ‘speed demon’ if you have ‘sunday driver’ or vice versa. That issue is for another day though. Thank you!

get data with attr from modal window

I have a modal window for uploading files, it is used in this piece of code

<a class="btn btn-default btn-md btnUpload" data-toggle="modal" href="#" data-target="#modal-upload">
  <i class="fa fa-cloud-upload"></i> Upload
</a>

<div class="dz_params_item"
  data-entity_id="<?=$item->request_id?>"
  data-action_url="/files/upload/<?=$item->request_id?>"
></div>

The window itself is a little lower on the page

<div class="modal fade" id="modal-upload" tabindex="-1" role="dialog" aria-hidden="true">
    ...
</div>

To open it and upload files, I use javascript

I have shortened the code a little everywhere so that there is no confusion, but if something is missing, then I will add

(function( $ ){
    $.dispatcherFiles = {
        $filesDropzone: null,
        $parallelUploads: 100,
        $maxFiles: 10,
        $modalId: '#modal-upload',
        $files: [],

        cacheDom: function(){
            this.$body = $('body');
        },

        functions: {
            openUploadFilesModal: function (e) {
                let that = this;

                let dropzoneParamEl = $(e.currentTarget).closest('.field_form').find('.dz_params_item');
                let action_url = $(dropzoneParamEl).attr('data-action_url');          

                $(this.$modalId + ' #filesDropzone').addClass('dropzone');

                this.$filesDropzone = new Dropzone(that.$modalId + ' .dropzone', {
                    url: action_url,
                    uploadMultiple: true,
                    parallelUploads: that.$parallelUploads,
                    maxFiles: that.$maxFiles,
                });
            },

            hideUploadFilesModal: function (e) {
                this.$filesDropzone.destroy();
            },
        },

        events: function(){
            this.$body.on('shown.bs.modal', this.$modalId, this.functions.openUploadFilesModal.bind(this));
            this.$body.on('hidden.bs.modal', this.$modalId, this.functions.hideUploadFilesModal.bind(this));
        },

        init: function () {
            this.cacheDom();
            this.events();
        }
    };

    $.dispatcherFiles.init();

})(jQuery);

So, in this example, the main problem I have is to get data-action_url from the html page

I am trying to do it with these lines

let dropzoneParamEl = $(e.currentTarget).closest('.field_form').find('.dz_params_item');
let action_url = $(dropzoneParamEl).attr('data-action_url'); 

But in the end my variable is undefined, even though the previous variable dropzoneParamEl is defined and I get the DOM of that element

And this is all just because my function is triggered when the window is opened shown.bs.modal

If I receive data via click, then I can get the attribute I need

But as far as I understand, I can’t use the click modal for opening, because then nothing will work at all

How can I get the value of data-action_url when opening the modal in this case? I’ll clarify right away that I can have several such upload buttons, and I need the value of exactly the element that was clicked

Proxy object in Vue 3 will not let me access data

I have an app in Vue 3 where I make a call to the back end of my code to get data. The data is returned nested in JSON arrays and objects, and I then assign the data to a property in my component. I am trying to assign the JSON object to data in my parent component and then pass the data as a prop to my child component. However, every time I do this, the data keeps getting assigned as Proxy(Object) which seems to make it more difficult to access the data in the child component.

My code is as follows:

/* Parent Component */
<template>
  <div>
    <child-component :myData="rawData"></child-component>
  </div>
</template>
<script>
  import ChildComponent from '../components/ChildComponent.vue';
  export default {
    components: {
      ChildComponent
    },
    data() {
      return {
        rawData: {}
      }
    },
    methods: {
      getData() {
        fetch('/my-endpoint, { method: 'GET' })
          .then((response) => response.json())
          .then((data) => {
            this.rawData = data[0].data[0];
          })
      }
    }
  }
</script>

/* Child Component */
<script>
  props: {
    myData: {
      type: Object
    }
  },
  data() {
    displayData: myData
  }
</script>

When I try to console.log() any of the data that holds my fetch call (rawData, myData or displayData) I’m seeing Proxy (Object) in the console, and I can’t access any of the data in the object. I see the data in the Vue dev tools plugin, but I cannot use any of it. Even trying to do something like console.log(displayData.id) or console.log(displayData.description), which are properties I know exist in these objects and properties I see in the Vue dev tools plugin, I just get undefined in the console.

What I have tried to do:

  • import { isProxy, toRaw } from 'vue'; in both the parent and child components and then if(isProxy(myData)) toRaw(myData); (and the same with rawData and displayData). This does not work and the objects are still proxies.

  • JSON.parse(JSON.stringify(myData)); in both the parent and child components (and the same with rawData and displayData). This does not work and the objects are still proxies.

  • Out of desperation, changing the prop declaration in the child component to just props: { myData: Object } and even just props: ['myData']. This does not work and the objects are still proxies.

How can I access the data in these objects? I’d prefer for them to not be proxy objects, but if I cannot change them then how do I get data if they need to stay as proxies?