How to receive message from web socket channel sent from Java in JavaScript

I want to make my JavaScript application be able to listen to a specific web socket channel, but failed.

Here is my JavaScript :

async function callLogin() {
    ...

    const destination = '/app/cards/1';
    console.log("destination : " + destination)

    // Initialize WebSocket connection
    const socket = new WebSocket('ws://localhost:8080/gs-guide-websocket');

    socket.onopen = function() {
        showGreeting("WebSocket onopen.");
        console.log('WebSocket onopen');

        // Initialize Stomp Client
        const stompClient = new StompJs.Client({
            brokerURL: 'ws://localhost:8080/gs-guide-websocket'
        });
//        const stompClient = Stomp.Client(socket); // Correct initialization method
//        const stompClient = Stomp.over(socket);

        // Subscribe to the WebSocket channel
        stompClient.activate();
        stompClient.onConnect = function(frame) {
//        stompClient.connect = function(frame) {
//        stompClient.connect({}, function(frame) {
            showGreeting("stompClient connect.");
            console.log('stompClient connect: ' + frame);

            stompClient.subscribe(destination, function(message) {
                console.log("Received message : " + message.body);
                showGreeting("Receive message from : " + destination);
                // Process incoming cards data here
            });
        };

        stompClient.onmessage = function(event) {
            console.log("message" + event);
            const message = event.data;
        };

        socket.onmessage = function(event) {
            console.log("message" + event);
            const message = event.data;
        };

    };

    socket.onerror = function(error) {
        console.error('WebSocket Error:', error);
        showGreeting("WebSocket Error: " + error.message);
    };

    socket.onclose = function(event) {
        console.log('WebSocket closed:', event);
        showGreeting("WebSocket closed.");
    };

}

On the other hand, I send message to the web socket channel by Java web service, here’s my Web socket configuration in Java :

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/gs-guide-websocket");
    }
}

And here is the method to send web socket to specific channel, I created a API so that I can test repeatedly :

@PostMapping("/login")
public ResponseEntity<Object> send() {
    String destination = "/app/cards/1";
    messagingTemplate.convertAndSend(destination, "Let's play! Here's your cards:");
    return new ResponseEntity<>(destination, HttpStatus.OK);
}

And here is the current result,
enter image description here

It seems that the connect was created successfully, but it couldn’t receive the message which sent from my Java service.

I have some experience in Java, but I’m a totally novice of JavaScript and web socket, and I’ve asked ChatGPT for dozens of times, it gave me some other methods, but there’re some other issues.(The commented code in my code is the “other methods”)

What I want to achieve is that my JavaScript can obtain an id from a RESTful API, then subscribe to specific channel, let’s say 'ws://localhost:8080/gs-guide-websocket/app/user/12345', and then it can receive messages through that channel afterwards.

Can anyone help me to find where might be wrong? Thanks in advance!

MapKit JS Not Showing Suburb of Marker

I’m using MapKit JS to plot markers on a Map – so far so good. I’ve noticed that it doesn’t show the Suburb name for the location of the marker so far in my testing. Here’s an example

enter image description here

The marker is located in Hornsby which isn’t showing on the map. If I move the market to an adjacent suburb Wahroonga I get the following:

enter image description here

Now Wahroonga isn’t showing but Hornsby is showing. I’m trying to find if there’s a control that determines when the suburb for the marker is shown or not but haven’t been able to find anything so far.

Here’s the code for my map if that helps:

    const main = async() => {
    await setupMapKitJs();
    
    // Create the Map and Geocoder
    const map = new mapkit.Map("map-container");
    const geocoder = new mapkit.Geocoder({ language: "en-US" });
    
    // Create the "Marker" annotation, setting properties in the constructor.
    const event = new mapkit.Coordinate(-33.7015776, 151.0960029);
    const eventAnnotation = new mapkit.MarkerAnnotation(event, {
        color: "red",
        title: "",
        glyphText: "" 
    });
    
    // Add and show both annotations on the map
    map.showItems([eventAnnotation]);


};

main();

Updating a state variable in Redux store causing unwanted re-render of the entire app

I’m trying to learn redux-toolkit with a project.

I’m using “toEditPostId” variable (initial value is null) inside the store to get the id of the post I want to edit, the app works fine when I set its value to an id string, but when I click the clear button in my form component which calls the “dispatch(setToEditPostId(null))”, then the entire app re-renders and “handleSubmit” function is automatically called and that then adds a new empty post, which I don’t want to happen.

I have added “****************” near the snippets which are causing problem.

import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import axiosInstance  from "../utils/axiosInstance";

export const fetchMemoryPosts = createAsyncThunk('posts/fetchPosts', async (_, thunkApi)=>{

  try {
    const response = await axiosInstance.get('/posts');
    return response.data.posts;
  } catch (error) {
    const errorMessage = error.response.data.match(/Error: (.*?)<br>/)[1];
    const errorCode = error.response.status;
    return thunkApi.rejectWithValue({errorMessage,errorCode});
  }
});

export const createMemoryPost = createAsyncThunk('posts/createPosts', async(data, thunkApi)=>{

  const tagsArr = data.tags.split(',').map((ele)=> ele.trim());
  const preparedData = {...data, tags: tagsArr};

  try {
    const response = await axiosInstance.post('/posts/create', preparedData);
    return response.data.data;
  } catch (error) {
    const errorMessage = error.response.data.match(/Error: (.*?)<br>/)[1];
    const errorCode = error.response.status
    return thunkApi.rejectWithValue({errorMessage, errorCode})
  }
})

const initialState = {
  posts: [],
  status: 'idle',
  error: null,
  toEditPostId: null, //The state variable to track the id of the post to edit*************
}

const postsSlice = createSlice({
  name: 'posts',
  initialState,
  reducers: {     // changing the value to an id and back to null here***********************
    setToEditPostId(state,action){
      state.toEditPostId = action.payload;
    }
  },
  extraReducers(builder){
    builder
    .addCase(fetchMemoryPosts.pending, (state,_)=>{
      state.status = 'loading';
    })
    .addCase(fetchMemoryPosts.fulfilled, (state, action)=>{
      state.status = 'success';
      state.posts = action.payload;
    })
    .addCase(fetchMemoryPosts.rejected, (state, action)=>{
      state.status = 'failure';
      state.error = action.payload;
    })
    .addCase(createMemoryPost.fulfilled, (state, action)=>{
      state.status = 'success';
      state.posts = state.posts.concat(action.payload);
    })
    .addCase(createMemoryPost.rejected, (state, action)=>{
      state.status = 'failure';
      state.error = action.payload;
    })
  }
});

export const getAllPostsSelector = (state) => state.posts.posts;
export const getPostsErrorSelector = (state) => state.posts.error;
export const getPostsStatusSelector = (state) => state.posts.status;
export const getToEditPostIdSelector = (state) => state.posts.toEditPostId;


export const { setToEditPostId } = postsSlice.actions;


export default postsSlice.reducer;

Below is the Form component.

import React, { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { createMemoryPost, setToEditPostId, getToEditPostIdSelector, getAllPostsSelector } from '../../features/postsSlice';

const Form = () => {
  const dispatch = useDispatch();

  const allPosts = useSelector(getAllPostsSelector);
  const postId = useSelector(getToEditPostIdSelector);

  let targetPost;
  if(postId){
    targetPost = allPosts.filter((post) => post._id === postId);
  }

  console.log("pi->", postId)
  console.log("po->", targetPost);


  const initialPostDataState = {
    creator: '', title: '', message:'', tags:''
  }

  const [postData, setPostData] = useState(initialPostDataState);

  // Below function runs unnecessarily when the dispatch(setToEditPostId(null)) is called********************************* 
  const handleSubmit =(e)=>{
    console.log("it ran");
    e.preventDefault()
    dispatch(createMemoryPost(postData));

    setPostData(initialPostDataState);
  }


  const handleInput =(e)=>{
    setPostData({...postData, [e.target.name]: e.target.value})
  }

  const clearForm = ()=>{
    dispatch(setToEditPostId(null))
    setPostData(initialPostDataState);
  }

  return (
    <main className='bg-transparent_bg w-full flex'>
      <form className='w-full text-center space-y-3 p-2 box-border' 
        onSubmit={handleSubmit}
      >
        <h3
         className='font-extrabold '
        >
          {postId !== null? "" : "Create a memory"}
        </h3>
        <input 
          className='input'
          type="text" 
          placeholder='Creator' 
          name='creator'
          value={postData.creator}
          onChange={handleInput}
        />
        <input 
          className='input'
          type="text" 
          placeholder='Title' 
          name='title'
          value={postData.title}
          onChange={handleInput}
        />
        <textarea 
          className='input'
          placeholder='Message'
          name="message"
          cols="30" 
          rows="5"
          value={postData.message}
          onChange={handleInput}
        />
        <input 
          className='input'
          type="text" 
          placeholder='Tags (coma seperated)' 
          name='tags'
          value={postData.tags}
          onChange={handleInput}
        />

        <div className='flex justify-around py-1 box-border'>
          <button
            type='submit'
            className='bg-blue-400 w-24'
          >
            Submit
          </button>
          <button // clear button to call dispatch to set value to null *********************
            onClick={()=>dispatch(setToEditPostId(null))}
            className='bg-red-500 w-24'
          >
            Clear
          </button>
        </div>
      </form>
    </main>
  )
}

export default Form;

yup.ref is not working inside the yup.date().min

I have a requirement where end date is selected before start date. I’m using yup schema.

const validateSchema = Yup.object().shape({
  startDate: Yup.date()
    .default(() => new Date())
    .typeError("Please Enter valid Date Format")
    .required("Field is Mandatory"),
  endDate: Yup.date()
    .default(() => new Date())
    .typeError("Please Enter valid Date Format")
    .required("Field is Mandatory")
    .min(Yup.ref("startDate"), "Minimum Date"),
});

code sandbox link: Code Sand box link
YUP Schema Link : yup Schema Link

I want to hide tag and video source url. Show a video only in a div

I want to hide the tag and video source URL in my HTML code. Show a video only in a div. This is my code below.
I can give you two screenshots to understand more.
To add my code I can see here
But I want like this

document.addEventListener('DOMContentLoaded', function() {
            const videoContainer = document.getElementById('video-container');

            // Function to dynamically embed the YouTube video
            function embedYouTubeVideo(videoId) {
                // Create the iframe element
                const iframe = document.createElement('iframe');
                iframe.setAttribute('width', '560');
                iframe.setAttribute('height', '315');
                iframe.setAttribute('src', `https://www.youtube.com/embed/${videoId}`);
                iframe.setAttribute('title', 'Embedded Video');
                iframe.setAttribute('frameborder', '0');
                iframe.setAttribute('allow', 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture');
                iframe.setAttribute('allowfullscreen', '');

                // Append the iframe to the video container
                videoContainer.appendChild(iframe);
            }

            // Call the function to embed the YouTube video with the specified video ID
            embedYouTubeVideo('XlMlg5ZAMgw'); // Replace with your YouTube video ID
        });
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Embedded YouTube Video Example</title>
</head>
<body>
    <div id="video-container">
    </div>
</body>
</html>

Can’t find a way to run addEventListener multiple times, any ideas to make it run multiple times (Limited by Scope)

const clearBtn = document.getElementById("clear");
const addBookBtn = document.querySelector(".inital_display");
const books = document.querySelector(".books");
const modal = document.querySelector(".modal");

const myLibrary = [];

function Book(title, author, pages, isRead) {
    this.title = title;
    this.author = author;
    this.pages = pages;
    this.isRead = isRead;
}

function getBook() {
    const inputTitle = document.getElementById("input_Title").value;
    const inputAuthor = document.getElementById("input_Author").value;
    const inputPages = document.getElementById("input_Pages").value;
    const isChecked = document.getElementById("read").checked;
    return new Book(inputTitle, inputAuthor, inputPages, isChecked);
}

function addBook() {
    addBookBtn.addEventListener('click', () => {
        modal.style.display = "block";
        books.style.display = "grid";
    });
}
function submit() {
    const submitBookBtn = document.querySelector("#submit");
    submitBookBtn.addEventListener('click', () => {
        submitBookReport = getBook();
        myLibrary.push(submitBookReport);
        modal.style.display = "none";

        render();
    });
}

function render() {
    bookElements = getBook();

    const book = document.createElement("div");
    const title = document.createElement("p");
    const author = document.createElement("p");
    const pages = document.createElement("p");

    title.textContent = bookElements.title;
    author.textContent = bookElements.author;
    pages.textContent = bookElements.pages + " pages";

    book.classList.add("book");

    books.appendChild(book);
    book.appendChild(title);
    book.appendChild(author);
    book.appendChild(pages);

    addButtons(book, bookElements);
}

function addButtons(parent, elements) {
    const readBtn = document.createElement("button");
    const removeBtn = document.createElement("button");

    readBtn.classList.add("is-read");
    removeBtn.classList.add("remove-button");

    parent.appendChild(readBtn);
    parent.appendChild(removeBtn);


    readBtn.addEventListener('click', () => {
        if (elements.isRead == true) {
            readBtn.classList.remove('is-read');
            readBtn.classList.add("not-read");
        }
        else {
            readBtn.classList.remove('not-read');
            readBtn.classList.add('is-read');
        }
    });
}

function toggleRemove() {

}

function clear() {
    clearBtn.addEventListener('click', () => {
        books.replaceChildren();
    });
}



addBook();
getBook();
submit();
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="styles.css">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,[email protected],100..700,0..1,-50..200" />
    <title>Document</title>
</head>
<body>
    <div class="container">
        <div class="header league-spartan">
            <div class="logo">
                Library
            </div>
            <div class="Clear">
                <button id="clear">Clear</button>
            </div>
        </div>
        <div class="display">
            <div class="inital_display">
                <span class="material-symbols-outlined">Add</span><span id="add_text">Add Book</span>
            </div>
            <div class="books">
                <!--div output-->
            </div>
        </div>
        <div class="modal">
            <form action="#">
                <header>Add new book</header>
                <input type="text" id="input_Title" placeholder="Title" required>
                <input type="text" id="input_Author" placeholder="Author" required>
                <input type="number" id="input_Pages" placeholder="Pages" required>
                <div>
                    <label for="#">Did you read it?</label>
                    <input type="checkbox" name="read" id="read">
                </div>
                <button type="submit" id="submit">Submit</button>
            </form>
        </div>
        <div class="footer">
            <p>Copyright © 2024 IfrahimA</p>
            <svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="50" height="50" viewBox="0 0 30 30">
            <path d="M15,3C8.373,3,3,8.373,3,15c0,5.623,3.872,10.328,9.092,11.63C12.036,26.468,12,26.28,12,26.047v-2.051 c-0.487,0-1.303,0-1.508,0c-0.821,0-1.551-0.353-1.905-1.009c-0.393-0.729-0.461-1.844-1.435-2.526 c-0.289-0.227-0.069-0.486,0.264-0.451c0.615,0.174,1.125,0.596,1.605,1.222c0.478,0.627,0.703,0.769,1.596,0.769 c0.433,0,1.081-0.025,1.691-0.121c0.328-0.833,0.895-1.6,1.588-1.962c-3.996-0.411-5.903-2.399-5.903-5.098 c0-1.162,0.495-2.286,1.336-3.233C9.053,10.647,8.706,8.73,9.435,8c1.798,0,2.885,1.166,3.146,1.481C13.477,9.174,14.461,9,15.495,9 c1.036,0,2.024,0.174,2.922,0.483C18.675,9.17,19.763,8,21.565,8c0.732,0.731,0.381,2.656,0.102,3.594 c0.836,0.945,1.328,2.066,1.328,3.226c0,2.697-1.904,4.684-5.894,5.097C18.199,20.49,19,22.1,19,23.313v2.734 c0,0.104-0.023,0.179-0.035,0.268C23.641,24.676,27,20.236,27,15C27,8.373,21.627,3,15,3z"></path>
            </svg>
        </div>   
    </div>
    <script src="script.js"></script>
</body>
</html>

If you take a close look at the addButtons function. The readBtn only runs once. I have tried to run it outside of the scope, but I am unable to retrieve the elements in order to perform that operation. What are some ways to perform the code below indefinitely. I am pretty new to .js and any help would be greatly appreciated.

readBtn.addEventListener('click', () => {
        if (elements.isRead == true) {
            readBtn.classList.remove('is-read');
            readBtn.classList.add("not-read");
        }
        else {
            readBtn.classList.remove('not-read');
            readBtn.classList.add('is-read');
        }
    });

Any other attempt to trying to run it outside of the scope results in an error.

Codepen –> https://codepen.io/Ifrahim-Ansari/pen/JjVqyZm

How to achieve a typewriter effect with an array of words

I achieved a loop typewriter effect; however, after it’s first way through the array the first word in the array is not getting typed again. Plus, I’m getting a couple of ‘undefined’ after the last word before it starts over on the second word. I want it to start over at the first word. Here’s my code:

'use client';
import React, {useEffect} from "react";

const words = ["Business", "Company", "Startup"];

let i = 0;
let a = 0;
let txt = `${words[a]}`;
let speed = 1100;
let loop = true;

export default function Home() {
  const typeWriter = (headerMessage: any) => {
    if (i < txt.length) {
      headerMessage.innerHTML += txt.charAt(i);
      i++;
      setTimeout(() => typeWriter(headerMessage), speed);
    } else if (loop) {
      clearText(headerMessage);
    }
  }

  const clearText = (headerMessage: any) => {
    headerMessage.innerHTML = "";
    i = 0;
    a++;
    txt = `${words[a]}`;
    if (a > 3) {
      a=0;
    }
    setTimeout(() => {
      typeWriter(headerMessage);
   }, 2000);
  }

  useEffect (() => {
    const headerMessage = document.getElementById("header-message");
    if (headerMessage) {
      typeWriter(headerMessage);
    }
      
  }, []);
  return (
    <main>
      <section>
        <section>
          <div>Let Us Help Grow Your<p id="header-message"></p>.</div>
        </section>
        <section></section>
      </section>
    </main>
  );
}

Is aria-labelledby necessary when there is “for” and “id” association with label and input?

Below is the html structure for Text Field component from Adobe Spectrum: https://react-spectrum.adobe.com/react-spectrum/TextField.html
There is for attribute on <label> and id on <input> which gets screen reader to read out the label when input is focused. So why is aria-labelledby here is necessary? As per their document, it states
“If a visible label isn’t specified, an aria-label must be provided to the TextField for accessibility. If the field is labeled by a separate element, an aria-labelledby prop must be provided using the id of the labeling element instead.”
But isn’t for and id association enough?

<div class="A-HlBa_spectrum-Field A-HlBa_spectrum-Field--positionTop YO3Nla_spectrum-Textfield-wrapper">
  <label id="react-aria3159902326-:r2i:" class="A-HlBa_spectrum-FieldLabel" for="react-aria3159902326-:r2h:">Name</label>
  <div class="YO3Nla_spectrum-Textfield YO3Nla_spectrum-FocusRing YO3Nla_spectrum-FocusRing-ring A-HlBa_spectrum-Field-field">
    <input type="text" id="react-aria3159902326-:r2h:" aria-labelledby="react-aria3159902326-:r2i:" class="YO3Nla_spectrum-Textfield-input YO3Nla_i18nFontFamily" value="">
  </div>
</div>

How to Create Sticky, Cohesive Shape-to-Shape (Containers) Morphing with CSS and JavaScript?

I’m trying to create an effect where two rectangular shapes (with rounded ends), each containing text, move toward each other, merge/morph into a singular rounded rectangle as I scroll down the page, and separate again when I scroll up. The shapes need to remain sticky to the viewport position during scrolling.
enter image description here

What I’ve Tried:

  • Applying CSS translations and transformations along with JS adjustments of the border-radius properties.
  • Incorporating clip-path, but I end up with ellipses.
  • Using HTML Shapes, but I need them to be containers.

The closest I’ve gotten is merely getting the shapes to move toward each other and slightly overlap. Other attempts have resulted in ellipse shapes, unnatural border-radius, or a lack of cohesion between the two elements.

document.addEventListener('scroll', () => {
    const scrollPercent = window.scrollY / (document.body.scrollHeight - window.innerHeight);
   
    const movement = (window.innerWidth / 2 - 115) * scrollPercent;

    const shape1 = document.querySelector('.shape:nth-child(1)');
    const shape2 = document.querySelector('.shape:nth-child(2)');
    shape1.style.transform = `translateX(${movement}px)`;
    shape2.style.transform = `translateX(-${movement}px)`;
});
body {
    width: 90%;
    margin: 0 auto;
    padding: 20px;
    height: 2000px;
}

.container {
    position: sticky;
    top: 20px;
    display: flex;
    justify-content: space-between;
}

.shape {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 100px;
    height: 30px;
    border-radius: 15px;
    background-color: #000;
    color: #fff;
    transition: transform 0.3s ease-out;
    transform: translateX(0%);
}
<body>
    <div class="container">
        <div class="shape" id="shape1">Shape 1</div>
        <div class="shape" id="shape2">Shape 2</div>
    </div>
</body>

Question:
I feel like I’m missing something with clip-path and that this is the route I need to take. How can I improve my CSS and adjust my JavaScript to achieve the morphing effect shown in the image above while maintaining rounded outer edges and building cohesion between the two containers? I appreciate any suggestions or corrections to my current approach. Thank you.

How do I call a python function recommender.py in javascript? link function in python to be used in my script.js on button click without using flask [duplicate]

I have a file recommender.py, which contains a python function get_recommendations(title)
I want to use this in my script.js file

// Function to handle rating submission
function submitRating(movieTitle) {
    const ratingInput = document.getElementById(`rating-${movieTitle}`).value;

    // Store rating in dictionary
    userRatings[movieTitle] = parseFloat(ratingInput);

    // Log userRatings for testing (remove this line in production)
    console.log('User Ratings:', userRatings);
    
    // Call a function to handle further processing (if needed)
    handleRatingSubmission();
}

// Function to handle further processing after rating submission
function handleRatingSubmission() {
    var userRatingsArray = Object.entries(userRatings);

// Sort the array based on the values
    userRatingsArray.sort(function(a, b) {
       return a[1] - b[1]; // Change this if values are not numeric
    });
    console.log(userRatingsArray)
    function getRatingByTitle(title) {
        for (var i = 0; i < userRatingsArray.length; i++) {
            if (userRatingsArray[i][0] === title) {
                return userRatingsArray[i][1];
            }
        }
        // Return null if title not found
        return null;
    }
    var highestmovies = userRatingsArray.slice(0, -2);
    if((getRatingByTitle(highestmovies[1])-getRatingByTitle(highestmovies[0]))>3){
        return get_recommendations(highestmovies[1])
    }
    else{
        var arr1=get_recommendations(highestmovies[1]).splice(0,4)
        var arr2=get_recommendations(highestmovies[0]).splice(0,3)
        arr1= arr1.concat(arr2)
        uniqarr= Array.from(new Set(arr1))
        uniqarr=uniqarr.splice(0,5)
        return uniqarr.sort(function(a, b) {
            return a[1] - b[1]; 
         });
    }

}

I want to use the python get_recommendations function in the Javascript code
How do I go about this? I am not familiar with Javascript at all, any help will be appreciated

I tried to use AJAX request, and converting the entire python code to Javascript but it did not work as expected.

How to appendChild in all the elements in loop having specific Text in javascript?

I am creating a Dynamic Tree of elements by using an Array Values maintaining the level by attribute value of Parent, which match from the element Button Text
I later on use as accordion.

here the issue coming is, it does not create element for all the elements having that specific Text

I have even used the For Loop and then try to insert with nextElementSibling as you can see in below function

function appendSymptomToForm(symptom, symptomElements, container) {
    if (symptom.parent === 'none') {
        symptomForm.appendChild(container);
    } else {
        
var aTags = document.getElementsByTagName("button");
var searchText = symptom.parent;
var found;

for (var i = 0; i < aTags.length; i++) {    
  if (aTags[i].textContent == searchText) {  

    found = aTags[i].nextElementSibling;    
            found.insertBefore(container, found.nextElementSibling);
  }
}
    }
    console.log(`Symptom ${symptom.text} appended to the form.`);
}

Below I have created the fiddle which give you full understanding, that I have 3 Levels in the array named, window.symptomData.
Every element add according to its Parent Attribute

for example note second Level B:

{ depth: 3, text: ‘Third level B’, parent: ‘second level B’, tooltip:
‘Descrie simptomele după o perioadă de ore’ }

Here you will see that there are multiple buttons of second Level B but it add Third Level only under the Last Element

Please refer the function appendSymptomToForm in the fiddle, where
it does appendChild

Working Fiddle

window.symptomData = [
    { depth: 0, text: 'De aproximativ', parent: 'none', tooltip: 'Perioadă nespecificată de timp, folosită pentru estimări' },
    { depth: 1, text: '1', parent: 'De aproximativ', tooltip: 'Al doilea nivel de timp estimat, similar cu primul' },
    { depth: 1, text: '2', parent: 'De aproximativ', tooltip: 'Al doilea nivel de timp estimat, similar cu primul' },
    { depth: 1, text: '3', parent: 'De aproximativ', tooltip: 'Al doilea nivel de timp estimat, similar cu primul' },
    { depth: 1, text: '4', parent: 'De aproximativ', tooltip: 'Al doilea nivel de timp estimat, similar cu primul' },
    
    { depth: 2, text: 'second level A', parent: '1', tooltip: 'Durată exprimată în ore' },
    { depth: 2, text: 'second level A', parent: '1', tooltip: 'Durată exprimată în zile' },
    { depth: 2, text: 'second level A', parent: '1', tooltip: 'Durată de timp' },    
    { depth: 2, text: 'second level A', parent: '1', tooltip: 'Durată exprimată în luni' },
    { depth: 2, text: 'second level A', parent: '1', tooltip: 'Durată exprimată în ani' },

    { depth: 2, text: 'second level B', parent: '2', tooltip: 'Durată exprimată în ore' },
    { depth: 2, text: 'second level B', parent: '2', tooltip: 'Durată exprimată în zile' },
    { depth: 2, text: 'second level B', parent: '2', tooltip: 'Durată exprimată în săptămâni' },
    { depth: 2, text: 'second level B', parent: '2', tooltip: 'Durată exprimată în luni' },
    { depth: 2, text: 'second level B', parent: '2', tooltip: 'Durată exprimată în ani' },

    { depth: 2, text: 'second level B', parent: '3', tooltip: 'Durată exprimată în ore' },
    { depth: 2, text: 'second level B', parent: '3', tooltip: 'Durată exprimată în zile' },
    { depth: 2, text: 'second level B', parent: '3', tooltip: 'Durată exprimată în săptămâni' },
    { depth: 2, text: 'second level B', parent: '3', tooltip: 'Durată exprimată în luni' },
    { depth: 2, text: 'second level B', parent: '3', tooltip: 'Durată exprimată în ani' },
    
    { depth: 2, text: 'second level B', parent: '4', tooltip: 'Durată exprimată în ore' },
    { depth: 2, text: 'second level B', parent: '4', tooltip: 'Durată exprimată în zile' },
    { depth: 2, text: 'second level B', parent: '4', tooltip: 'Durată exprimată în săptămâni' },
    { depth: 2, text: 'second level B', parent: '4', tooltip: 'Durată exprimată în luni' },
    { depth: 2, text: 'second level B', parent: '4', tooltip: 'Durată exprimată în ani' },
    
    { depth: 3, text: 'Third level A', parent: 'second level A', tooltip: 'Descrie simptomele după o perioadă de ore' },
    { depth: 3, text: 'Third level A', parent: 'second level A', tooltip: 'Descrie simptomele după o perioadă de zile' },
    { depth: 3, text: 'Third level A', parent: 'second level A', tooltip: 'Descrie simptomele după o perioadă de săptămâni' },
    { depth: 3, text: 'Third level A', parent: 'second level A', tooltip: 'Descrie simptomele după o perioadă de luni' },
    { depth: 3, text: 'Third level A', parent: 'second level A', tooltip: 'Descrie simptomele după o perioadă de ani' },
    
    { depth: 3, text: 'Third level B', parent: 'second level B', tooltip: 'Descrie simptomele după o perioadă de ore' },
    { depth: 3, text: 'Third level B', parent: 'second level B', tooltip: 'Descrie simptomele după o perioadă de zile' },
    { depth: 3, text: 'Third level B', parent: 'second level B', tooltip: 'Descrie simptomele după o perioadă de săptămâni' },
    { depth: 3, text: 'Third level B', parent: 'second level B', tooltip: 'Descrie simptomele după o perioadă de luni' },
    { depth: 3, text: 'Third level B', parent: 'second level B', tooltip: 'Descrie simptomele după o perioadă de ani' },
];

// script.js
document.addEventListener('DOMContentLoaded', function() {
    console.log('DOMContentLoaded event triggered, initializing symptoms setup...');
    const symptomData = window.symptomData; // Now pulling from the global variable set by sd.js

    const symptomForm = document.getElementById('symptomForm');
    if (!symptomForm) {
        console.error('Failed to find symptom form on the page.');
        return;
    }

    let symptomElements = {};
    const tooltipDiv = document.createElement('div');
    setupTooltipDiv(tooltipDiv);
    document.body.appendChild(tooltipDiv);

    symptomData.forEach(symptom => {
        const container = document.createElement('div');
        setupSymptomContainer(symptom, container);

        const button = document.createElement('button');
        setupSymptomButton(symptom, button, container);

        const childrenContainer = document.createElement('div');
        setupChildrenContainer(childrenContainer, container);

        symptomElements[symptom.text] = { button, container, childrenContainer };

        setupButtonEvents(button, childrenContainer);
        appendSymptomToForm(symptom, symptomElements, container);
    });

    setupSendButton();
});

function setupTooltipDiv(tooltipDiv) {
    tooltipDiv.id = 'tooltipDiv';
    tooltipDiv.style = "position: fixed; bottom: 20px; left: 20px; padding: 10px; " +
                       "background-color: rgba(0, 0, 0, 0.75); color: white; border-radius: 5px; display: none;";
    console.log('Tooltip div setup completed.');
}

function setupSymptomContainer(symptom, container) {
    container.className = `symptom-instance depth-${symptom.depth}`;
    console.log(`Setup container for symptom: ${symptom.text}`);
}

function setupSymptomButton(symptom, button, container) {
    button.textContent = symptom.text;
    button.className = 'symptom-button';
    button.title = symptom.tooltip;
    container.appendChild(button);
    console.log(`Button created for symptom: ${symptom.text}`);
}

function setupChildrenContainer(childrenContainer, container) {
    childrenContainer.className = 'sub-symptoms hidden';
    container.appendChild(childrenContainer);
    console.log('Children container setup completed.');
}

function setupButtonEvents(button, childrenContainer) {
    button.onclick = () => {
        childrenContainer.classList.toggle('hidden');
        button.classList.toggle('pressed');
        scrollToButton(button);
        console.log(`Visibility toggled for: ${button.textContent}, New state: ${childrenContainer.className}`);
    };
    button.addEventListener('touchstart', () => showTooltip(button, button.title), { passive: true });
    button.addEventListener('touchend', hideTooltip, { passive: true });
}

function appendSymptomToForm(symptom, symptomElements, container) {
       if (symptom.parent === 'none') {
        symptomForm.appendChild(container);
    } else {
        
var aTags = document.getElementsByTagName("button");
var searchText = symptom.parent;
var found;

for (var i = 0; i < aTags.length; i++) {    
  if (aTags[i].textContent == searchText) {  

    found = aTags[i].nextElementSibling;    
            found.insertBefore(container, found.nextElementSibling);
  }
}
    }
    console.log(`Symptom ${symptom.text} appended to the form.`);
}

function scrollToButton(button) {
    const buttonRect = button.getBoundingClientRect();
    const visibleAreaStart = window.innerHeight / 4;
    const scrollYOffset = buttonRect.top - visibleAreaStart + window.scrollY;
    window.scrollTo({
        top: scrollYOffset,
        behavior: 'smooth'
    });
    console.log(`Scrolled to button: ${button.textContent}`);
}

function setupSendButton() {
    const sendButton = document.createElement('button');
    sendButton.textContent = 'Copiaza Selectate';
    sendButton.addEventListener('click', () => {
        const selectedSymptoms = Array.from(document.querySelectorAll('.symptom-button.pressed'))
            .map(btn => btn.textContent.trim())
            .join(', ');
        navigator.clipboard.writeText(selectedSymptoms)
            .then(() => {
                console.log('Selected symptoms copied to clipboard.');
                alert('Selected symptoms copied to clipboard.');
            })
            .catch(err => {
                console.error('Error copying to clipboard:', err);
                alert('Failed to copy symptoms. See console for errors.');
            });
    });
    document.body.appendChild(sendButton);
    console.log('Send button setup completed.');
}

function showTooltip(button, text) {
    const tooltipDiv = document.getElementById('tooltipDiv');
    tooltipDiv.textContent = text;
    tooltipDiv.style.display = 'block';
    console.log(`Tooltip shown for ${button.textContent}: ${text}`);
}

function hideTooltip() {
    const tooltipDiv = document.getElementById('tooltipDiv');
    tooltipDiv.style.display = 'none';
    console.log('Tooltip hidden.');
}
    <div id="symptomForm">
    </div>

Calling Yahoo Finance API in RapidAPI via axios returns error 500

I’m subscribed to the Yahoo Finance API via RapidAPI and I’m calling the API using axios like this:

 const apiKey = ref([MY API KEY])
 const apiURL = ref('https://yahoo-finance127.p.rapidapi.com')

 const headers = ref({
   'x-rapidapi-key': apiKey.value,
   'x-rapidapi-host': apiURL.value
 })

 axios.get(apiURL.value + '/price/NVDA', { headers: headers.value })
   .then(response => console.log(response.data.data))
   .catch(error => console.error(error.message))

Any idea why this is returning an error 500?

ReactJS: Moving to a new page from auto refresh page not working

I auto a refresh a page (say Page1) in every 5 second interval using setTimeout and callback function.

When I move to a new page (say Page2), its going new page and after few seconds again returning to Page1.

I tried window beforeunload event listener, react useBeforeUnload, nothing works. Here is the minimal code to reproduce the issue.

const SampleTestStats = () => {
  let allowStateChange = true;
  let sampleTimeOut = null;
  let SAMPLE_TEST_STATS_REFRESH_TIME = 5000;
  const [result, setResult] = useState([{ tid: 0, tcname: "none"},]);

  const user = JSON.parse(localStorage.getItem('user'));
    
  function refreshPage() {
    sampleTimeOut = setTimeout(refreshPage, SAMPLE_TEST_STATS_REFRESH_TIME);
    window.location.href = "/components/view/sampletest/stats";
  }

  useBeforeUnload(
    React.useCallback(() => {
      console.log('In useBeforeUnload');
      allowStateChange = false;
      clearTimeout(sampleTimeOut);
    })
  );

  const fetchTestStats = async () => {
    try {
      const res = await axios.post('/test/current/active/data', 
      {uid: user.uid, email: user.email} ,
      {headers: {
        'Authorization': user.jwt,
      }}).then( 
      function (res) {
        if(res.status === 200) {
          if(allowStateChange) {
            let newResult = {tid: res.data[0].tid, tcname: res.data[0].testname};
            setResult([newResult]);
          }
        }
      });
    }catch(err) {
    }
  }

  useEffect ( () => {
    fetchTestStats();
  }, []); 
  
  sampleTimeOut = setTimeout(refreshPage, SAMPLE_TEST_STATS_REFRESH_TIME);
  return (`My simple refresh test page, test id = ${result[0].tid} and test name = ${result[0].tcname}.`);
}

Can somebody please help me, when I move to a new page Page2 again automatically it should not come back to old page Page1.

Solid JS Trouble Passing Information from Child to Child

I’ve created a card component which has it’s background image set from it’s parent component. These cards act as buttons to open modals with more details and share an image. I don’t want the modal constrained to the size of the card. I want it to appear over the rows of cards.

I tried to:

  1. I set a signal in my parent component.
  2. Then passed the setter for the signal into my card component.
  3. In my card component I use the setter to set the new signal value upon opening the modal.
  4. Then passed the new signal value into the modal as a prop.
  5. I use the prop value for the modal image.

PARENT COMPONENT

export const ClassSelect = () => {
    const [classes] = createResource(getClasses);
    const [modalToggle, setModalToggle] = createSignal(false);

//--- 1.SET THE SIGNAL ---
    const [modalBackground, setModalBackground] = createSignal('');

    return (
        <div className="classSelectLayoutStyles">
            <h1 className="pl-4 text-white font-extrabold text-shadow-main text-header-md shadow-fuchsia-900">
                Select a Class!
            </h1>
            <div className="classSelectGridStyles">
                <For each={classes()}>{(_class) =>
                    <SelectionCard
                    name={_class.class_name}
                    backgrounds={classBackgrounds}
                    cardShrink={"classBackgroundShrink"}
                    imgShrink={"classImageShrink"}
                    modalToggle={modalToggle}
                    setModalToggle={setModalToggle}
//--- 2.PASS THE SETTER ---
                    modalBackground={modalBackground}
                    **setModalBackground={setModalBackground}**
                />
                }</For>
            </div>
            <Show when={modalToggle()}>
//--- 3.PASS THE NEW SIGNAL VALUE ---
                <ClassDescriptionModal setModalToggle={setModalToggle} modalBackground={modalBackground}/>
            </Show>
        </div>
    );
};

CARD COMPONENT

export const SelectionCard = (props) => {
  const selectionName = props.name;
  const selectionBackgrounds = props.backgrounds;
  const cardShrink = props.cardShrink;
  const imgShrink = props.imgShrink;
  const setModalToggle = props.setModalToggle;
  const modalBackground = props.modalBackground;
  const setModalBackground = props.setModalBackground;

  const selectionBackground = selectionBackgrounds[selectionName.toLowerCase().replace(/s/g, "")];

  const createSelectionClass = (selectionBackgrounds) => {
    if (selectionBackgrounds) {
      return (
        imgShrink +
        " " +
        selectionBackground +
        " saturate-30 hover:saturate-100 flex justify-center w-full h-full"
      );
    } else {
      return "selectionBackground bg-skulls bg-gray-900 saturate-30 hover:saturate-100 flex justify-center w-full h-full";
    }
  };
//--- 4.SET THE NEW SIGNAL VALUE UPON OPENING THE MODAL ---
  const openModal = () => {
    setModalBackground(selectionBackground);
    setModalToggle(true);
  };

  return (
    <div
      onClick={openModal}
      className={
        cardShrink
          ? "baseLayoutStyles " + cardShrink
          : "baseLayoutStyles cardShrink"
      }
    >
      <div className={createSelectionClass(selectionBackgrounds)}>
        <div className="text-center text-white text-xl font-extrabold pt-4 bg-colorHeader rounded-t w-full h-1/6 text-shadow shadow-gray-800">
          {selectionName}
        </div>
      </div>
    </div>
  );
};

MODAL COMPONENT

export const ClassDescriptionModal = (props) => {
  const setModalToggle = props.setModalToggle;
  const modalBackground = props.modalBackground;

  const getModalClass = (modalBackground) => {
    return "w-1/2 h-full "+ modalBackground +" rounded-l-lg";
  }

  const closeModal = () => setModalToggle(false);

  return (
    <div onClick={closeModal} className="fixed top-0 left-0 right-0 bottom-0 bg-black bg-opacity-10 z-50 flex items-center justify-center">
      <div className={"baseLayoutStyles flex flex-row absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-5/6 h-5/6 bg-skulls bg-gray-900 rounded-lg"}>

//--- 5.MODAL IMAGE ---
        <div className={getModalClass(modalBackground)}></div>

        <div className="w-1/2 h-full p-4">
          <button
              onClick={closeModal}
              className="px-4 py-2 bg-fuchsia-900 text-white rounded"
          >
            Close
          </button>
         </div>
      </div>
    </div>
  );
};

Disabling inputs in Bootstrap based on toggle switch selection?

Reading through the documentation, I’m trying to find a way in bootstrap 5 to disable other input fields if a toggle switch input is set to ‘off’?

Parent element is #member_form, switch is ‘toggleswitch’.

The following will disable the field when anything is the form is clicked. But I’d like to switch from enabled to disabled and back based on the the toggleswitch element?

    $(document).on('click', '#member_form', function(){
        $("#input_name").attr('disabled','disabled');
    });

Any suggestions?