Run Typescript Within Javascript Application

I have a typescript function in plain text. How do I execute this within a javascript application?

let ts_text = `function add_five(num: number): number {
    let other_num: number = 5;
    return num + other_num;
}`;

let func = // make the function somehow

func(5); // 10

Screens overlapping momentarily when using router.push() from Expo-Router

I am trying to navigate between 2 pages using Expo Router’s router.push() method. My navigator type is stack. While the method did navigate me to the new page, there is a momentary overlapping between the old page and the new page. It seems like the old page does not disappear until the new page gets animated in, as you can see in the following image:

As you can see in the picture, the right form comes in from the right and pushes to old form to the left. The old form would stay there momentarily before it disappears

The followings are my code:

layout.tsx

import { View, Image, KeyboardAvoidingView, StyleSheet, Platform } from "react-native";
import React, { useState, useEffect } from "react";
import { LinearGradient } from 'expo-linear-gradient'; // Use expo-linear-gradient
import { useAppContext } from "@/Builder/Context/RootContext";
import { orientation } from "@/Builder/Type/Enum";
import { Stack } from "expo-router";
import { StatusBar } from "expo-status-bar";



export default function AuthenticationStackRootLayout() {
    const appContext = useAppContext();
    console.log("Current Orientation: " + appContext.deviceInitialState.orientation)
    const styles = StyleSheet.create({
        rootAuthenticationView: {
            position: 'absolute',
            left: 0,
            right: 0,
            top: 0,
            bottom: 0,
            zIndex: 1,
            
        },

        backgroundContainer: {
            position: 'absolute',
            left: 0,
            right: 0,
            top: 0,
            bottom: 0,
            zIndex: 0,
        },

        imagePortrait: {
            height: "100%",
            aspectRatio: 3 / 2,
            flexShrink: 1,
            left: -500
        },

        imageLandscape: {
            width: "100%",
            flexShrink: 1
        },

        formContainer: {
            position: 'absolute',
            left: 0,
            right: 0,
            top: 0,
            bottom: 0,
            zIndex: 2,
            elevation: 2
        },

        linearGradient: {
            position: 'absolute',
            left: 0,
            right: 0,
            top: 0,
            bottom: 0,
            zIndex: 1,
            elevation: 1
        },

    })
    return (
        <View style={styles.rootAuthenticationView}>
            <StatusBar></StatusBar>
            <View style={[styles.backgroundContainer]}>
                <Image
                    source={require("../../assets/images/BackgroundColor.jpg")}
                    style={[appContext.deviceInitialState.orientation === orientation.LANDSCAPE ? styles.imageLandscape : styles.imagePortrait
                    ]}>
                </Image>
            </View>
            <LinearGradient
                colors={['rgba(18, 18, 18, 0.2)', 'rgba(18, 18, 18, 0.7)']}
                start={{ x: 0, y: 0 }}
                end={{ x: 0, y: 0.5 }}
                style={StyleSheet.absoluteFill}
            />

            <KeyboardAvoidingView
                style={styles.formContainer}
                behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
                <Stack screenOptions={{
                    headerShown: false,
                    contentStyle: { backgroundColor: "transparent" },
                }} />
            </KeyboardAvoidingView>

        </View> 
    )
}

index.tsx

import { Redirect } from "expo-router";

export default function AuthenticationIndex(){
    return <Redirect href="/Authentication/login" />
}

Login Page (The original page)

import React, {useState} from "react";
import { View, Image, Text, Pressable, StyleSheet, Keyboard, } from "react-native";
import { LogInForm } from "@/Builder/Component/Form/LogInForm";

export default function LogInPage(){
    const [credentials, setCredentials] = useState<Record<string, string>>(
        {
            username: "",
            password: ""
        }
    )
    const [fieldFocusState, setFieldFocusState] = useState<Record<string, boolean>>(
        {
            username: false,
            password: false
        }
    )



    const styles = StyleSheet.create({

        pressableContainer: {
            position: "absolute",
            top: 0,
            right: 0,
            left: 0,
            bottom: 0,
            flexShrink: 0,
            flexDirection: 'column',
            alignItems: 'center',
            justifyContent: 'center',
            gap: 32,
        },

      });
    
    return (
        <Pressable 
                style = {[styles.pressableContainer]}
                onPress={()=>{
                    Keyboard.dismiss();
                    const updatedFocusState = {...fieldFocusState};
                    for (const key of Object.keys(updatedFocusState)){
                        updatedFocusState[key] = false
                    }
                    setFieldFocusState(updatedFocusState)
                }}>

                <View style = {{width: 350, flexDirection: 'column', alignItems: 'center', gap: 12}}>
                    <Image source={require("../../assets/images/Logo.png")} style = {{width: 60, height: 60}}></Image>
                    <Text style = {{
                        width: 220, 
                        fontSize: 20, 
                        lineHeight: 28, 
                        fontFamily: 'Roboto', 
                        fontWeight: 500, 
                        color: "#FFFFFF",
                        textAlign: 'center'}}>
                        Vui Lòng Điền Thông Tin Đăng Nhập
                    </Text>
                </View>
                <LogInForm formDataState={
                    {
                        formData: credentials,
                        handler: setCredentials
                    }
                } focusState={{
                    focusState: fieldFocusState,
                    handler: setFieldFocusState
                }}></LogInForm>
                
            </Pressable>
       
    )
} 

The Forget My Password Page (Destination Page)

import React, { useState } from "react";
import { View, Image, Text, Pressable, StyleSheet, Keyboard, } from "react-native";
import { ForgetPasswordForm } from "@/Builder/Component/Form/ForgetPasswordForm";




export default function ForgetPasswordPage() {
    const [forgetPasswordForm, setForgetPasswordForm] = useState<Record<string, string>>(
        {
            userName: "",
            businessPhoneNumber: ""
        }
    )
    const [fieldFocusState, setFieldFocusState] = useState<Record<string, boolean>>(
        {
            userName: false,
            businessPhoneNunber: false,

        }
    )

    const styles = StyleSheet.create({

        pressableContainer: {
            position: "absolute",
            top: 0,
            right: 0,
            left: 0,
            bottom: 0,
            flexShrink: 0,
            flexDirection: 'column',
            alignItems: 'center',
            justifyContent: 'center',
            gap: 32
        },

    });

    return (
        <Pressable
            style={[styles.pressableContainer]}
            onPress={() => {
                Keyboard.dismiss();
                const updatedFocusState = { ...fieldFocusState };
                for (const key of Object.keys(updatedFocusState)) {
                    updatedFocusState[key] = false
                }
                setFieldFocusState(updatedFocusState)
            }}>

            <View style={{ width: 350, flexDirection: 'column', alignItems: 'center', gap: 12 }}>
                <Image source={require("../../assets/images/Logo.png")} style={{ width: 60, height: 60 }}></Image>
                <Text style={{
                    width: 300,
                    fontSize: 20,
                    lineHeight: 28,
                    fontFamily: 'Roboto',
                    fontWeight: 500,
                    color: "#FFFFFF",
                    textAlign: 'center'
                }}>
                    Vui Lòng Điền Tên Đăng Nhập và Số Điện Thoại Công Ty
                </Text>
            </View>
            <ForgetPasswordForm
                formDataState={{
                    formData: forgetPasswordForm,
                    handler: setForgetPasswordForm
                }}
                focusState={{
                    focusState: fieldFocusState,
                    handler: setFieldFocusState
                }}></ForgetPasswordForm>

        </Pressable>

    )
}

I have tried changing the animation style to fade, which could somewhat hide the overlapping on android. The issue is still very apparent on ios. Thank you

How to make next.js build show all static files generated without squashing?

I build by next.js app like so

next build

and the output is

...

Route (app)                                             Size     First Load JS
┌ ○ /                                                   136 B           105 kB
├ ○ /_not-found                                         979 B           106 kB
├ ● /[state]/about                                      304 B           109 kB
├   ├ /alabama/about
├   ├ /alaska/about
├   ├ /arizona/about
├   └ [+47 more paths]
├ ● /[state]/agent/[agent_name]                         298 B           109 kB
├   ├ /connecticut/agent/pelletier-mechanical-services
├   ├ /connecticut/agent/petro-home-services
├   ├ /connecticut/agent/santa-energy-corporation
├   └ [+242 more paths]
├ ƒ /[state]/agents                                     327 B           109 kB
├ ƒ /[state]/blog                                       341 B           109 kB
└ ● /[state]/blog/[id]                                  341 B           109 kB
+ First Load JS shared by all                           105 kB
  ├ chunks/4bd1b696-b54c66733e4d5abb.js                 52.9 kB
  ├ chunks/517-5eea2bc287c7e3d6.js                      50.5 kB
  └ other shared chunks (total)                         1.94 kB

...

but I want to see all files, not +242 more paths.

How do I get it to show me all generated paths?

How to extract objectID from nested React props structure in Facebook Ads Manager DOM element?

I’m trying to extract the objectID from a specific DOM element in Facebook Ads Manager. The element has the class combination “_4lg0 _4lg6 _4h2q _4h2m”. When I inspect the React props of this element, I get the following nested structure:

    className: '_4lg0 _4lg6 _4h2q _4h2m',
    style: {},
    children: Array(2) [
        undefined,
        {
            $$typeof: Symbol(react.element),
            key: null,
            props: {
                children: {
                    $$typeof: Symbol(react.element),
                    key: null,
                    props: {
                        children: {
                            $$typeof: Symbol(react.element),
                            key: null,
                            props: {
                                breakdownKey: 'unit',
                                breakdowns: [],
                                objectID: '120215406781110608',  // <-- Need to extract this
                                objectType: 'ADGROUP',
                                rowType: 'summary'
                                // ... other props
                            }
                        }
                    }
                }
            }
        }
    ]
}

I’ve tried accessing it using:
javascript

const props = element[reactPropsKey];
const objectID = props?.children?.[1]?.props?.children?.props?.children?.props?.objectID;

But I’m not getting the objectID. What’s the correct way to traverse this nested structure to reliably extract the objectID?

Note: This is for a Chrome extension that needs to read data from Facebook Ads Manager.

Some bits of code running before they should [duplicate]

I have the following page:

const player = document.querySelector("#player")
const computer = document.querySelector("#computer")
const body = document.querySelector("body")
const face = document.querySelector("#face")
const options = document.querySelector("#options")
options.addEventListener("mousedown", (e) => {
  let target = e.target
  if (target.nodeName === "BUTTON") {
    face.setAttribute("src", "rps-cautious.svg")
  }
})
body.addEventListener("mouseup", (e) => {
  face.setAttribute("src", "rps-smiling.svg")
})
let userInput
let computerChoice
let results
options.addEventListener("click", (e) => {
  let target = e.target;
  switch (target.id) {
    case "Rock":
      userInput = 0;
      player.textContent = "Rock";
      computerInput()
      results = (compare(userInput, computerChoice))
      break;
    case "Paper":
      userInput = 1;
      player.textContent = "Paper";
      computerInput()
      results = (compare(userInput, computerChoice))
      break;
    case "Scissors":
      userInput = 2;
      player.textContent = "Scissors";
      computerInput()
      results = (compare(userInput, computerChoice))
      break;
  }
}, {
  once: true
})
console.log(results)

function computerInput() {
  computerChoice = Math.floor(Math.random() * 3);
  if (computerChoice === 0) {
    computer.textContent = "Rock"
  } else if (computerChoice === 1) {
    computer.textContent = "Paper"
  } else {
    computer.textContent = "Scissors"
  }
  return computerChoice
}

function compare(userInput, computerInput) {
  if (userInput !== computerInput) {
    if (userInput + computerInput !== 2) {
      if (userInput > computerInput) {
        return 0
      } else {
        return 1
      }
    } else if (userInput > computerInput) {
      return 1
    } else {
      return 0
    }
  } else {
    return 2
  }
}
@import url('https://fonts.googleapis.com/css2?family=Pixelify+Sans:[email protected]&display=swap');

body,
html {
  height: 100%;
  background-color: #c0c0c0;
  margin: 20px;
}

#header {
  display: flex;
  justify-content: center;
  border-top: #808080 4px solid;
  border-left: #808080 4px solid;
  border-right: white 4px solid;
  border-bottom: white 4px solid;
}

img {
  margin: 10px;
}

#playground {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  height: 75%;
  margin: 15px 0;
  border-top: #808080 4px solid;
  border-left: #808080 4px solid;
  border-right: white 4px solid;
  border-bottom: white 4px solid;
}

#results,
#options {
  display: flex;
  flex-direction: row;
  justify-content: center;
}

#options {
  justify-content: space-around;
}

p {
  font-family: "Pixelify Sans", serif;
  font-size: 100px;
  margin: 0;
}

#options>* {
  border-top: #808080 4px solid;
  border-left: #808080 4px solid;
  border-right: #808080 4px solid;
  border-bottom: #808080 4px solid;
  margin: 0 20px 20px;
}

div>button {
  font-family: "Pixelify Sans", serif;
  font-size: 30px;
  height: 90px;
  width: 150px;
  border-top: white 4px solid;
  border-left: white 4px solid;
  border-right: #808080 4px solid;
  border-bottom: #808080 4px solid;
  border-radius: 0;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <link rel="stylesheet" href="style.css">
  <script src="script.js" defer></script>
  <meta charset="UTF-8">
  <title>rock paper scissors</title>
  <link rel="icon" href="rps-smiling-icon.svg">
  <style>

  </style>
</head>

<body>
  <div id="header">
    <img alt="smiling face" src="rps-smiling.svg" id="face" onmousedown="">
  </div>
  <div id="playground">
    <div id="results">
      <p id="player">???</p>
      <p>|</p>
      <p id="computer">???</p>
    </div>
    <div id="options">
      <div>
        <button id="Rock">Rock</button>
      </div>
      <div>
        <button id="Paper">Paper</button>
      </div>
      <div>
        <button id="Scissors">Scissors</button>
      </div>
    </div>
  </div>
</body>

</html>

I noticed that some parts of Javascript code (for example the console.log(results)) runs before it should.
I’m trying to make it so it only generates the random number and compare the results AFTER the user clicked a button however it is just running before it (why I opted to put the RNG in the switch statement) why is this happening?

dynamically adding elements to select tag destroys its functionality

Im trying to dynamically add options to a select tag based on certain conditions

https://jsfiddle.net/kvnhdpyg/

                <select id="metodode" style="cursor:pointer;" >
                    <option id="first" value="" disabled selected>Escolha uma opçao</option>
                </select>



                <script>
                    document.getElementById('metodode').addEventListener('click', function(e) {
                        this.innerHTML = '';
                        const elemento = document.createElement('option');
                        elemento.text = 'Escolha uma opçao';
                        elemento.value = '';
                        elemento.disabled = true;
                        elemento.selected = true;
                        this.appendChild(elemento);

                        for (let i = 0; i < 5; i++) {
                            const elemento = document.createElement('option');
                            elemento.text = "test123" 
                            this.appendChild(elemento); 
                        }
                    });
                </script>


here is the short form version of it, dynamically adding option tags to select destroys it’s functionality, clicking on the dynamic option tags doesn’t put its text in the select tag as it would with normal option tags

i’ve tried adding event listeners as well but it doesn’t work, i can console.log() them but no click

Is there a bug in the Javascript precedence table, or in the await specification?

Below are the contents of a file I created with claude.ai’s help to demonstrate a problem. I don’t know where to submit the bug, so my main question is: Is this really a bug and if so, is it documentation ((.) method access is lower precedence than await) or implementation? If it is a bug, where should it be submitted? If it isn’t, what am I misinterpreting?

// Bug Report: Member Access (.) vs await Operator Precedence Inconsistency

// According to JavaScript's operator precedence table:
// - Member access (.) has precedence of 19
// - await has precedence of 16
// Therefore, .json() should be called before await is applied

// Setup: A function that returns a Promise that also has a json method

function getMockResponse() {
  let p = Promise.resolve({
    json: () => Promise.resolve({
      data: 'test'
    })
  });
  p.json = () => {
    console.log('Promise.json called');
    return Promise.resolve({
      data: 'from Promise.json'
    });
  };
  return p;
}

// The issue:
async function demonstratePrecedence() {
  // These two expressions should be equivalent if . has higher precedence than await
  console.log('Test 1: With direct chaining:');
  const result1 = await getMockResponse().json();
  console.log('result1:', result1); // Promise.json NOT called

  console.log('nTest 2: With parenthesized await:');
  const result2 = (await getMockResponse()).json();
  console.log('result2:', result2); // Different behavior!
}

// The following fixes work by explicitly controlling precedence:
async function demonstrateWorkarounds() {
  console.log('nTest 3: Forcing .json() first:');
  const result3 = await (getMockResponse().json());
  console.log('result3:', result3);

  console.log('nTest 4: Using two awaits:');
  const result4 = await (await getMockResponse()).json();
  console.log('result4:', result4);
}

/*
This demonstrates that despite member access (.) having higher precedence than await,
the await operator is being applied before the member access in practice.

If member access truly had higher precedence:
- getMockResponse().json() should be evaluated first
- This would call the Promise's json method (logging "Promise.json called")
- await would then be applied to the result

Instead:
- await getMockResponse() is evaluated first
- .json() is called on the resolved value
- The Promise's json method is never called

This inconsistency between documented precedence and actual behavior affects common patterns
in JavaScript, particularly when working with Promise-returning APIs that have chained methods.

Test this code by running:
async function test() {
    await demonstratePrecedence();
    await demonstrateWorkarounds();
}
test();
*/
demonstratePrecedence();

Is there way to override mocha it function?

I am trying to integrate qase.io with cypress. However with Qase, I need to follow below pattern where I need to pass test function along with ID. For eg:

describe('My First Test', () => {
  qase(1,
    it('Several ids', () => {
      qase.title('My title');
      expect(true).to.equal(true);
    })
  );
)

Is there a way I can customize the block so that it() accepts testId as whatever’s before colon.

describe('My First Test', () => {
    it('1: Several ids', () => {
      qase.title('My title');
      expect(true).to.equal(true);
    })
)

Randomly select 2 elements from an array where each element is selected 4 times and the pairs are not duplicated

I am looking to select 2 elements from an array and pair them up. Each element should be selected exactly 4 times and each pair should be unique. For example, if I have the following array:

arr = [p1, p2, p3, p7, p10, p15, p17, p19, p22, p27]

I want to generate something similar to the following:

result: [[p2,p19],[p27,p10],[p15,p3],[p19,p17],[p27,p7],[p3,p17],[p27,p22],[p22,p3],[p15,p1],[p7,p2],[p19,p1],[p17,p15],[p15,p27],[p3,p7],[p10,p22],[p17,p27],[p2,p3],[p27,p1],[p19,p22],[p2,p17]]

In what I have “working” I get unique pairs, however, I do not get exactly 4 instance of each element. I get the following instances for each element:
p1 – 3, p2 – 4, p3 – 5, p7 – 3, p10 – 2, p15 – 4, p17 – 5, p19 – 4, p22 – 4, p27 – 6

Here is the array I am using:

let arr = [p1, p2, p3, p7, p10, p15, p17, p19, p22, p27];

Here is the function that I am using:

function selectUniquePairs(arr) {
    if (arr.length < 2) {
      return "Array must contain at least two elements.";
    }
  
    const selectedPairs = new Set();
    const result = [];
  
    for (let i = 0; i < arr.length * 2; i++) {
      let index1, index2;
      do {
        index1 = Math.floor(Math.random() * arr.length);
        index2 = Math.floor(Math.random() * arr.length);
      } while (index1 === index2 || selectedPairs.has(JSON.stringify([index1, index2].sort())));
  
      const pair = [arr[index1], arr[index2]];
      result.push(pair);
      selectedPairs.add(JSON.stringify([index1, index2].sort()));
    }
  
    return result;
}

Any help would be greatly appreciated.

I am wanting to do this in pure javascript, no additional libraries.

Spacebar causes the game to reset after switching to other difficulties in my typing speed game

I’m developing a typing speed game with difficulty levels (easy, medium, hard), where the game tracks typing speed, accuracy, and time. After switching from easy to medium (or other levels), when I press the spacebar to type the next character, the sample text unexpectedly resets to a new set of words.

This reset issue only occurs after switching the difficulty. The game essentially restarts, as if it’s a fresh session, and the timer and typing stats reset as well.

I’m not sure what causes this behavior. Has anyone encountered something similar or have any suggestions for fixing this issue?

What I tried:

I attempted various methods to control the reset behavior, including resetting the game state conditionally in the resetGame() function, manually updating and clearing game-related variables, and ensuring the startTime, currentIndex, and other values are properly managed when switching between difficulty levels. I also tried moving the spacebar logic out of the handleKeydown() event to a different function, but the issue persists.

What I expected:

I expected that when switching from easy to medium difficulty (or other levels), the spacebar would work as normal and move through the text without causing the game to reset or the timer to start from zero. After switching difficulty, the sampleText should update correctly and typing should continue seamlessly from the new text without a reset.

What actually happened:

Instead, after switching the difficulty and pressing the spacebar, the game behaves as though it’s a fresh session, resetting the sampleText, the typing speed, the timer, and the current character index. The game restarts as if I’ve just opened it for the first time after difficulty change.

Script.js

document.addEventListener("DOMContentLoaded", async function () {
  const timerDisplay = document.getElementById("timer");
  const speedDisplay = document.getElementById("speed");
  const accuracyDisplay = document.getElementById("accuracy");
  const textDisplay = document.getElementById("text-display");
  const retryButton = document.getElementById("retry-button");
  const changeDifficultyButton = document.getElementById("change-difficulty");
  const difficultyOptions = document.getElementById("difficulty-options");

  let sampleText = await getWords();
  let startTime, timerInterval;
  let currentIndex = 0;                 // tracks the position of the current character the user is typing
  let mistakesCounter = 0;
  let currentDifficulty = "easy";


  // Initialize game
  textDisplay.innerHTML = sampleText
    .split("")
    .map((char) => `<span>${char}</span>`)
    .join("");
  initializeCursor();
  highlightCurrentDifficulty();


  // Event listeners
  document.addEventListener("keydown", handleKeydown);
  retryButton.addEventListener("click", resetGame);
  changeDifficultyButton.addEventListener("click", toggleDifficultyOptions);
  document.querySelectorAll("#difficulty-options button").forEach((button) => {
    button.addEventListener("click", handleDifficultyChange);
  });


  // Functions

  /*
  * Upon key press
  */
  function handleKeydown(event) {
    // Start the timer on the first keypress
    if (!startTime) {
      startTime = new Date();
      startTimer();
    }

    // Ignore all keys except Backspace
    if (event.key.length > 1 && event.key !== "Backspace") return;

    const spans = textDisplay.querySelectorAll("span");
    if (event.key === "Backspace") {
      handleBackspace(spans);
      return;
    }

    // Prevent overflow
    if (currentIndex >= sampleText.length) return;

    const typedKey = event.key;
    const expectedChar = sampleText[currentIndex];

    if (typedKey === expectedChar) {
      spans[currentIndex].classList.add("correct");
    } else {
      spans[currentIndex].classList.add("incorrect");
      mistakesCounter++;
    }

    currentIndex++;
    highlightCurrentCharacter(spans);

    // Stop the timer when all characters are typed
    if (currentIndex === sampleText.length) {
      stopTimer();
      displayTypingSpeed();
      displayAccuracy();
    }
  }


  /*
  * Backspace Handler (Removes correct and incorrect text styling)
  */
  function handleBackspace(spans) {
    if (currentIndex > 0) {
      spans[currentIndex].classList.remove("current");
      currentIndex--;
      spans[currentIndex].classList.remove("correct", "incorrect");
    }
    highlightCurrentCharacter(spans);
  }


  /*
  * Initialize cursor (Place it at the start)
  */
  function initializeCursor() {
    const spans = textDisplay.querySelectorAll("span");
    if (spans.length > 0) spans[0].classList.add("current");
  }


  /*
  * Place cursor on the current letter
  */
  function highlightCurrentCharacter(spans) {
    spans.forEach((span) => span.classList.remove("current"));
    if (currentIndex < spans.length) spans[currentIndex].classList.add("current");
  }

  
  /*
  * Start Timer
  */
  function startTimer() {
    timerInterval = setInterval(() => {
      const elapsedTime = new Date() - startTime;
      const seconds = Math.floor(elapsedTime / 1000);
      timerDisplay.textContent = seconds;
    }, 1000);
  }


  /*
  * Stop Timer
  */
  function stopTimer() {
    clearInterval(timerInterval);
  }


  /*
  * Display typing speed (WPM)
  */
  function displayTypingSpeed() {
    if (!startTime) return;
    const wordsTyped = sampleText.split(" ").length;
    const timeInMinutes = (new Date() - startTime) / 1000 / 60;
    const wpm = Math.floor(wordsTyped / timeInMinutes);
    speedDisplay.textContent = wpm;
  }


  /*
  * Display accuracy
  */
  function displayAccuracy() {
    const totalChars = sampleText.length;
    if (totalChars === 0) {
      accuracyDisplay.textContent = "100.00";
      return;
    }
    const accuracy = (((totalChars - mistakesCounter) / totalChars) * 100).toFixed(2);
    accuracyDisplay.textContent = accuracy;
  }


  /*
  * API random word fetcher
  */
  async function getWords(difficulty = "easy") {
    try {
      let wordLength, wordCount;
      switch (difficulty) {
        case "easy":
          wordLength = 3;
          wordCount = 20;
          break;
        case "medium":
          wordLength = 5;
          wordCount = 30;
          break;
        case "hard":
          wordLength = 7;
          wordCount = 40;
          break;
        default:
          wordLength = 5;
          wordCount = 30;
      }

      const response = await fetch(
        `https://random-word-api.herokuapp.com/word?number=${wordCount}&length=${wordLength}`
      );
      const words = await response.json();
      return words.join(" ");
    } catch (error) {
      console.error("Error fetching words:", error);
      return "Peter piper bit a pan of pickled pepper and the quick brown fox jumps over the moon.";
    }
  }


  /*
  * Reset Game
  */
  async function resetGame() {
    stopTimer();
    timerDisplay.textContent = "0";
    speedDisplay.textContent = "0";
    accuracyDisplay.textContent = "0";
    startTime = null;
    currentIndex = 0;
    mistakesCounter = 0;

    sampleText = await getWords(currentDifficulty);
    textDisplay.innerHTML = sampleText
      .split("")
      .map((char) => `<span>${char}</span>`)
      .join("");

    const spans = textDisplay.querySelectorAll("span");
    spans.forEach((span) => {
      span.classList.remove("correct", "incorrect", "current");
    });

    initializeCursor(); // Reset the cursor to the first character
  }


  /*
  *
  */
  function toggleDifficultyOptions() {
    difficultyOptions.classList.toggle("active");
  }


  /*
  *
  */
  function handleDifficultyChange(e) {
    const selectedDifficulty = e.target.getAttribute("data-difficulty");
    currentDifficulty = selectedDifficulty; 
    resetGame(); 
    difficultyOptions.classList.remove("active"); 
    highlightCurrentDifficulty(); 
  }


  /*
  *
  */
  function highlightCurrentDifficulty() {
    document.querySelectorAll("#difficulty-options button").forEach((button) => {
      button.classList.remove("active-difficulty");
    });

    const currentDifficultyButton = document.querySelector(
      `#difficulty-options button[data-difficulty="${currentDifficulty}"]`
    );
    if (currentDifficultyButton) {
      currentDifficultyButton.classList.add("active-difficulty");
    }
  }
});

Styles.CSS

body {
  font-family: "Poppins", sans-serif;
  margin: 0;
  padding: 0;
  background-color: #f4f4f9;
  color: #33333369;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
}

h1 {
  font-size: 3.5rem;
  font-weight: 600;
  color: #000000;
  margin-bottom: 20px;
}

#text-display {
  font-size: 2.5rem;
  line-height: 1.8;
  text-align: center; 
  text-justify: inter-word;
  color: #33333361;
  margin: 20px 0;
  max-width: 1500px;
  padding: 0 30px;
  white-space: pre-wrap;
}

/* Stats Container */
.stats {
  display: flex;
  justify-content: center;
  gap: 30px;
  margin-top: 20px;
}

.stats p {
  font-size: 1.2rem;
  font-weight: 600;
  color: #555;
}

.stats span {
  color: #2c3e50;
  font-weight: 700;
}

/* Cursor and Highlight Styles */
.current {
  border-left: 3px solid #000000;
  animation: blink 0.7s infinite;
}

.correct {
  color: #000000db;
  font-size: 2.7rem;
}

.incorrect {
  background-color: rgba(255, 0, 0, 0.359);
  color: #db2612;
  text-decoration: line-through;
}

/* Blinking Cursor Animation */
@keyframes blink {
  0%,
  100% {
    border-left-color: transparent;
  }
  50% {
    border-left-color: #000102ab;
  }
}

#controls {
  position: relative;
  display: inline-block;
  margin-top: 20px;
  text-align: center;
}

#controls button {
  padding: 12px 24px;
  margin-top: 10px;
  font-size: 2.5rem;
  font-weight: 600;
  background-color: #f4f4f9;
  color: #333;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  transition: background-color 0.3s ease, transform 0.6s ease;
}

#controls button:hover {
  color: #000;
  transform: translateY(-5px);
}

#controls button:active {
  transform: translateY(0);
}

#difficulty-options {
  display: flex;
  gap: 10px;
  justify-content: center;
  margin-top: 10px;
  opacity: 0;
  transform: translateY(-10px);
  transition: opacity 0.3s ease-in-out, transform 0.3s ease-in-out;
  pointer-events: none;
}

#difficulty-options.active {
  opacity: 1;
  transform: translateY(0);
  pointer-events: all;
}

#difficulty-options button {
  font-size: 1.5rem;
  padding: 5px 10px;
  border: none;
  border-radius: 5px;
  background-color: #f4f4f9;
  color: #333;
  cursor: pointer;
  transition: all 0.3s ease;
}

#difficulty-options button.active-difficulty {
  background-color: #13111134;
  color: rgb(0, 0, 0);
}

#difficulty-options button:hover {
  background-color: #ddd;
  color: #000;
}

/* Caret style */
#change-difficulty .caret {
  display: inline-block;
  transition: transform 0.3s ease;
}

#change-difficulty .caret.down {
  transform: rotate(90deg);
}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Speed Typing Test</title>
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap" rel="stylesheet">
  <link rel="stylesheet" href="styles.css">
</head>

<body>
  <h1>TypeIt</h1>
  <div id="text-display"></div>
  <div class="stats">
    <p>Time: <span id="timer">0</span>s</p>
    <p>Speed: <span id="speed">0</span> WPM</p>
    <p>Accuracy: <span id="accuracy">0</span>%</p>
  </div>

  <div id="controls">
    <button id="retry-button">> Retry</button>
    <button id="change-difficulty"><span class="caret">></span> Change Difficulty </button>
    <div id="difficulty-options">
      <button data-difficulty="easy">Easy</button>
      <button data-difficulty="medium">Medium</button>
      <button data-difficulty="hard">Hard</button>
    </div>
  </div>
  

  <!-- Script -->
  <script src="script.js"></script>
</body>
</html>

How to send an image’s address property from an element to a quick view?

I created a quick preview of my products on the site so that the user can see the product information, including the product image, in a preview by clicking a button. This is the code for my view part where the product is on the site.
enter image description here
And this is a quick preview I made.
enter image description here
And this is the JavaScript part I wrote for it.
enter image description here

But encountered this error during execution.
enter image description here

Handling Text Selection and Dynamic Span Wrapping with Class Manipulation in plain JavaScript

i want it to so that when a user highlights a text and clicks on a button that for example makes that text bold, we convert the selected text node into a span and add a class to it.
but let say they only high light an invidiual letter, we conver that individual letter into a span and let say user then decides to highlight the rest of the text for that character, we remove the old span and retreive the class from it and group it into a new span with the old class adding into that.

this also the same vice verse. if a text ndoe is already a span and a single letter is highlighted we create its own span for it. but right now i am trying to collect the text node and i seem to be capturing text nodes with empty space and the parent container is all over the place based on different circumstances. such as double clicking highlight and where i start the highlight.
i am using the following text as a test case/

this is text is here replaceable

TLDR trying to replicate https://quilljs.com/playground/snow but without using quill or other thrid party as they dont seem to do what i want.

      let selection = this.window.getSelection();
      let node = null;

      for (let rangeNumber = selection.rangeCount-1; rangeNumber >= 0; rangeNumber--) {
          let range = selection.getRangeAt(rangeNumber);
          // range.collapse(true)
          console.log(range)
  
          if (range.startContainer === range.endContainer && range.endContainer.nodeType === Node.TEXT_NODE) {
              range.startContainer.splitText(range.endOffset);
              let textNode = range.startContainer.splitText(range.startOffset);
              rangeNodes.push(textNode);
              console.log("same container")
          } else {
        /* edge-case for rare circumstances where, the end-container may contain a text node, but not be the text node itself, end-container is redefined for iterator */
              let startContainer=range.startContainer;
              let endContainer=range.endContainer;
              if (range.endContainer.nodeType != Node.TEXT_NODE && range.endContainer.childNodes.length>range.endOffset) endContainer=range.endContainer.childNodes[range.endOffset];
              if (range.startContainer.nodeType != Node.TEXT_NODE && range.startOffset>0) startContainer=range.startContainer.childNodes[range.startOffset-1];
              /* collect all text nodes inside range, ignore them if they are marked as non-selectable through css */
              let textIterator = document.createNodeIterator(range.commonAncestorContainer, NodeFilter.SHOW_TEXT, (node) => (node.compareDocumentPosition(startContainer)==Node.DOCUMENT_POSITION_PRECEDING && node.compareDocumentPosition(endContainer)==Node.DOCUMENT_POSITION_FOLLOWING) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT );
              while (node = textIterator.nextNode()) { console.log("textirator"); if (!isTextNodeUnparsedWhitespace(node) && window.getComputedStyle(node.parentElement).userSelect!="none") rangeNodes.push(node);}
              /* separate first and final text node */
              if (range.endContainer.nodeType === Node.TEXT_NODE && window.getComputedStyle(range.endContainer.parentElement).userSelect!="none") {
                        const endNode = range.endContainer.splitText(range.endOffset);

                        const text  = document.createTextNode(range.endContainer.textContent);
                        console.log(text.textContent , "endcontainer")
                        rangeNodes.push(text);

                        // range.endContainer.parentNode.replaceChild(text, range.endContainer);  
                        
                       
                        // console.log(range.endContainer, range.endContainer,range.endContainer.parentElement, range.startOffset, range.endOffset,"end node")

                    }
                    if (range.startContainer.nodeType === Node.TEXT_NODE && window.getComputedStyle(range.startContainer.parentElement).userSelect!="none") {
                        const startNode = range.startContainer.splitText(range.startOffset);
                        // console.log(startNode, range.startContainer)
                        console.log(startNode.textContent , "startcontainer")

                        rangeNodes.unshift(startNode);
                    }
          }

      }

Using Fetch() how do I append a to an existing element ID?

I’m trying to make a rudimentary scraper for a subreddit I like.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>Place Holder</h1>
    <p id="name"></p>
</body>

<script>    

// API for get requests
let fetchRes = fetch('https://www.reddit.com/r/meme/top.json');
fetchRes.then(res =>
    res.json()).then(d => {
        console.log(d)
        // for testing purposes, use the following:
        // console.log(d.data.children[0].data.id);
        for (let i = 0; i < d.data.children.length; i++) {
            x = d.data.children[i].data.url
        
            document.getElementById("name").append("<br><img src='" + x + "'>")
            console.log(d.data.children[i].data.url);
        }
    
    })

</script>
</html>

If my code is:

.document.getElementById("name").innerHTML = x

Then it will grab the latest post/image and place it perfectly into my page. HOWEVER, if I keep the .append, it just lists all the img urls instead of properly embedding them. What am I doing wrong?

Why am I getting this binary shift error?

I have a large number:

 let v = 204391396381585;

It is below the max safe int size of 2^53.

I do a binary shift:

v >>= 6;

I am expecting the result:

v === 3193615568462

ie a whole number which is the original v but divided by 2^6

Instead I get:

v === -28160434

Can anyone tell me what might be going wrong? Obviously it is something to do with the negative bit of a number, but can anyone tell me more?