How to insert tags on different pages using EJS?

I use EJS to connect repeating parts of page structure. Can you tell me if it is possible to add tags to pages using this or another method?

I understand that you can make a nested object with page keys and tag parameters. But this is not a universal method.

Now I have this code:

import {defineConfig} from "vite";
import {resolve} from "path";
import {ViteEjsPlugin} from "vite-plugin-ejs";

export default defineConfig({
    plugins: [
        ViteEjsPlugin(),
    ],
    build: {
        rollupOptions: {
            input: {
                main: resolve(__dirname, "index.html"),
                order: resolve(__dirname, "order.html"),
                notFound: resolve(__dirname, "404.html"),
                about: resolve(__dirname, "about.html"),
                deliveryPayment: resolve(__dirname, "delivery_payment.html"),
                faq: resolve(__dirname, "faq.html"),
                paymentError: resolve(__dirname, "payment_error.html"),
                successfulPayment: resolve(__dirname, "successful_payment.html"),
                contacts: resolve(__dirname, "contacts.html"),
                corporateInformation: resolve(__dirname, "corporate_information.html"),
                searchError: resolve(__dirname, "search_error.html"),
            },
        },
    },
});
<%- include("src/templates/menu.ejs") %>
<%- include("src/templates/order-call.ejs") %>
<%- include("src/templates/cart.ejs") %>
<%- include("src/templates/header.ejs") %>

Making a Google Workspace add-on interface in HTML

I am planning to build a Google Workspace add-on. However, I am not fond of their CardService that isn’t very flexible. I would like to make a more visually appealing interface of my own, using HTML, JS, CSS.

I know the Editor add-ons lets you do that, but it is the former framework and comes with many limitations.

Is their a way to inject HTML/JS content using the CardService to be able to build custom interfaces?

Pass className to styled-components

I used the styled-components to style react-big-calendar and I need to pass classes to each part I need with a different name instead of passing a generic class to the styled component’s attrs. How can I do this?
here is my sample code

Div = styled.div.attrs(() => ({
    className: "rbc-my-header",
  })) < {
    "calendar": any,
    "offRange": any,
    "offRangeBG": any,
    "header": any,

  } >
  `
          .rbc-calendar {
            background-color: transparent;
            ${({calendar}) => calendar};
            ${({calendar}) => `className: $ { calendar.classes}`};
          }

          .rbc-off-range {
            background-color: transparent;
            opacity: 0.5;
            ${({offRange}) => offRange};
          }

          .rbc-off-range-bg {
            ${({offRangeBG}) => offRangeBG};
          }

          .rbc-header {
            background-color: transparent;
            ${({header}) => header};
          }

        `

i need to pass somthing like this

               .rbc-calendar {
                background-color: transparent;
                ${({calendar}) => calendar};
                ***className --> name of specific class***
              }
.
.
.

              .rbc-header {
                background-color: transparent;
                ${({header}) => header};
                ***className --> name of specific class***
              }

Legitimate way to add an external script to Next.js 15 app router

I’m trying to add cdn-cookieyes policy to a specific page on Next.js project, but no luck achieving that following the doc instructions.
When I add the script tag to the app.js above the main <main> tag inside the <html> tag the script content ‘the policy content’ is displaying in every page at the bottom.

When I add the script tag in cookies-policy.js page only , the content is shown only when I hard refresh the page and it’s being inserted outside the container div.

If I use the HTML generated policy then every time I do the scan I need to update it manually.

Why is JSON, fetched after login form page, displayed fullscreen instead of logged to console? (Jetty web app question)

I have a webapp running in (embedded) Jetty 12 web container.

I surf (tested with Firefox and Chrome) to the home page http://localhost:8080 that queries an endpoint servlet for JSON data and displays it to the console. The home page is behind a login form page.

The issue is as if the login form page redirected to the endpoint page instead of staying on the home page upon successful authentication.

Steps to reproduce the issue (not systematically but issue shows up consistently at the end):

  • launch ./start.sh in a terminal

  • surf to http://localhost:8080

  • login with the foo:bar credential (foo login, bar password)

  • open the browser console (and leave it open) and check that endpoint data is displayed at least once in the browser console

  • shutdown the webapp (i.e. CTRL-C in the terminal, there will be network errors in the browser console)

  • relaunch the webapp with ./start.sh in the terminal

  • check that JSON parsing errors appear in the browser console

  • refresh the browser page (which is the home page which resides at http://localhost:8080)

  • log in again

  • then (unexpected behavior) the JSON data is displayed fullscreen rather than in the console (the address bar of the browser even displays http://localhost:8080/endpoint)

So the question is: how do I prevent a simple JSON fetch to go fullscreen instead of just to the console?

Many thanks in advance.

Here is the source tree:

  • src/main/java/EndpointServlet.java

  • src/main/java/MyServlet.java

  • src/main/java/WebApp.java

  • src/main/webapp/identification.jsp

  • src/main/webapp/logout.jsp

  • src/main/webapp/WEB-INF/web.xml

  • pom.xml

  • start.sh

import java.io.IOException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

public class EndpointServlet extends HttpServlet {
  protected void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
    res.setContentType("application/json; charset=UTF-8");
    res.getWriter().append("{ "key": 123456789 }");
  }
}
import java.io.IOException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

public class MyServlet extends HttpServlet {
  protected void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
    res.getWriter().append("""
<!DOCTYPE html>
<html>
<head>
<script>
const url = "/endpoint";

async function f() {
  const response = await fetch(url, { method: "GET" });
  const data = await response.json();
  console.log(data);
}

setInterval(function() { f() }, 5000); // fetch JSON data from /endpoint every 5s
</script>
</head>
<body>Hello, web!</body>
</html>
""");
  }
}
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.security.UserStore;
import org.eclipse.jetty.ee10.webapp.WebAppContext;
import org.eclipse.jetty.util.security.Credential;

public class WebApp {
  public static void main(String[] args) throws Exception {
    Server server = new Server(8080);
    WebAppContext context = new WebAppContext();
    context.setContextPath("/");
    context.setWar(args[0]);
    HashLoginService loginService =
      new HashLoginService("Form-based user authentification realm");
    UserStore userStore = new UserStore();
    userStore.addUser("foo", Credential.getCredential("bar"), new String[] { "admin" });
    loginService.setUserStore(userStore);
    server.addBean(loginService);
    server.setHandler(context);
    server.start();
    server.join();
  }
}

identification.jsp:

<html>
<body>

<form method="POST" action="j_security_check" name="loginForm">
<input type="text" name="j_username" id="j_username" />
<input type="password" name="j_password" id="j_password" />
<input name="submit" type="submit" value="Connection" />
</form>

</body>
</html>

logout.jsp:

<%
request.getSession().invalidate();
%>

web.xml:

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
  version="6.0">

<servlet>
  <servlet-name>LoginServlet</servlet-name>
  <jsp-file>/identification.jsp</jsp-file>
</servlet>
<servlet-mapping>
  <servlet-name>LoginServlet</servlet-name>
  <url-pattern>/identification</url-pattern>
</servlet-mapping>

<servlet>
  <servlet-name>LogoutServlet</servlet-name>
  <jsp-file>/logout.jsp</jsp-file>
</servlet>
<servlet-mapping>
  <servlet-name>LogoutServlet</servlet-name>
  <url-pattern>/logout</url-pattern>
</servlet-mapping>

<servlet>
  <servlet-name>MyServlet</servlet-name>
  <servlet-class>MyServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>MyServlet</servlet-name>
  <url-pattern></url-pattern> <!-- empty "" actually means "/" -->
</servlet-mapping>

<servlet>
  <servlet-name>EndpointServlet</servlet-name>
  <servlet-class>EndpointServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>EndpointServlet</servlet-name>
  <url-pattern>/endpoint</url-pattern>
</servlet-mapping>

<login-config>
  <realm-name>Form-based user authentification realm</realm-name>
  <auth-method>FORM</auth-method>
  <form-login-config>
    <form-login-page>/identification</form-login-page>
  </form-login-config>
</login-config>

<security-role>
  <role-name>admin</role-name>
</security-role>

<security-constraint>
  <web-resource-collection>
    <url-pattern>/*</url-pattern>
  </web-resource-collection>
  <auth-constraint>
    <role-name>admin</role-name>
  </auth-constraint>
</security-constraint>

</web-app>

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>testproject</groupId>
<artifactId>testproject</artifactId>
<packaging>war</packaging>
<version>1</version>

<name>Test project</name>
<url>http://localhost/</url>

<properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  <maven.compiler.source>21</maven.compiler.source>
  <maven.compiler.target>21</maven.compiler.target>
  <jetty.version>12.1.0</jetty.version>
</properties>

<build>
  <plugins>

    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.3</version>
      <configuration>
        <encoding>UTF-8</encoding>
        <meminitial>256m</meminitial>
        <maxmem>2048m</maxmem>
        <compilerArgs>
          <arg>-Xlint:all</arg>
          <arg>-O</arg>
        </compilerArgs>
      </configuration>
    </plugin>

    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-war-plugin</artifactId>
      <version>3.4.0</version>
      <!-- manually remove all jars from WEB-INF/lib/ -->
      <configuration>
        <packagingExcludes>WEB-INF/lib/*.jar</packagingExcludes>
      </configuration>
    </plugin>

    <plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>exec-maven-plugin</artifactId>
      <version>3.5.0</version>
      <executions>
        <execution>
          <id>run the webapp</id>
          <goals>
            <goal>java</goal>
          </goals>
        </execution>
      </executions>
    </plugin>

  </plugins>

</build>

<dependencies>

  <!-- https://mvnrepository.com/artifact/org.eclipse.jetty/jetty-server -->
  <dependency>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-server</artifactId>
    <version>${jetty.version}</version>
  </dependency>

  <!-- https://mvnrepository.com/artifact/org.eclipse.jetty/jetty-security -->
  <dependency>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-security</artifactId>
    <version>${jetty.version}</version>
  </dependency>

   <!-- https://mvnrepository.com/artifact/org.eclipse.jetty.ee10/jetty-ee10-apache-jsp -->
  <dependency>
    <groupId>org.eclipse.jetty.ee10</groupId>
    <artifactId>jetty-ee10-apache-jsp</artifactId>
    <version>${jetty.version}</version>
    <!-- workaround to remove duplicate logging classes
         see https://stackoverflow.com/questions/63910110/java-util-serviceconfigurationerror-org-apache-juli-logging-log-org-eclipse-je -->
    <classifier>nolog</classifier>
  </dependency>

  <!-- https://mvnrepository.com/artifact/org.eclipse.jetty.ee10/jetty-ee10-annotations -->
  <dependency>
    <groupId>org.eclipse.jetty.ee10</groupId>
    <artifactId>jetty-ee10-annotations</artifactId>
    <version>${jetty.version}</version>
  </dependency>

  <!-- https://mvnrepository.com/artifact/org.eclipse.jetty.ee10/jetty-ee10-servlet -->
  <dependency>
    <groupId>org.eclipse.jetty.ee10</groupId>
    <artifactId>jetty-ee10-servlet</artifactId>
    <version>${jetty.version}</version>
  </dependency>

  <!-- https://mvnrepository.com/artifact/org.eclipse.jetty.ee10/jetty-ee10-webapp -->
  <dependency>
    <groupId>org.eclipse.jetty.ee10</groupId>
    <artifactId>jetty-ee10-webapp</artifactId>
    <version>${jetty.version}</version>
  </dependency>

</dependencies>

</project>

start.sh:

#!/bin/bash
mvn exec:java -Dexec.mainClass=WebApp -Dexec.args="target/testproject-1.war"

How can I make div content appear on page load if a specific value is saved to session storage?

I’m making an online choose-your-own-adventure-style novelization of Deltarune, and there are events that only happen if you’ve done something previously (like speak to a character or collect an item). I’m doing this with sessionStorage/localStorage, and it’s working well to display a name the player chooses, but I can’t figure out how to make a section of text appear with this method (though I assume it’s possible).

Basically, if the player selects a certain dialogue option, the value “yesChalk” of key “talkNoelleChalk” will be saved to sessionStorage (this part is not actually implemented yet, but I know how to do it. I’ve been doing this manually with the inspect tool for testing). On another page, I want to automatically run a function when the page loads to check if the player has this value, and if they do, to then show a div containing extra dialogue.

JavaScript:

function showNoelleChalk() {
  const talkNoelleChalk = sessionStorage.getItem("talkNoelleChalk");
  var x = document.getElementById("noelleChalk");
  if (x.style.display === "block" && talkNoelleChalk === "yesChalk") {
    x.style.display = "none";
  } else {
    x.style.display = "block";
  }
}

HTML div with extra dialogue:

<div id="noelleChalk">
  <p>this is the dialogue</p>
</div>

Running the script:

<body onLoad="showNoelleChalk()">

CSS that should keep the div hidden:

#noelleChalk {
  width: 100%;
  padding-left: 0;
  padding-right: 0;
  text-align: left;
  display: none;
}

I have also tried giving the div a class with display:none;, but that doesn’t seem to work either. I think there’s probably something I’m doing wrong with the script.

The GreedyMesh Function is not rendering correctly

Ive tried multiple different versions and tried bug fixing, but i cant figure this out. My game is failing to render anything and it gives this error:

(index):568  Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'mergeGeometries')
    at greedyMesh ((index):568:52)
    at rebuildWorldMesh ((index):617:16)
    at Socket.<anonymous> ((index):777:3)
    at Emitter.emit (index.js:136:20)
    at Socket.emitEvent (socket.js:553:20)
    at Socket.onevent (socket.js:540:18)
    at Socket.onpacket (socket.js:508:22)
    at Emitter.emit (index.js:136:20)
    at manager.js:217:18

Does anyone know how to fix it? heres the github repo and the game link

Ive tried different versions, asking on other platforms, looking at the lines of code individually

Problem with publishing Jupyter Notebook online

I am currently working on an interactive UI in Jupyter Notebook based mainly on IPy Widgets to feature 3D interactive models created and exported previously using Blender. I used an HTML 3D model viewer to show the 3D model (see code below), which works perfectly fine but when I try to publish the Jupyter Notebook e.g. using Voíla it will show everything except for the 3D model (see images attached). Has anyone else encountered this issue or has an idea of how to solve it?

Any hint would be much appreciated, cheers!

JupyterNotebook before publishing with 3D model shown correctly

JupyterNotebook after publishing with Voila

The HTML model viewer code:

from IPython.display import HTML, Javascript, display

# Load the model-viewer script once
display(Javascript("""
if (!window.modelViewerLoaded) {
    const script = document.createElement('script');
    script.type = 'module';
    script.src = 'https://unpkg.com/@google/model-viewer/dist/model-viewer.min.js';
    document.head.appendChild(script);
    window.modelViewerLoaded = true;
}
"""))

# Define the model viewer display function
def display_model_waterdepth(glb_path):
    return HTML(f"""
    <div class="mv-wrap" style="position: relative; width: 100%; height: 375px;">
      <model-viewer src="{glb_path}" alt="Waterdepth model"
        interaction-prompt="auto" interaction-prompt-threshold="8000"
        disable-default-lighting shadow-intensity="0" shadow-softness="0"
        exposure="0.003" environment-image="neutral" camera-controls 
        background-color="#FDF0F5" camera-orbit="0deg 0deg 7000m" 
        min-camera-orbit="auto auto 1m" max-camera-orbit="auto auto 10000m"
        field-of-view="45deg"
        style="width: 100%; height: 100%; filter: brightness(1.0) contrast(1.3);">
      </model-viewer>

      <div style="position: absolute; bottom: 10px; right: 10px; 
                  display: flex; flex-direction: column; align-items: flex-end; gap: 5px; z-index: 10;">
        <button data-zoomplus style="background-color: #f8f8f8; width: 25px; height: 25px;">+</button>
        <button data-zoomminus style="background-color: #f8f8f8; width: 25px; height: 25px;">-</button>
        <button data-reset style="background-color: #f8f8f8; width: 25px; height: 25px;">⟳</button>
        <button data-focus="1" style="background-color: #f8f8f8; width: 100px; height: 25px;">Neubacher Au</button>
        <button data-focus="2" style="background-color: #f8f8f8; width: 100px; height: 25px;">Ofenloch</button>
      </div>
    </div>

    <script>
    (function() {{
      const root = document.currentScript.previousElementSibling;
      const viewer = root.querySelector('model-viewer');

      root.querySelector('[data-zoomplus]').addEventListener('click', () => {{
        const o = viewer.getCameraOrbit();
        viewer.cameraOrbit = `${{o.theta}}rad ${{o.phi}}rad ${{o.radius * 0.9}}m`;
      }});
      root.querySelector('[data-zoomminus]').addEventListener('click', () => {{
        const o = viewer.getCameraOrbit();
        viewer.cameraOrbit = `${{o.theta}}rad ${{o.phi}}rad ${{o.radius * 1.1}}m`;
      }});
      root.querySelector('[data-reset]').addEventListener('click', () => {{
        viewer.cameraOrbit = "0deg 0deg 7000m";
        viewer.cameraTarget = "auto auto auto";
        viewer.fieldOfView = "45deg";
        viewer.jumpCameraToGoal();
      }});
      root.querySelectorAll('[data-focus]').forEach(btn => {{
        btn.addEventListener('click', () => {{
          const area = btn.getAttribute('data-focus');
          if (area === "1") {{
            viewer.cameraOrbit = "0deg 0deg 2300m";
            viewer.cameraTarget = "-850m 0m -450m";
          }} else {{
            viewer.cameraOrbit = "55deg 0deg 1800m";
            viewer.cameraTarget = "1000m 230m -250m";
          }}
          viewer.jumpCameraToGoal();
        }});
      }});
    }})();
    </script>
    """)

Objects as keys in maps: Memory duplication?

I would like to map from objects that already exist elsewhere in the code, to, say, numbers.

var map = new Map();
var keyObj = {a: "b"};

map.set(keyObj, 3);

Does keyObj now exist twice in memory? Or is only a address to the original keyObj stored in the map?

choosing between thing to create like an app [closed]

This are the topic I want to create like an app :

  1. AI-Powered Mental Health Companion
  2. Sustainable Shopping Scanner
  3. Remote Work Productivity Booster
  4. Personalized Nutrition Coach
  5. AR Home Workout Trainer
  6. Local Community Swap Network
  7. AI Language Learning Buddy
  8. Pet Care Reminder & Vet Finder

I want to create something valuable to people and provide value and I am between the line.

SO I am trying to create something, that can help people and I am still in process

AG Grid React: nested (child) grid blinks on every 5s update even with immutableData + deltaRowDataMode. How do I stop the flash?

I have a parent AG Grid that renders a nested child grid inside a custom “detail” row. I poll an API every 5 seconds and update both the parent rows and the child rows. The child grid visibly blinks (flashes) on each poll, which looks like it is being torn down and recreated.

I’m already using:

Stable row IDs (getRowId) for both grids based on Tick + Time

immutableData and deltaRowDataMode on both grids

React.memo on the child grid with a custom prop comparer

An update helper that diffs incoming rows and only moves/updates what changed

Still getting a flash on the second grid whenever new data arrives.

Only changed rows should update. The nested grid should not tear down or blink when polling updates arrive.

What happens

On every poll, the child grid area flashes for a frame. It looks like React is re-rendering the child grid container or AG Grid is remounting the rows despite stable IDs.

How the UI is structured

I do not use AG Grid’s built-in Master/Detail.

I emulate a detail row by injecting an extra row with __kind: “detail” below the clicked parent row.

That detail row cellRenderer returns a component (another ).

React-pdf-highloghter first time load issue

import { useCallback, useEffect, useRef, useState } from "react"
import { XIcon } from "lucide-react"

import { Button } from "../ui/button"
import {
  RightDrawer,
  RightDrawerTitle,
  RightDrawerHeader,
  RightDrawerContent,
  RightDrawerClose,
  RightDrawerDescription,
} from "@/components/right-drawer"

import {
  PdfLoader,
  PdfHighlighter,
  Highlight,
  Popup,
  AreaHighlight,
  type IHighlight,
  Tip,
  ScaledPosition,
  NewHighlight,
  Content,
} from "react-pdf-highlighter"

import { Spinner } from "../ui/spinner"

export interface SourceWithCitations {
  title: string
  document_url: string
  citations: any[]
}

interface DocumentWithCitationsSidebarProps {
  isOpen: boolean
  onClose: () => void
  sources: SourceWithCitations | null
}

const HighlightPopup = ({ comment }: { comment?: { text?: string; emoji?: string } }) =>
  comment && comment.text ? (
    <div className="Highlight__popup">
      {comment.emoji} {comment.text}
    </div>
  ) : null

const resetHash = () => {
  document.location.hash = ""
}

const getNextId = () => String(Math.random()).slice(2)

const parseIdFromHash = () =>
  document.location.hash.slice("#highlight-".length)

export function DocumentWithCitationsSidebar({
  isOpen,
  onClose,
  sources,
}: DocumentWithCitationsSidebarProps) {

  const [highlights, setHighlights] = useState<Array<IHighlight>>(sources?.citations ?? [])

  // store scrollTo ref from PdfHighlighter
  const scrollViewerTo = useRef<(highlight: IHighlight) => void>(() => {})

  // Reset highlights whenever sources change
  useEffect(() => {
    if (sources?.citations) {
      const mapped = sources.citations.map((c, i) => ({
        id: c.id ?? String(i + 1),
        content: c.content ?? { text: "" },
        comment: c.comment ?? {},
        position: c.position,
      }))
      setHighlights(mapped)
    } else {
      setHighlights([])
    }
  }, [sources])

  // After highlights are set, force re-render/scroll
  useEffect(() => {
    if (highlights.length > 0 && scrollViewerTo.current) {
      // wait for PdfHighlighter to fully render pages
      setTimeout(() => {
        scrollViewerTo.current(highlights[0])
        // trigger a resize to ensure highlights paint correctly
        window.dispatchEvent(new Event("resize"))
      }, 50)
    }
  }, [highlights])

  const handleOpenChange = (open: boolean) => {
    if (!open) {
      onClose()
    }
  }

  const getHighlightById = useCallback(
    (id: string) => highlights.find((h) => h.id === id),
    [highlights],
  )

  const scrollToHighlightFromHash = useCallback(() => {
    const highlight = getHighlightById(parseIdFromHash())
    if (highlight) {
      scrollViewerTo.current(highlight)
    }
  }, [getHighlightById])

  useEffect(() => {
    window.addEventListener("hashchange", scrollToHighlightFromHash, false)
    return () => {
      window.removeEventListener("hashchange", scrollToHighlightFromHash, false)
    }
  }, [scrollToHighlightFromHash])

  const addHighlight = (highlight: NewHighlight) => {
    console.log("Saving highlight", highlight)
    setHighlights((prev) => [
      { ...highlight, id: getNextId() } as IHighlight,
      ...prev,
    ])
  }

  const updateHighlight = (
    highlightId: string,
    position: Partial<ScaledPosition>,
    content: Partial<Content>,
  ) => {
    console.log("Updating highlight", highlightId, position, content)
    setHighlights((prev) =>
      prev.map((h) =>
        h.id === highlightId
          ? {
              ...h,
              position: { ...h.position, ...position },
              content: { ...h.content, ...content },
            }
          : h,
      ),
    )
  }

  return (
    <RightDrawer open={isOpen} onOpenChange={handleOpenChange}>
      <RightDrawerContent className="w-[700px] max-w-[90vw]">
        <RightDrawerHeader className="flex items-center justify-between p-6 pb-4 border-b border-slate-100">
          <div>
            <RightDrawerTitle className="text-lg font-semibold text-slate-900">
              {sources?.title}
            </RightDrawerTitle>
            <RightDrawerDescription className="text-sm text-slate-500">
              {sources?.document_url}
            </RightDrawerDescription>
          </div>
          <RightDrawerClose asChild>
            <Button
              variant="ghost"
              size="sm"
              className="text-slate-400 hover:text-slate-600 hover:bg-slate-50"
            >
              <XIcon className="w-4 h-4" />
            </Button>
          </RightDrawerClose>
        </RightDrawerHeader>

        {sources?.document_url && (
          <PdfLoader url={sources.document_url} beforeLoad={<Spinner />}>
            {(pdfDocument) => (
              <PdfHighlighter
                pdfDocument={pdfDocument}
                enableAreaSelection={(event) => event.altKey}
                onScrollChange={resetHash}
                scrollRef={(scrollTo) => {
                  scrollViewerTo.current = scrollTo
                }}
                onSelectionFinished={(
                  position,
                  content,
                  hideTipAndSelection,
                  transformSelection,
                ) => (
                  <Tip
                    onOpen={transformSelection}
                    onConfirm={(comment) => {
                      addHighlight({ content, position, comment })
                      hideTipAndSelection()
                    }}
                  />
                )}
                highlightTransform={(
                  highlight,
                  index,
                  setTip,
                  hideTip,
                  viewportToScaled,
                  screenshot,
                  isScrolledTo,
                ) => {
                  const isTextHighlight = !highlight.content?.image

                  const component = isTextHighlight ? (
                    <Highlight
                      isScrolledTo={isScrolledTo}
                      position={highlight.position}
                      comment={highlight.comment}
                    />
                  ) : (
                    <AreaHighlight
                      isScrolledTo={isScrolledTo}
                      highlight={highlight}
                      onChange={(boundingRect) => {
                        updateHighlight(
                          highlight.id,
                          { boundingRect: viewportToScaled(boundingRect) },
                          { image: screenshot(boundingRect) },
                        )
                      }}
                    />
                  )

                  return (
                    <Popup
                      key={index}
                      popupContent={
                        <HighlightPopup comment={highlight.comment} />
                      }
                      onMouseOver={(popupContent) =>
                        setTip(highlight, () => popupContent)
                      }
                      onMouseOut={hideTip}
                    >
                      {component}
                    </Popup>
                  )
                }}
                highlights={highlights}
              />
            )}
          </PdfLoader>
        )}
      </RightDrawerContent>
    </RightDrawer>
  )
}

This code works correctly to load the documents but the highlights are not coming in the start. When i click on the document anywhere only then I am able to see them why?

I guess somehow the highlights are not able to be present in the start but somehow they comes in one-click. That is what I am not able to understand actually.

Slider inside of Horizontal FlatList: dragging slider also scrolls FlatList

I have a React Native screen that renders a horizontal FlatList.
Each item in the list contains a Slider (from @react-native-community/slider).

  • On iOS, when I try to drag the slider thumb horizontally, the FlatList scroll gesture also gets triggered.
  • On Android, it works fine: the slider moves without scrolling the list.
  <FlatList
          data={pages}
          ref={flatListRef}
          horizontal
          pagingEnabled
          bounces={false}
          showsHorizontalScrollIndicator={false}
          keyExtractor={(_, index) => index.toString()}
          onMomentumScrollEnd={handleScroll}
          renderItem={({ item }) => (
            <View style={[styles.pageContainer, { width: containerWidth }]}>
              {item.map((device: any) => (
                 <TouchableOpacity style={[styles.groupHeader, { width: containerWidth }]} key={device.id}>
              <Textc size={mvs(24)} medium>{groupName}</Textc>
              <Image source={bulbOn} style={[styles.iconImage, { width: s(100) }]} />
              <View style={{ height: mvs(42), justifyContent: 'center', width: '60%' }}>
                <Slider
                  animateTransitions
                  maximumTrackTintColor={Colors.gray400}
                  minimumTrackTintColor={Colors.primary}
                  thumbTintColor={Colors.primary}
                  // value={value}
                  minimumValue={0}
                  maximumValue={100}
                  step={1}
                  onSlidingComplete={([num]) => {
                     setValue(num)
                    onAction("LED_BRIGHTNESS", num)
                  }}
                />
              </View>
            </TouchableOpacity>
              ))}
            </View>
          )}
        />

I’ve tried:

  • Wrapping Slider in TouchableOpacity or PanGestureHandler → didn’t help.

  • onStartShouldSetResponderCapture={() => true} on parent View on Slider → but it stops the slider and flatlist still scrolls

  • Temporary fix: disable FlatList scroll while dragging the slider using onSlidingStart and onSlidingComplete

Is there a proper way to let the slider thumb consume horizontal gestures, without disabling FlatList scrolling manually?

How to correctly close a listening port in oak?

I’m trying to close the port manually (in somewhere else) but not sure the way to do it.

A smallest example:

import { Application, Router } from 'jsr:@oak/oak'
const app = new Application()
const router = new Router()

app.use(router.routes())
app.use(router.allowedMethods())

router.get('/', (ctx) => {
  ctx.response.body = JSON.stringify({ message: 'Hello, Oak!' })
})

const ac = new AbortController()
const promise = app.listen({ port: 8000, signal: ac.signal })

async function close() {
  ac.abort()
  await promise
  // never reached
  console.log('Server closed')
}

await close()

Vue V-for to loop through Objects in Array to display with intput type text box and select option in html page

The below code is a working code. The “additional” columns displays correctly, just like a simple input box. But I would like to edit this code to “select” option for “sex” and “city”. Would be great if someone gives suggestion. Thank you.

    function student(){
       this['name']='',
       this['age']='',
       this['course']='',
       this['additional']=[]
    }

    function additional(){
      this['sex']='',
      this['phone']='',
      this['city']=''
    }

    var student = new student();

    var data=new Vue({
    el="#app",
    data(){
       return{
         student:student,
         sexOptions:['Male','Female'],
         cityOptions:['city1','city2','city3']
       }
    },
    mounted(){
    },
    methods: {
    createadditional: function(){
    var val = this.student['course'];
    var len = this.student['additional'].length;
    var diff = val - len;
    
    if(diff < 0){
      this.student['additional'].splice(diff);
      }else if (diff > 0){
      while (len < val){
      var newadditional = new additional();
      this.student['additional'].push(newadditional);
      len++;
      }
     }  
    },      
   },
   watch:{
   },
   computed: {
    additional_display: {
    get: function(){
    return this.student['additional'].slice(0,this.student['course']);
    },
    },
    }
 });


 <form action="saveSchoolData"  id = "schoolForm" method="post"> 
<table>
<tr> <th> Name: </th> <td> <input type="text" v-model = "school['name']"> </td> </tr>
<tr> <th> Age: </th> <td> <input type="text" v-model = "school['Age']"> </td> </tr>
<tr> <th> Course: </th> <td> <input type="text" v-model = "school['Course']"> </td>       
</tr>
</table>

<table  v-if = "school.course> 0" >
<tr>
<td>Nbr</td>
<td>Sex</td>
<td>Phone</td>
<td>City</td>
</tr>

<tr v-for='additional in additional_display' >
<td>{{additional_display.indexOf(school)+1}}</td>
<td v-for="key in Object.keys(additional)">
{{key}}
<input v-model="additional[key]"> 
</td>
</tr>

</table>

 <input type="button" value="Save" id="saveButton" onclick="saveSchool()" />

 </form>

I would like to have the code like this below, but not getting correct – the values are not getting passed through action when i click “Save”.

<tr v-for='additional in additional_display' >
<td>{{additional_display.indexOf(school)+1}}</td>
<td><select v-model="additional['sex']">
    <option v-for="option in sexOptions" v-bind:value="option">
    {{ option }}
    </option>
    </select>
</td>
<td><input type="text" v-model="additional['phone']>
<td><select v-model="additional['city']">
    <option v-for="option in cityOptions" v-bind:value="option">
    {{ option }}
    </option>
    </select>
</td>
</tr>