State representing an array of data in the component not getting updated when used inside a function

I am trying to make an infinite scrolling list of pokemons in react using IntersectionObserverAPI where i have an empty div element at the end of the page and when it comes to view more pokemons are fetched from the API.

But this uses the pokemons array (which is the state representing all the pokemons on the page) for the offset to load the data using the length property. But the length property inside the loadPokemons function is always 0 i don’t know why. I have tried tried many things but same thing happens.

This is the Pokemons component -:

In this whenever the observer intersects it calls the loadPokemons function which fetched the data using the fetchPokemons function by passing in the offset as pokemons.length but this always gives 0 i don’t know why. Please help.

import { useEffect, useRef, useState } from "react";
import Pokemon from "./Pokemon";
import { type Pokemon as PokemonDataType } from "./types";

type ResponseType = {
    count: number,
    next: string,
    previous: string | null,
    results: PokemonDataType[]
}

const fetchPokemons = async (url: string, offset: number, limit: number): Promise<PokemonDataType[]> => {
    const response = await fetch(`${url}?offset=${offset}&limit=${limit}`);
    const data: ResponseType = await response.json();
    const pokemons = data.results.map(result => { return { name: result.name, url: `https://img.pokemondb.net/artwork/${result.name}.jpg` } });
    return pokemons;
}

const url = "https://pokeapi.co/api/v2/pokemon";

export default function Pokemons() {

    const [pokemons, setPokemons] = useState<PokemonDataType[]>([]);
    const [isLoading, setIsLoading] = useState<boolean>(false);
    const myRef = useRef<HTMLDivElement | null>(null);

    useEffect(() => {

        const loadInitialPokemons = async () => {
            const initData = await fetchPokemons(url, 0, 12);
            setPokemons(initData);

            const observer = new IntersectionObserver((entries) => {
                for (let entry of entries) {
                    if (entry.isIntersecting && !isLoading) {
                        loadPokemons();
                    }
                }
            });

            if (myRef.current) {
                observer.observe(myRef.current);
            }
        }

        loadInitialPokemons();

    }, []);


    const loadPokemons = async () => {
        if (isLoading) return;
        setIsLoading(true);
        const morePokemons = await fetchPokemons(url, pokemons.length, 5);
        setPokemons(prevPokemons => [...prevPokemons, ...morePokemons]);
        setIsLoading(false);
    }

    return (
        <div>

            <ul>
                {pokemons.map((pokemon, idx) => <Pokemon key={idx} name={pokemon.name} url={pokemon.url} />)}
            </ul>
            {isLoading && <h4>Loading....</h4>}
            <div ref={myRef}></div>
        </div>
    );
}

This is the Pokemon type alias

export type Pokemon = {
    url: string,
    name: string
}

This is the Pokemon component -:

import { type Pokemon } from "./types";

export default function Pokemon({ name, url }: Pokemon) {
    return (
        <li style={{ display: "block", width: "100%" }}>
            <img src={url} />
            <h3 style={{ textAlign: "center" }}>{name}</h3>
        </li>
    );
}

This is the App component -:

import './App.css';
import Pokemons from './Pokemons';

function App() {

  return (
    <>
      <Pokemons />
    </>
  );
}

export default App;

At first i initialized the observer api outside the loadInitialPokemons function but it gave the same problem as it gives now with the observerAPI being initialized inside the the function.

Implement commands in a content-editable textarea in React/Javascript?

Thinking of emulating off of the content areas such as Notion or Obsidian, I’m attempting to design a page content component that allows for commands such as “/bold” that makes the following text bold, as well as deleting the command meaning “hello /bold” would be “hello ” once the command is submitted (‘enter’ or so).

Thus far, the challenge has been making use of a contenteditable as is not editable, however to do this means I have to PATCH and GET the content everytime it changes, currently utilizing through an onInput={handleInput} type of trigger.

The primary problem derives from how to edit the content when manually deleting text such as the command content. Currently, I attempt to PATCH everytime I delete a command (triggered by submitting a valid command), however this means I need to either reload the page or GET the content again which resets the cursor position alongside delays.

<div
    name="page-content" 
    id="page-content" 
    contenteditable="true"
    className="page-content-container"
    onKeyDown={handleKeyDown}
    onInput={handleInput}
/>
const updateContent = async (newContent) => {
        setContent(newContent);
    
        try {
          const response = await fetch(`/pages/${id}`, {
            method: 'PATCH',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ content: newContent }),
          });
    
          if (!response.ok) {
            const errorData = await response.json();
            console.error('Failed to update content:', errorData);
          }
        } catch (err) {
          console.error('Error:', err);
        }
    }
if (foundCommand) {
    e.preventDefault();

    // Remove the command and '/' before it from the content
    const currentContent = document.getElementById('page-content').innerHTML;
    const commandStart = currentContent.lastIndexOf('/') + 1;
    const newContent = currentContent.substring(0, commandStart - 1); // Remove command including the slash

    // Update content of the div
    document.getElementById('page-content').innerHTML = newContent;

    // Update the content
    updateContent(newContent);
    foundCommand.execute();
}

I’m sure there are better ways to do this, however I’m tackling everything for the first time and intend to redo the whole thing later on when I realize how inefficiently I designed it. Any courses on notetaking software and the like would be fantastic. Thanks!

Google Maps API update Advanced Marker

Has anyone experienced issues using the new AdvancedMarkerElement with MarkerClusterer in the latest Google Maps API update?

I’ve been digging through the docs here: MarkerClusterer GitHub, but couldn’t find a solid reason why my marker clusters aren’t working anymore after switching to AdvancedMarkerElement. From what I’ve gathered, some folks have mentioned that MarkerClusterer doesn’t support AdvancedMarkerElement natively.

Is this true? Do I really need to build custom clustering logic just to get advanced markers working with clusters, or is there a better workaround? Any tips or examples would be super appreciated!

I attempted to reposition the tags in different parts of the HTML to ensure the MarkerClusterer was loaded at the right time. Initially, I thought that maybe the script order was preventing the cluster from being detected properly.
I also tried using the import statement in my JavaScript code to bring in MarkerClusterer directly. However, I ran into problems because my project wasn’t set up as a module. Converting it into a module introduced other complications that I wasn’t expecting.module, and making it a module wasn’t as straightforward as I expected.

Meshes overlapping with sin() and cos() animation

I’m new to JavaScript and Three.js, nice to meet all of you !

This code is for creating 4 cubes and one arrow. Like this image:

Image1

// Scene
const scene = new THREE.Scene();

// Groups
const cubes = new THREE.Group();

// Ambient Light
const light = new THREE.AmbientLight(0xffffff, 1);
scene.add(light)

// Reference Circle or Path
const circle = new THREE.CircleGeometry(5, 100)
const circlePath = new THREE.Path()
const stroke = new THREE.LineBasicMaterial({color : 'white'})
const ref = new THREE.Line(circle, stroke)
scene.add(ref)

// Mesh 
const geometry = new THREE.BoxGeometry(1, 1, 1)
const material = new THREE.MeshBasicMaterial({ color: 'red' })
const mesh = new THREE.Mesh(geometry, material)

// Mesh 2  
const geometry2 = new THREE.BoxGeometry(1, 1, 1)
const material2 = new THREE.MeshBasicMaterial({ color: 'blue' })
const mesh2 = new THREE.Mesh(geometry2, material2)

// // Mesh 3 
const geometry3 = new THREE.BoxGeometry(1, 1, 1)
const material3 = new THREE.MeshBasicMaterial({ color: 'green' })
const mesh3 = new THREE.Mesh(geometry3, material3)

// // Mesh 4 
const geometry4 = new THREE.BoxGeometry(1, 1, 1)
const material4 = new THREE.MeshBasicMaterial({ color: 'purple' })
const mesh4 = new THREE.Mesh(geometry4, material4)

// Mesh 5 Arrow
const geometry5 = new THREE.ConeGeometry(1, 4, 3)
const material5 = new THREE.MeshBasicMaterial({ color: 'yellow' })
const arrow = new THREE.Mesh(geometry5, material5)

scene.add(mesh, mesh2, mesh3, mesh4, arrow)


const axesHelper = new THREE.AxesHelper();
scene.add(axesHelper)

// Camera

const aspect = {
    width: window.innerWidth,
    height: window.innerHeight
}

const camera = new THREE.PerspectiveCamera(75, aspect.width / aspect.height)
camera.position.x = -0.15;
camera.position.z = 10;

scene.add(camera)

// Renderer 
const canvas = document.querySelector('.draw')
const renderer = new THREE.WebGLRenderer({ canvas });
renderer.setSize(aspect.width, aspect.height)
renderer.render(scene, camera)

const clock = new THREE.Clock();

const animate = () => {
    const time = clock.getElapsedTime()
    console.log(time);
    const a = time;
    let px;
    let pz;
    let r = 5;

    px = r * Math.cos(a);
    pz = r * Math.sin(a);

    mesh.position.set(px, pz, 0);
    mesh.rotation.x = time * Math.PI * 0.1;
    mesh.rotation.y = time * Math.PI * 0.3;

    mesh2.position.set(px, pz, 0);
    mesh2.rotation.x = time * Math.PI * 0.1;
    mesh2.rotation.y = time * Math.PI * 0.3;
    
    mesh3.position.set(px2, pz, 0);
    mesh3.rotation.x = time * Math.PI * 0.1;
    mesh3.rotation.y = time * Math.PI * 0.3;

    mesh4.position.set(px, pz, 0);
    mesh4.rotation.x = time * Math.PI * 0.1;
    mesh4.rotation.y = time * Math.PI * 0.3;

    arrow.rotation.y = time * Math.PI * 0.7;

    renderer.render(scene, camera)
    window.requestAnimationFrame(animate)
}
animate();

The problem I’m having is that when the animate() loop starts, I have all my geometry overlapped like this:

Image2

Do you have any suggestions on what could solve the overlapping ? Like doing some kind of delay maybe, not sure how to apply it.

What I understood was to create 4 loops for each cube. May be possible I’m not understanding correctly because when the program is running, I get: Image1.

Any suggestions on what could be done to make a delay for each mesh to avoid overlapping ?

Thanks for your time. 🙂

google sheets script: display cell addresses of color filled cells

i don’t know much coding/javascript so was hoping i could get some help.

i’d like help to script a function that would allow me to find the cell addresses of all cells with grey fill (#dbd9d9) and display the result as a list. this is close to what i need, but it only displays the cell address of first and last filled cells of a specified row.

the following works (sorry, i didn’t save the link of where i found it), but it returns the hex of each cell in the range:

function getBgColor(input) {
var bgs = SpreadsheetApp.getActiveSheet().getRange("C1:Z6").getBackgrounds(),
colors = [];
for(var i = 0; i < bgs.length; i++){
colors.push(bgs[i]);
}
return colors;
}

could this be adapted to return cell addresses instead?

thanks for reading.

Google Auth2.0 API rejects with IdentityCredentialError: Error retrieving a token

I’m using Google Auth 2.0 with a React frontend and ExpressJS/Node backend. I am trying to send an email using NodeMailer, but first I have to authenticate the user using the Google Auth 2.0 service.

On localhost the application functions like normal, but when I am hosting the application on railway.app servers, the request seems to fail and I get the error message:

admin:1 The fetch of the id assertion endpoint resulted in a network error: ERR_FAILEDUnderstand this error admin:1 The provider’s token fetch resulted in an error response code.Understand this error client:70 [GSI_LOGGER]: FedCM get() rejects with IdentityCredentialError: Error retrieving a token.

I have tried changing the Google Cloud console credentials javascript origins and redirect URI’s to the correct locations, but to no avail.

I have also tried to change the .env variables I am using for CORS and Google authentication, but again to no avail.

Github Link: https://github.com/ethancs13/dbdbdb

React: why is my conditionally rendered component not being rendered even though condition is being satisfied?

In React, have a parent component which conditionally renders the Output component based on whether there is a selected thread:

<div className="flex-grow overflow-y-auto p-4">
  {myStore.selectedThread ? (
    <Suspense
      fallback={
        <div className="flex justify-center items-center align-middle h-full">
          <Loader active={true} className="w-36 h-36" />
          <p className="text-xs text-gray-500">Loading messages...</p>
        </div>
      }
    >
      <Output loading={loading} />
    </Suspense>
  ) : (
    <div className="flex flex-col items-center justify-center h-full">
      <h1 className="text-6xl font-bold text-violet-900 mb-4">
        Hi, {store.profile.fname} {store.profile.lname}!
      </h1>
      <p className="text-gray-500 text-xl mb-8">
        Hit record and let the magic begin.
      </p>
      <RecordingComponent myStore={myStore} />
    </div>
  )}
</div>

and, in the RecordingComponent inside the parent component, I am selecting a thread using a MobX store function after the handlePostTranscription() function:

const audioTranscriberStatus =
  myStore.inputActiveRecord?.audioTranscriber?.status;
console.log(audioTranscriberStatus);
useEffect(() => {
  const handlePostTranscription = async () => {
    const { inputActiveRecord, selectedThread } = myStore;
    if (!inputActiveRecord || selectedThread) {
      return;
    }

    try {
      const newThread = await createThread();
      const newThreadId = newThread.thread_id;
      setForceRender((prev) => !prev);

      await updateHistory(inputActiveRecord._id, { threadId: newThreadId });
      const transcriptionText = inputActiveRecord.outputs.join(" ");
      await addMessage(newThreadId, "user", transcriptionText);
      await runAssistant(
        transcriptionText,
        newThreadId,
        "asst_L24bszgfqSOxw3yT0dTOaIzZ",
        "",
      );

      myStore.selectThread(newThreadId);
      console.log(myStore.selectedThread);
    } catch (error) {
      console.error("Error in post-transcription handling:", error);
    }
  };

  if (audioTranscriberStatus === "done") {
    handlePostTranscription();
  }
}, [audioTranscriberStatus]);

And in the debug logs, I can see that it is correctly setting the thread, which means, myStore.selectedThread is true which should render the Output component supposedly.

However, my problem is that in the parent component, the Output is not rendering — I am still seeing the welcome screen. This is not the case when I am using the HistoryPanel component or the TextInputComponent component to set a thread. They both appear to make the Output component render successfully.

From TextInputComponent:

const handleTextSubmit = async () => {
  try {
    setLoading(true);

    // Save the text using the API that goes through the middleware
    const response = await saveText(message);

    if (response.data.history && response.data.history._id) {
      const fetchedHistory = response.data.history;
      let currentThreadId = fetchedHistory.threadId;

      if (!currentThreadId) {
        // Create a new thread if none exists
        const newThread = await createThread();
        currentThreadId = newThread.thread_id;

        // Update history with the new thread ID
        await updateHistory(fetchedHistory._id, {
          threadId: currentThreadId,
        });
      }

      // Add the message to the thread
      await addMessage(currentThreadId, "user", message);

      // Run the assistant on the message
      await runAssistant(
        message,
        currentThreadId,
        "asst_L24bszgfqSOxw3yT0dTOaIzZ",
        "",
      );

      myStore.selectThread(currentThreadId);
    }
  } catch (error) {
    console.error(error);
  } finally {
    setMessage("");
    setLoading(false);
  }
};

From HistoryPanel:

    const handleHistoryClick = async (threadId) => {
      try {
        setSelectedThreadId(threadId);
        myStore.selectThread(threadId);
      } catch (error) {
        console.error("Error selecting thread:", error);
      }
    };

Finally, myStore:

  selectThread = async (threadId) => {
    if (this.selectedThread !== threadId) {
      this.selectedThread = threadId;
      await this.fetchThreadMessages(threadId);
    }
  };

Would any of you know what is causing this?

I have also tried just adding a query param to the url that has the threadId and render the Output component if the url has this param, however, in the handlePostTranscription() function, when I use window.location.href or even useHistory, it doesn’t even change the url. So there is definitely something with that async function that’s messing something up.

EsLint error async/await promise callback function

I am getting an error on eslint expecting ( and not a { here.

loginStateChanged: async (params) => {                                      
                                     ^ Expected '(' and instead saw '{'.

I can’t seem to figure out what is going on with the error here. When I run the grunt build it says this and when looking at the file and code it is listed in, I am not seeing the issue. The function is a call back and I know that you have to handle the promised return, as specified in this post

Why am I getting an ESLint error for async function with Promise return?

Here is the function:

loginStateChanged: async (params) => {
    UiApi.Logger.debug('ProductHooks', 'onLoginStateChanged', params);
    if (params.state !== 'WORKING') return;
    await CommonFunctions.refreshCallVariables();
}

However, I cannot get the syntax down.

Thank you!

I tried updating settings.json to

{
    "editor.codeActionsOnSave": {       
        "source.fixAll": "explicit"
    },
    "jshint.optoins": {
    "esversion": 6
    },
    "eslint.validate": ["javascript"] 
}

and I have updated my eslint file here

module.exports = {
    env: {
        browser: true,
        commonjs: true,
        es6: true   
    },
    extends: ['eslint:recommended', 'plugin:requirejs/recommended'],
    parserOptions: {
        ecmaVersion: 2020,
        sourceType: 'module'
    },
    globals: {
        _: 'readonly',
        $: 'readonly',
        jQuery: 'readonly'
    },
    rules: {
        'max-len': ['warn', { code: 260 }],
        'function-paren-newline': ['warn', 'never'],
        quotes: ['warn', 'single'],
        'comma-dangle': ['warn', 'never'],
        'no-unused-vars': 'warn'
    },
    plugins: ['requirejs'],
        ignorePatterns: ['GruntFile.js', 'src/libconfig.js', '.data', 'dist', 'libs', 'out', 'tmp']
    };

Error Installing Thirdweb with npm: ERR! code ERR_SOCKET_TIMEOUT

npm ERR! code ERR_SOCKET_TIMEOUT
npm ERR! network Socket timeout
npm ERR! network This is a problem related to network connectivity.
npm ERR! network In most cases you are behind a proxy or have bad network settings.
npm ERR! network If you are behind a proxy, please make sure that the
npm ERR! network ‘proxy’ config is set properly. See: ‘npm help config’

npm ERR! A complete log of this run can be found in:
npm ERR! C:UserslightAppDataLocalnpm-cache_logs2024-08-28T17_25_15_584Z-debug-0.log

I want to install Thirdweb for the first time.
I’m using [Node.js version] : v18.13.0
and [npm version] : 8.19.3

What could be causing this ERR_SOCKET_TIMEOUT error?
How can I fix the issue and successfully install Thirdweb?

Primefaces dataTable not rendered correctly after change page

I created a notifications bin. Firstly its structure was coded using p:tabView tag and two tabs, each tab with a p:dataTable inside. When I try to change the page of one of the p:dataTable, the new page is not rendered correctly and paginator dissapears. I thought that the problem was the p:tabView component and I changed the structure to nested h:panelGroup. In two ways problem persists.

This is the initial state of the page:

Initial state

When I press the page 2, the dataTable is rendered like this:

error page

Now, if I press the “Actualizar” button (update button), now the page 2 is rendered correctly:

page 2

I don’t understand this behavior. This is the previous code using p:tabView tag:

<f:metadata>
    <f:event type="preRenderView" listener="#{notificacionesBean.updateNotificacionesButton()}"/>
</f:metadata>
<p:scrollPanel id="localPanel" widgetVar="localPanel" mode="native" >
    <div style="margin-left: 14px;">
        <h3>
            Notificaciones
        </h3>
    </div>
    <p:tabView id="bandejas" activeIndex="#{notificacionesBean.activeTab}" dynamic="true" widgetVar="bandejasViewTab" >
        <p:ajax event="tabChange" update="bandejas" listener="#{notificacionesBean.loadTab}" />
        <p:tab title="Bandeja de Entrada (#{notificacionesBean.unread})" >
            <f:facet name="title">
                <i class="pi pi-inbox" />&nbsp;
                <h:outputText value="Bandeja de Entrada (#{notificacionesBean.unread})" />
            </f:facet>
            <p:commandButton icon="pi pi-refresh" value="Actualizar" actionListener="#{notificacionesBean.updateNotificacionesButton()}" />
            &nbsp;
            <p:commandButton actionListener="#{notificacionesBean.marcarComoLeidoMulti()}" update="bandejas globalForm:menItNotif" process="inbox @this" value="Marcar como leído(s)" icon="fa fa-regular fa-envelope-open" />
            &nbsp;
            <p:commandButton actionListener="#{notificacionesBean.marcarComoNoLeidoMulti()}" update="bandejas globalForm:menItNotif" process="inbox @this" icon="pi pi-envelope" value="Marcar como no leído(s)" />
            &nbsp;
            <p:commandButton actionListener="#{notificacionesBean.eliminarMulti()}" update="bandejas globalForm:menItNotif" process="inbox @this" icon="pi pi-trash" value="Eliminar" />
            <br/>
            <br/>
            <p:dataTable id="inbox" rows="25" emptyMessage="Usted no tiene notificaciones nuevas" paginator="true" paginatorAlwaysVisible="false" var="msj" value="#{notificacionesBean.inboxMsjs}" selection="#{notificacionesBean.notifSeleccionadas}" rowKey="#{msj.idMsj}" widgetVar="inbox" rowIndexVar="indexMsj" selectionMode="multiple" >
                <p:ajax event="rowSelect" listener="#{notificacionesBean.notificacionSeleccion}" />
                <p:column selectionBox="true" style="text-align: center;" width="30" />
                <p:column headerText="Remitente" style="width: 300px;">
                    <h:outputText value="#{notificacionesBean.abreviarCampo(msj.sender.nombre.replace('/', ' '), 37)}" style="font-weight: #{msj.fontWeight()}; display: block;" />
                </p:column>
                <p:column headerText="Asunto" >
                    <h:outputText value="#{notificacionesBean.abreviarCampo(msj.asuntoEstilizado(), 200)}" style="font-weight: #{msj.fontWeight()}; display: block;" />
                </p:column>
                <p:column headerText="Fecha" style="width: 55px;">
                    <center>
                        <h:outputText value="#{notificacionesBean.fechaEstilizada(msj)}" style="font-weight: #{msj.fontWeight()}; display: block;" />
                    </center>
                </p:column>
                <p:column style="width: 66px;">
                    <center>
                        <p:commandButton actionListener="#{notificacionesBean.eliminarUno(msj)}" update="globalForm:bandejas globalForm:menItNotif" icon="pi pi-trash" title="Eliminar" />
                        <p:commandButton actionListener="#{notificacionesBean.cambiarEstatusLeido(msj)}" update="globalForm:bandejas globalForm:menItNotif" icon="#{notificacionesBean.iconEnvelope(msj)}" title="#{notificacionesBean.titleEnvelope(msj)}" />
                    </center>
                </p:column>
            </p:dataTable>
        </p:tab>    
        <p:tab title="Papelera">
            <f:facet name="title">
                <i class="pi pi-trash" />&nbsp;
                <h:outputText value="Papelera" />
            </f:facet>
            <p:commandButton actionListener="#{notificacionesBean.moverAinbox()}" update="bandejas globalForm:menItNotif" process="trash @this" icon="pi pi-inbox" value="Mover a bandeja de entrada" />
            &nbsp;
            <p:commandButton actionListener="#{notificacionesBean.marcarComoLeidoTrash()}" update="bandejas" process="trash @this" icon="fa fa-envelope-open" value="Marcar como leído(s)" />
            &nbsp;
            <p:commandButton actionListener="#{notificacionesBean.marcarComoNoLeidoTrash()}" update="bandejas" process="trash @this" icon="pi pi-envelope" value="Marcar como no leído(s)" />
            <br/>
            <br/>
            <p:dataTable id="trash" rows="25" emptyMessage="La bandeja esta vacía" paginator="true" paginatorAlwaysVisible="false" var="msj" value="#{notificacionesBean.trashBinMsjs}" selection="#{notificacionesBean.notifSeleccionadasTrash}" rowKey="#{msj.idMsj}" widgetVar="trash" rowIndexVar="trashMsj" selectionMode="multiple" >
                <p:ajax event="rowSelect" listener="#{notificacionesBean.notificacionSeleccionTrash}" />
                <p:column selectionBox="true" style="text-align: center;" width="30" />
                <p:column headerText="Remitente" style="width: 300px;">
                    <h:outputText value="#{notificacionesBean.abreviarCampo(msj.sender.nombre, 37)}" style="font-weight: #{msj.fontWeight()}; display: block;" />
                </p:column>
                <p:column headerText="Asunto" >
                    <h:outputText value="#{notificacionesBean.abreviarCampo(msj.asuntoEstilizado(), 200)}" style="font-weight: #{msj.fontWeight()}; display: block;" />
                </p:column>
                <p:column headerText="Fecha" style="width: 55px;">
                    <center>
                        <h:outputText value="#{notificacionesBean.fechaEstilizada(msj)}" style="font-weight: #{msj.fontWeight()}; display: block;" />
                    </center>
                </p:column>
                <p:column style="width: 66px;">
                    <center>
                        <p:commandButton actionListener="#{notificacionesBean.moverAinboxMsj(msj)}" update="globalForm:bandejas globalForm:menItNotif" icon="pi pi-inbox" title="Mover a bandeja de entrada" />
                        <p:commandButton actionListener="#{notificacionesBean.cambiarEstatusLeido(msj)}" update="globalForm:bandejas globalForm:menItNotif" icon="#{notificacionesBean.iconEnvelope(msj)}" title="#{notificacionesBean.titleEnvelope(msj)}" />
                    </center>
                </p:column>
            </p:dataTable>
        </p:tab>
    </p:tabView>
</p:scrollPanel>

This is the current code using nested h:panelGroup:

<f:metadata>
    <f:event type="preRenderView" listener="#{notificacionesBean.updateNotificacionesButton()}"/>
</f:metadata>
<p:scrollPanel id="localPanel" widgetVar="localPanel" mode="native" >
    <h3>
        Notificaciones
    </h3>
    <h:panelGroup id="bandejas">
        <table>
            <tr>
                <td>
                    <p:commandLink actionListener="#{notificacionesBean.setActiveTab(0)}" update="bandejas">
                        <div class="#{notificacionesBean.inboxClass()}">
                            <i class="pi pi-inbox" style="margin-right: 10px;" />Bandeja de Entrada (#{notificacionesBean.unread})
                        </div>
                    </p:commandLink>
                </td>
                <td>
                    <p:commandLink actionListener="#{notificacionesBean.setActiveTab(1)}" update="bandejas">
                        <div class="#{notificacionesBean.trashClass()}">
                            <i class="pi pi-trash" style="margin-right: 10px;" />Papelera
                        </div>
                    </p:commandLink>
                </td>
            </tr>
        </table>
        <br/>
        <h:panelGroup rendered="#{notificacionesBean.activeTab == 0}">
            <p:commandButton icon="pi pi-refresh" value="Actualizar" actionListener="#{notificacionesBean.updateNotificacionesButton()}" />
            &nbsp;
            <p:commandButton actionListener="#{notificacionesBean.marcarComoLeidoMulti()}" update="bandejas globalForm:menItNotif" process="inbox @this" value="Marcar como leído(s)" icon="fa fa-regular fa-envelope-open" />
            &nbsp;
            <p:commandButton actionListener="#{notificacionesBean.marcarComoNoLeidoMulti()}" update="bandejas globalForm:menItNotif" process="inbox @this" icon="pi pi-envelope" value="Marcar como no leído(s)" />
            &nbsp;
            <p:commandButton actionListener="#{notificacionesBean.eliminarMulti()}" update="bandejas globalForm:menItNotif" process="inbox @this" icon="pi pi-trash" value="Eliminar" />
            <br/>
            <p:dataTable id="inbox" rows="25" emptyMessage="Usted no tiene notificaciones nuevas" paginator="true" paginatorAlwaysVisible="true" var="msj" value="#{notificacionesBean.inboxMsjs}" selection="#{notificacionesBean.notifSeleccionadas}" rowKey="#{msj.idMsj}" widgetVar="inbox" rowIndexVar="indexMsj" selectionMode="multiple" >
                <p:ajax event="rowSelect" listener="#{notificacionesBean.notificacionSeleccion}" />
                <p:column selectionBox="true" style="text-align: center;" width="30" />
                <p:column headerText="Remitente" style="width: 300px;">
                    <h:outputText value="#{notificacionesBean.abreviarCampo(msj.sender.nombre.replace('/', ' '), 37)}" style="font-weight: #{msj.fontWeight()}; display: block;" />
                </p:column>
                <p:column headerText="Asunto" >
                    <h:outputText value="#{notificacionesBean.abreviarCampo(msj.asuntoEstilizado(), 200)}" style="font-weight: #{msj.fontWeight()}; display: block;" />
                </p:column>
                <p:column headerText="Fecha" style="width: 55px;">
                    <center>
                        <h:outputText value="#{notificacionesBean.fechaEstilizada(msj)}" style="font-weight: #{msj.fontWeight()}; display: block;" />
                    </center>
                </p:column>
                <p:column style="width: 66px;">
                    <center>
                        <p:commandButton actionListener="#{notificacionesBean.eliminarUno(msj)}" update="globalForm:bandejas globalForm:menItNotif" icon="pi pi-trash" title="Eliminar" />
                        <p:commandButton actionListener="#{notificacionesBean.cambiarEstatusLeido(msj)}" update="globalForm:bandejas globalForm:menItNotif" icon="#{notificacionesBean.iconEnvelope(msj)}" title="#{notificacionesBean.titleEnvelope(msj)}" />
                    </center>
                </p:column>
            </p:dataTable>
        </h:panelGroup>
        <h:panelGroup rendered="#{notificacionesBean.activeTab == 1}">
            <p:commandButton actionListener="#{notificacionesBean.moverAinbox()}" update="bandejas globalForm:menItNotif" process="trash @this" icon="pi pi-inbox" value="Mover a bandeja de entrada" />
            &nbsp;
            <p:commandButton actionListener="#{notificacionesBean.marcarComoLeidoTrash()}" update="bandejas" process="trash @this" icon="fa fa-envelope-open" value="Marcar como leído(s)" />
            &nbsp;
            <p:commandButton actionListener="#{notificacionesBean.marcarComoNoLeidoTrash()}" update="bandejas" process="trash @this" icon="pi pi-envelope" value="Marcar como no leído(s)" />
            <br/>
            <br/>
            <p:dataTable id="trash" rows="25" emptyMessage="La bandeja esta vacía" paginator="true" paginatorAlwaysVisible="true" var="msj" value="#{notificacionesBean.trashBinMsjs}" selection="#{notificacionesBean.notifSeleccionadasTrash}" rowKey="#{msj.idMsj}" widgetVar="trash" rowIndexVar="trashMsj" selectionMode="multiple" >
                <p:ajax event="rowSelect" listener="#{notificacionesBean.notificacionSeleccionTrash}" />
                <p:column selectionBox="true" style="text-align: center;" width="30" />
                <p:column headerText="Remitente" style="width: 300px;">
                    <h:outputText value="#{notificacionesBean.abreviarCampo(msj.sender.nombre, 37)}" style="font-weight: #{msj.fontWeight()}; display: block;" />
                </p:column>
                <p:column headerText="Asunto" >
                    <h:outputText value="#{notificacionesBean.abreviarCampo(msj.asuntoEstilizado(), 200)}" style="font-weight: #{msj.fontWeight()}; display: block;" />
                </p:column>
                <p:column headerText="Fecha" style="width: 55px;">
                    <center>
                        <h:outputText value="#{notificacionesBean.fechaEstilizada(msj)}" style="font-weight: #{msj.fontWeight()}; display: block;" />
                    </center>
                </p:column>
                <p:column style="width: 66px;">
                    <center>
                        <p:commandButton actionListener="#{notificacionesBean.moverAinboxMsj(msj)}" update="globalForm:bandejas globalForm:menItNotif" icon="pi pi-inbox" title="Mover a bandeja de entrada" />
                        <p:commandButton actionListener="#{notificacionesBean.cambiarEstatusLeido(msj)}" update="globalForm:bandejas globalForm:menItNotif" icon="#{notificacionesBean.iconEnvelope(msj)}" title="#{notificacionesBean.titleEnvelope(msj)}" />
                    </center>
                </p:column>
            </p:dataTable>
        </h:panelGroup>
    </h:panelGroup>
</p:scrollPanel>

This is the code of “Actualizar” button (update button):

public void updateNotificacionesButton() {
    inboxMsjs = mensajesService.findMensajesBandejaEntrada(usuario.getIdUsuario(), (short) 1);
    unread = inboxMsjs.size();
    PrimeFaces.current().ajax().update("globalForm:bandejas");
}

I am using this in my project:

  • Primefaces 14.0.4
  • Payara 6.2024.5
  • OpenJDK 17.0.2
  • Jakarta 10.0

I’ll appreciate appreciate any hint about what is happening. Thanks.

How to select URL parameter and exclude all the other stuff that comes after it?

I’m using dynamic text based on a URL parameter. Basically, the code selects the URL parameter and inserts it into a paragraph. However, in my case, I want to exclude all the other stuff that comes after the parameter, such as forward slash, fragments, and other strings.

Destination URL is like this:

https://example.com/?ref=mainParam/blah/blah/blah

I want to select just the mainParam (discard everything else) and insert it into a paragraph.

Here’s the code:

var url = new URL(window.location.href);
var mainParam = url.searchParams.get("ref");
document.getElementById("mainParam").innerHTML = mainParam;
Welcome to <p id='mainParam'></p>

being a pain when the div is not visible

So i have made 3 divs, one a little bit above the other, each separared by a <br>. However when my function hides one of them, the <br> is still there, therefore each div is misplaced when all the others are hidden. (i am terrible at explaining, take a look)

<div id="myDiv1">div 1</div> <br>

<div id="myDiv2">div 2</div> <br>

<div id="myDiv3">div 3</div>

<script>
function hide1() {
  var x = document.getElementById("myDiv1");
  if (x.style.display==="none") {
    x.style.display="block";
  }
  else {
    x.style.display="none";
  }
}

i have 2 more functions for the other divs. Can anyone help me? (sorry if this is a stupid question)

I tried putting the <br> inside the <div> in hopes of <br> visibility being none as well, but it just didn’t read it.

Vue Component not rendering correctly on initial load

I’m encountering a strange issue with my Vue application that uses Contentful for content management. When I navigate to a page from the menu, the component, which is responsible for fetching data from Contentful GraphQL, doesn’t render correctly.

Specific problem:

  • The lists in the component, which should be rendered as <ol> elements, are instead appearing as <ul> elements.
  • This issue only occurs on the initial load from the menu. If I refresh the page, the component renders correctly with <ol> elements.

Before the refresh

After the refresh

This here is an example

https://jsfiddle.net/qukompgw/

Issue with displaying a location on Google maps using Java+JavaScript+JavaFX

I’ve been trying to create a Java desktop app using Java, JavaScript and JavaFX and one part of the app should be able to display a location on the map using the location of the venue taken from the database (street + city, no postal code) and once I run the app it seems to show the location correctly for a second or two and then it completely disapears like it’s shown in the images below.

Before

After

I used Maps JavaScript API and Geocoding API. I’m trying to get the app to consistently show the location without it disappearing without it running into an issue. This is the method that I’m currently using to display the map:

public void showMap(Venue venue) {
        WebEngine webEngine = mapView.getEngine();

        Location location = venue.getLocation();
        String address = location.toString();
        String encodedAddress = URLEncoder.encode(address, StandardCharsets.UTF_8);

        String mapHTML = "<html>" +
                "<head>" +
                "<script src="https://maps.googleapis.com/maps/api/js?key=API_KEY"></script>" +
                "<script>" +
                "function initMap() {" +
                "  var geocoder = new google.maps.Geocoder();" +
                "  geocoder.geocode({'address': '" + encodedAddress + "'}, function(results, status) {" +
                "    if (status === 'OK') {" +
                "      var mapOptions = {" +
                "        zoom: 15," +
                "        center: results[0].geometry.location," +
                "        mapTypeId: google.maps.MapTypeId.ROADMAP" +
                "      };" +
                "      var map = new google.maps.Map(document.getElementById('map'), mapOptions);" +
                "      new google.maps.Marker({" +
                "        position: results[0].geometry.location," +
                "        map: map" +
                "      });" +
                "    } else {" +
                "      alert('Geocode was not successful for the following reason: ' + status);" +
                "    }" +
                "  });" +
                "}" +
                "</script>" +
                "</head>" +
                "<body onload='initMap()'>" +
                "<div id='map' style='width:100%;height:100%;'></div>" +
                "</body>" +
                "</html>";

        webEngine.loadContent(mapHTML);
    }

I used WebView on JavaFX to add the map as well. Anybody knows what could I add to the code to fix this. Should I maybe add another class that would do the geocoding for the given location or is there something wrong with the displayed code. Anything helps