Need help to create animation to randomly change text characters in JS

I need to make animation like on this website in menu:
https://displaay.net/typefaces/retail/

Is there an existing solutions? I’ve tried to make it with copilot, but didn’t succeed.

<script>
document.addEventListener('DOMContentLoaded', function() {
    var titles = [
        'Text1',
        'Text12',
        'Text3'
    ];
    var currentIndex = 0;

    function changeTitle() {
        // Select the _H1 element
        var element = document.querySelector('._H1');
        if (element) {
            // Split the current title into characters and wrap each character in a span
            var chars = element.textContent.split('');
            element.innerHTML = chars.map(char => `<span>${char}</span>`).join('');

            // Function to change a character to a random one
            function changeChar(index) {
                if (index < chars.length) {
                    var randomChar = String.fromCharCode(Math.floor(Math.random() * (126 - 33 + 1)) + 33);
                    chars[index] = `<span class="animate">${randomChar}</span>`;
                    element.innerHTML = chars.join('');
                    setTimeout(() => changeChar(index + 1), 20); // Adjust the delay as needed
                } else {
                    // After all characters have changed, change the text to the next title
                    setTimeout(() => {
                        element.innerHTML = titles[currentIndex];
                        currentIndex = (currentIndex + 1) % titles.length; // Loop through the titles
                    }, 2000); // Wait for 2 seconds before changing the text
                }
            }

            // Start changing the characters
            changeChar(0);
        }
    }

    // Change the title immediately and then every 5 seconds
    changeTitle();
    setInterval(changeTitle, 5000); // 5000 milliseconds = 5 seconds
});

Does e.target work differently on mobile?

I have noticed that when I was debugging with the devtools and set it to the screen to be mobile, e.target was detecting the parent divs(especially the ones’ display is flex) instead of the children are visible and clickable. When it is just a computer screen mode, it works fine and works as it should.

Is this normal? Is there a way to work around it?

Here is my code:

<div class="top">
      <div class="list-container clicked__clue" id="books">
        <ul class="list">
          <li class="list-item book_4" draggable="true">
            <p class="list-item-name">기이현상청 사건일지</p>
          </li>
          <li class="list-item book_1" draggable="true">
            <p class="list-item-name">맨 끝줄 소년</p>
          </li>
          <li class="list-item book_5" draggable="true">
            <p class="list-item-name">억지로라도 쉬어가라</p>
          </li>
          <li class="list-item book_3" draggable="true">
            <p class="list-item-name">로펌 인 코리아</p>
          </li>
          <li class="list-item book_7" draggable="true">
            <p class="list-item-name">거미 여인의 키스</p>
          </li>
          <li class="list-item book_6" draggable="true">
            <p class="list-item-name">을사늑약 1905</p>
          </li>
          <li class="list-item book_9" draggable="true">
            <p class="list-item-name">다른 방식으로 보기</p>
          </li>
          <li class="list-item book_2" draggable="true">
            <p class="list-item-name">발이 없는 나의 여인은 노래한다</p>
          </li>
          <li class="list-item book_8" draggable="true">
            <p class="list-item-name">닐과 순다리</p>
          </li>
        </ul>
      </div>
    </div>
.list-container {
    background: #f9e2c3;
    position: relative;
    margin: auto;
}

.list {
    list-style-type: none;
    margin: 0;
    padding: 1rem;
    font-size: 1.5rem;
}

.list-item {
    display: flex;
    float: left;
    align-self: baseline;
    padding: 1rem;
    text-orientation: upright;
    writing-mode: vertical-lr;
}

.list-item-name {
    font-family: "Consolas";
    user-select: none;
}
const list = document.querySelector(".list");

let draggedTarget;
let helper;
document.addEventListener("dragstart", function(e) {
  draggedTarget = e.target;

  helper = document.createElement("div");
  helper.innerText = draggedTarget.querySelector(".list-item-name").innerText;
  helper.style.position = "absolute";
  helper.style.top = "-9999px";
  helper.style.padding = "1rem";
  helper.style.backgroundColor = "#000";
  helper.style.color = "#ddd";
  helper.style.fontSize = "1.5rem";
  helper.style.fontFamily = "Consolas";
  document.querySelector(".top").appendChild(helper);
  
  e.dataTransfer.setDragImage(helper, 0, -30);
});

document.addEventListener("dragenter", function(e) {
    
    if (e.target !== draggedTarget && e.target.classList[0] === "list-item") {
        const ep = e.target.previousElementSibling;
        const en = e.target.nextElementSibling;
        const dp = draggedTarget.previousElementSibling;
        const dn = draggedTarget.nextElementSibling;

        if (!ep && !dn) {
            list.removeChild(draggedTarget);
            e.target.insertAdjacentElement("beforebegin", draggedTarget);
        } else if (!en && !dp) {
            list.removeChild(draggedTarget);
            e.target.insertAdjacentElement("afterend", draggedTarget);
        } else if (ep && ep != draggedTarget) {
            list.removeChild(e.target);
            list.removeChild(draggedTarget);
            ep.insertAdjacentElement("afterend", draggedTarget);
            draggedTarget.insertAdjacentElement("afterend", e.target);
        } else if (!ep) {
            list.removeChild(e.target);
            list.removeChild(draggedTarget);
            dn.insertAdjacentElement("beforebegin", e.target);
            e.target.insertAdjacentElement("beforebegin", draggedTarget);
        } else if (en && en != draggedTarget) {
            list.removeChild(e.target);
            list.removeChild(draggedTarget);
            en.insertAdjacentElement("beforebegin", draggedTarget);
            draggedTarget.insertAdjacentElement("beforebegin", e.target);
        } else if (!en) {
            list.removeChild(e.target);
            dp.insertAdjacentElement("afterend", e.target);
        }
  } 
});

document.addEventListener("dragover", function(e) {
  e.preventDefault(); // why necessary ?
});

document.addEventListener("drop", function(e) {
  e.preventDefault();
  helper.parentNode.removeChild(helper);
}); 

Force an async method to stop running it’s code

Is there a way to force an async method to stop running? Or is there a simple way to add support to stop running an async method?

I have this code that a user can start by clicking a start button:

async runTests() {
      await this.test1();
      await this.test2();
      await this.test3();
      await this.test4();
      await this.test5();
      await this.test6();
      await this.test7();
      await this.test8();
      await this.test9();
      await this.test10();
}

But now I need a way to stop it.

Is there a way to cancel this call or to exit out of it midway?

I would love something like,

window.cancelAsyncFunction(this.runTest);

Note: Typescript converts async calls into some pseudo async Javascript so I believe it’s possible but there would be benefits to having a native call if one exists.

Transform a javascript into pyscript

I just want to translate the following js script

<script>
        let textbox = document.getElementById("message");

        let timer = setTimeout(function() {
            location.reload();
        }, 5000);
        // Every 5 seconds, messages will get refreshed 

        textbox.onkeydown = function(e) { // Once key pressed, then function starts & timer stops
            clearTimeout(timer)

            timer = setTimeout(function() {
                location.reload(); // reload starts whole process again
            }, 5000) // User get 5 seconds between key presses to continue writing their message
        };
    </script>

into pyscript

Devise Layout for Login

I create custom layout for admin and not using applicaiton.html.erb, i am using new layout admin.html.erb and i can import in any controller and its working fine, but i need to use this for devise login page (session ) i tried alot of ways but no luck so far, if i add this line in application_contrller.rb its working fine (layout ‘home’) but i dont need for all of my application only for admin side login page.

i tried this as well in application.rb but no luck

config.to_prepare do
Devise::SessionsController.layout “admin”

end

My Colum Carousels won’t come back around when I want them to

I have a few columns to display content on a React page I’m building. I’ve been able to animate them so they reach the end of the container and then loop back around – however the first image waits for the second image to pass through the container before showing up again, leaving a large gap of white space for a few seconds which will get more problematic as I add more images. Any help would be appreciated!

import React, { useState, useEffect } from 'react';
import '../../App.css';


function Portfolio() {
    const [offset1, setOffset1] = useState(0);
    const [offset2, setOffset2] = useState(0);
    const [offset3, setOffset3] = useState(0);
    const columnHeight = 500; // Height of each col
    const numColumns = 5; // Number of col
    const totalHeight = columnHeight * numColumns; // Total height of all columns

    useEffect(() => {
        const workHeight = document.querySelector('.work').clientHeight;
        
        const interval = setInterval(() => {
            setOffset1(prevOffset1 => {
                // Move images upwards
                const newOffset1 = prevOffset1 - 1;

                // Check if offset reached below the work height
                if (newOffset1 <= -workHeight) {
                    // Reset offset to work height to restart the loop
                    return workHeight;
                } else {
                    return newOffset1;
                }
            });

            setOffset2(prevOffset2 => {
                // Move images downwards (reverse direction)
                const newOffset2 = prevOffset2 + 1;

                if (newOffset2 >= workHeight) {
                    
                    return -workHeight;
                } else {
                    return newOffset2;
                }
            });
        }, 20); // Adjust speed 

        return () => clearInterval(interval);
    }, []);
    return (
        <div className="work" style={{  zIndex: '-1' }}>
            <div className="column" style={{ transform: `translateY(${offset1}px)` }} >
                <div className="item">
                    <img src={require("../../assets/pictures/hair4.jpeg")} alt="hair"/>
                </div>
                <div className="item">
                    <img src={require("../../assets/pictures/lambchops.jpg")} alt="hair" />
                </div>
            </div>
            <div className="column" style={{ transform: `translateY(${offset2}px)` }}>
                <div className="item">
                    <img src={require("../../assets/pictures/hair2.jpeg")} alt="hair" />
                </div>
                <div className="item four">
                    <img src={require("../../assets/pictures/hair3.jpeg")} alt="hair" />
                </div>
            </div>
            <div className="column" style={{ transform: `translateY(${offset1}px)` }}>
                <div className="item nine">
                    <img src={require("../../assets/pictures/boyf.jpeg")} alt="hair" />
                </div>
                <div className="item nine">
                    <img src={require("../../assets/pictures/cool.jpeg")} alt="hair" />
                </div>
            </div>
            <div className="column" style={{ transform: `translateY(${offset2}px)` }}>
                <div className="item">
                    <img src={require("../../assets/pictures/balcony.jpeg")} alt="hair" />
                </div>
                <div className="item eight">
                    <img src={require("../../assets/pictures/niketech.jpeg")} alt="hair" />
                </div>
            </div>
            
            <div className="column" style={{ transform: `translateY(${offset1}px)` }}>
                <div className="item">
                    <img src={require("../../assets/pictures/sinkdye.JPG")} alt="hair" />
                </div>
                <div className="item">
                    <video autoPlay muted loop>
                        <source src={require("../../assets/video/final_mov.mp4")} type="video/mp4" />
                        Your browser does not support the video tag.
                    </video>
                </div>
            </div>
        </div>
    );
}

export default Portfolio;

I tried using pure CSS styles instead of script, I also tried adding the transform property to each item and each image, but no dice.

How to Replace values within an object that is in an array?

The problem I am facing is that I am trying to replace the text and date with an edit function. I got it working to a point where it is replacing the text via the DOM, but when the page refreshes the edited version resets to its old values. I think I know why, it is because the values within the object that is in the array need to stay changed and it is not, which I do not think I am doing correctly.

I think maybe using a map, which could create a new array and render the updated array on the DOM.

Please review the code below:

let Editedmodal = document.querySelector("#edit-modal");
let editBtn = document.querySelector(".edit");

function editTask(id) {
  let taskIndex = taskArray.findIndex((task) => task.id === id);
  let taskElement = document.querySelector(`.task-to-do[data-id="${id}"]`);

  let Editedmodal = document.querySelector("#edit-modal");


  EditedInputTask.value = taskArray[taskIndex].task;
  EditedInputDate.value = taskArray[taskIndex].date;

  Editedmodal.style.display = "grid";
  /*Submit Edited task Form*/
  EditedsubmitForm.addEventListener("click", (e) => {

    e.preventDefault();
    /*Form Validaion*/
    if (!EditedInputTask.value) {
      EditedInputNoTask.style.display = "block";
      EditedInputTask.style.marginTop = "-1em";
      timeout = setTimeout(() => {
        EditedInputNoTask.style.display = "none";
        EditedInputTask.style.marginTop = "0";
      }, 3000);
    }

    if (!EditedInputDate.value) {
      EditedInputNoDate.style.display = "block";
      EditedInputDate.style.marginTop = "-1em";

      timeout = setTimeout(() => {
        EditedInputNoDate.style.display = "none";
        EditedInputDate.style.marginTop = "0";
      }, 3000);
    } else {
      Editedmodal.style.display = "none";
      EditedInputTask.value = "";
      EditedInputDate.value = "";
      taskArray[taskIndex].task = taskObjEdited;
      taskArray[taskObjEdited.task] = DateStore;
    }

    taskArray[taskIndex].task = EditedInputTask.value;
    taskArray[taskIndex].date = EditedInputDate.value;

    taskElement.querySelector("#list-item-date").textContent = `Due: ${taskArray[taskIndex].date}`;
    taskElement.querySelector("#list-item-task").textContent = taskArray[taskIndex].task;

  });

function storeTaskArrayLocally() {
  localStorage.setItem("taskLocalstorage", JSON.stringify(taskArray));
}

function initializeTaskAraryFromLocalStoraege() {
  const storedTask = localStorage.getItem("taskLocalstorage");

  if (storedTask) {
    taskArray = JSON.parse(storedTask);
    renderTask();
  }
}

Jest ci flag with runInBand flag

Certainly! Here’s the revised question with additional details about the --ci flag:


Hi, quick question here. I have this command that I run in my React project. It’s executed on a pipeline for my PRs, and sometimes the tests fail.

In package.json:

"test:ci": "jest --coverage --ci --reporters=default --reporters=jest-junit"

After a few hours of research, I found that adding the --runInBand flag was a solution to those random failing tests. As far as I understand, the --ci flag configures Jest to run in Continuous Integration (CI) mode, optimizing its behavior for use in CI environments by disabling watch mode, optimizing output, and handling test execution differently for automation.On the other hand --runInBand forces Jest to run tests serially (one at a time) instead of in parallel.

My question is the following:

Does adding the --runInBand flag affect the validity of the --ci flag in the command above?

Add SVG marker to SVG Map using JS

I would like to add a SVG marker to a SVG Map that is in an iframe tag. The add is done via the press of a button on the HTML page.

`<input type="button" onclick="addMarker()">`


`<script type = "text/javascript" src="./resources/javascript/marker.js"></script>`

The addMarker() function is in the marker.js file.

The SVG marker that I would like to add is a standalone svg file in my Visual Studio Code project:

    <?xml version="1.0" ?>
    <svg id="marker" height="44" version="1.1" width="44" viewBox="0 0 25 25" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><g transform="translate(0 -1028.4)"><path d="m12.031 1030.4c-3.8657 0-6.9998 3.1-6.9998 7 0 1.3 0.4017 2.6 1.0938 3.7 0.0334 0.1 0.059 0.1 0.0938 0.2l4.3432 8c0.204 0.6 0.782 1.1 1.438 1.1s1.202-0.5 1.406-1.1l4.844-8.7c0.499-1 0.781-2.1 0.781-3.2 0-3.9-3.134-7-7-7zm-0.031 3.9c1.933 0 3.5 1.6 3.5 3.5 0 2-1.567 3.5-3.5 3.5s-3.5-1.5-3.5-3.5c0-1.9 1.567-3.5 3.5-3.5z" fill="#c0392b"/><path d="m12.031 1.0312c-3.8657 0-6.9998 3.134-6.9998 7 0 1.383 0.4017 2.6648 1.0938 3.7498 0.0334 0.053 0.059 0.105 0.0938 0.157l4.3432 8.062c0.204 0.586 0.782 1.031 1.438 1.031s1.202-0.445 1.406-1.031l4.844-8.75c0.499-0.963 0.781-2.06 0.781-3.2188 0-3.866-3.134-7-7-7zm-0.031 3.9688c1.933 0 3.5 1.567 3.5 3.5s-1.567 3.5-3.5 3.5-3.5-1.567-3.5-3.5 1.567-3.5 3.5-3.5z" fill="#e74c3c" transform="translate(0 1028.4)"/></g>
</svg>

The addMarker() function looks like this:

// ADD MARKER TO MAP

     function addMarker() {
     let marker = document.querySelector(".marker");
     const add = document.getElementById("map").contentDocument.documentElement;
  add.appendChild(marker);
};

For some reason the marker is not appearing when I press the button; I think it has to do with the how I am defining the marker (retrieving the marker SVG)?

any one can fix this interaction?

client.on(‘interactionCreate’, async interaction => {
if (!interaction.isStringSelectMenu()) return;

    // Check if the interaction is from the correct select menu
    if (interaction.customId === 'select') {
        // Check which option was selected
        const selectedOption = interaction.values[0];

        // Check which option was selected and respond accordingly
        if (selectedOption === 'option1') {
            // If option1 was selected, create a hidden channel
            const category = interaction.guild.channels.cache.find(c => c.name === 'Tickets'); // Replace with the name of your category
            if (!category) return interaction.reply('Error: Category not found.');

            // Define permission overwrites
            const permissionOverwrites = [
                {
                    id: interaction.guild.roles.everyone.id,
                    allow: ['VIEW_CHANNEL', 'MANAGE_CHANNELS'], // Allow everyone to view and manage the channel
                },
                {
                    id: interaction.user.id,
                    allow: ['VIEW_CHANNEL'], // Allow the user who triggered the interaction to view the channel
                },
                {
                    id: '1224861452347768912', // Replace with req[0].ID
                    deny: ['VIEW_CHANNEL'], // Deny access to specific role or user
                },
                {
                    id: '1224861452347768912', // Replace with staff[0].ID
                    allow: ['VIEW_CHANNEL'], // Allow access to specific role or user
                }
            ];
            
            
            

            const hiddenChannel = await interaction.guild.channels.create({
                name: 'Hidden Channel',
                type: ChannelType.GuildText,
                parent: category,
                permissionOverwrites: permissionOverwrites,
            });

            await interaction.reply(`You selected option 1 (Sell) and a hidden channel has been created: <#${hiddenChannel.id}>.`);
        } else if (selectedOption === 'option2') {
            // If option2 was selected, send a different message
            await interaction.reply('You selected option 2 (Buy).');
        }

        // Reset the select menu to its default state after selection
        const row = new ActionRowBuilder()
            .addComponents(
                new StringSelectMenuBuilder()
                    .setCustomId('select')
                    .setPlaceholder('Nothing selected')
                    .addOptions(
                        {
                            label: 'Sell',
                            description: 'This is a description',
                            value: 'option1',
                        },
                        {
                            label: 'Buy',
                            description: 'This is also a description',
                            value: 'option2',
                        },
                    ),
            );

        // Update the message with the new select menu
        await interaction.message.edit({ components: [row] });
    }
});
node:events:497
      throw er; // Unhandled 'error' event
      ^

RangeError [BitFieldInvalid]: Invalid bitfield flag or number: VIEW_CHANNEL.
    at PermissionsBitField.resolve (C:UsersvcrleDesktopTicketnode_modulesdiscord.jssrcutilBitField.js:174:11)
    at C:UsersvcrleDesktopTicketnode_modulesdiscord.jssrcutilBitField.js:168:35
    at Array.map (<anonymous>)
    at PermissionsBitField.resolve (C:UsersvcrleDesktopTicketnode_modulesdiscord.jssrcutilBitField.js:168:18)
    at PermissionOverwrites.resolve (C:UsersvcrleDesktopTicketnode_modulesdiscord.jssrcstructuresPermissionOverwrites.js:190:34)
    at C:UsersvcrleDesktopTicketnode_modulesdiscord.jssrcmanagersGuildChannelManager.js:169:89
    at Array.map (<anonymous>)
    at GuildChannelManager.create (C:UsersvcrleDesktopTicketnode_modulesdiscord.jssrcmanagersGuildChannelManager.js:169:51)
    at Client.<anonymous> (C:UsersvcrleDesktopTicketindex.js:82:72)
    at Client.emit (node:events:519:28)
Emitted 'error' event on Client instance at:
    at emitUnhandledRejectionOrErr (node:events:402:10)
    at process.processTicksAndRejections (node:internal/process/task_queues:84:21) {
  code: 'BitFieldInvalid'
}

Node.js v21.7.1
PS C:UsersvcrleDesktopTicket>

i am working on my discord.js project thats when user selects option 1 get created channel only can view author and who have staff role am seeing this error to much and i dont know how to solve it so anybody there can help ?

What is the safe way to conditional wrap input with state

Previously, I check if error exist and wrap the input and error message in div conditionally. This incur a problem that the input lose focus when re-render. Is there any way to wrap the input conditionally, I don’t want input to be wrap by div when error is not exist.

Below is my code without conditional wrapping:

import * as React from "react"

import { cn } from "@/lib/utils"
import { FieldError } from "react-hook-form";
import ErrorText from "../shared/ErrorText";

export interface InputProps
  extends React.InputHTMLAttributes<HTMLInputElement> {
  error?: FieldError | undefined;
  errorClassName?: string;
}

const Input = React.forwardRef<HTMLInputElement, InputProps>(
  ({ className, type, error, errorClassName, ...props }, ref) => {
    return <div className="flex flex-col">
      <input
        type={type}
        className={cn(
          "flex h-12 w-full rounded-xl border border-input bg-background px-3 py-2 text-md file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
          className
        )}
        ref={ref}
        {...props}
      />
      {error && <ErrorText className={errorClassName}>{error.message}</ErrorText>}
    </div>
  }
)
Input.displayName = "Input"

export { Input }

Below is my code with conditional wrapping. This lose focus when re-render (error message change):

export interface InputProps
  extends React.InputHTMLAttributes<HTMLInputElement> {
  error?: FieldError | undefined;
  errorClassName?: string;
}

const Input = React.forwardRef<HTMLInputElement, InputProps>(
  ({ className, type, error, errorClassName, ...props }, ref) => {
    const child = (
      <>
        <input
          type={type}
          className={cn(
            "flex h-12 w-full rounded-xl border border-input bg-background px-3 py-2 text-md file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
            className
          )}
          ref={ref}
          {...props}
        />
      </>
    )

    if (error) {
      return (
        <div className="flex flex-col gap-1">
          {child}
          {<ErrorText className={errorClassName}>{error.message}</ErrorText>}
        </div>
      )
    }
    return child;
  }
)
Input.displayName = "Input"

export { Input }

Integration of Synxis with C# Webview and Sebre APIs

I’m currently working on integrating SynXis with a C# webview to streamline the process of pushing values from an ID scanner into fields such as first name, last name, and address. Additionally, I’m interested in retrieving data post-reservation, such as confirmation numbers and stay dates. Initially, I attempted to achieve this directly on the website but encountered a cross-origin iframe issue. Subsequently, I discovered that Sebre offers a comprehensive set of APIs. However, I’m uncertain which specific APIs would enable me to accomplish these tasks. My overarching objective is to scan an ID, extract the data, and seamlessly inject it into SynXis to enhance the efficiency of front desk operations.

I need a method to allow me to inject and get data from a SynXis site.

How to round an average down using Math.Floor?

In javascript, when I use Math.round on the number 2.5, it rounds to the number 3, when I need to get the number 2

The option of using Math.floor does not suit me

I wrote a function to solve the problem, but out of curiosity I had a question – is there an easier way to achieve the result?

Thank you.

Here is my function:

function MathRoundFloor(number, attribute) {
    let number_trunc = Math.trunc(number * 100) / 100
    let last_digits = Number.isInteger(number_trunc)
      ? number_trunc % 10
      : number_trunc.toString().slice(-2)
    let last_digit = Number(last_digits.replace('.', ''))
    if (last_digit == 5 && !attribute) {
      number = Math.floor(number_trunc * 1) / 1
    } else if (last_digit == 50 && !attribute) {
      number = Math.floor(number_trunc * 10) / 10
    } else if (last_digit == 5 && attribute) {
      number = Math.floor(number_trunc * 1) / 1
    } else if (last_digit == 50 && attribute) {
      number = Math.floor(number_trunc * 10) / 10
    } else if ((last_digit !== 5 || last_digit !== 50) && attribute) {
      number = Math.round(number_trunc * 1) / 1
    } else {
      number = Math.round(number_trunc * 10) / 10
    }

    console.log(number_trunc, last_digit, last_digits, number)
    return number
  }

How can we know user location or Ip address in React?

I want to know user location and i tried multiple api but all of them are giving me wrong state and city name, if i don’t provide ip address, like this api -> https://ipapi.co/json
but if i pass ip address to above api then i get correct state and city name.

So can anyone suggest how to get user ip address so i can pass in above url or how can i get user address like correct state and city. [I am running a react project]

Thank you

How do I look for the 7shape in the game of Connect 4 using bitboards for each player?

The shape I am looking for looks like this:

enter image description here

I have two bitboards that represent two players in the game Connect 4. The bits that are used are bits from 0 to 48, so 49 bits in total. The representation looks like this:

  6 13 20 27 34 41 48   55 62     Additional row
+---------------------+ 
| 5 12 19 26 33 40 47 | 54 61     top row
| 4 11 18 25 32 39 46 | 53 60
| 3 10 17 24 31 38 45 | 52 59
| 2  9 16 23 30 37 44 | 51 58
| 1  8 15 22 29 36 43 | 50 57
| 0  7 14 21 28 35 42 | 49 56 63  bottom row
+---------------------+

The top row is not being used for anything particular, but this setup makes it easier to check for wins. There are 7 columns and 6 rows as in the game of Connect 4.

The bits are structured as follows:

... 0000000 0000000 0000010 0000011 0000000 0000000 0000000 // encoding Xs
... 0000000 0000000 0000001 0000100 0000001 0000000 0000000 // encoding Os
      col 6   col 5   col 4   col 3   col 2   col 1   col 0

So we use 7 bits for each column, we ignore the last bit in each column as there are only 6 rows per column.

The position in the picture can be represented with two bits.

Red (player 1) bitboard: 101000011000001100000000. The most significant bit here is the middle column move at the bottom. The first move that red made in the middle of the board.

Here is the bitboard for player 0 (yellow): 1010000000100000010000001. The least significant bit here is the leftmost move by yellow at the bottom of the board.

In order to confirm this 7shape, we need to check that all reds pieces exists, the way it is drawn on the picture, but at the same time make sure that the two crossed positions are not full, but empty.

I tried first to see if I could identify the 7shape without the two crossed out positions.

I tried this function:

has7shape(bitboard, player) {
    const bp = bitboard[player];
    if ((bp & (bp >> 2n) & (bp >> 7n) & (bp >> 8n) & (bp >> 15n)) !== 0n) return true; 
    console.log(bitboard[player].toString(2));
    console.log(bitboard[1-player].toString(2));
    return false;        
}

I tried to count the red piece position in this way: Red bitboard: 101000011000001100000000. I can see that if I start counting from the left, I go first two times to the right to find the second red piece we need, then I go 7 times to find the next, then 8 times, then the last one at 15 times.

But the code returns false in this position.

How can I identify this shape for the red player, including the two crossed out spots that should not be filled, but empty.