scroll to the top of the page in react/js

I have a page diveded in 3 components 1)sidebar 2)content wrapper which containts the 1)LoggedIn div and 2)main content after the submition of the form a modal is shown and after that i want the main content to scroll up in the original position (like refreshing the page)

This is the code for the MainPage component

<div className="main-container">
            <Sidebar />
            <div className="content-wrapper">
                <div className="LoggedIn">
                    <p className="LoggedInAs">
                        Συνδεδεμένος ως {user} 
                    </p>
                </div>
                <div className="content">
                    {children}
                </div>
            </div>
        </div>

and then this is the code for the Employee component

function handleSubmit(event) {
        event.preventDefault();
        if (name && epitheto && code) {
            handleAddYpallilos();
            setName("");
            setEpitheto("");
            setCode("");
            setShowModal2(true);
            const cont = document.querySelector(".content");
            cont.scrollTo({
                top: 0,
                behavior: 'smooth'
            })
        } else {
            console.log("ERROR");
        }
    }
return(<div className="content">...<div/>)

the problem is that i dont get the error from the consolelog so that means the code is performing but it doesnt work??

window scrollto top in react/js

I have a page diveded in 3 components 1)sidebar 2)content wrapper which containts the 1)LoggedIn div and 2)main content after the submition of the form a modal is shown and after that i want the main content to scroll up in the original position (like refreshing the page)

This is the code for the MainPage component

<div className="main-container">
            <Sidebar />
            <div className="content-wrapper">
                <div className="LoggedIn">
                    <p className="LoggedInAs">
                        Συνδεδεμένος ως {user} 
                    </p>
                </div>
                <div className="content">
                    {children}
                </div>
            </div>
        </div>

and then this is the code for the Employee component

function handleSubmit(event) {
        event.preventDefault();
        if (name && epitheto && code) {
            handleAddYpallilos();
            setName("");
            setEpitheto("");
            setCode("");
            setShowModal2(true);
            const cont = document.querySelector(".content");
            cont.scrollTo({
                top: 0,
                behavior: 'smooth'
            })
        } else {
            console.log("ERROR");
        }
    }
return(<div className="content">...<div/>)

Socket io not listening to events

I’m using node.js and socket.io v4.8.0. I’m trying to create a basic chat application that updates my postgress db once an event such as “send message” has been called. I am able to establish a connection. However whenever I try to listen to an event the callback function is never triggered.

My client side and server side version match too both being v4+


import express from "express";
import { Server } from "socket.io";
import { authMiddleware } from "./middleware";
import { createServer } from "http";
import { getDb } from "./db";
import { chatParticipant, message } from "./schema";
import { and, eq } from "drizzle-orm";

const app = express();
const httpServer = createServer(app);
const io = new Server(httpServer);
const port = process.env.PORT || 8080;
const db = getDb();

app.use(authMiddleware);

app.use(express.json());

const INACTIVITY_TIMEOUT = 10 * 60 * 1000;

io.on("connection", (socket) => {
  console.log("A user connected");

  let currentChatId: number | null = null;
  let currentUserId: string | null = null;
  let inactivityTimer: NodeJS.Timeout | null = null;

  function resetInactivityTimer() {
    if (inactivityTimer) {
      clearTimeout(inactivityTimer);
    }
    inactivityTimer = setTimeout(() => {
      console.log(`Closing inactive connection for user ${currentUserId}`);
      socket.disconnect(true);
    }, INACTIVITY_TIMEOUT);
  }

  resetInactivityTimer();

  socket.on("join chat", async (chatId: number, userId: string) => {
    console.log("join chat", chatId, userId);
    resetInactivityTimer();
    try {
      const userChatParticipant = await db.query.chatParticipant.findFirst({
        where: and(
          eq(chatParticipant.chatId, chatId),
          eq(chatParticipant.userId, userId)
        ),
      });

      if (!userChatParticipant) {
        socket.emit("error", "You are not a participant of this chat");
        return;
      }

      currentChatId = chatId;
      currentUserId = userId;
      socket.join(`chat_${chatId}`);
      console.log(`User ${userId} joined chat ${chatId}`);

      const recentMessages = await db
        .select()
        .from(message)
        .where(eq(message.chatId, chatId))
        .orderBy(message.createdAt)
        .limit(50);

      socket.emit("recent messages", recentMessages);
    } catch (error) {
      console.error("Error joining chat:", error);
      socket.emit("error", "An error occurred while joining the chat");
    }
  });

  socket.on("leave chat", () => {
    resetInactivityTimer();
    if (currentChatId && currentUserId) {
      socket.leave(`chat_${currentChatId}`);
      console.log(`User ${currentUserId} left chat ${currentChatId}`);
      currentChatId = null;
      currentUserId = null;
    }
  });

  socket.on("send message", async (content: string) => {
    resetInactivityTimer();
    if (!currentChatId || !currentUserId) {
      socket.emit("error", "You are not in a chat room");
      return;
    }

    try {
      const [newMessage] = await db
        .insert(message)
        .values({
          senderId: currentUserId,
          chatId: currentChatId,
          content,
        })
        .returning();

      io.to(`chat_${currentChatId}`).emit("new message", {
        ...newMessage,
        content: newMessage.content,
      });
    } catch (error) {
      console.error("Error sending message:", error);
      socket.emit("error", "An error occurred while sending the message");
    }
  });

  socket.on("disconnect", () => {
    console.log("User disconnected");
    if (inactivityTimer) {
      clearTimeout(inactivityTimer);
    }
  });
});

// Start the server
httpServer.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});```


Expecting the console logs to be logged and the database to be updated/queried.

“Images not loading on Vercel deployment but work on localhost”

I have my Node application deployed on Vercel: node-demo-ashen.vercel.app. The problem I am encountering is that on localhost:3000 the images are loading fine, but my images are not loading on Vercel. I have also configured my vercel.json file several times:
{
“version”: 2,
“builds”: [
{
“src”: “server.js”,
“use”: “@vercel/node”
}
],
“routes”: [
{
“src”: “/images/(.)”,
“dest”: “/public/images/$1”
},
{
“src”: “/(.
)”,
“dest”: “/server.js”
}
]
}
Help me fix this issue.

I have tried configuring the vercel.json file and also tried logging out and logging in again to resolve the issue, but it seems that it is not working. The images are loading fine on localhost, but on Vercel, images are not loading at all.

emailjs emails going to spam

i am using emailjs service in one of my work for a company in contact page.The issue is the Email sent from the contact Page is directing to spam folder in Gmail app.

how to get the email to the general page.i am using Gmail as the service provider

Error promise timeout when running whatsapp bot

I’m encountering an issue when running my WhatsApp bot using the Baileys library. Every time I try to use the “pppanjang” feature to change or set the WhatsApp profile picture, I receive the following error:



Error: Timed Out

    at C:UsersHP G4ODownloadsplatform-toolsryo2node_modules@whiskeysocketsbaileyslibUtilsgenerics.js:136:32 {

      data: {

        stack: 'Errorn' +

          '    at promiseTimeout (C:\Users\HP G4O\Downloads\platform-tools\ryo2\node_modules\@whiskeysockets\baileys\lib\Utils\generics.js:131:19)n' +

          '    at waitForMessage (C:\Users\HP G4O\Downloads\platform-tools\ryo2\node_modules\@whiskeysockets\baileys\lib\Socket\socket.js:114:53)n' +

          '    at Object.query (C:\Users\HP G4O\Downloads\platform-tools\ryo2\node_modules\@whiskeysockets\baileys\lib\Socket\socket.js:136:22)n' +

          '    at okta (C:\Users\HP G4O\Downloads\platform-tools\ryo2\oka.js:1829:12)'

      },

      isBoom: true,

      isServer: false,

      output: {

        statusCode: 408,

        payload: {

          statusCode: 408,

          error: 'Request Time-out',

          message: 'Timed Out'

        },

        headers: {}

      }

    }

}

This happens when I send the message “pppanjang” which is supposed to configure WhatsApp profile settings. However, I always get this timeout error.

Has anyone encountered this issue before or know what might be causing it? Any help would be appreciated!

I tried using the “pppanjang” feature, which is supposed to set the WhatsApp bot’s profile picture. I expected the bot to update the profile picture successfully, but instead, I encountered a “Timed Out” error. This happens every time I send the “pppanjang” command.

Stuck trying to get list item to appear upon click of button

Trying to have “li” appear every time I click the add button. My function is set to have an addEventListener but the function isn’t working.

Here is my JS:

document.querySelector('#submit-btn').addEventListener('click', addATodoItem)



function addATodoItem (){

    //contains value of input
    let formInput = document.querySelector('#myInput').value;
   //selects the unordered list
    const list = document.querySelector("#myUL");
    //puts in the value of input in a new li in the selected unordered list
    list.innerHTML += `<li><a href="#"${formInput}</li>`;
}

I double checked my code and even saw the HTML to see if anything has changed, but I can’t even get the function to console.log when I click it so I feel like there is something broken to the function being called.

I am expecting that when I click the ‘add’ button, the value will appear as a new HTML <li>

Here is my HTML too:

<section id="myHeader" class="header">
    <h2>My To Do List</h2>
    <input type="text" id="myInput" placeholder="Add to do...">
    <input id="submit-btn" type="submit" value="Add">
</section>
<section>
    <ul id="myUL">
        <li></li>
    </ul>
</section>

Server 499 Error Specifically when using Firefox

I am going to try to provide enough detail and info to make this (semi)-reproducible but there are a lot of factors at play so it might be tricky.

I have a full stack app build with React and Python. The front and back end are deployed separately, but both on Render. The domain is hosted with GoDaddy, and I am using a subdomain for the backend to avoid cookie issues.

My app works as expected in Chrome and Safari, but in Firefox I frequently get an error.

The two error messages I see are:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://api.torsera.com/process_story. (Reason: CORS request did not succeed). Status code: (null).

and

Error: 
Object { stack: "Fb@https://www.torsera.com/static/js/main.a32a5f2f.js:2:734425nOw</</m.onerror@https://www.torsera.com/static/js/main.a32a5f2f.js:2:751607nEventHandlerNonNull*Ow</<@https://www.torsera.com/static/js/main.a32a5f2f.js:2:751584nOw<@https://www.torsera.com/static/js/main.a32a5f2f.js:2:750679ne_@https://www.torsera.com/static/js/main.a32a5f2f.js:2:757729n_request@https://www.torsera.com/static/js/main.a32a5f2f.js:2:760570nrequest@https://www.torsera.com/static/js/main.a32a5f2f.js:2:759092nt/<@https://www.torsera.com/static/js/main.a32a5f2f.js:2:761020nJy/<@https://www.torsera.com/static/js/main.a32a5f2f.js:2:728072nWM@https://www.torsera.com/static/js/main.a32a5f2f.js:2:1231453nonClick@https://www.torsera.com/static/js/main.a32a5f2f.js:2:1234296nLe@https://www.torsera.com/static/js/main.a32a5f2f.js:2:39487nVe@https://www.torsera.com/static/js/main.a32a5f2f.js:2:39641n730/jr/<@https://www.torsera.com/static/js/main.a32a5f2f.js:2:59541njr@https://www.torsera.com/static/js/main.a32a5f2f.js:2:59635nFr@https://www.torsera.com/static/js/main.a32a5f2f.js:2:60052n730/$r/<@https://www.torsera.com/static/js/main.a32a5f2f.js:2:65494nuu@https://www.torsera.com/static/js/main.a32a5f2f.js:2:129152nRe@https://www.torsera.com/static/js/main.a32a5f2f.js:2:38619n$r@https://www.torsera.com/static/js/main.a32a5f2f.js:2:61346nHt@https://www.torsera.com/static/js/main.a32a5f2f.js:2:45742nKt@https://www.torsera.com/static/js/main.a32a5f2f.js:2:45524nEventListener.handleEvent*qr@https://www.torsera.com/static/js/main.a32a5f2f.js:2:60849nBr@https://www.torsera.com/static/js/main.a32a5f2f.js:2:60248n730/zr/<@https://www.torsera.com/static/js/main.a32a5f2f.js:2:60414nzr@https://www.torsera.com/static/js/main.a32a5f2f.js:2:60358n730/t.createRoot@https://www.torsera.com/static/js/main.a32a5f2f.js:2:150747n@https://www.torsera.com/static/js/main.a32a5f2f.js:2:1293094n@https://www.torsera.com/static/js/main.a32a5f2f.js:2:1293227n@https://www.torsera.com/static/js/main.a32a5f2f.js:2:1293231n", message: "Network Error", name: "AxiosError", code: "ERR_NETWORK", config: {…}, request: XMLHttpRequest }
home-page-util-functions.js:233:14

After quite a bit of research I discovered that despite the error mentioning CORS this is not really a CORS issue.

The endpoint I am hitting is returning a 200 response to the options request but the actual POST request is NOT getting any response.

I found various posts on stackoverflow and this mdn doc: mdn but none of this seem to be the issue I am having, because my request does succeed on Firefox occasionally.

I checked my server logs and I found that when my request fails there is always a log like this somewhere in server logs: 499 api.torsera.com/process_storyclientIP="69.180.xxx.xxx" requestID="893c3004-ca76-4fc4" responseTimeMS=29965 responseBytes=0 userAgent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:130.0) Gecko/20100101 Firefox/130.0"

That error doesn’t always seem to appear in the same place in the logs and importantly my backend continues to process the user request even after this error appears.

The notable thing from this error is responseTimeMS=29965 which makes me believe there is some type of timeout happening.

IMPORTANT The backend process I am running is making multiple calls to external apis. So I believe it is my connection with the external apis that is throwing the 499 error.

However, if that is the case I am not sure why it would be browser dependent.

I have tried increasing network.http.connection-timeout in Firefox and that didn’t change anything.

Here are the request headers I am using:

Accept: application/json
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: en-US,en;q=0.5
Alt-Used: api.torsera.com
Connection: keep-alive
Content-Length: 148
Content-Type: application/json
Cookie: _ga_4FS2W9D=GS1.1.172775.5.1.17258.0.0.0; _ga=GA1.1.561638967.1726769877; session=eyJhbGciOiE15OXB1Q0puYmpEN2dRTzlQT09kTnl4VG1
Host: api.torsera.com
Origin: https://www.torsera.com
Priority: u=0
Referer: https://www.torsera.com/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
TE: trailer

If there are any other details that I can provide let me know. I am very determined to get to the bottom of this issue.

How to add different scroll speed when using ScrollTrigger

I have three background-images where each one of them should have a different scrollspeed. I tried to use scrollTrigger from gsap but for some reason the scrolling speed is the same on each Image.

I have made an JSFIDDLE where you can check it out and maybe suggest how to achieve that.

Here is the code:

gsap.registerPlugin(ScrollTrigger);

    let tl = gsap.timeline({
      scrollTrigger: {
        trigger: "section",
        start: "top top",
        end: "bottom top",
        scrub: true,
      }
    });

    tl.to("#layer1", {
      backgroundPositionY: "5%", 
      ease: "none"
    }, 0) 

      .to("#layer2", {
         backgroundPositionY: "90%", 
         ease: "none"
       }, 0) 

      .to("#layer3", {
         backgroundPositionY: "40%", 
          ease: "none"
      }, 0);
  html {
      scroll-behavior: smooth;
    }

    .parallax-item {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 100%;
      min-height: 150vh;
    }

    #layer1 {
      background: url('https://images.unsplash.com/photo-1663305411753-4c305e177ff3?crop=entropy&cs=tinysrgb&fm=jpg&ixid=MnwzMjM4NDZ8MHwxfHJhbmRvbXx8fHx8fHx8fDE2NjM5NDA4ODE&ixlib=rb-1.2.1&q=80') no-repeat center center fixed;
      background-size: cover;
    }

    #layer2 {
      background: url('https://images.unsplash.com/photo-1663183539627-adbe2c8ef43d?crop=entropy&cs=tinysrgb&fm=jpg&ixid=MnwzMjM4NDZ8MHwxfHJhbmRvbXx8fHx8fHx8fDE2NjM5Mzk5ODc&ixlib=rb-1.2.1&q=80') no-repeat center center fixed;
      background-size: cover;
    }

    #layer3 {
      background: url('https://images.unsplash.com/photo-1506748686214-e9df14d4d9d0?ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80') no-repeat center center fixed;
      background-size: cover;
    }
  <section>
          <div id="layer1" class="parallax-item"></div>
          <div id="layer2" class="parallax-item"></div>
          <div id="layer3" class="parallax-item"></div>
        </section>

I have implemented a ShuffleJS select dropdown but there are a few glitches

I want to use ShuffleJS (see https://vestride.github.io/Shuffle) to filter out items on a <select> list by typing my search keyword on the <select>‘s input text area and the items in the <select> dropdown to be filtered out dynamically as I type. Unfortunately I have not managed this. And so, I followed the idea in How to add shufflejs for select tag which suggests creating a DIY <select> of some sorts which then ShuffleJS seems to handle OK.

So, instead of using a <select>:

  1. I create a <textarea> to type my search. It will act the same as the textarea of a <select>,
  2. I stored all items (to be filtered out) as <li> elements inside a <ul>,
  3. I let ShuffleJS know where these are located.

I have one complication which I think I handled well:

My option items form a very long list and I have two or more of those search-and-select elements in my form with the exact same option items. For example they can be From/To locations in a map, train stops, etc. And so I decided to use only 1 list of option items (the train stops) to be shared among many From/To/etc. search text areas in the same page/form.

This works mostly OK but there are a few problems that I need help with:

  1. The most important problem is with the logic of closing the “dropdown” containing the items to be filtered/selected when the user has made a selection by clicking on an option item in the “dropdown” or user has not made a selection by clicking elsewhere in the form. (By “dropdown” I mean the thing that pops up when I click on the search text area and contains, initially, all the option items, later to be filtered out as I type in that area.). I detect that the user has clicked on somewhere outside the search text area by the onblur event. In which case I close the “dropdown” and clear the search area with no selection by the user. This works fine. However, when the user clicks on an item on the “dropdown” with the intention to select an option item, this is still considered an onblur event for the search textarea and it is handled first, i.e. no selection, text area is cleared. By the time this is handled, there is no “dropdown” and the onclick on the option item fails. I solved this by delaying the onblur for a few milliseconds hoping that the onclick will be handled first, save the user selection and then close the “dropdown”. This works but I suspect there is a race condition looming there and I am not comfortable with this. Is there any better solution?

  2. I would like to make the options dropdown appear not only when I click on the search textarea but also when I use the keyboard to navigate the elements, using the TAB key. the onfocus event does not seem to work.

  3. When I click on a search text area and the “dropdown” appears with all the options, I can not just click on one and select it if I don’t first type something in the text area in order for ShuffleJS to do some filtering, even if I erase my typing afterwards (so as to obtain the unfiltered list of option items). In this situation (i.e. without first typing a search term), clicking on an option does not copy it onto the text area and closing the “dropdown”. Why is that and do you have any hints on how I can fix it?

I don’t use any framework. Just javascript and ShuffleJS (perhaps bootstrap/jquery).

Edit: I have a fiddle for this here : https://jsfiddle.net/bliako/8sm13gx9/11/

The code is below:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
    <meta charset="utf-8">
        <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
        <meta http-equiv="Pragma" content="no-cache" />
        <meta http-equiv="Expires" content="0" />
    <title>ShuffleJS select dropdown example</title>

    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/w3-css/4.1.0/w3.css" />

     <script src="https://cdnjs.cloudflare.com/ajax/libs/Shuffle/6.1.0/shuffle.min.js" integrity="sha512-r8mIpk3ypCMwNxH6srRZGbjHQlOFt3Mq2vrZ/iymx6g9JUqTeVavofeX6gbrxAC74X5HmBy5gxyhCm6OiXrM0Q==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
</body>

  <div class="row h-100 justify-content-center align-items-center">
    <form
      id="searchform"
      name="searchform"
      class="myappsearch"
      action=''
    >
      <div class="form-group col"> <!-- begin the A search text area -->
        <legend><span>Select A <small>(onblur is handled with a timeout after onclick, works)</small>:</span></legend>
        <textarea class="form-control form-control-sm  filter__search js-shuffle-search"
                  id="search-textarea-A"
                  type="search"
                  rows="1"
                  required
          onkeydown='handle_keydown_in_search_textarea(this, event);'
      onblur='this.value = ""; mythis = this; setTimeout(function() { close_shuffle_dropdown(mythis); }, 200);'
                  onclick='A_clicked(this);'
        ></textarea>
<!-- this is a lame solution to the dropdown disappearing before the
     onclick event on it is handled: Just act on the onblur after some
     milliseconds so that the onclick has time to be handled first:
                  onblur='close_shuffle_dropdown(this);'

      onblur='this.value = ""; mythis = this; setTimeout(function() { close_shuffle_dropdown(mythis); }, 200);'
-->
      </div> <!-- end the A search text area: -->
      <br />

      <div class="form-group col"> <!-- begin the Select B search text area -->
        <legend><span>Select B <small>(onblur is handled before onclick, problem)</small>:</span></legend>
        <textarea class="form-control form-control-sm  filter__search js-shuffle-search"
                  id="search-textarea-B"
                  type="search"
                  rows="1"
                  required
          onkeydown='handle_keydown_in_search_textarea(this, event);'
                  onblur='close_shuffle_dropdown(this);'
                  onclick='B_clicked(this);'
        ></textarea>
      </div> <!-- end the Select B search text area -->
</div>

<!-- this UL contains all the available options to select
     Shufflejs displays this in its own way in a "dropdown"
     and then, by typing on ANY of the two search textareas
     you can see the options filtered out.
     Clicking on an option will copy the value of
     that option to the respective search textarea (we have two!)
-->
<div id='select-options-container'
     class='custom-select'
     style='display:none; position:absolute;'
>
  <ul id='select-options'
      style='background:#000000;width:100px;'
  >
    <li class='select-item'
        style='color:#ffffff;'
        id='Orange'
        onclick='item_has_been_selected(this);'
    >Orange</li>
    <li class='select-item'
        style='color:#ffffff;'
        id='Black'
        onclick='item_has_been_selected(this);'
    >Black</li>
    <li class='select-item'
        style='color:#ffffff;'
        id='Green123'
        onclick='item_has_been_selected(this);'
    >Green123</li>
    <li class='select-item'
        style='color:#ffffff;'
        id='Green567'
        onclick='item_has_been_selected(this);'
    >Green567</li>
  </ul>
</div>

<script>
var Shuffle = window.Shuffle;
var currentSearchTextarea = null;

class ShufflejsFilterer {
  constructor(element) {
    this.element = element;
    this.shuffle = new Shuffle(element, {
        itemSelector: '.select-item',
        //sizer: element.querySelector('.my-sizer-element'),
    });

    this._activeFilters = [];

    // Log events:
    //this.addShuffleEventListeners();

    // create the search filter:
    this.addSearchFilter();
  }

  /**
   * Shuffle uses the CustomEvent constructor to dispatch events. You can listen
   * for them like you normally would (with jQuery for example).
   */
  addShuffleEventListeners() {
    this.shuffle.on(Shuffle.EventType.LAYOUT, (data) => {
      console.log('layout. data:', data);
    });
    this.shuffle.on(Shuffle.EventType.REMOVED, (data) => {
      console.log('removed. data:', data);
    });
  }

  // Advanced filtering
  addSearchFilter() {
    // modified to handle more than 1 search-boxes
    const searchInputs = document.querySelectorAll('.js-shuffle-search');
    if (searchInputs.length==0) {
      return;
    }
// no we call this on our
//    searchInputs.forEach( (asearchInput) => {
//      asearchInput.addEventListener('keydown', this._handleSearchKeydown.bind(this));
//    });
  }

  /**
   * Filter the shuffle instance by items with a title that matches the search input.
   * @param {Event} evt Event object.
   */
  _handleSearchKeydown(evt) {
    // this is e.g. the Search textarea A or B
    currentSearchTextarea = evt.target;
    // and this is what the user has typed as a search text
    const searchText = evt.target.value.toLowerCase();
        console.log("searching with this "+searchText);
    this.shuffle.filter((element, shuffle) => {
      // get the text content of the client element which is
      // the text (or anything else via data-attributes)
      // of each element part of the select-items set
      const contents = element.textContent.toLowerCase().trim();
      // and filter it out if it does not contain our search text
      return contents.indexOf(searchText) !== -1;
    });
  }
} // end class ShufflejsFilterer

///////////////////////////////////////
/// other JS functions
///////////////////////////////////////

function handle_keydown_in_search_textarea(
    caller_obj,
    event
){
    if (event.keyCode == 27){
        // on ESCape close the shuffle-dropdown and select nothing
        caller_obj.value = '';
        close_shuffle_dropdown(caller_obj);
        return; // nothing to do
    }
    // let ShuffleJS handle it now
    window.myFilterer._handleSearchKeydown(event);
}
function close_shuffle_dropdown(
    caller_obj
){
    console.log("close_shuffle_dropdown() : called ...");
    var selObj = document.getElementById('select-options-container');
    //selObj.style.position = 'absolute'; // already set
    selObj.style.display = 'none'; // hide
    // we need to reset the contents of the <ul>
    // if you don't complete (by clicking an item of the <ul>)
    // the <ul> appears truncated but search text is empty.
    // this is what causes it to reset!!!! it is part of _init()
    window.myFilterer.shuffle.filter(window.myFilterer.shuffle.options.group, window.myFilterer.shuffle.options.initialSort);
}

function item_has_been_selected(
    item_obj
){
    // once an item has been selected we copy its value to the currently
    // selected textarea:
    currentSearchTextarea.value = item_obj.textContent;
    // and then we close the shuffle dropdown:
    document.getElementById("select-options-container").style.display = "none";
}

// Search textarea (A) was clicked, so we show the shuffle dropdown
function A_clicked(
  obj
){
    const pos = obj.getBoundingClientRect();
    var selObj = document.getElementById('select-options-container');
    /* place the "dropdown" with all the select items in there,
       as formatted by Shufflejs, under the client element
           (search textarea)
    */
    //selObj.style.position = 'absolute'; // already set
    selObj.style.left = pos.left+'px';
    selObj.style.top = String(pos.bottom+10)+'px';
    // and show the "dropdown"
    selObj.style.display = 'inline';
}
// Search textarea (B) was clicked, so we show the shuffle dropdown
// it is the same as the above
function B_clicked(
  obj
){
console.log("my val: "+obj.value);
    A_clicked(obj);
}

///////////////////////////////////////
/// things to do when DOM loaded:
///////////////////////////////////////

document.addEventListener('DOMContentLoaded', () => {
  // create the Shufflejs filterer
  window.myFilterer = new ShufflejsFilterer(document.getElementById('select-options'));

/*
window.myFilterer.applyCss({
    INITIAL: {
      position: 'absolute',
      top: 0,
      visibility: 'visible',
      willChange: 'transform',
    }
});
*/


  ['search-textarea-A', 'search-textarea-B'].forEach( (k) => {
    var obj = document.getElementById(k);
    obj.value = '';
  });
}); // end DOMContentLoaded
</script>
</body>
</html>

How to keep Next.js Client Side and Server Side states in sync?

I’m very confused of what might be the best practise to handle server side and client side state in combination with next.js. As a side note I’m already using tanstack query and jotai for Statemanagement. But I’m open for other options. I read the whole documentation of Tanstack Query and Next.js but I’m still confused to what might be the best approach because they only covered server side or client side only but in combination seems still under dev.

Problem:

How to keep server state and client state in sync while following good practicies.

I’m having three files in this example:

Navbar (server-side)

This fetches the user server side and displays the menu depending if someone is logged in or not. It’s also fetching userData which is dependent on user so it awaits the user fetch and then fetches userData.

export default async function Navbar({ lang }: NavbarProps) {
  const supabase = createClient();

  const queryClient = new QueryClient();
  const user = await queryClient.fetchQuery({
    queryKey: ["user"],
    queryFn: () => getUserServer(supabase),
  });

  const cookieHeader = cookies().toString();
  const userData = await queryClient.fetchQuery({
    queryKey: ["userData", user?.id],
    queryFn: () => fetchUserDataServer(cookieHeader),
  });

LoggedInHome (server-side)

This fetches the user server side to redirect if a user is not logged in.

export default async function LoggedInHomePage({
  params: { lang },
}: LoggedInHomePageProps) {
  const supabase = createClient();

  const queryClient = new QueryClient();

  const user = await queryClient.fetchQuery({
    queryKey: ["user"],
    queryFn: () => getUserServer(supabase),
  });

  if (!user) {
    redirect(SIGN_IN);
  }

  await queryClient.prefetchQuery({
    queryKey: ["profile"],
    queryFn: () => fetchProfile(supabase),
  });

Affix (client-side)

An component which shows credits of a user that frequently updates but uses the
user and userData. The data is currently received by the server and updated on the client if the user is prefetched.

const TrailAffix: React.FC<TailAffixProps> = () => {
  // useQuery hook
  const {
    data: user,
    isLoading: isUserLoading,
    error: userError,
  } = useGetUser();

  // dependent useQuery hook
  const {
    data,
    isError: isUserDataError,
    isFetching,
  } = useGetUserData({
    userId: user?.id,
  });

Before I was using await queryClient.prefetchQuery({ but now as I have state on the server that is not only passing it to the client component but also uses it, I’m worried that the server-side state can becomes out of sync.
As you can see the state is on both server and server side. I’m not sure how to avoid refetches and make sure everything is only fetches once when loading the page but also in a fresh state when i update the states.

Stack:

Next.js 15 App Router
Tanstack Query 5

Add tooltip to button in rintrojs Shiny

I would like to create an introtour in my shiny app using the rintrojs package with introjs function. In this introtour I would like to add a tooltip to the next button. In the documentation of intro.js there is mentioned the Tour HTML attribute data-intro which should be the tooltip text. But I’m not sure how we could implement this in an rintrojs. Here is some reproducible code from the documentation:

library(rintrojs)
library(shiny)

ui <- shinyUI(fluidPage(
  introjsUI(), 
  mainPanel(
    introBox(
      tableOutput("mtcars"),
      data.step = 1,
      data.intro = "This is the table"
    ),
    introBox(
      actionButton("btn","Intro"),
      data.step = 2,
      data.intro = "This is the button",
      data.hint = "Here is clue"
    )
  )))
server <- shinyServer(function(input, output, session) {
  
  hintjs(session, options = list("hintButtonLabel"="That was a hint"))
  
  output$mtcars <- renderTable({
    head(mtcars)
  })
  observeEvent(input$btn,
               introjs(session, options = list("nextLabel"="Onwards and Upwards"),
                       events = list("oncomplete"=I('alert("It is over")'))))
})

shinyApp(ui = ui, server = server)

Output when you start in Intro:

enter image description here

Now I would like to add a tooltip to the “Onwards and Upwards” button. So I was wondering if anyone knows how to add a tooltip to the next button of a rintrojs?

Hiding the global javascript context with my own

I’m reading the MDN web docs on globalThis.

It says:

Note: The globalThis property is configurable and writable so that
code authors can hide it when executing untrusted code and prevent
exposing the global object.

I want to do exactly this, creating a sandbox of sorts so that a function can be written which accesses variables in the sandbox without needing to prefix it with anything and also preventing any variables not in the sandbox object from being accessible – like an improved alternative to the deprecated “with” construct which will fail to find anything not in the global context I define.

I wrote a proof of concept running in an ES6 module:

let myContext = { a:1, b:2 }
let f = ()=> {
    let savedGlobal = globalThis
    globalThis = myContext
    let ret = a+b
    savedGlobal.globalThis = savedGlobal
    return ret
}
f()

As an explanation, I am first saving the current value of globalThis to a local variable, as I expect that otherwise the original value won’t be accessible from my new global context. Then I hide the existing global context by overwriting it with my own, which the documentation seems to suggest is possible. Then I try to assign a local variable to the result of a+b which should be 1+2 = 3, then I restore the global context from the local saved value and return the value I calculated.

If I log the variables, I see that globalThis is the Window object before I assign to it, and it’s myContext after, but I still get a reference error “a is not defined” despite the fact that I would expect that it would find it in the now global context “myContext”. It also successfully ran the console.log despite the fact that I would expect it to no longer be visible after reassigning globalThis.

Behaviour of setInterval with respect to Event loop

Trying to figure out why the output of the following code is the way it is

console.log("Start");

setInterval(function() {
    console.log("setInterval");
}, 5000);

let date = new Date();
while(new Date() - date <= 10000) {}

console.log("End");

Actual Output

  • Start
  • …. 10 seconds ….
  • End
  • setInterval
  • …. 5 seconds ….
  • setInterval

Since the while block blocks the main thread for 10 seconds, the callback function of setInterval should have been pushed twice in the task queue since it has a timer of 5 seconds. So the output should have been

Expected Output

  • Start
  • …. 10 seconds ….
  • End
  • setInterval
  • setInterval
  • …. 5 seconds ….
  • setInterval