The user input in my html form is not being delivered to my google sheet

I am running this program in app script and I am not sure where the problem is. When I try to fill up the sign up form and submit it, none of the values that I enter gets into my google spread sheet.

Here’s the html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Login & Registration Form</title>
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap">
  <style>
  /* Import Google font - Poppins */
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap');
*{
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Poppins', sans-serif;
}
body{
  min-height: 100vh;
  width: 100%;
  background: #009579;
}
.container{
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%,-50%);
  max-width: 430px;
  width: 100%;
  background: #fff;
  border-radius: 7px;
  box-shadow: 0 5px 10px rgba(0,0,0,0.3);
}
.container .registration{
  display: none;
}
#check:checked ~ .registration{
  display: block;
}
#check:checked ~ .login{
  display: none;
}
#check{
  display: none;
}
.container .form{
  padding: 2rem;
}
.form header{
  font-size: 2rem;
  font-weight: 500;
  text-align: center;
  margin-bottom: 1.5rem;
}
 .form input{
   height: 60px;
   width: 100%;
   padding: 0 15px;
   font-size: 17px;
   margin-bottom: 1.3rem;
   border: 1px solid #ddd;
   border-radius: 6px;
   outline: none;
 }
 .form input:focus{
   box-shadow: 0 1px 0 rgba(0,0,0,0.2);
 }
.form a{
  font-size: 16px;
  color: #009579;
  text-decoration: none;
}
.form a:hover{
  text-decoration: underline;
}
.form input.button{
  color: #fff;
  background: #009579;
  font-size: 1.2rem;
  font-weight: 500;
  letter-spacing: 1px;
  margin-top: 1.7rem;
  cursor: pointer;
  transition: 0.4s;
}
.form input.button:hover{
  background: #006653;
}
.signup{
  font-size: 17px;
  text-align: center;
}
.signup label{
  color: #009579;
  cursor: pointer;
}
.signup label:hover{
  text-decoration: underline;
}
  </style>
</head>
<body>
  <div class="container">
    <input type="checkbox" id="check">
    <div class="login form">
      <header>Login</header>
      <form id="loginForm">
        <input type="email" placeholder="Enter your email" id="loginEmail">
        <input type="password" placeholder="Enter your password" id="loginPassword">
        <input type="button" class="button" value="Login" id="loginButton">
      </form>
      <div class="signup">
        <span class="signup">Don't have an account?
         <label for="check">Signup</label>
        </span>
      </div>
    </div>
    <div class="registration form">
      <header>Create an account</header>

<form id="signupForm">
  <input type="text" placeholder="Enter your full name" id="signupName">
  <input type="text" placeholder="Enter your email" id="signupEmail">
  <label for="position">Position:</label>
  <select name="Position" id="position">
    <option value="student">Student</option>
    <option value="teacher">Teacher</option>
  </select> <br>
  <label for="strand">Strand:</label><br>
  <select name="Strand" id="Strand">
    <option value="">--Please select your strand below:--</option>
    <option value="abm">ABM</option>
    <option value="ESTEM-C">ESTEM-C</option>
    <option value="ESTEM-E">ESTEM-E</option>
    <option value="ESTEM-H">ESTEM-H</option>
    <option value="HUMSS">HUMSS</option>
    <option value="TVL">TVL</option>
  </select>
  <input type="text" placeholder="Section" id="Section">
  <input type="password" placeholder="Create a password" id="signupPassword">
  <input type="password" placeholder="Confirm your password" id="confirmPassword">
  <input type="button" class="button" value="Signup" id="signupButton">
</form>

      <div class="signup">
        <span class="signup">Already have an account?
         <label for="check">Login</label>
        </span>
      </div>
    </div>
  </div>
  
<script>
  function submitSUForm() {
    var name = document.getElementById("signupName").value;
    var email = document.getElementById("signupEmail").value;
    var position = document.getElementById("Position").value;
    var strand = document.getElementById("Strand").value;
    var email = document.getElementById("Section").value;
    var password = document.getElementById("signupPassword").value;
    var confirmPassword = document.getElementById("confirmPassword").value;
    if (password !== confirmPassword) {
      alert("Passwords do not match.");
      return; // Stop further execution
    }
  
    google.script.run.signupUser(mame, email, position, strand, section, password);
  }

  document.addEventListener('DOMContentLoaded', function() {
    const loginButton = document.getElementById('loginButton');
    const signupButton = document.getElementById('signupButton');

    loginButton.addEventListener('click', function() {
      console.log("Login button clicked");
      alert("Login button clicked"); // For testing purposes
      const email = document.getElementById('loginEmail').value;
      const password = document.getElementById('loginPassword').value;

      google.script.run.withSuccessHandler(onLoginSuccess).loginUser(email, password);
    });

    signupButton.addEventListener('click', function() {
      console.log("Signup button clicked");
      alert("Signup button clicked"); // For testing purposes
      submitForm(); // Call the submitForm function here

      // Remaining signup button logic
    });

    function onLoginSuccess(result) {
      if (result) {
        // Redirect to the specified URL upon successful login
        window.location.href = 'https://www.astoecompany.com';
      } else {
        alert('Login failed');
      }
    }

    function onSignupSuccess(result) {
      if (result) {
        alert('Signup successful');
        window.location.href = 'https://www.astoecompany.com';
      } else {
        alert('Signup failed');
      }
    }
  });


</script>

</body>
</html>

and here’s the gs code:

function doGet() {
  return HtmlService.createHtmlOutputFromFile('dbpage');
}

function loginUser(loginEmail, loginPassword) {
  var sheet = SpreadsheetApp.openById('***').getSheetByName('Login');
  var data = sheet.getDataRange().getValues();

  for (var i = 1; i < data.length; i++) {
    if (data[i][1] === email && data[i][5] === password) {
  return false; 
    }
}
}

function signupUser(signupName, signupEmail, position, strand, section, password, confirmPassword) {
  if (signupName === '' || signupEmail === '' || position === '' || strand === '' || section === '' || password === '' || confirmPassword === '') {
    return false; // Empty fields are not allowed
  }

  var sheet = SpreadsheetApp.openById('**').getSheetByName('Login');
  var data = sheet.getDataRange().getValues();

  for (var i = 1; i < data.length; i++) {
    if (data[i][1] === email) {
      return false; 
    }
  }

  if (password === confirmPassword) {
    sheet.appendRow([signupName, signupEmail, position, strand, section, password]); 
    return true; 
  } else {
    return false;
  }
} 

Is there any problem with the eventlistener that I added? Amateur here. Thank you so much.

Retrieving maximum element height in a row in bootstrap

I’m working with the al-folio Jekyll template which uses Bootstrap 5 and I’m trying to customize the behavior of the projects page in particular. Right now, the default behavior is to create cards for each project that can be different heights depending on text length, image dimensions, etc. Right now this results in this cards that look like this: current behavior

I want to change this so that the cards in each row are the same height by setting each card to the height of the tallest card in its row. However, I’m not sure how to find the element that has the maximum height in the current row, and allow it to update if the user resizes the website.

What I want the output to look like is something like this Desired behavior

I modified the generated HTML template code (available here) and got a result that matches what I want. I manually inspected the elements and found the grid item that had the maximum height. I then changed all <div class="grid-item"> to have this same height as a style element and then changed the <div class="card hoverable"> to <div class="card hoverable h-100"> to force the card to take up the whole space. This resulted in the picture above.

My question is, how would I automate this process so that the cards are generated to have the same height as the other cards in their row, along with automatic resizing when the amount of items in the row changes?

The other part of the al-folio that might be useful is the projects page here

Cant retrieve headers from network source type “Fetch/Redirect”

So I’m working on a flask app that runs a javascript function upon hitting a button. This calls a fetch request to an app route, that then calls a cloudfront function. This calculates some data, then returns a custom header with the calculation result. The issue is I’m not able to use the fetch request to actually retrieve the data, as it’s returning headers from another response and I’m not sure why. This is my javascript code im using:

function fibonacci() {
                        var n = document.getElementById('fibCFInput').value;
                        console.log("testing.." + n)


                        console.log("cloudfront test...")
                        fetch("https://<cloud url>/fibonacci/" + n)
                                .then(response => {

                                response.headers.forEach((value, name) => {
                                console.log(`${name}: ${value}`);
                                });

                                const fibval = response.headers.get("fibval");
                                console.log(`fibval value: ${fibval}`);
                        })
                        .catch(err => {
                        console.error('Error fetching data:', err);
                        });

                        console.log("fetch break")

                        console.log("fibonacci test")
                        fetch('/fibonacci/' + n, {redirect: "follow"})
                        .then(response => {
                                response.headers.forEach((value,name)=>{
                                console.log(`${name}: ${value}`);
                                });
                                const fibval = response.headers.get("Fibval");
                                console.log(fibval)
                        })
                        .catch(err => {
                        console.error('Error fetching data:', err);
                        });
                        }

I have two test cases to try requesting straight from cloudfront, and another going through the app route. interestingly enough, the cloudfront fetch returns no headers at all.

I’ve tried adding different CORS settings as I thought that might be the issue, but with CORS fully enabled on the domain and the cloudfront function returning Access-control-allow-origin: * (for testing purposes), I’m not sure what may be the issue other than the redirect mechanism.

Why can’t I get a result from the Office.context.mailbox.item.to.getAsync function?

Writing an Outlook Add-In and trying to get the recipients from message compose mode using the Office Javascript API. I can see successful results in the console logs but I only get undefined as a result.

I created a promise:

function createPromise() {
    return new Office.Promise(function (resolve, reject) {
        try {
            Office.context.mailbox.item.to.getAsync(
                function (result) {
                    console.log("in result fxn");
                    if (result.status === Office.AsyncResultStatus.Succeeded) {
                        console.log("success");
                        console.log(result.value);    //console shows accurate results
                        resolve(result.value);
                    } else {
                        console.log("failed");
                        console.error(result.error);
                        resolve(result.error);
                    }
                }
            );
        }
        catch (error) {
            console.log("failed promise");
            reject("failed to create promise");
        }
    });
}

And then called the promise using await:

async function getTo() {
    return await createPromise();
}

But the function that calls getTo is logging that the promise is pending.

function () {
    var to = getTo();
    var nm = {};
    if (to) {
        console.log("we are inside if to and to is: ");
        console.log(to);              //this logs PromiseĀ {<pending>}
        if (to.length > 0) {
            nm[eml] = to[0].emailAddress;
            nm[first] = to[0].givenName;
            nm[last] = to[0].surname;
            nm[full] = to[0].displayName;
        }
    }
    return nm;
}

I’ve tried several approaches and read many Microsoft docs (hoping what I’m reading isn’t out of date) and still no luck. TIA.

why when i do logout the cookie is not destroyed?

I have this logout controller it should destroy the cookie it worked in postman fine but in client side when i dispatched and hit logout button the token is still in the network storage and i can make requests with it also when i reload the page user get logged in again

authController

const logoutUser =  catchAsync(async (req, res) => {
  // Clear the token cookie by setting it to null and expiring it immediately
  res.cookie("token", null, {
    expires: new Date(Date.now()),
    httpOnly: true,
  });

  res.status(200).json({
    success: true,
    message: "Logged Out",
  });

  res.status(200).json({ success: true, message: "Logged Out" });
});

userAction

// Logout User Action
export const logoutUser = () => async (dispatch) => {
  try {
    await axios.get(`${API_URL}/auth/logout`);
    dispatch({ type: LOGOUT_USER_SUCCESS });
  } catch (error) {
    dispatch({ type: LOGOUT_USER_FAIL, payload: error.response.data.message });
  }
};

logout

const { isAuthenticated } = useSelector((state) => state.auth);
  const handleLogout = () => {
    dispatch(logoutUser()); 
    navigate('/')// Dispatch the logout action when the logout button is clicked
  };

i tried removing the cookie from the application storage by setting it to null and expiring it using js but this only worked in localhost because he i deployed the project on vercel the cookie is not shown in the cookie storage it only sent with the request and can only access it from the network pannel so there is no way to manage it from clientside

html + java script ! need help to understand why am getting (invalid username or password)

am trying to do a homework in web dev and there is a part i need help with because it should work but i have no idea why its not
the username in the test is doc1 and the password is pass1

function docauth(event)
{
    var DU = "doc1";
    var DP = "pass1";
    if(document.getElementById("docuser") === DU && 
       document.getElementById("docpass") === DP)
    {
        alert("login success!");
    } 
    else 
    {             
        alert("invalid username or password");
    }
}
<head>
    <title>Doctor page</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
    <fieldset>
        <legend>doctor login</legend>
        <form id="docLOG" onsubmit="docauth(event)">
        <label for="docuser">Username:</label>
        <input type="text" id="docuser" name="docuser" required><br><br>
        <label for="docpass">Password:</label>
        <input type="text" id="docpass" name="docpass" required><br><br>
        <input type="submit" value="Login">
        </form>
    </fieldset> 
</body>
</html>

it should say after entering doc1 and pass1 (login success!)
what i tried is changing the var DU and var DP and even the if statement from document.getElementById to form.element and adding var form = document.getElementById
but nothing worked

Using Javascript to change a div’s text depending on what button is pressed

I’m sure this is easier than what I’m making it out to be, but – I need to change a paragraph depending on what button is pressed. I want to use the same buttons as the ones I click on to change the main-img.

To reiterate, my goal is: if I click on a button, for example, Executioner, I want the image to change to the executioner image (like i already have set up) and subclassDesc to change to the appropriate subclass information that I need.

This is the HTML (I dont think the mainbox information is super relevant for this question so ignore that if you will – I just need to know how to properly change the stated information.)

    <div id="imgContain">
        <img id="main-img" src="default.png">
    </div>
    <div id="mainBox">
        <div class="tabMain">
            <button class="tablinks active" onclick="mainTab(event, 'Overview')" id="defaultOpen">Overview</button>
            <button class="tablinks" onclick="mainTab(event, 'Subclasses')">Subclasses</button>
            <button class="tablinks" onclick="mainTab(event, 'Spells')">Spells</button>
        </div>

        <div id="Overview" class="tabcontentMain">
            <h3>Overview</h3>
            <p>blablabla.</p>
            <p id="subclassDesc">
                <h3>Insert Subclass Here</h3>
                insert subclass info here
            </p>    
        </div>
        <div id="Subclasses" class="tabcontentMain">
            <h3>Subclasses</h3>
            <p>
                <button id="subclass" onclick="changeImg('./assets/010.-Arbalest.png')">Arbalest</button>
                <br><br>
                <button id="subclass" onclick="changeImg('./assets/011.-Dreadnaught.png')">Dreadnought</button>
                <br><br>
                <button id="subclass" onclick="changeImg('./assets/012.-Executioner.png')">Executioner</button>
                <br><br>
                <button id="subclass" onclick="changeImg('./assets/013.-Lancer.png')">Lancer</button>
                <br><br>
                <button id="subclass" onclick="changeImg('./assets/014.-Titan.png')">Titan</button>
            </p>
        </div>

This is the Javascript


function changeImg(uri) {
    var image = document.getElementById('main-img');

    image.src = uri;
}

function insertTxt() {
    const button = document.getElementById('subclass');
    const p = document.getElementById('subclassDesc');

//what do i do here? Do i even need this?//
}

I just need answers, I’m very new to Javascript and don’t really fully understand everything. I don’t even know what to do with the function.
Do i need if else statements? How do I do all this on the same function with different parameters?

Customizable centered box grid in html/css?

This is what my site currently looks like:

enter image description here

I am trying to make the boxes a fixed square width and want them to be always centered horizontally and vertically. either like

[] [] [] []

or

[] []

[] []

currently they slope to the side:

enter image description here

Is there a way to make this work without javascript?

current html:

            <div class="grid-item">
                <a href="https://download.tails.net/tails/stable/tails-amd64-6.0/tails-amd64-6.0.img">
                    <img class="app-image" src="assets/tails.png" height="100px">
                    <div class="app-title">Tails 6</div>
                    <div class="app-description">Amnesic live system.</div>
                </a>
            </div>

current css:

html {
  height: 100%;
  background-color: #0f0f0f;
  margin: 0;
}

.body-default {
  color: #fff;
  display: flex;
  height: 100%;
  justify-content: center ;
  align-items: center;
  margin: 0;
  font-family: sans-serif;
}

.grid-container {
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  grid-auto-rows: 200px;
  grid-gap: 20px;
  width: 100%;
  justify-content: center;
  align-items: center;
}

.grid-item {
  border: 2px solid #4e4e4e;
  padding: 5px;
  text-align: center;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: center;
  border-radius: 12.5px;
  background-color: #242424;
  transition: transform 0.2s cubic-bezier(0,.75,.25,1);
  transform-origin: center;
  backface-visibility: hidden;
  transform: translateZ(0);
  -webkit-font-smoothing: subpixel-antialiased;
}

.app-title {
  font-weight: bold;
  font-size:15px;
  margin-bottom: 10px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.app-description {
  flex-grow: 1;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: #808080;
}

.app-image {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: 100px;
  margin: auto;
  padding: 10px;
}

.grid-item:hover {
  transform: scale(1.05);
}

.centered-box {
  text-align: center;
  margin: 0 auto;
  width: 50%;
  padding: 20px;
}

How do I call a remote script in a Chrome Extension that only interacts with the extension popup/sidebar

I am attempting to load a remote js file into my popup/sidebar using the following code

const newScript = document.createElement('script')
newScript.src = 'https://mycompany.com/dist/myscript.js'
const myTarget = document.getElementById('offcanvas')
myTarget.appendChild(newScript)

Which results in the following errors

Refused to load the script ‘https://mycompany.com/dist/myscript.js’ because it violates the following Content Security Policy directive: “script-src ‘self'”. Note that ‘script-src-elem’ was not explicitly set, so ‘script-src’ is used as a fallback.

Refused to load the script ‘https://mycompany.com/dist/myscript.j’ because it violates the following Content Security Policy directive: “script-src ‘self’ ‘wasm-unsafe-eval’ ‘inline-speculation-rules’ http://localhost:* http://127.0.0.1:*”. Note that ‘script-src-elem’ was not explicitly set, so ‘script-src’ is used as a fallback.

If I instead download the js file and include it in the extension bundle like this though it works as expected

const newScript = document.createElement('script')
newScript.src = 'myscript.js'
const myTarget = document.getElementById('offcanvas')
myTarget.appendChild(newScript)

I prefer to call the remote file so the latest version is always being referenced, but it’s not clear to me how to resolve this.

Can someone point me in the right direction please.

Map numbered values into separate objects

I’m attempting to map an array from this:

[
  {
    "person_1": "jim",
    "person_2": "bob"
  }
]

to this:

people: [
  {
    "person": "jim"
  },
  {
    "person": "bob"
  }
]

Right now, my map method is to select each of the values, but it seems inefficient:

const ogArray = [{
  "person_1": "jim",
  "person_2": "bob"
}]
const newArray = ogArray.map((person) => {
  return {
    people: [{
        person: person.person_1
      },
      {
        person: person.person_2
      }
    ]
  }
});

console.log(newArray);

The above method works but it’s not DRY and I wish I could select each object with a wildcard like person_*

Loader is stuck

So I am building a SPA using react and fetching some images from an API. I want to show a loader till i get a response. I have the code here but the loader does not seem to spin for some reason. I’m not sure why. I am using axios to fetch the API. I have the code for the components below.

photogallery.js

/* eslint-disable react-hooks/exhaustive-deps */
/* eslint-disable jsx-a11y/img-redundant-alt */
import React, { useState, useEffect } from "react";
import "./PhotoGallery.css";
import ImageModal from "./ImageModal";
import Loader from "./Loader";
import axios from "axios";

const PhotoGallery = () => {
  const [isLoading, setIsLoading] = useState(false);

  const [photos, setPhotos] = useState([]);
  const [selectedPhoto, setSelectedPhoto] = useState(null);

  const headers = {
    Authorization: "my_key",
  };

  const fetchApi = async () => {
    setIsLoading(true);
    await axios
      .get("https://api.pexels.com/v1/curated", { headers })
      .then(({ data }) => {
        const photoUrls = data.photos.map((photo) => photo.src.original);
        setPhotos(photoUrls);
      });
    setIsLoading(false);
  };

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

  const handlePhotoClick = (photo) => {
    setSelectedPhoto(photo);
  };

  const handleCloseModal = () => {
    setSelectedPhoto(null);
  };

  return (
    <>
      {isLoading ? (
        <Loader />
      ) : (
        <div className="photo-gallery">
          {photos.map((photo, index) => (
            <div
              className="photo"
              key={index}
              onClick={() => handlePhotoClick(photo)}
            >
              <img src={photo} alt={`Photo ${index + 1}`} />
            </div>
          ))}
          {selectedPhoto && (
            <ImageModal photo={selectedPhoto} onClose={handleCloseModal} />
          )}
        </div>
      )}
    </>
  );
};

export default PhotoGallery;

Loader.js

import React from "react";
import "./Loader.css";

const Loader = () => {
  return <div className="loader"></div>;
};

export default Loader;

Loader.css


.loader {
    border: 4px solid rgba(0, 0, 0, 0.1);
    width: 36px;
    height: 36px;
    border-radius: 50%;
    border-left-color: #09f;
    animation: spin 1s linear infinite;
    
  }
  
  @keyframes spin {
    0% {
      transform: rotate(0deg);
    }
    100% {
      transform: rotate(360deg);
    }
  }

How to prevent textarea scrolling to cursor on focus?

Question:
When a textbox is focused with Javascript, is there a way to tell the browser to NOT scroll to the current cursor position?


Goal:
I want to scroll a textarea, and navigate around its text, using buttons. But clicking a button causes the textarea to lose focus. So I have an event listener that listens for ‘blur’ and applies ‘focus’.

Example:-
Situation: I’m looking at the top of the text, but the cursor is in the middle. The textarea is focused. I click my scroll-to-the-bottom button which executes this

txtarea.scrollTo({top: txtarea.scrollHeight, behavior: "smooth"});

Result: The textarea loses focus. The event listener fires and re-focuses the textarea. The textarea scrolls (an instant jump) to show the cursor. The scrollTo then executes and the textarea smoothly scrolls to the bottom of the text.


Minimum working example (Chromium and Firefox):

<!DOCTYPE html> 
<html>
   <head>
   </head>
   <body>
      <textarea rows="20" cols="30" id="textbox">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin ac tellus a tortor aliquam placerat in tincidunt neque. Fusce a sapien lacus. Aliquam suscipit condimentum tempor. Vestibulum dignissim turpis in ipsum rhoncus, sed porttitor urna suscipit. Phasellus varius diam at elit eleifend dignissim. Donec id condimentum tellus, vitae elementum ex. Fusce scelerisque, nisl vel condimentum hendrerit, nulla magna dictum lacus, ac euismod metus ipsum at felis. Curabitur rutrum molestie accumsan. Cras vitae lobortis metus.
Curabitur gravida, erat ut congue ullamcorper, metus nibh auctor ex, a ultricies libero elit quis risus. In gravida ipsum a mi interdum egestas. Nam eu ante molestie, semper mi vitae, hendrerit ligula. Duis ac semper orci. Vestibulum sapien nunc, eleifend id gravida a, aliquet quis erat. Vestibulum porttitor vel neque sed vehicula. Aliquam dignissim lorem tortor, eget rhoncus tortor rutrum nec. Nunc aliquam nisi sed mauris condimentum lacinia. Suspendisse tristique luctus vulputate. Integer efficitur, sem in iaculis porttitor, risus arcu consequat tellus, quis ultrices eros libero vitae elit. Aenean diam ipsum, fringilla sed arcu sed, blandit posuere justo. Maecenas porttitor est quis commodo sollicitudin.
Sed justo nibh, gravida id velit dignissim, aliquet viverra lacus. In non ligula luctus, malesuada justo quis, placerat velit. Nullam justo massa, blandit a sapien nec, pellentesque gravida nisl. Sed pellentesque sit amet nunc molestie egestas. Nullam ultrices orci non sagittis maximus. Vestibulum cursus vel velit malesuada mollis. Sed dapibus, massa quis suscipit dictum, ligula metus vehicula est, vel tincidunt magna quam ut orci. Aenean aliquet rutrum metus et finibus.
      </textarea>
      <script>
         const txtarea = document.getElementById("textbox");
         setTimeout(() => {
            txtarea.focus();
         }, 8000);
      </script>
   </body>
</html>

Load the page, scroll the textarea about half way down, click in the text, scroll back to the top, click outside the textarea.

After a few seconds, the textbox will receive focus and immediately scroll to make the cursor position visible.


How can I render only the last message of chat locally, with animation in react native?

I have a chat app and it fetches all the messages from Firestore when user opens a chat window at the first run with useEffect(), but when a new message is getting sent by the user it must get added to local state for better user experience with local timeStamp with a fade-in animation instead of back and fort from database, , right now it works fine but for some reason the sent messages gets displayed and gets removed very quickly and gets displayed again. I feel like it’s fetching from the database instead of locally. how can I make this work?

“`

const NewChatSection = ({ navigation, route }) => {
  const [messages, setMessages] = useState([]);
  const [message, setMessage] = useState("");
  const [lastMessage, setdddLastMessage] = useState(null);
  const scrollViewRef = useRef();
  const db = getFirestore();
  const auth = FIREBASE_AUTH;
  const { uid, displayName } = route.params;
  const userUIDs = [auth.currentUser.uid, uid].sort();
  const chatId = userUIDs.join("-");
  const chatRef = doc(db, "chats", chatId);
  const messagesRef = collection(db, "chats", chatId, "messages");
  const fadeAnim = useRef(new Animated.Value(0)).current;
  const fadeIn = () => {
    Animated.timing(fadeAnim, {
      toValue: 1,
      duration: 500,
      useNativeDriver: true,
    }).start();
  };

  if (Platform.OS === "android") {
    if (UIManager.setLayoutAnimationEnabledExperimental) {
      UIManager.setLayoutAnimationEnabledExperimental(true);
    }
  }

  const handleSend = async () => {
    if (message.trim() === "") {
      return;
    }

    const newMessage = {
      text: message,
      timestamp: new Date(), // This timestamp is for local display purposes only
      senderName: auth.currentUser.displayName,
      senderId: auth.currentUser.uid,
      receiverId: uid,
      receiverName: displayName,
      type: "sentMessage",
    };

    const newMessageForDb = {
      ...newMessage,
      timestamp: serverTimestamp(), // Use serverTimestamp for the database
    };

    // Optimistically update the local state with the new message
    setMessages((prevMessages) => [...prevMessages, newMessage]);

    try {
      await addDoc(messagesRef, newMessageForDb);
      setMessage("");
      fadeIn(); // Trigger the animation for the local message
    } catch (error) {
      console.error("Error sending message: ", error);
    }
  };

  useEffect(() => {
    const receiverUID = route.params?.uid;
    const currentUserUID = auth.currentUser.uid;
    const userUIDs = [currentUserUID, receiverUID].sort();
    const chatId = userUIDs.join("-");
    const messagesRef = collection(db, "chats", chatId, "messages");
    const q = query(messagesRef, orderBy("timestamp"));

    const unsubscribe = onSnapshot(q, (querySnapshot) => {
      const fetchedMessages = querySnapshot.docs.map((doc) => {
        let msg = doc.data();
        msg.type =
          msg.senderId === auth.currentUser.uid
            ? "sentMessage"
            : "receivedMessage";
        return msg;
      });
      setMessages(fetchedMessages);
      if (fetchedMessages.length > 0) {
        const lastMessage = fetchedMessages[fetchedMessages.length - 1];
        const users = {
          participants: [auth.currentUser.uid, uid].sort(),
          senderName: auth.currentUser.displayName,
          receiverName: displayName,
          lastMessage: lastMessage.text,
          lastMessageTimestamp: lastMessage.timestamp,
          deleted: false,
        };
        setDoc(chatRef, users, { merge: true });
      }
    });

    return () => unsubscribe();
  }, []);

  return (
    <KeyboardAvoidingView
      behavior={Platform.OS === "ios" ? "padding" : "height"}
      style={styles.container}
      // animationType="slide"
    >
      <SafeAreaView style={styles.safeAreaContainer}>
        <View style={styles.header}>
          <TouchableOpacity
            onPress={() => navigation.goBack()}
            style={styles.closeButton}
          >
            <Svg
              xmlns="http://www.w3.org/2000/svg"
              fill="none"
              viewBox="0 0 24 24"
              stroke="#FFFFFF"
              width={30}
              height={30}
            >
              <Path
                strokeLinecap="round"
                strokeLinejoin="round"
                strokeWidth={2}
                d="M15 19l-7-7 7-7"
              />
            </Svg>
          </TouchableOpacity>
          <Text style={styles.title}>{displayName}</Text>
        </View>
        <ScrollView
          style={styles.scrollViewContent}
          keyboardShouldPersistTaps="handled"
          ref={scrollViewRef}
          onContentSizeChange={() => {
            scrollViewRef.current.scrollToEnd({ animated: true });
          }}
        >
          {Array.isArray(messages) &&
            messages.map(
              (msg, index) => (
                console.log("MESSAGE: ", msg),
                (
                  <View
                    key={index}
                    style={[
                      msg.type === "sentMessage"
                        ? styles.messageContainer
                        : styles.messageContainerReceived,
                      {
                        flexDirection: "row",
                        justifyContent: "space-between",
                        alignItems: "center",
                      },
                    ]}
                  >
                    <Text style={styles.messageText}>{msg.text}</Text>
                    {msg.timestamp && (
                      <Text style={styles.messageTimestamp}>
                        {format(
                          msg.timestamp instanceof Date
                            ? msg.timestamp
                            : msg.timestamp.toDate(),
                          "p"
                        )}
                      </Text>
                    )}
                  </View>
                )
              )
            )}
/////////////////////////////////////COMMENTED OUT
          {/* {lastMessage && (
            <Animated.View
              style={[
                { opacity: fadeAnim },
                lastMessage.type === "sentMessage"
                  ? styles.messageContainer
                  : styles.messageContainerReceived,
                {
                  flexDirection: "row",
                  justifyContent: "space-between",
                  alignItems: "center",
                },
              ]}
            >
              <Text style={styles.messageText}>{lastMessage.text}</Text>
              <Text style={styles.messageTimestamp}>
                {format(new Date(), "p")}
              </Text>
            </Animated.View>
          )} */}
/////////////////////////////////COMMENTED OUT
        </ScrollView>

        <View style={styles.inputContainer}>
          <TextInput
            placeholder="Type your message..."
            style={styles.input}
            multiline
            value={message}
            onChangeText={setMessage}
            placeholderTextColor={"#ccc"}
          />

          <TouchableOpacity onPress={handleSend} style={styles.sendButton}>
            <Icon name="send" size={22} color="white" />
          </TouchableOpacity>
        </View>
      </SafeAreaView>
    </KeyboardAvoidingView>
  );
};

“`

I tried separating all the messages from the last message, but it didn’t work and it was making it super complicated, maybe the time is getting said twice, but after the first render everything else that’s happening on the screen must get done locally.

How to know which sku is clicked on product page in bigcommerce?

Just one simple question, How to know which sku is clicked on frontend site via javascript so that I can fetch the clicked sku detail and process it further.

I’ve found below code from one of the app installed on the website. Which console the output of clicked SKU number. However, its very large code to debug and find a way to know this.

enter image description here

Also, below are the sku options which I want to know what is being clicked via JS to print on console.

enter image description here

Thanks in advance.