How to add a special character to A Password Validation Form

I am trying to make a password validation in javascript for my register form, I found several questions here using the same example from W3Schools and I followed all the examples with results. I am pretty sure nobody knows there is still a problem everyone is missing. It does make a check mark for special characters but it does not require one for the form to be successfully submitted and the user to be registered.

var myInput = document.getElementById("password");
var letter = document.getElementById("letter");
var capital = document.getElementById("capital");
var number = document.getElementById("number");
var length = document.getElementById("length");
var special = document.getElementById("special");

// When the user clicks on the password field, show the message box
myInput.onfocus = function() {
    document.getElementById("message").style.display = "block";
}

// When the user clicks outside of the password field, hide the message box
myInput.onblur = function() {
    document.getElementById("message").style.display = "none";
}

// When the user starts to type something inside the password field
myInput.onkeyup = function() {
// Validate lowercase letters
var lowerCaseLetters = /[a-z]/g;
if(myInput.value.match(lowerCaseLetters)) {  
letter.classList.remove("invalid");
letter.classList.add("valid");
} else {
letter.classList.remove("valid");
letter.classList.add("invalid");
}

// Validate capital letters
var upperCaseLetters = /[A-Z]/g;
if(myInput.value.match(upperCaseLetters)) {  
capital.classList.remove("invalid");
capital.classList.add("valid");
} else {
capital.classList.remove("valid");
capital.classList.add("invalid");
}

// Validate numbers
var numbers = /[0-9]/g;
if(myInput.value.match(numbers)) {  
number.classList.remove("invalid");
number.classList.add("valid");
} else {
number.classList.remove("valid");
number.classList.add("invalid");
}

// Validate length
if(myInput.value.length >= 8) {
length.classList.remove("invalid");
length.classList.add("valid");
} else {
length.classList.remove("valid");
length.classList.add("invalid");
}

// Validate special
var specialcharacters = /[`!@#$%^&*()_+-=[]{};':"\|,.<>/?~]/g;
if(myInput.value.match(specialcharacters)) {
special.classList.remove("invalid");
special.classList.add("valid");
} else {
special.classList.remove("valid");
special.classList.add("invalid");
}
}
<style>
#message {
display:none;
background: #EFEFEF;
color: #000;
position: relative;
margin-top: 0px;
text-align:left;
width:100%;
}
#message p {
padding: 2px 35px 2px 60px;
font-size: 18px;
}
/* Add a green text color and a checkmark when the requirements are right */
.valid {
color: green;
}
.valid:before {
position: relative;
left: -20px;
content: "✔";
}
/* Add a red text color and an "x" when the requirements are wrong */
.invalid {
color: red;
}
.invalid:before {
position: relative;
left: -20px;
content: "✖";
color: red;
}
</style>
<form>
<input type="password" name="password" placeholder="Password" id="password" required minlength="8" maxlength="32" pattern="(?=.*d)(?=.*[a-z])(?=.*[A-Z]).{8,}">
</form>

<div id="message">
<div style="padding-top:8px;"></div>
<h2 style="padding-left:40px;font-size:19px;text-decoration:underline;font-weight:650;color:#333;">Password Requirements:</h2>
<p id="letter" class="invalid"><span style="font-weight:600;font-size:17px;">A lowercase letter</span></p>
<p id="capital" class="invalid"><span style="font-weight:600;font-size:17px;">A capital letter</span></p>
<p id="number" class="invalid"><span style="font-weight:600;font-size:17px;">A number</span></p>
<p id="special" class="invalid"><span style="font-weight:600;font-size:17px;">A special character</span></p>
<p id="length" class="invalid"><span style="font-weight:600;font-size:17px;">A minimum of 8 characters</span></p>
</div>

Could it have something to do with the html pattern? Or any other help or ideas?

How to fix TypeError: Cannot read properties of undefined (reading ‘backdrop’)

Why is it that every time I add new data to the database using an AJAX request, I can’t click the button to open the modal for view and update, and an error appears in the console

I should be able to view or edit the newly added data using AJAX but its not working

$.ajax({
url: “{{ route(‘admin.store_violation’) }}”,
method: ‘POST’,
data: formData,
success: function(response) {
if(response.status == ‘success’) {
$(‘#violationFormAdmin’)[0].reset();

                    $('#violationTable').load(location.href + ' #violationTable', function() {

                        $('.viewModal').on('click', function() {
                            let id = $(this).data('id');  // Get the violation ID from the data attribute
                            let targetModal = $(this).data('bs-target');  // Get the target modal ID

                            $(targetModal).find('.modal-body').html('Violation ID: ' + id);

                            // Check if modal instance exists and dispose of it
                            let modalInstance = bootstrap.Modal.getInstance(document.querySelector(targetModal));
                            if (modalInstance) {
                                modalInstance.dispose();
                            }
                            $('.modal').modal({
                            backdrop: 'static',
                            keyboard: true
                        });

                            $(targetModal).modal('show');
                            console.log("View violation with ID: " + id);
                        });

                        $('.editModal').on('click', function() {
                            let id = $(this).data('id');
                            let targetModal = $(this).data('bs-target');

                            $(targetModal).find('.modal-body').html('Edit Violation ID: ' + id);

                            // Check if modal instance exists and dispose of it
                            let modalInstance = bootstrap.Modal.getInstance(document.querySelector(targetModal));
                            if (modalInstance) {
                                modalInstance.dispose();
                            }
                            $('.modal').modal({
                            backdrop: 'static', // Reset backdrop functionality
                            keyboard: true  // Allow closing the modal using the keyboard (Esc)
                        });
                            $(targetModal).modal('show');

                            console.log("Edit violation with ID: " + id);  // This log shows the violation ID
                        });


                    });

                    Swal.fire({
                        toast: true,
                        position: 'top-right',
                        iconColor: 'white',
                        customClass: {
                            popup: 'colored-toast',
                        },
                        showConfirmButton: false,
                        timer: 2500,
                        timerProgressBar: true,
                        icon: 'success',
                        title: 'Violation added successfully',
                    });
                }
            },

Cannot generate ECDSA keys from seed due to “Cannot create a key using the specified key usages” error

I’m trying to generate ECDSA keys using seed and salt as inputs. My aim is to get it working with the pure browser javascript (SubtleCrypto) without the use of any external libs, it’s an important consideration.

The below sample code expectedly fails over a “SyntaxErrors: Cannot create a key using the specified key usages” due to a mismatch between the Eliptic Curve key type and Raw key data format when importing a private key. According to MDN private ECDSA keys can only be imported using PCSS8 or JWT formats. Then to generate a PCSS8 (for instance) a I ought to have an existing key so I can call its exportKey(), which I don’t have at first place, so it’s pretty much a chicken an egg situation for me.

Does anyone have any idea of how to I get the below code working using the exact inputs I have?

// Step 1: PBKDF2 to derive seed from mnemonic and password
async function mnemonicToSeed(mnemonic, password = '') {
    const mnemonicBuffer = new TextEncoder().encode(mnemonic.normalize('NFKD'));
    const saltBuffer = new TextEncoder().encode('mnemonic' + password.normalize('NFKD'));

    const keyMaterial = await window.crypto.subtle.importKey(
        'raw',
        mnemonicBuffer,
        { name: 'PBKDF2' },
        false,
        ['deriveBits']
    );

    const seed = await window.crypto.subtle.deriveBits(
        {
            name: 'PBKDF2',
            salt: saltBuffer,
            iterations: 2048,
            hash: 'SHA-512'
        },
        keyMaterial,
        512 // 512 bits = 64 bytes
    );

    return new Uint8Array(seed); // Return the seed as a Uint8Array
}

// Helper function to convert Uint8Array to hex string
function toHex(buffer) {
    return Array.from(buffer).map(b => b.toString(16).padStart(2, '0')).join('');
}

// Step 2: Generate an ECDSA key pair using WebCrypto and the P-384 curve
async function generateECDSAKeys(mnemonic, password) {
    // Step 2.1: Convert mnemonic to seed
    const seed = await mnemonicToSeed(mnemonic, password);

    // Step 2.2: Use part of the seed as the private key
    const privateKeyBytes = seed.slice(0, 48); // First 48 bytes as private key material (384 bits)

    // Step 2.3: Import the private key into WebCrypto (P-384 curve)
    const privateKey = await window.crypto.subtle.importKey(
        'raw',
        privateKeyBytes,
        { name: 'ECDSA', namedCurve: 'P-384' },
        true,
        ['sign']
    );

    // Step 2.4: Export the public key derived from the private key
    const publicKey = await window.crypto.subtle.exportKey('spki', privateKey);

    // Step 2.5: Export the private key in raw format (for display)
    const exportedPrivateKey = await window.crypto.subtle.exportKey('raw', privateKey);

    return {
        privateKey: toHex(new Uint8Array(exportedPrivateKey)),
        publicKey: toHex(new Uint8Array(publicKey))
    };
}





// Example usage
const mnemonic = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';
const password = 'your_password';

generateECDSAKeys(mnemonic, password).then(keys => {
    console.log('Private Key:', keys.privateKey);
    console.log('Public Key:', keys.publicKey);
}).catch(console.error);

Cannot handle errors using formidable in node.js

I’m using node.js formidable to upload files to my express server.

I want to be able to handle some of the errors, like the a file wasn’t chosen, the file size outside of the limit, file type check etc. and the be able to return a specific error based to the client based on the result.

But I just can’t seem to find the righta good way to do this?

I’m trying to do this in form.parse() but I’m have issues here because it stops processing the file if it exceeds the file limits? this means I can’t do any kind of check as there is no data in file.uploaded?

This is my code:

app.post('/putdata', async (req, res, error) => {

    let fileUploaded = '';
    var form = new formidable.IncomingForm({

        //* Set up incoming data requirments
        maxFileSize: 1 * 1024 * 1024,
        minFileSize: 1,

    });

    console.log('Max file size allowed : ' + form.options.minFileSize);
    console.log('Min file size allowed : ' + form.options.maxFileSize);

    const uploaded = await new Promise((resolve,reject) => {

    form.parse(req, function (err, fields, files) {

    
        //* Handle no file uploaded
        if(!files.uploaded) {
            console.log('file not selected.')
            res.status(400).send('No file recieved for upload');
            return;
        } 

        if (err) {
            console.log('error : ' + err)
            return;
        }

        fileUploaded = 'complete';
        resolve(true);
    });

    });
    console.log(fileUploaded);

});

What I am I doing wrong here?

Thanks for any helpsuggestions.

Store range of values in IndexedDB and query by one value

I want to store list of events in IndexedDB. Each event has start date and end date. Then I need to query today events. I store dates as ISO strings (e. g. 2024-09-15), so string comparison makes sense.

In SQL it would be something like this:

SELECT * FROM events WHERE startDate >= $1 AND endDate <= $1

But in IndexedDB you cannot make queries so freely.

I’m wondering if there a possibility to either create a composite index and use IDBKeyRange (composite indices aren’t really well documented) or create some generated field that includes both start and end dates and somehow do ranged queries for it.

How to get “Results per Row” (from a ‘clicked entry’ off a “dropdown menu”) to show up correctly?

Coding Hobbyist here trying to figure out how to: “Create a Digital Archive.”

more specifically:

A.) “when someone stumbles upon this (HTML/CSS/JavaScript only) webpage, they’ll see a list of items (that, when their mouse hovers over such an item, such an item zooms in).

B.) The list of items they’ll see, will be either:
3 entries per row,
5 entries per row,
or 10 entries per row. (almost like, you’re looking through someone’s archive of artwork. (a random passerbyer, can click from the dropdown menu, if they wanna see “3,5,or 10” images at a time (that’s the code we’re working on together today.).

C.) I have coded together something that shows 3 entries per row.

C.1) I’m stuck. i do not know what’s the best method/code/ability to move forward. Like:

C.1.1) If a random person comes to my webpage, and wants to see “5 entries per row.” How do i get “image number 4” to show up after the third entry? but then BOUNCE BACK TO THE NEXT ROW, if someone chooses “theyd rather see 3 entries per row.”

Here is my provided code before i continue further:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Digital Archive 3-5-10 Images Per Row</title>
<style>
.CenterOfCardCreationPage {
text-align: center;
}
.ContainerForCardCreationContainer {
flex-direction: column;
}
.CardCreationContainer {
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: flex-start; 
padding: 20px;
}
.CardCreationColumn {
flex: 0 0 30%; 
margin: 10px;
padding: 10px;
text-align: center;
}
.CardCreationButton {
display: inline-block;
padding: 10px 20px;
color: white;
text-decoration: none;
border: none;
cursor: pointer;
}
.CardCreationImage {
width: 100%;
height: auto;
object-fit: contain;
}
@media (max-width: 600px) {
.CardCreationColumn {
flex: 0 0 45%;
}
}
@media (max-width: 400px) {
.CardCreationColumn {
flex: 0 0 90%;
}
}
</style>
</head>
<body>
<header class="CenterOfCardCreationPage">
<h1>Items Per Page: 3,5 or 10?</h1>
<label for="resultsPerPage">How many Results would you like?</label>
<select id="resultsPerPage">
<option value="1">3</option>
<option value="2">5</option>
<option value="3">10</option>
</select>
</header>
<div class="ContainerForCardCreationContainer">
<div class="CardCreationContainer">
<div class="CardCreationColumn">
<button id="uploadButton1" onclick="uploadImage(1)">Upload Image</button>
<div id="imagePlaceholder1" class="CardCreationButton">
<img id="image1" class="CardCreationImage" src="" alt="An Image 01" />
</div>
</div>
<div class="CardCreationColumn">
<button id="uploadButton2" onclick="uploadImage(2)">Upload Image</button>
<div id="imagePlaceholder2" class="CardCreationButton">
<img id="image2" class="CardCreationImage" src="" alt="An Image 02" />
</div>
</div>
<div class="CardCreationColumn">
<button id="uploadButton3" onclick="uploadImage(3)">Upload Image</button>
<div id="imagePlaceholder3" class="CardCreationButton">
<img id="image3" class="CardCreationImage" src="" alt="An Image 03" />
</div>
</div>
</div>
<div class="CardCreationContainer">
<div class="CardCreationColumn">
<button id="uploadButton4" onclick="uploadImage(4)">Upload Image</button>
<div id="imagePlaceholder4" class="CardCreationButton">
<img id="image4" class="CardCreationImage" src="" alt="An Image 04" />
</div>
</div>
<div class="CardCreationColumn">
<button id="uploadButton5" onclick="uploadImage(5)">Upload Image</button>
<div id="imagePlaceholder5" class="CardCreationButton">
<img id="image5" class="CardCreationImage" src="" alt="An Image 05" />
</div>
</div>
<div class="CardCreationColumn">
<button id="uploadButton6" onclick="uploadImage(6)">Upload Image</button>
<div id="imagePlaceholder6" class="CardCreationButton">
<img id="image6" class="CardCreationImage" src="" alt="An Image 06" />
</div>
</div>
</div>
<div class="CardCreationContainer">
<div class="CardCreationColumn">
<button id="uploadButton7" onclick="uploadImage(7)">Upload Image</button>
<div id="imagePlaceholder7" class="CardCreationButton">
<img id="image7" class="CardCreationImage" src="" alt="An Image 74" />
</div>
</div>
<div class="CardCreationColumn">
<button id="uploadButton8" onclick="uploadImage(8)">Upload Image</button>
<div id="imagePlaceholder8" class="CardCreationButton">
<img id="image8" class="CardCreationImage" src="" alt="An Image 08" />
</div>
</div>
<div class="CardCreationColumn">
<button id="uploadButton9" onclick="uploadImage(9)">Upload Image</button>
<div id="imagePlaceholder9" class="CardCreationButton">
<img id="image9" class="CardCreationImage" src="" alt="An Image 09" />
</div>
</div>
</div>
</div>
<!-- Footer with centered text -->
<footer class="CenterOfCardCreationPage">
<h2>Thank you for checking this code out!</h2>
</footer>
<script>
//the code below is the stuff for dropdownmenu
const resultsPerPageSelect = document.getElementById('resultsPerPage');
const cardCreationContainers = document.getElementsByClassName('CardCreationContainer');
resultsPerPageSelect.addEventListener('change', (event) => {
const selectedOption = parseInt(event.target.value, 10);
for (let i = 0; i < cardCreationContainers.length; i++) {
if (i < selectedOption) {
cardCreationContainers[i].style.display = 'flex';
} else {
cardCreationContainers[i].style.display = 'none';
}
}
});
// Initial display based on the selected option
resultsPerPageSelect.dispatchEvent(new Event('change'));
// the stuff below is the code for uploading images
let uploadedImages = 0;
// Function to handle image upload
function uploadImage(CardCreationColumnNumber) {
const input = document.createElement('input');
input.type = 'file';
input.accept = 'image/*';
input.onchange = function () {
const file = this.files[0];
const reader = new FileReader();

reader.onload = function () {
const imagePlaceholder = document.getElementById(`image${CardCreationColumnNumber}`);
imagePlaceholder.src = reader.result;
uploadedImages++;
// Enable the second button if the first image is uploaded 
if (CardCreationColumnNumber === 1) {
const secondButton = document.getElementById('uploadButton27');
secondButton.disabled = false;
}
};
reader.readAsDataURL(file);
};
input.click();
}
</script>
</body>
</html>

C.1.2.) Like, what i tried was plugging in the “fourth and fifth image” (and then the 6th to 10th) into the first row, (and such equivalents in the second two rows) but that didnt work. when someone would change from 5 rows back to 3, or 10 rows back to 3, those “IDs, that represented other images, would disappear from view, and only the next visible set of rows would show their IDs”.

D.) Which leads to my question, (for I think I’m seeing this too much from one point of view and not wanting to abandon it cause I worked on it for a hot minute). “How do i properly fix/upgrade this so that when a random passerbyer sees this webpage, they can choose if they want to see 3, 5, 10 results/images per ROW, and if and when they ever wish to change it back to 3 images per ROW, we dont lose image number 4-10 in the first row just for the second row to show its first 3 options (which would have been image 11, 12, 13 (and then the third row showing images 21, 22, & 23) instead of just “image 4,5,6 being removed from the first row, and being placed in the second row; and image 7 8 and 9 being placed in third row.”

(Note: Semi-unrelated-note about this question: I think i kept saying: “Results per page” when i meant “Results per row” i edited it here and there but if i missed any- my b- but thats what i mean here. Results per page would be cool but not the goal right now.)

Y’all get what I be asking? I’m stuck on how to move forward; any help (or even any sage advice on how to better tackle this on) would be greatly appreciated!

-Scholah

React Native FlatList onScroll Becomes Unresponsive with Large Data Sets in Expo App

I’m working on an Expo React Native app that has a header, footer, and an action button toggle that animates based on the scroll direction. The app has two tabs on the home page: “Social Posts” and “Rankings”. The “Social Posts” tab displays dynamic content loaded from an API, while the “Rankings” tab is static.

The issue I’m facing is with the “Social Posts” tab, which uses a FlatList to display a large amount of data. When the list reaches the end, it loads more data using onEndReached. The header, footer, and button animate out of view when scrolling down, which is working as expected. However, as the data grows larger, the onScroll event in the FlatList becomes unresponsive and does not fire consistently.

This inconsistency causes the header, footer, and button to get stuck in their last state and stop responding to scroll events. I’ve tried various performance optimizations, including using useMemo and useCallback on each list item, but the problem persists. The scroll experience becomes laggy and feels less smooth when there’s a large dataset.

Demo:

I’ve created a Snack demo that replicates the issue. You can find the complete code and see the problem in action by visiting the demo.

Here is a simplified version of my code:

import React, { useState, useEffect, useCallback } from 'react';
import { View, Text, FlatList, StyleSheet, ActivityIndicator, Image } from 'react-native';
import throttle from 'lodash.throttle';
import useWindowScrollStore from '../store/useWindowScrollStore';

function SocialFeed() {
  const [data, setData] = useState([]);
  const [page, setPage] = useState(1);
  const [loading, setLoading] = useState(false);
  const [hasMore, setHasMore] = useState(true);

  // Fetch data from the DummyJSON API
  const fetchData = async () => {
    if (loading) return;

    setLoading(true);
    try {
      const response = await fetch(`https://dummyjson.com/products?limit=10&skip=${(page - 1) * 10}`);
      const result = await response.json();

      if (result.products.length > 0) {
        setData((prevData) => [...prevData, ...result.products]);
        setPage(page + 1);
      } else {
        setHasMore(false);
      }
    } catch (error) {
      console.error('Error fetching data:', error);
    } finally {
      setLoading(false);
    }
  };

  // Initial fetch
  useEffect(() => {
    fetchData();
  }, []);

  const onListScroll = useCallback(
    throttle((nativeEvent) => {
      useWindowScrollStore.getState().setScrollY(nativeEvent.contentOffset.y);
    }, 100),
    []
  );

  const renderItem = ({ item }) => (
    <View style={styles.postContainer}>
      <Image source={{ uri: item.thumbnail }} style={styles.image} />
      <Text style={styles.postText}>{item.title}</Text>
      <Text style={styles.descriptionText}>{item.description}</Text>
    </View>
  );

  const renderFooter = () => {
    if (!loading) return null;
    return <ActivityIndicator size="large" color="#0000ff" />;
  };

  return (
    <View style={styles.container}>
      <FlatList
        data={data}
        renderItem={renderItem}
        keyExtractor={(item) => item.id.toString()}
        onScroll={({ nativeEvent }) => onListScroll(nativeEvent)}
        onEndReached={hasMore ? fetchData : null}
        onEndReachedThreshold={0.5}
        ListFooterComponent={renderFooter}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 10,
  },
  postContainer: {
    backgroundColor: '#f0f0f0',
    padding: 15,
    marginVertical: 8,
    borderRadius: 10,
  },
  postText: {
    fontSize: 16,
    color: '#333',
    fontWeight: 'bold',
  },
  descriptionText: {
    fontSize: 14,
    color: '#666',
    marginTop: 5,
  },
  image: {
    width: '100%',
    height: 200,
    borderRadius: 10,
    marginBottom: 10,
  },
});

export default SocialFeed;

What I’ve Tried:

  • Throttling the onScroll event using lodash.throttle.
  • Using useMemo and useCallback to optimize the rendering of list items.
  • Implementing performance improvements by reducing re-renders and optimizing state updates.

The Problem:

Despite these optimizations, the onScroll event still lags or stops firing correctly when the list becomes large. This issue affects the header, footer, and action button toggle functionality, making them unresponsive to scroll events.

Question:

How can I improve the responsiveness of the onScroll event in a FlatList with large datasets? Are there other optimization techniques I should consider for better performance and a smoother scroll experience?

Any advice or suggestions would be greatly appreciated!

Error: Cannot find module ‘./types/express’ when running TypeScript project with ts-node

Iam geting 2 errors that are below , created the src/types/express.d.ts and

 `declare global {
             namespace Express {
             interface Request {
               user?: any;
                  }
                 }
                  }

                 export {}; // This line makes this file a module`

if i remove the import in the src/index.ts Property ‘user’ does not exist on type ‘Request<ParamsDictionary, any, any, ParsedQs, Record<string, any>>’.
enter image description here
if i import it import "./types/express";
the error

enter image description here

Tsconfig.json

{ "compilerOptions": { "target": "ES6", "module": "commonjs", "outDir": "./dist", "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, "skipLibCheck": true, "typeRoots": ["./node_modules/@types", "./src/types"] }, "include": ["src/**/*.ts", "src/types/**/*.d.ts"] }

i tried to to add the user to the request in the express.js

not able to interact with monaco editor api in leetcode

I am working on a chrome extension where I want to inject some piece of text into monaco code editor present on leetcode.

I am tring to access the monaco api through chrome extension but I am failing to do so, but if I type window.monaco in console of browser it shows the monaco object.

Following is the code I am using for accessing monaco object

manifest.json

{
  "manifest_version": 3,
  "name": "LeetCode Template Injector",
  "version": "1.0",
  "description": "Insert algorithm templates into LeetCode editor.",
  "permissions": ["activeTab", "scripting"],
  "action": {},
  "content_scripts": [
    {
      "matches": ["https://leetcode.com/problems/*"],
      "js": ["content.js"]
    }
  ]
}

content.js

function checkMonacoEditor() {
  const interval = setInterval(() => {
    if (typeof monaco !== "undefined" && monaco.editor.getModels().length > 0) {
      console.log("monaco editor found");
    } else {
      console.log("Waiting for Monaco editor...");
    }
  }, 1000);
}

window.addEventListener("load", function () {
  checkMonacoEditor();
});

Here is a screenshot of my browser console

enter image description here

How to implement scroll-based video switching like YouTube Shorts in HTML/CSS/JavaScript?

I’m working on a video container design using HTML, CSS, and JavaScript, and I want to implement a feature where scrolling automatically switches to the next video, similar to how YouTube Shorts behaves.

I have a basic design where I load a video, along with interaction buttons like follow, like, comment, and share. However, I need help with the JavaScript functionality that allows the video to change when the user scrolls past the current one.

Here’s my HTML structure:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Responsive Shorts Design</title>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" rel="stylesheet">
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div class="container">
        <!-- Video Section -->
        <div class="video-container">
            <video id="video-player" src="videos/video1.mp4" controls></video>
            <!-- Follow Button -->
            <button class="follow-button">Follow</button>

            <!-- Interaction buttons on the video player -->
            <div class="actions">
                <div class="action-button like">
                    <span><i class="fa-regular fa-heart"></i></span>
                    <span>452</span>
                </div>
                <div class="action-button comment">
                    <span><i class="fa-regular fa-comment"></i></span>
                    <span>6</span>
                </div>
                <div class="action-button share">
                    <span><i class="fa-solid fa-share"></i></span>
                    <span>Share</span>
                </div>
            </div>
        </div>
    </div>

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

And here’s my CSS:

/* Global Styles */
body, html {
    margin: 0;
    padding: 0;
    overflow-x: hidden;
}

.container {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    overflow: hidden;
}

.video-container {
    width: 100%;
    height: 100%;
}

video {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-family: Arial, sans-serif;
}

body {
    background-color: #181818;
    color: white;
}

.container {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-between;
    padding: 20px;
    height: 100vh;
}

/* Video Section */
.video-container {
    width: 100%;
    max-width: 400px;
    height: 800px;
    position: relative;
    display: flex;
    justify-content: center;
    align-items: center;
}

video {
    width: 100%;
    height: 100%;
    border-radius: 10px;
    position: relative;
}

/* Follow Button */
.follow-button {
    position: absolute;
    top: 10px;
    right: 10px;
    padding: 8px 12px;
    background-color: #ff0000;
    color: white;
    border: none;
    border-radius: 20px;
    cursor: pointer;
    font-size: 14px;
    transition: background-color 0.3s ease;
}

.follow-button:hover {
    background-color: #cc0000;
}

/* Actions Section: Buttons on the right side of the video */
.actions {
    position: absolute;
    right: 10px;
    top: 20%;
    display: flex;
    flex-direction: column;
    align-items: center;
}

.action-button {
    margin: 10px 0;
    color: white;
    text-align: center;
    cursor: pointer;
    padding: 10px;
    background-color: rgba(0, 0, 0, 0.5); /* Semi-transparent background */
    border-radius: 50%;
    width: 50px;
    height: 50px;
    opacity: 0.8; /* Transparency effect */
    transition: opacity 0.3s ease;
}

.action-button:hover {
    opacity: 1;
}

/* Ensure icons are centered within the buttons */
.action-button span {
    display: block;
}

/* Subscribe Section */
.subscribe-section {
    display: flex;
    align-items: center;
    justify-content: space-between;
    background-color: #333;
    padding: 10px 15px;
    border-radius: 10px;
    max-width: 400px;
    width: 100%;
    margin-top: 10px;
}

.profile-pic {
    width: 50px;
    height: 50px;
    border-radius: 50%;
}

.subscribe-info {
    flex-grow: 1;
    padding-left: 10px;
}

.subscribe-button {
    padding: 10px 15px;
    background-color: #ff0000;
    border: none;
    border-radius: 5px;
    color: white;
    cursor: pointer;
}

/* Responsive Media Queries */
@media (max-width: 768px) {
    .actions {
        right: 5px;
        top: 15%;
    }

    .subscribe-section {
        flex-direction: column;
        align-items: center;
        padding: 15px;
    }

    .profile-pic {
        width: 40px;
        height: 40px;
    }

    .subscribe-button {
        margin-top: 10px;
        width: 100%;
    }
}

@media (max-width: 480px) {
    .video-container {
        max-width: 100%;
    }

    .actions {
        position: static;
        flex-direction: row;
        width: 100%;
        justify-content: space-evenly;
    }
}

The idea is to switch between multiple videos automatically based on the user’s scroll interaction. I have an array of videos and need to load the next one when scrolling. Here’s the JavaScript I’ve tried:

document.addEventListener('DOMContentLoaded', function() {
    const videos = [
        "videos/video1.mp4",
        "videos/video2.mp4",
        "videos/video3.mp4",
        // Add more videos as needed
    ];

    let currentVideoIndex = 0;
    const videoPlayer = document.getElementById('video-player');

    // Function to load the next video
    function loadNextVideo() {
        currentVideoIndex++;
        if (currentVideoIndex >= videos.length) {
            currentVideoIndex = 0; // Loop back to the first video
        }
        videoPlayer.src = videos[currentVideoIndex];
        videoPlayer.play();
    }

    // Using IntersectionObserver to detect when the user scrolls past the current video
    const observer = new IntersectionObserver((entries) => {
        entries.forEach(entry => {
            if (entry.isIntersecting) {
                // If the current video is fully visible, play it
                videoPlayer.play();
            } else {
                // If the video is not visible anymore, load the next video
                loadNextVideo();
            }
        });
    }, {
        threshold: 0.75 // Video is considered visible when 75% of it is on screen
    });

    // Observing the video container
    observer.observe(videoPlayer);
});

The Issue:
I want to achieve the same experience as YouTube Shorts, where each scroll jumps directly to the next video. However, I’m not sure if this approach with IntersectionObserver is the best for this case, or if there’s a better way to do this.

What would be the best way to implement this kind of scroll-based video switching?

Edit:
my updated js:

console.log("Scroller");

// Define the video array
const videos = [
    "videos/video1.mp4",
    "videos/video2.mp4",
    "videos/video3.mp4",
    // Add more videos as needed
  ];
  
  // Get the container and video player elements
  const container = document.querySelector('.container');
  const videoPlayer = document.getElementById('video-player');
  
  // Initialize the current video index
  let currentVideoIndex = 0;
  
  // Initialize a flag to indicate whether the user has interacted with the document
  let userHasInteracted = false;
  
  // Add the scroll event listener to the container
  container.addEventListener('scroll', (e) => {
    // Get the video offset and height
    const videoOffset = videoPlayer.offsetTop;
    const videoHeight = videoPlayer.offsetHeight;
  
    // Get the scroll position and direction
    const scrollPosition = container.scrollTop;
    const scrollDirection = e.deltaY > 0 ? 'down' : 'up';
  
    // Check if the user has scrolled down and the current video is no longer visible
    if (scrollDirection === 'down' && scrollPosition > videoOffset + videoHeight - 20) {
      // Load the next video
      loadNextVideo();
    }
  });
  
  // Function to load the next video
  function loadNextVideo() {
    // Increment the current video index
    currentVideoIndex++;
  
    // Loop back to the first video if we've reached the end of the array
    if (currentVideoIndex >= videos.length) {
      currentVideoIndex = 0;
    }
  
    // Update the video player source
    videoPlayer.src = videos[currentVideoIndex];
  
    // If the user has interacted with the document, play the video automatically
    if (userHasInteracted) {
      videoPlayer.play();
    }
  }
  
  // Add an event listener to the document to listen for user interaction
  document.addEventListener('click', () => {
    // Set the flag to indicate that the user has interacted with the document
    userHasInteracted = true;
  
    // If the video is not playing, play it
    if (!videoPlayer.paused) {
      videoPlayer.play();
    }
  });
  
  // Initialize the video player with the first video
  videoPlayer.src = videos[0];

Fetch Telegram API in Google Cloud VM Instance is Failed

So, i want to send Telegram API Bot in Google Cloud VM Instance using Ubuntu latest version or the highest version. I’m using NodeJS program and fetch to run the API.

But i got this error:

TypeError: fetch failed
    at node:internal/deps/undici/undici:13185:13
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
    at async exports.sendMessage (/root/anonymous/controller/telegram/sendMessageController.js:19:21) {
  [cause]: AggregateError [ETIMEDOUT]: 
      at internalConnectMultiple (node:net:1117:18)
      at internalConnectMultiple (node:net:1185:5)
      at Timeout.internalConnectMultipleTimeout (node:net:1711:5)
      at listOnTimeout (node:internal/timers:596:11)
      at process.processTimers (node:internal/timers:529:7) {
    code: 'ETIMEDOUT',
    [errors]: [ [Error], [Error] ]
  }
}

This my code (sendMessageController.js) :

const dotenv = require("dotenv");

dotenv.config();

exports.sendMessage = async (req, res) => {
  const { message } = req.body;

  if (!req.body || Object.keys(req.body).length === 0) {
    return res.status(400).json({
      status: 400,
      message: "Bad request",
    });
  }

  try {
    const token = process.env.TELEGRAM_TOKEN;
    const url = process.env.TELEGRAM_API_URL;
    const channel = process.env.TELEGRAM_CHANNEL_ID;
    const request = await fetch(`${url}/bot${token}/sendMessage`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        chat_id: channel,
        text: message.replace(/[_*[]()~`>#+-=|{}.!-]/g, "\$&"),
        parse_mode: "MarkdownV2",
      }),
    });

    const response = await request.json();

    console.log(response);
    res.status(200).json({ status: 200, message: "Success", data: response });
  } catch (error) {
    console.error(error);
    res.status(500).json({ status: 500, message: "Internal server error" });
  }
};

I’m triggering using REST API, the issue is from this code.

I don’t now what to do, maybe you all experts can figure my problem out. If there’s a question, don’t be shy to ask for it.

Thank you

What i expect is the fetch is working, nothing failed like in Localhost.

React useState() hook not updating

I am trying to save the error API responses for the backend as an array/object using useState hook. to my surprise, the state value did not get updated. (Note: this is a practice challenge from a youtube post)

  const onSubmit = (ev) => {
    ev.preventDefault();

    const payload = { ...survey }; // destructure and create new object payload
    if (payload.image) {
      payload.image = payload.image_url;
    }
    delete payload.image_url;
    let res = null;
    if (id) {
      res = axiosClient.put(`/survey/${id}`, payload);
    } else {
      res = axiosClient.post("/survey", payload);
    }

    res
      .then((res) => {
        console.log(res);
        navigate("/surveys");
        if (id) {
          showToast("The survey was updated");
        } else {
          showToast("The survey was created");
        }
      })
      .catch((err) => {
        if (err && err.response) {
          setError(err.response.data.message);
          setErry('1234');
        }
         console.log(err, err.response);
         console.log(erry)
     
      
  
      });
  };

//the form
 <form action="#" method="POST" onSubmit={onSubmit}>

Another trial to this while trying to isolate the problem

const [count, setCount] = useState(0);

  const increment = (ev) => {
       ev.preventDefault();
      setCount(4);
      alert('The count is ' + count);
  }

//the form
 <form action="#" method="POST" onSubmit={increment }>

// i still get count as 0 every time i click submit.

what am i missing please?

Page refreshes everytime i click on download

I have made this program to generate adj list by visualizing a graph and the problem is when I download a list, the refreshes hence all my work is lost. can you please help?

heres the github link
https://github.com/Ujjwal238/graph-isomorphism
html file is
https://github.com/Ujjwal238/graph-isomorphism/blob/main/html-code.html
and js file is
https://github.com/Ujjwal238/graph-isomorphism/blob/main/javascript-code.js

const workspaces = [{
    vertices: [],
    edges: [],
    canvas: document.getElementById('graphCanvas1'),
    fileName: 'input.txt'
  },
  {
    vertices: [],
    edges: [],
    canvas: document.getElementById('graphCanvas2'),
    fileName: 'input2.txt'
  }
];

let selectedVertex = [null, null];
let draggingVertex = [null, null];
let isDrawingEdge = [false, false];
let isRemovingVertex = [false, false];

function drawVertex(ctx, x, y, index) {
  ctx.beginPath();
  ctx.arc(x, y, 20, 0, 2 * Math.PI);
  ctx.fillStyle = '#3498db';
  ctx.fill();
  ctx.stroke();
  ctx.fillStyle = '#fff';
  ctx.font = '16px Arial';
  ctx.textAlign = 'center';
  ctx.textBaseline = 'middle';
  ctx.fillText(index, x, y);
}

function drawEdge(ctx, start, end) {
  ctx.beginPath();
  ctx.moveTo(start.x, start.y);
  ctx.lineTo(end.x, end.y);
  ctx.stroke();
}

function redrawGraph(workspaceIndex) {
  const workspace = workspaces[workspaceIndex];
  const ctx = workspace.canvas.getContext('2d');
  ctx.clearRect(0, 0, workspace.canvas.width, workspace.canvas.height);
  workspace.edges.forEach(edge => drawEdge(ctx, workspace.vertices[edge[0]], workspace.vertices[edge[1]]));
  workspace.vertices.forEach((vertex, index) => drawVertex(ctx, vertex.x, vertex.y, index + 1));
}

function addVertex(workspaceIndex) {
  const workspace = workspaces[workspaceIndex - 1];
  const x = Math.random() * (workspace.canvas.width - 40) + 20;
  const y = Math.random() * (workspace.canvas.height - 40) + 20;
  workspace.vertices.push({
    x,
    y
  });
  redrawGraph(workspaceIndex - 1);
}

function toggleRemoveMode(workspaceIndex) {

  const index = workspaceIndex - 1;
  isRemovingVertex[index] = !isRemovingVertex[index];
  const btn = document.querySelector(`#workspace${workspaceIndex} button:nth-child(2)`);
  btn.textContent = isRemovingVertex[index] ? 'Cancel Remove' : 'Remove Vertex';
  workspaces[index].canvas.style.cursor = isRemovingVertex[index] ? 'not-allowed' : 'default';

}

function generateList(workspaceIndex) {
  const workspace = workspaces[workspaceIndex - 1];
  const adjacencyList = [];

  workspace.vertices.forEach((vertex, index) => {
    const neighbors = [];
    workspace.edges.forEach(edge => {
      if (edge[0] === index) {
        neighbors.push(edge[1] + 1);
      } else if (edge[1] === index) {
        neighbors.push(edge[0] + 1);
      }
    });
    adjacencyList.push(`${index + 1} ${neighbors.join(' ')}`);
  });

  const listString = adjacencyList.join('n');
  const blob = new Blob([listString], {
    type: 'text/plain'
  });
  const url = URL.createObjectURL(blob);

  const a = document.createElement('a');
  a.href = url;
  a.download = workspace.fileName;
  a.target = '_blank';
  a.click();
  URL.revokeObjectURL(url);
}

workspaces.forEach((workspace, index) => {
  workspace.canvas.addEventListener('mousedown', (event) => handleMouseDown(event, index));
  workspace.canvas.addEventListener('mousemove', (event) => handleMouseMove(event, index));
  workspace.canvas.addEventListener('mouseup', () => handleMouseUp(index));
  workspace.canvas.addEventListener('dblclick', (event) => handleDoubleClick(event, index));
});

function handleMouseDown(event, workspaceIndex) {
  const workspace = workspaces[workspaceIndex];
  const rect = workspace.canvas.getBoundingClientRect();
  const x = event.clientX - rect.left;
  const y = event.clientY - rect.top;

  const clickedVertexIndex = workspace.vertices.findIndex(v =>
    Math.sqrt((v.x - x) ** 2 + (v.y - y) ** 2) < 20
  );

  if (clickedVertexIndex !== -1) {
    if (isRemovingVertex[workspaceIndex]) {
      workspace.vertices.splice(clickedVertexIndex, 1);
      workspace.edges = workspace.edges.filter(edge => edge[0] !== clickedVertexIndex && edge[1] !== clickedVertexIndex);
      workspace.edges = workspace.edges.map(edge => [
        edge[0] > clickedVertexIndex ? edge[0] - 1 : edge[0],
        edge[1] > clickedVertexIndex ? edge[1] - 1 : edge[1]
      ]);
      redrawGraph(workspaceIndex);
      isRemovingVertex[workspaceIndex] = false;
      toggleRemoveMode(workspaceIndex + 1);
    } else if (isDrawingEdge[workspaceIndex]) {
      if (selectedVertex[workspaceIndex] !== clickedVertexIndex) {
        workspace.edges.push([selectedVertex[workspaceIndex], clickedVertexIndex]);
        redrawGraph(workspaceIndex);
      }
      isDrawingEdge[workspaceIndex] = false;
      selectedVertex[workspaceIndex] = null;
      workspace.canvas.style.cursor = 'default';
    } else {
      draggingVertex[workspaceIndex] = clickedVertexIndex;
      workspace.canvas.style.cursor = 'grabbing';
    }
  } else {
    isDrawingEdge[workspaceIndex] = false;
    selectedVertex[workspaceIndex] = null;
    workspace.canvas.style.cursor = 'default';
  }
}

function handleMouseMove(event, workspaceIndex) {
  const workspace = workspaces[workspaceIndex];
  const rect = workspace.canvas.getBoundingClientRect();
  const x = event.clientX - rect.left;
  const y = event.clientY - rect.top;

  if (draggingVertex[workspaceIndex] !== null) {
    workspace.vertices[draggingVertex[workspaceIndex]].x = x;
    workspace.vertices[draggingVertex[workspaceIndex]].y = y;
    redrawGraph(workspaceIndex);
  }
}

function handleMouseUp(workspaceIndex) {
  if (draggingVertex[workspaceIndex] !== null) {
    draggingVertex[workspaceIndex] = null;
    workspaces[workspaceIndex].canvas.style.cursor = 'default';
  } else if (selectedVertex[workspaceIndex] !== null) {
    isDrawingEdge[workspaceIndex] = true;
    workspaces[workspaceIndex].canvas.style.cursor = 'crosshair';
  }
}

function handleDoubleClick(event, workspaceIndex) {
  const workspace = workspaces[workspaceIndex];
  const rect = workspace.canvas.getBoundingClientRect();
  const x = event.clientX - rect.left;
  const y = event.clientY - rect.top;

  const clickedVertexIndex = workspace.vertices.findIndex(v =>
    Math.sqrt((v.x - x) ** 2 + (v.y - y) ** 2) < 20
  );

  if (clickedVertexIndex !== -1) {
    selectedVertex[workspaceIndex] = clickedVertexIndex;
    isDrawingEdge[workspaceIndex] = true;
    workspace.canvas.style.cursor = 'crosshair';
  }
}
body {
  font-family: Arial, sans-serif;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  margin: 0;
  background-color: #f0efef;
}

.container {
  display: flex;
  justify-content: space-around;
  width: 100%;
  max-width: 1200px;
}

.workspace {
  text-align: center;
}

.graphCanvas {
  border: 1px solid #000;
  background-color: #fff;
  cursor: default;
}

button {
  margin: 10px;
  padding: 5px 10px;
  font-size: 16px;
}

.red-button {
  background-color: red;
  /* color: white; optional, to change the text color */
}
<div class="container">
  <div id="workspace1" class="workspace">
    <h2>Graph 1 (input.txt)</h2>
    <canvas id="graphCanvas1" class="graphCanvas" width="400" height="400"></canvas>
    <br>
    <button onclick="addVertex(1)">Add Vertex</button>
    <button onclick="toggleRemoveMode(1)">Remove Vertex</button>
    <button onclick="generateList(1)">Generate Adjacency List</button>
  </div>
  <div id="workspace2" class="workspace">
    <h2>Graph 2 (input2.txt)</h2>
    <canvas id="graphCanvas2" class="graphCanvas" width="400" height="400"></canvas>
    <br>
    <button onclick="addVertex(2)">Add Vertex</button>
    <button onclick="toggleRemoveMode(2)">Remove Vertex</button>
    <button onclick="generateList(2)">Generate Adjacency List</button>
  </div>
</div>
<script src="javascript-code.js"></script>

the download part

const a = document.createElement('a');
    a.href = url;
    a.download = workspace.fileName;
    a.target = '_blank';
    a.click();
    URL.revokeObjectURL(url);

i have tried Ai,s help but all it gives are redundant answers. `

How can I contribute to beginner-friendly open-source projects in JavaScript and React as a college student?

I’m a college student with experience in JavaScript and React, and I want to start contributing to open-source projects. While I’ve researched how to get started, most resources I’ve found are too general, and I’m struggling to find projects that are beginner-friendly and relevant to my skills.

I’ve tried searching for issues labeled “good first issue” and “beginner-friendly” on GitHub, but many projects seem inactive or advanced for my level. I also want to know the best way to approach maintainers and how to submit my first meaningful pull request.

Any recommendations for active open-source projects that welcome beginners in web development, or tips on how to navigate the contribution process, would be really appreciated.