Adjusting Website Viewport for Mobile and PC Users

So I’m normally using common viewport for PC users. As I basically learnt viewport codes for cross-compatibilities (i.e, webkit for Safari and Chrome browsers content rendering). However, I want the website to be accessible for every device and browsers.

Now, the questions are:

  1. Does this require .js file to make the website accessible to every single of device and browsers?
  2. What code would be used to make the task possible? (website accessible to every device and browsers)
  3. How do I make the website landscape-only for Android or iPhone users, thereby forcing users to rotate 90 degrees?
  4. (Optional) I would like to see your recommendation about the cross-compatibility toolkit to check the viewport on different browser and devices without having the website go online.

Thank you!

I only knew basic viewport such as device-width and initial-scale=”1.0″, and I tried to figure out by looking at the Q&A out there (and not sure how I should address the problem on Google).

Uncaught TypeError: addToMovieList is not a function

// MovieList.jsx
import "./movieList.scss";
import axios from "axios";
import { useEffect, useState } from "react";
import Card from "../card/Card";

function MovieList({ savedMovies, setSavedMovies }) {
  const [movieList, setMovieList] = useState(() => {
    const storedMovieList = JSON.parse(localStorage.getItem("movieList"));
    return storedMovieList || [];
  });

  useEffect(() => {
    if (!movieList.length) {
      fetchMovieList();
    }
  }, []); // Fetch movie list only on component mount if movieList is not available

  useEffect(() => {
    localStorage.setItem("movieList", JSON.stringify(movieList));
  }, [movieList]); // Update local storage whenever movieList changes

  const fetchMovieList = () => {
    axios
      .get(
        `https://api.themoviedb.org/3/discover/movie?api_key=${import.meta.env.VITE_API_KEY}`
      )
      .then((res) => {
        setMovieList(res.data.results);
      })
      .catch((err) => {
        console.log(err);
      });
  };


  const addToMovieList = (movieId) => {
    // Find the movie to add from savedMovies
    const movieToAdd = savedMovies.find(movie => movie.id === movieId);
    
    // Check if the movie to add exists
    if (movieToAdd) {
      // Update movieList state by adding the movie
      setMovieList(prevMovieList => [...prevMovieList, movieToAdd]);
    }
  };
  

  const removeFromMovieList = (movieId) => {
    setMovieList((prevMovieList) =>
      prevMovieList.filter((movie) => movie.id !== movieId)
    );
  };

  return (
    <div className="movieList">
      <Card
        movieList={movieList}
        savedMovies={savedMovies}
        setSavedMovies={setSavedMovies}
        removeFromMovieList={removeFromMovieList}
        addToMovieList={addToMovieList}
      />
    </div>
  );
}

export default MovieList;

// Card.jsx code
import { useState, useEffect } from "react";
import "./card.scss";

function Card({ movieList, savedMovies, setSavedMovies, source, removeFromMovieList, addToMovieList }) {
  const [saved, setSaved] = useState(null);
  
  const handleButtonClick = (movie) => {
    const isSaved = savedMovies.find((savedMovie) => savedMovie.id === movie.id);

    if (isSaved) {
      // If the movie is already saved, remove it
      const updatedSavedMovies = savedMovies.filter((savedMovie) => savedMovie.id !== movie.id);
      setSavedMovies(updatedSavedMovies);
      // Add the movie back to the movieList
      addToMovieList(movie.id); // Add the movie back to movieList
    } else {
      // If the movie is not saved, add it to savedMovies
      setSavedMovies((prevSavedMovies) => [...prevSavedMovies, movie]);
      // Remove the movie from the movieList
      removeFromMovieList(movie.id);
    }
    // Toggle the saved state of the movie
    setSaved((prevSaved) => (prevSaved === movie.id ? null : movie.id));
  };

  useEffect(() => {
    localStorage.setItem("savedMovies", JSON.stringify(savedMovies));
  }, [savedMovies]);

  return (
    <div className="cardContainer">
      {(source === "saved" ? savedMovies : movieList).map((movie) => (
        <div className="card" key={movie.id}>
          <div className="save">
            <button
              onClick={() => {
                handleButtonClick(movie);
              }}
              className={`button ${saved === movie.id ? "saved" : ""}`}
            >
              {saved === movie.id ? (
                <img src="/trash.png" alt="Remove from saved" />
              ) : (
                <img src="/star.png" alt="Add to saved" />
              )}
            </button>
          </div>
          <img
            src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`}
            alt=""
          />
          <p>{movie.title}</p>
        </div>
      ))}
    </div>
  );
}

export default Card;

Please help me with this. I want to have my button add the selected movie back to the original movieList local storage. My local storage has the original movie list to display on one tab, and a savedMovies array to display on a different tab. I’m trying to call the addToMovieList function in the card component to add the movie back to my original movie list array when I click on the button, however I’m getting the TypeError. How come my removeFromMovieList works fine but not addToMovieList?

Switching between system, dark, and light mode

I am using MUI in my Next.js web app to switch between system, light, and dark mode. I am having it persist between sessions by saving the theme selected in local storage. I have placed the ability to change the theme of the web app within a dropdown in the settings modal, so changing of the theme occurs through a useContext. The issue I’m encountering is that theming is not persistent across all of my components if the theme the user selects is either the “system” theme (if your system them is dark mode), or “dark” theme. In addition, I also receive this error if my theme is not “light” theme on initial load or when switching from “light” theme to one of the others:

Warning: Prop `className` did not match. Server: "MuiButtonBase-root MuiIconButton-root MuiIconButton-colorInherit MuiIconButton-edgeStart MuiIconButton-sizeMedium css-134qg7o-MuiButtonBase-root-MuiIconButton-root" Client: "MuiButtonBase-root MuiIconButton-root MuiIconButton-colorInherit MuiIconButton-edgeStart MuiIconButton-sizeMedium css-6pxnsq-MuiButtonBase-root-MuiIconButton-root

After some searching, I originally thought it was because I had not been using CssBaseline within the ThemeProvider tags, however, after adding it, it appears to have only made things worse, and the error persists. I will show the different behavior in screenshots below:

Expected behavior if in “system” or “dark” mode (This is without CssBaseline between the ThemeProvider tags:
enter image description here

The actual behavior without CssBaseline on load in with “system” or “dark” mode:
enter image description here

The behavior on load when in “system” or “dark” mode with CssBaseline:
enter image description here

The behavior when switching from “light” mode to “system” or “dark” mode:
enter image description here

Listed below is my context code and how I’m getting the theme from the system, how I’m storing it in local storage, and how I’m switching it:

const ThemeContext = createContext()

const useThemeContext = () => useContext(ThemeContext)

export const ThemeModeProviderComponent = ({ children }) => {
  const systemTheme = typeof window !== 'undefined' && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'

  const [selectedTheme, setSelectedTheme] = useState(() =>
    typeof localStorage !== 'undefined' && localStorage.getItem('theme') || 'system'
  )

  const themes = {
    light: createTheme({
      palette: {
        mode: 'light',
        primary: {
          main: '#0065bd'
        },
        secondary: {
          main: '#00b6d3'
        }
      }
    }),
    dark: createTheme({
      palette: {
        mode: 'dark',
        primary: {
          main: '#0065bd'
        },
        secondary: {
          main: '#00b6d3'
        }
      }
    }),
    system: createTheme({
      palette: {
        mode: systemTheme,
        primary: {
          main: '#0065bd'
        },
        secondary: {
          main: '#00b6d3'
        }
      }
    })
  }

  useEffect(() => {
    if (selectedTheme === 'system') {
      const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
      themes.system.palette.mode = systemTheme
    }
  }, [selectedTheme, themes.system])

  const handleThemeChange = (event) => {
    const { value } = event.target

    setSelectedTheme(value)
    localStorage.setItem('theme', value)
  }

  return (
    <ThemeContext.Provider value={{ selectedTheme, handleThemeChange }}>
      <ThemeProvider theme={themes[selectedTheme]}>
          <CssBaseline enableColorScheme/>
          {children}
      </ThemeProvider>
    </ThemeContext.Provider>
  )
}

export const ThemeSelector = () => {
  const { selectedTheme, handleThemeChange } = useThemeContext()

  if (typeof window === 'undefined') return null

  return (
    <FormControl>
      <Select
        value={selectedTheme}
        onChange={handleThemeChange}
      >
        <MenuItem value='system'>System</MenuItem>
        <MenuItem value='dark'>Dark</MenuItem>
        <MenuItem value='light'>Light</MenuItem>
      </Select>
    </FormControl>
  )
}

Another possibility is that, because of the way I’m handling the showing and hiding of the drawer, it could be affecting the style. I basically copied the persistent drawer example from the MUI website here, but I don’t think it’s the case, as, as we’ve seen in the images, it it working properly to an extent.

Generated button wont submit data to my google spreadsheet

i have these function on my google script app to generate some button on a table

FYI i have no knowledge of JS, and i just made this with chat GPT

// Function to handle button clicks
function handleButtonClick(rowIndex, colIndex) {
  google.script.run.withSuccessHandler(function(response) {
    // Do something after button click, if needed
  }).handleButtonClick(rowIndex, colIndex);
}

// Function to handle date button clicks
function handleDateButtonClick(rowIndex, colIndex) {
  google.script.run.withSuccessHandler(function(response) {
    // Do something after date button click, if needed
  }).handleDateButtonClick(rowIndex, colIndex);
}

function submitData(client, tanggalDatang, jenisBarang) {
  var sheet = SpreadsheetApp.openById('SPREADSHEET_ID').getSheetByName('Utama');
  var dataRange = sheet.getDataRange();
  var values = dataRange.getValues();
  var matchedRowData = '';
  var totalFound = 0;

  for (var i = 1; i < values.length; i++) {
    if (values[i][3] == client && Utilities.formatDate(values[i][1], Session.getScriptTimeZone(), 'dd/MM/yyyy') == tanggalDatang && (jenisBarang === '' || values[i][4] == jenisBarang)) {
      totalFound++;
      matchedRowData += '<table class="table table-bordered">';
      for (var j = 0; j < values[i].length; j++) {
        var cellValue = values[i][j];
        var orderId = values[i][0];
        var trId = orderId + '_' + (j + 1);
        if (i === 1) {
          matchedRowData += '<tr id="' + trId + '"><th style="width: 30%; font-weight:bold;">' + values[0][j] + '</th><td>' + cellValue + '</td>';
        } else {
          matchedRowData += '<tr id="' + trId + '"><td style="width: 30%;">' + values[0][j] + '</td><td>' + cellValue + '</td>';
        }
        if (j >= 13 && j <= 19) { 
          matchedRowData += '<td style="width: 15%;"><button onclick="handleButtonClick(' + i + ', ' + (j + 1) + ')">Button</button></td>';
        } else if (j >= 7 && j <= 9) { 
          matchedRowData += '<td style="width: 15%;"><button onclick="handleDateButtonClick(' + i + ', ' + (j + 1) + ')">Add Date</button></td>';
        }
      }
      matchedRowData += '</tr></table><br>';
    }
  }

  matchedRowData = '<h3>Data dari <strong>' + client + '</strong> tanggal <strong>' + tanggalDatang + '</strong> - Total: <strong>' + totalFound + '</strong> item </h3>' + matchedRowData;

  return matchedRowData;
}

and this is my script on index html to handle that GS

        function handleSubmit(event) {
            event.preventDefault();
            var client = document.getElementById("clientSelect").value;
            var tanggalDatang = document.getElementById("tanggalDatangSelect").value;
            var jenisBarang = document.getElementById("jenisBarangSelect").value;
            google.script.run.withSuccessHandler(function (matchedRowData) {
                var matchedRowDiv = document.getElementById("matchedRow");
                matchedRowDiv.innerHTML = matchedRowData;
            }).submitData(client, tanggalDatang, jenisBarang);
        }

        // Function to handle button clicks generated by submitData function
        function handleButtonClick(rowIndex, colIndex) {
            // Implement your logic to handle button clicks here
            alert("Button clicked! Row: " + rowIndex + ", Column: " + colIndex);
        }

and this is the preview when a button clicked
https://i.stack.imgur.com/Sqgc1.png

as you see when a button clicked , it could read the spreadsheet cell name that i generate inside
but it does not submit anything to my sheet.
the log from browser console is

Uncaught ReferenceError: handleDateButtonClick is not defined
at HTMLButtonElement.onclick (userCodeAppPanel:1:1)

which part is still wrong?
thank you in advance

i tried to make a dummy button to post on designated cell, it worked,
so it wasnt premission issue

Chart JS. I have configured my x axis to show the hours of the full date in data.labels. However, it still shows the original labels below

chart.js 4.4.2
date-fns 2.30
chartjs-adapter-date-fns” 3.0.0

I wanted to truancate the x-axis as it was labeling it in a YYYY:MM:DD HH:MM:SS. I achieved that via options.scales.x.ticks and options.scales.x.time. However, I am still displaying the orignal unwanted x axis.

import 'chartjs-adapter-date-fns';
import { enUS } from 'date-fns/locale';
import { ForecastObj } from './appTypes.types';

export async function renderChart(forecast: ForecastObj[]) {
  const chartCtr = document.querySelector('#temp-chart') as HTMLCanvasElement;

  new Chart(chartCtr, {
    type: 'line',
    options: {
      animation: false,
      scales: {
        xAxis: {
          adapters: {
            date: {
              locale: enUS,
            },
          },
          type: 'time',
          ticks: {
            stepSize: 3,
            major: {
              enabled: true,
            },
          },
          time: {
            unit: 'hour',
            tooltipFormat: 'HH:mm',
          },
        },
      },
    },
    data: {
      labels: forecast.map((row) => row.date),
      datasets: [
        {
          label: 'temp every 3 hrs',
          data: forecast.map((row) => row.temp),
        },
      ],
    },
  });
}

I would like to remove the lower x axis (the original).
Results

javascript extracting floating point numbers regex are not matched properly

I’ve below javascript program –

var rx = /^the values should(?: between (d+(.d+)?) and (d+(.d+)?))$/;
var sentence = "the values should between 1.1 and 2.7";
var arr = rx.exec(sentence);
console.log(JSON.stringify(arr));

I want to extract the number 1.1 and 2.7 into into an array from the matched line.

When I run the above program I get the below result

["the values should between 1.1 and 2.7","1.1",".1","2.7",".7"]

In the above program 1.1 becomes .1 and 2.7 becomes .7.

How can I match it in javascript correctly.

How to align all elements on same axis

I am trying to align all my elements on the same axis. The element can be anything: input, dropdown, button, etc. I am trying to accomplish this using only CSS. I know we can use MUI Stack component to align them but I only want to do it via CSS. The first image below shows an example of how it currently looks, which you can see is unaligned. The second image is the expected alignment that I want. Not sure how to proceed to make it aligned?

It is not aligned

It is aligned

import * as React from "react";
import Button from "@mui/material/Button";
import TextField from "@mui/material/TextField";

export default function BasicButtons() {
  return (
    <span>
      <TextField id="standard-basic" label="Standard" variant="standard" />
      <Button variant="contained">Contained</Button>
      <Button variant="outlined">Outlined</Button>
    </span>
  );
}

Using PHP inside of CSS and JavaScript

Im trying to have a text line popup once the comment button is clicked for each line(row) dynamically.

When you click on the comment button, a line should popup under the buttons within the same row.

On DOM inspect, the lines and buttons all have unique names and id’s

I just cant get it to work as a unique event for each row.

Here is an image for reference

<div class="container-xxl flex-grow-1 container-p-y">
             
<h2 align="center"><?php echo $appname?></h2><br />
   <div class="form-group">
   <form name="add_name" id="add_name">
                    
   <div class="table-responsive">
      <table class="table table-bordered" id="dynamic_field">
         <?php while ($checks = mysqli_fetch_array($checksqry)) {
            echo '<tr>';
            echo '<td style="width: 20%">'.$checks['check_name'].' <br><br> 
            <input type="radio" class="btn-check" name="btn[' . $checks['id'] . ']" id="btnpass[' . $checks['id'] . ']" value="Pass">
            <label class="btn rounded-pill btn-outline-success" for="btnpass[' . $checks['id'] . ']">Pass</label>&Tab;&Tab;
                    
           <input type="radio" class="btn-check" name="btn[' . $checks['id'] . ']" id="btnwarning[' . $checks['id'] . ']" value="Warning">
           <label class="btn rounded-pill btn-outline-warning" for="btnwarning[' . $checks['id'] . ']">Warning</label>&Tab;&Tab;
                    
           <input type="radio" class="btn-check" name="btn[' . $checks['id'] . ']" id="btnfail[' . $checks['id'] . ']" value="Fail">
           <label class="btn rounded-pill btn-outline-danger" for="btnfail[' . $checks['id'] . ']">Fail</label>&Tab;&Tab;
                    
           <button onclick="myFunction()" type="button" name="comment[' . $checks['id'] . ']" id="comment[' . $checks['id'] . ']" class="btn btn-info" style="float: right"><img src="assets/comment.png" width="20px"></button> 
<br><br>
           <div id="commentlinediv[' . $checks['id'] . ']">
           <input type="text" class="text-line" placeholder="Type Comment Here" id="commentline[' . $checks['id'] . ']"/>
</div>
</td>';
echo '<tr>';}?>
                        
</table>
<input type="button" name="submit" id="submit" class="btn btn-info" value="Submit" />
</div>
</form>
</div>
</div>
input[type="text"] {
   border:none; /* Get rid of the browser's styling */
   border-bottom:1px solid black; /* Add your own border */
}

.text-line {
   background-color: transparent;
   color: black;
   outline: none;
   outline-style: none;
   border-top: none;
   border-left: none;
   border-right: none;
   border-bottom: solid #eeeeee 1px;
   padding: 3px 10px;
   width: 300px;
}
                
#commentlinediv[<?php echo $checks['id']?>]{
   display: none;
}
function myFunction() {
document.getElementById("commentlinediv[<?php $checks['id']?>]").style.display = "inline";
}

Map input to Key Value Pair

How do I map the vals to show be in key value pair

public getSearchHelpResult(evt: Event): void {
const vals = (evt as CustomEvent).detail;

this.showContinue = false;
[this.isGridVisible, this.showNoDataAlert] = [false, false];
this.gridColumns = [];
this.gridPayload.searchfilters = [];
this.gridPayload.appid = this.appId;
this.gridPayload.searchfield = vals.id;
this.gridPayload.searchfilters.push(vals);
console.log(vals)

right now the vals come as [{“ONE”:”9999″}] to look like this [{“id”:”ONE”,”value”:”9999″}]

I tried vals.map(val: {[key: string]: string}) => {
return {id: val.key, value: val.string}} but it didn’t work to get expected output.

Style Dictionary config.js – JSON not being transformed to CSS Variables successfully

I have a a JSON file that contains color and semantic theme variables, and an expected outcome I would like Style Dictionary to create in the CSS file using the provided “config.js” file.

Can you help me troubleshoot the config.js file so it successfully outputs the correct css variables?

Here’s the JSON content:

JSON file in my public repo

Here’s the expected outcome I would like in the CSS file, for the config.js file to propagate:

CSS file in my public repo

And here’s the content of my config.js file:

const StyleDictionary = require('style-dictionary');
const path = require('path');

// Define the Style Dictionary configuration
StyleDictionary.registerFormat({
  name: 'custom/css',
  formatter(dictionary) {
    console.log(dictionary); // Log the dictionary object to check its properties
    let css = '';

    // Generate CSS content from the tokens
    css += `:root {n`;
    Object.keys(dictionary.properties).forEach((key) => {
      const value = dictionary.properties[key];
      css += `  --${key}: ${value};n`;
    });
    css += `}nn`;

    // Generate light theme CSS
    css += `[data-theme="light"] {n`;
    css += `  /* Light theme styles */n`;
    css += `}nn`;

    // Generate dark theme CSS
    css += `[data-theme="dark"] {n`;
    css += `  /* Dark theme styles */n`;
    css += `}n`;

    return css;
  },
});

// Define the source JSON file
StyleDictionary.extend({
  source: [path.join(__dirname, '../json/fds-tokens-structure.json')],
});

// Define the platforms object
const platforms = {
  css: {
    transformGroup: 'css',
    buildPath: 'build/css',
    files: [
      {
        destination: 'fds-tokens-color.css',
        format: 'custom/css',
        options: {
          outputReferences: true,
        },
      },
    ],
  },
};

// Build the Style Dictionary for all platforms
StyleDictionary.buildAllPlatforms({ platforms });

I’m getting this error when I run “style-dictionary build”:

  Object.keys(this.options.platforms).forEach(function (key) {
         ^

TypeError: Cannot convert undefined or null to object
    at Function.keys (<anonymous>)
    at Object.buildAllPlatforms (/Volumes/T5/GitHub/FDS/packages/tokens/style-dictionary/node_modules/style-dictionary/lib/buildAllPlatforms.js:30:10)
    at Object.<anonymous> (/Volumes/T5/GitHub/FDS/packages/tokens/style-dictionary/config.js:56:17)
    at Module._compile (node:internal/modules/cjs/loader:1376:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1435:10)
    at Module.load (node:internal/modules/cjs/loader:1207:32)
    at Module._load (node:internal/modules/cjs/loader:1023:12)
    at Module.require (node:internal/modules/cjs/loader:1235:19)
    at require (node:internal/modules/helpers:176:18)
    at Object.extend (/usr/local/lib/node_modules/style-dictionary/lib/extend.js:95:15)

Thanks, and have a good weekend.

How to programatically open push notifications

Could you kindly help me write a script that simulates the opening of push notifications in a new tab without user interaction. I want the push notifications to open in a new tab without me having to click on them.

I tried autohotkey script and tampermonkey script but they did not work. I was expecting to see push notifications open in a new tab without me having to click the notifications themselves.

extension controlling Crynchyroll video

I’m creating a chrome extension where i can control the html5 video on a page.

It works fine for Youtube and Vimeo but i’m having trouble for Crunchyroll.

Crunchyroll apparently has their video inside of an iframe. So i cant seem to access it without running into cross-origin errors.

Would need to be able to do basic video controlling like play, pause, see and set current time etc.

Extensions do exist for Crunchyroll so it has to be possible somehow.
Cant seem to find a solution, most forums and stuff just get the html5 video the regular way.
But that does not work. Either everybody is wrong, Crunchy just changed or I’m missing something.

possible solutions:

  • can i inject a script into the iframe too, like my extension is injecting into the main tab content now?
  • are their custom controls that are available for Crunchyroll?

tried the regular way:

html5player = document.querySelector('video');

nothing found

tried connecting to the iframe:

var iframe = document.querySelector('iframe'),video;
if (iframe) {
  html5player = iframe.contentWindow.document.getElementsByTagName('video');
}

this will get you a cross-origin error

Why does scrollTop not take the value being set

I am running into an issue when setting scrollTop where, when set with a value, it reverts back to it’s old value. The result is a momentary flash as the scrollbar moves and then goes back to it’s original position. I am seeing this issue cross browser and cross operating systems.

There are some additional particulars to this issue which makes it even more weird.

  1. It only happens while you are manipulating the scrollbar. If you use your mouse wheel there is no problem.
  2. In the example I am providing, if you disable, for the outer div, either the overflow CSS attribute or both border radius attributes this problem goes away. To add to my misery the example I am providing is a HIGHLY boiled down version of the original program. In this program the outer div is beyond my control, and(hold on to your seat), exists OUTSIDE of the iframe my code is running in. THAT’S RIGHT! Some how the CSS is affecting stuff running inside an iframe. I checked and I cannot see the iframe change size or have it’s own CSS or attributes being modified in any way.

I have a fiddle which demonstrates the issue, however, to see how removing the CSS also removes the issue, it’s best ran on it’s own from your IDE. I think jsFiddle has their own CSS somewhere outside the iframe it’s running in causing the problem.

https://jsfiddle.net/CodeMedic42/oxut78b2/3/

I provided a debugger statement to stop your debugger where the issue is occurring. To see the issue, scroll down, using your mouse and dragging the scroll bar, to 1985:11 and when you get just past that, new items are added to the top of the list which pushes the scroll bar down. What I am doing is then resetting the scrollbar back to the spot where is was moved from.

If you haven’t guessed I am making an infinite list component. I ran into this issue while running it on Storybook.

Also if you are asking why I am using “overflow-anchor: none;” I will angrily refer you to Apple to ask them why Safari on Mac and iOS is the only modern browser that does not support it. If they did I would not be here right now.

I need to provide code for the jsFiddle link or StackOverflow won’t accept it. It’s just a copy from the fiddle.

function chooseColor(index) {
    const v = index % 10;

    if (v === 0) {
        return 'purple';
    }

    if (v === 1) {
        return 'orange';
    }

    if (v === 2) {
        return 'green';
    }

    if (v === 3) {
        return 'yellow';
    }

    if (v === 4) {
        return 'magenta';
    }

    if (v === 5) {
        return 'red';
    }

    if (v === 6) {
        return 'black';
    }

    if (v === 7) {
        return 'brown';
    }

    if (v === 8) {
        return 'pink';
    }

    return 'cyan';
}

function List() {
    const listRef = React.useRef();
    const itemsRef = React.useRef();
    const itemsRemoved = React.useRef(false);
    const shiftInfoRef = React.useRef(null);

    const [itemsMeta, setItemsMeta] = React.useState({ from: { year: 1974, month: 3 }, to: { year: 1991, month: 8 }});

    const items = React.useMemo(() => {
        const builder = [];
        let startingMonth = itemsMeta.from.month;
        let endingMonth = 12;

        for (let yearCounter = itemsMeta.from.year; yearCounter <= itemsMeta.to.year; yearCounter += 1) {
            if (yearCounter === itemsMeta.to.year) {
                endingMonth = itemsMeta.to.month;
            }

            for (let monthCounter = startingMonth; monthCounter <= endingMonth; monthCounter += 1) {
                startingMonth = 1;

                const color = chooseColor(yearCounter);
              
                const text = yearCounter + ':' + monthCounter;

                builder.push(<div key={yearCounter * 12 + monthCounter}style={{color: 'white', fontSize: 48, margin: 20, backgroundColor: color}}>{text}</div>);
            }
        }

        return builder;
    }, [ itemsMeta ]);

    const handleScroll = React.useCallback(() => {
        const scrollOn = 140;

        const targetChild = itemsRef.current.childNodes[scrollOn];
        const item = itemsRef.current.childNodes[scrollOn + 1];

        const childRect = targetChild.getBoundingClientRect();
        const listRect = listRef.current.getBoundingClientRect();
        const itemRect = item.getBoundingClientRect();

        if (!itemsRemoved.current && childRect.bottom < listRect.top) {
            console.log('Add items');
            itemsRemoved.current = true;

            setItemsMeta({ from: { year: 1979, month: 4 }, to: { year: 1991, month: 8 }});

            shiftInfoRef.current = {
                previousPosition: itemRect.top,
                item,
            };
        }
    });

    React.useLayoutEffect(() => {
        const targetChild = itemsRef.current.childNodes[70];

          targetChild.scrollIntoView({
            block: 'start',
            inline: 'start',
        });
    }, []);

    React.useLayoutEffect(() => {
        if (shiftInfoRef.current == null || itemsRef.current == null) {
            return;
        }

        const { previousPosition, item } = shiftInfoRef.current;

        const itemRect = item.getBoundingClientRect();

        const scrollTop = listRef.current.scrollTop - (previousPosition - itemRect.top);

        shiftInfoRef.current = null;

        debugger;
        // This fails when scrolling using the scrollbar, but works when using the mouse wheel. #rage
        listRef.current.scrollTop = scrollTop;
    });

    return (
        <div style={{
            position: 'absolute',
            width: '100%',
            height: '100%',
            borderTopLeftRadius: 5,
            borderBottomLeftRadius: 5,
            overflow: 'hidden',
        }}>
            <div
                ref={listRef}
                className="list"
                onScroll={handleScroll}
            >
                <div style={{ fontSize: '128px', margin: 20 }}>
                    Top Header
                </div>
                <div ref={itemsRef}>
                    {items}
                </div>
            </div>
        </div>
    );
}
:root {
    scroll-behavior: smooth;
}

* {
    box-sizing: border-box;
}

html,
body,
#app {
  padding: 0;
  margin: 0;
  background-color: white;
  height: 100%;
}

.list {
  height: 100%;
  overflow: auto;
  box-sizing: border-box;
  overflow-anchor: none;
}

Show and Hide DIV’s after 5000 seconds when .wpcf7-mail-sent-ok

I made a Contact Form 7 with a custom “Thank You!” message that appears after wpcf7mailsent.

I need it to reverse after seconds. My current code does not work:

addEventListener('wpcf7mailsent', function(event) {
    event.preventDefault();
    document.querySelector('.qtWRP').style.display = 'none';
    document.querySelector('.inputBTMx').style.display = 'none';
    document.querySelector('.cap').style.display = 'none';
    document.querySelector('.qtWRP2').style.display = 'block';
});

wpcf7Elm.addEventListener( 'wpcf7-mail-sent-ok', function( event ) {
jQuery ( 'form.wpcf7form' )[1000].reset();
}, false );;

Appreciate any help.

enter image description here

enter image description here