HOW TO deploy simple NodeJS Backend to AWS [closed]

I am a beginner in backend. I am wondering how I can deploy my backend written in NodeJS and Express to AWS, so that my front end can send requests to the backend. I already have a web app hosted on GitHub. I used ChatGPT and it told me to use AWS Elastic Beanstalk for backend. I already configured eb in my local machine, but I do not know what to do next.

Suppose my backend is extremely simple that only contains (so we can focus solely on deployment):

app.get('', (req, res)=>{res.status(200).send("Hello World")})

Any help is appreciated. Thanks!

Two animations in the same graphic (ECHARTS)

I tried triggering two animations after clicking a button. The first animation moves the center of the gauge upwards (and this works). The second (which doesn’t work) would be to move the pointers randomly and return to the initial value, as configured in the code below:

  const mychartspider1 = echarts.init(document.getElementById('gaugespiderinc1'));
  const maxValue = 100;
  const numPointers = 4; // Number of pointers
  let randomValuesInterval;
  let randomColorsInterval;
  let centerAnimationInterval;

  function getRandomValue(min, max) {
    return Math.random() * (max - min) + min;
  }

  function setRandomValues() {
    let data = [];

    for (let i = 0; i < numPointers; i++) {
      data.push({
        value: getRandomValue(0, maxValue)
      });
    }

    updateGaugeSpider(data);
  }

  function updateGaugeSpider(data) {
    option = {
      series: [{
          type: 'gauge',
          min: 0,
          max: 100,
          splitNumber: 10,
          radius: '75%',
          center: ['50%', '150%'],
          axisLine: {
            lineStyle: {
              color: [
                [1, '#49a6de']
              ],
              width: 3.5
            }
          },
          splitLine: {
            distance: -28,
            length: 28,
            lineStyle: {
              width: 5,
              color: '#49a6de'
            }
          },
          axisTick: {
            distance: -12,
            length: 10,
            lineStyle: {
              width: 2,
              color: '#49a6de'
            }
          },
          axisLabel: {
            distance: -64,
            color: '#49a6de',
            fontSize: 36,
            fontFamily: 'D-DIN',
            textStyle: {
              textBorderWidth: 1,
              textBorderColor: '#020202'
            }
          },
          anchor: {
            show: true,
            size: 25,
            itemStyle: {
              borderColor: "#020202",
              borderWidth: 2
            }
          },
          pointer: {
            offsetCenter: [0, "10%"],
            icon: "path://M2090.36389,615.30999 L2090.36389,615.30999 C2091.48372,615.30999 2092.40383,616.194028 2092.44859,617.312956 L2096.90698,728.755929 C2097.05155,732.369577 2094.2393,735.416212 2090.62566,735.56078 C2090.53845,735.564269 2090.45117,735.566014 2090.36389,735.566014 L2090.36389,735.566014 C2086.74736,735.566014 2083.81557,732.63423 2083.81557,729.017692 C2083.81557,728.930412 2083.81732,728.84314 2083.82081,728.755929 L2088.2792,617.312956 C2088.32396,616.194028 2089.24407,615.30999 2090.36389,615.30999 Z",
            length: "115%",
            itemStyle: {
              borderWidth: 1,
              borderColor: "#020202",
              shadowOffsetX: 4,
              shadowOffsetY: 4,
              shadowColor: "#020202",
              shadowBlur: 10,
            }
          },
          detail: {
            valueAnimation: true,
            borderWidth: 3,
            borderColor: '#858383',
            borderRadius: 5,
            color: '#020202',
            fontWeight: 'bold',
            width: 23,
            height: 18,
            fontSize: 20,
            fontFamily: 'DS-Digital',
            formatter: function(value) {
              return value.toFixed(0) + '%';
            }
          },
          data: data.map((item, index) => {
            const colors = ['#dd4b39', 'orange', 'lime', 'cyan'];
            const titleName = ['Name 1', 'Name 2', 'Name 3', 'Name 4'];
            const offsetName = [
              ['-45%', '70%'],
              ['-15%', '70%'],
              ['15%', '70%'],
              ['45%', '70%']
            ];
            const offsetDetail = [
              ['-45%', '84%'],
              ['-15%', '84%'],
              ['15%', '84%'],
              ['45%', '84%']
            ];
            return {
              value: item.value,
              itemStyle: {
                color: colors[index % colors.length]
              },
              name: titleName[index % titleName.length],
              title: {
                offsetCenter: offsetName[index % offsetName.length],
                color: colors[index % colors.length]
              },
              detail: {
                backgroundColor: colors[index % colors.length],
                offsetCenter: offsetDetail[index % offsetDetail.length]
              }
            };
          })
        },
        {
          type: 'gauge',
          min: 0,
          max: 60,
          splitNumber: 6,
          radius: '70%',
          center: ['50%', '150%'],
          axisLine: {
            lineStyle: {
              color: [
                [1, '#fee200']
              ],
              width: 3.5
            }
          },
          splitLine: {
            distance: 10,
            length: 28,
            lineStyle: {
              width: 5,
              color: '#fee200'
            }
          },
          axisTick: {
            show: false
          },
          axisLabel: {
            distance: 10,
            fontSize: 33,
            color: '#fee200',
            fontFamily: 'D-DIN',
            textStyle: {
              textBorderWidth: 1,
              textBorderColor: '#020202'
            }
          },
          pointer: {
            show: false
          },
          title: {
            show: false
          },
          anchor: {
            show: true,
            size: 14,
            itemStyle: {
              color: "#f00",
              borderColor: "#020202",
              borderWidth: 1
            }
          }
        }
      ]
    };

    mychartspider1.setOption(option);
  }

  let colorIndex = 0; // Variável para controlar o índice da cor a ser aplicada

  function setNextColor() {
    const colors = ['#f00', '#49a6de'];
    const color = colors[colorIndex]; // Seleciona a cor atual com base no índice
    colorIndex = (colorIndex + 1) % colors.length; // Atualiza o índice para a próxima cor
    return color;
  }

  function setRandomColors() {
    const color = setNextColor(); // Obtém a próxima cor sequencialmente
    mychartspider1.setOption({
      series: [{
        axisLabel: {
          color: color,
        },
        axisLine: {
          lineStyle: {
            color: [
              [1, color]
            ],
          }
        },
        splitLine: {
          lineStyle: {
            color: color
          }
        },
        axisTick: {
          lineStyle: {
            color: color
          }
        }
      }]
    });
  }

  // Button click event
  $('#startgaugeeffectbtnanimation1').one('click', function() {
    // Configure random values and colors initially
    setRandomValues();
    setRandomColors();

    // Update random values and colors every 500 milliseconds for 5 seconds
    randomValuesInterval = setInterval(setRandomValues, 500);
    randomColorsInterval = setInterval(setRandomColors, 500);

    setTimeout(() => {
      // Stop updating after 5 seconds
      clearInterval(randomValuesInterval);
      clearInterval(randomColorsInterval);

      // Restore input values
      let value1 = Number($('#number1').val());
      let value2 = Number($('#number2').val());
      let value3 = Number($('#number3').val());
      let value4 = Number($('#number4').val());
      updateGaugeSpiderFromInputs(value1, value2, value3, value4);
    }, 5000);
  });

  function updateGaugeSpiderFromInputs(value1, value2, value3, value4) {
    value1 = Number($('#number1').val());
    value2 = Number($('#number2').val());
    value3 = Number($('#number3').val());
    value4 = Number($('#number4').val());

    // Verifique se o intervalo está definido e, se sim, pare a animação
    if (randomValuesInterval) {
      clearInterval(randomValuesInterval);
      clearInterval(randomColorsInterval);
    }

    // Defina as cores finais diretamente
    updateGaugeSpider([{
        value: value1
      },
      {
        value: value2
      },
      {
        value: value3
      },
      {
        value: value4
      }
    ]);
  }

  // Input change event
  $('#number1, #number2, #number3, #number4').on('change', function() {
    updateGaugeSpiderFromInputs();
  });

  updateGaugeSpiderFromInputs();

  // animation center downUp
  // Função para iniciar a animação do centro do gauge para '50%'
  function startCenterAnimation() {
    let centerPosition = 150; // Inicializa a posição central
    let startTime; // Armazena o horário de início da animação

    function animateCenterChange(timestamp) {
      const duration = 5000; // Duração da animação em milissegundos
      const startValue = centerPosition; // Valor inicial da posição central
      const endValue = 50; // Valor final da posição central
      const progress = (timestamp - startTime) / duration; // Progresso da animação

      // Calcula o próximo valor da posição central com base no progresso
      const nextValue = startValue + (endValue - startValue) * progress;

      // Define o centro do gráfico com base no próximo valor
      mychartspider1.setOption({
        series: [{
            center: ['50%', nextValue + '%']
          },
          {
            center: ['50%', nextValue + '%']
          }
        ]
      });

      // Continua a animação se ainda não atingiu o fim
      if (progress < 1) {
        requestAnimationFrame(animateCenterChange);
      }
    }

    function handleClick() {
      startTime = performance.now(); // Obtém o horário de início da animação
      requestAnimationFrame(animateCenterChange); // Inicia a animação
    }

    document.getElementById('startgaugeeffectbtnanimation1').addEventListener('click', handleClick, {
      once: true
    });
  }

  // Inicializa a animação do centro do gauge quando o botão for clicado
  startCenterAnimation();
#gaugespiderinc1 {
  height: 500px;
  width: 500px;
}

body {
  background: #333;
}
<head>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/echarts.min.js"></script>
  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>

<input type="range" id="number1" min="0" max="100" value="25">
<input type="range" id="number2" min="0" max="100" value="50">
<input type="range" id="number3" min="0" max="100" value="75">
<input type="range" id="number4" min="0" max="100" value="100">

<div id='gaugespiderinc1'></div>

<button id='startgaugeeffectbtnanimation1'>
  Click me
</button>

See that the center animation works perfectly, but the pointers don’t move. Also note that the detail of the gauge is moving and the value is stopping according to the values of the HTML inputs, but I need the pointers to move randomly during the center animation (at the same time).

NodeJS/Puppeteer – can’t click an element

I’m trying to click on an element but whenever i click the focus seems to turn into an input.
Lemme try to rephrase: it is an clickable element who shows after i do some search. I want to click on it so i can do some other actions.
However, when i tell puppeteer to click on it, the focus seems to go into an input who’s close to this button.

I’ve did this with Selenium and got it working. But i had to leave Selenium due to performance issues and then i decided to go with Puppeteer for node.js . However i’m encountering this issue.

Problem occurring

Yellow is the button im trying to click. Green is where the focus is going on when i execute the click action. Ive noticed that when i pass the mouse on this blue button, its a bit unstable (sometimes its available for clicking, others isn`t. But it can be just my impression).

Ive also tried to disable this input to check if i could force` the focus to stay where i wanted. No success also.

The HTML code for where i`m trying to click is:
HTML CODE

I’ve noticed the focus is going to the previous div (class=search). But i have no idea why this is happening.

Here’s what i’ve tried so far (running on node.js)

const puppeteer = require('puppeteer');

(async () => {
    const browser = await puppeteer.launch({ 
        headless: false,
        args: [
            '--window-size=800,600' 
           
        ]
    });
    const page = await browser.newPage();

   //Begin navigation. Go to the URL, type login and password, press enter and login
    await page.goto('https://www.santandernegocios.com.br/portaldenegocios/#/externo');
    await page.waitForSelector('#userLogin__input'); 
    await page.waitForSelector('#userPassword__input'); 
    await page.type('#userLogin__input', 'EX108593'); 
    await page.type('#userPassword__input', '@BARC02');  
   await page.focus('#userPassword__input');
   await page.keyboard.press('Enter')

   //Waiting until it finishes loading the page
    await page.waitForNavigation();

   
    await page.waitForSelector('input[name="inputSearch"]');
    await page.type('input[name="inputSearch"]', '32877625000122');
    await page.focus('input[name="inputSearch"]');
    await page.keyboard.press('Enter')
    await page.waitForNavigation();
    //Waiting the first results being shown and html loading before proceed
    /*
    // Disable the input element
    await page.evaluate(() => {
        const inputElement = document.querySelector('input[name="inputSearch"]');
        if (inputElement) {
            inputElement.setAttribute('disabled', 'true');
        }
    });

    // Checking if it was disabled
    const isDisabled = await page.evaluate(() => {
        const inputElement = document.querySelector('input[name="inputSearch"]');
        return inputElement.hasAttribute('disabled');
    });

    console.log('Input element disabled:', isDisabled);
    */
   
   
   
   
   
   //Trying to reach the button
    try {
        
        const selector = 'div.show-menu-client.ng-star-inserted'; 
        await page.waitForSelector(selector, { visible: true, timeout: 10000 });

        // Check if the element is clickable
        await page.waitForFunction(
            selector => {
                const element = document.querySelector(selector);
                return element && !element.hasAttribute('disabled') && getComputedStyle(element).pointerEvents !== 'none';
            },
            {},
            selector
        );

        console.log('Clickable');

        // Interact with the element
        const element = await page.$(selector);
        if (element) {
            await element.click(); // Example click action
            console.log('Clicked.');
        } else {
            console.log('Element not found.');
        }
    } catch (error) {
        console.log('Error:', error.message);
    }



})();

Any input is appreciated. Thanks a lot!

navigator.clipboard.writeText not working on mobile

I have no idea why this doesn’t work:

js:

const copybutton = document.getElementById('copy');

copybutton.addEventListener('click', function(){

   copybutton.innerHTML = "[<i>email copied to clipboard</i>]";  
   navigator.clipboard.writeText("[email protected]");

}
)

html:

<button id="copy"> send a message</button>

All I managed to find is that it needs to be triggered by an event listener, which it definitely is. Works well on mobile. On mobile chrome it worked as an inline snippet but not when I made it into an event listener in a separate doc. Is the support bad for it?

(project uses JQuery as well, if that helps.)

Problem with push notifications in production React Native

When I test the notification system in a test environment using expo go, everything works as it should. However, when I create an APK through expo and install it on the phone, everything works except when I click on the notification, there is a problem because it does not redirect to the finished screen.

Screen1.js:

const getStoredNotifications = async () => {
    const notifications = await AsyncStorage.getItem('notifications');
    return notifications ? JSON.parse(notifications) : [];
};

const storeNotification = async (notificationId) => {
    const notifications = await getStoredNotifications();
    const updatedNotifications = [...notifications, notificationId];
    await AsyncStorage.setItem('notifications', JSON.stringify(updatedNotifications));
};

const scheduleReminder = async (item, immediate = false) => {
    const notifications = await getStoredNotifications();
  
    if (!immediate && notifications.includes(item.id)) {
      console.log(`Reminder already scheduled for item: ${decode(item.name)}`);
      return;
    }

    const itemStartDateTime = new Date(`${item.date}T${item.startTime}`);
    const triggerDate = immediate ? new Date(Date.now() + 5 * 1000) : new Date(itemStartDateTime.getTime() - 60 * 60 * 1000);
  
    if (triggerDate > new Date()) {    
      const latitude = parseFloat(item.latitude);
      const longitude = parseFloat(item.longitude);
      
      console.log(`Parsed coordinates: Latitude = ${latitude}, Longitude = ${longitude}`);
      
      if (!isNaN(latitude) && !isNaN(longitude)) {
        const formattedItem = {
          id: item.id,
          name: item.name,
          description: item.description,
          date: item.date,
          time: `${item.startTime} - ${item.endTime}`,
          location: item.location,
          latitude: latitude,
          longitude: longitude,
          phone: item.phone,
          image: item.imagePath,
          price: item.ticketPrice,
        };

        console.log('Scheduling reminder with item:', JSON.stringify(formattedItem));
  
        const notificationId = await Notifications.scheduleNotificationAsync({
          content: {
            title: `Starting soon!`,
            body: `Your item ${formattedItem.name} starts ${immediate ? 'soon' : 'in 1 hour'}.`,
            data: { item: formattedItem, channelId: 'reminders' },
          },
          trigger: { date: triggerDate },
          channelId: 'reminders',
        });
  
        console.log(`Reminder scheduled for item: ${formattedItem.name} with ID: ${notificationId}`);
        if (!immediate) {
          await storeNotification(item.id);
        }
      } else {
        console.warn('Invalid coordinates received in reminder:', `Latitude: ${latitude}`, `Longitude: ${longitude}`);
      }
    } else {
      console.log(`Trigger date is in the past. No reminder scheduled for item: ${item.name}`);
    }
  };

const fetchStoredItems = useCallback(async () => {
    setLoading(true);
    try {
      const user = JSON.parse(await AsyncStorage.getItem('user'));
      if (!user) {
        Alert.alert("Not Logged In", "Please log in.");
        return;
      }
      const response = await fetch(`${config.BASE_URL}api/fetchStoredItems?userId=${user.id}`);
      const data = await response.json();
      if (data.success) {
        const validItems = data.items.filter(item => {
          const itemEndDate = moment(item.date).add(7, 'days');
          const isArchived = item.status === 'Archived';
          const isPastEndDate = moment().isAfter(itemEndDate);
  
          return !isArchived && !isPastEndDate;
        });
  
        setStoredItems(validItems);
  
        const notifications = await getStoredNotifications();
  
        const unprocessedItems = validItems.filter(item => !notifications.includes(item.id));
  
        for (const item of unprocessedItems) {
          await scheduleReminder(item);
        }
      } else {
        Alert.alert("Error", "Unable to retrieve stored items.");
      }
    } catch (error) {
      console.error('Failed to fetch stored items', error);
      Alert.alert("Error", "Network issue.");
    } finally {
      setLoading(false);
    }
  }, []);

const handleTestReminder = async () => {
    if (storedItems.length === 0) {
      Alert.alert("No Stored Items", "You currently have no stored items to test.");
      return;
    }
    const item = storedItems[0];
    await scheduleReminder(item, true);
};

<TouchableOpacity onPress={handleTestReminder} style={styles.testButton}>
          <Text style={styles.testButtonText}>Test Reminder</Text>
</TouchableOpacity>

App.js:

import React, { useEffect, useRef, useState } from 'react';
import * as SplashScreen from 'expo-splash-screen';
import * as Font from 'expo-font';
import Navigation from './Components/StackNavigation';
import * as Notifications from 'expo-notifications';
import { navigationRef } from './Components/NavigationService';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { decode } from 'utf8';

SplashScreen.preventAutoHideAsync();

export default function App() {
  const [fontsLoaded, setFontsLoaded] = useState(false);
  const [isNavigating, setIsNavigating] = useState(false);
  const notificationListener = useRef(null);

  const checkNotificationPermissions = async () => {
    const { status } = await Notifications.getPermissionsAsync();
    let finalStatus = status;

    if (status !== 'granted') {
      const { status } = await Notifications.requestPermissionsAsync();
      finalStatus = status;
    }

    if (finalStatus !== 'granted') {
      Alert.alert('Permissions', 'Notification permission is not enabled.');
      return false;
    }

    return true;
  };

  const saveReminderData = async (item) => {
    try {
      const itemData = JSON.stringify(item);
      await AsyncStorage.setItem(`reminder_${item.id}`, itemData);
      console.log('Reminder data saved locally.');
    } catch (error) {
      console.error('Failed to save reminder data:', error);
    }
  };

  const removeReminderData = async (itemId) => {
    try {
      await AsyncStorage.removeItem(`reminder_${itemId}`);
      console.log('Reminder data removed.');
    } catch (error) {
      console.error('Failed to remove reminder data:', error);
    }
  };

  useEffect(() => {
    async function loadResourcesAndDataAsync() {
      try {
        const hasPermission = await checkNotificationPermissions();
        if (!hasPermission) {
          console.log('Notifications are not allowed');
        }

        Notifications.setNotificationHandler({
          handleNotification: async () => ({
            shouldShowAlert: true,
            shouldPlaySound: true,
            shouldSetBadge: false,
          }),
        });

        const existingChannel = await Notifications.getNotificationChannelAsync('reminders');
        if (!existingChannel) {
          await Notifications.setNotificationChannelAsync('reminders', {
            name: 'Reminders',
            importance: Notifications.AndroidImportance.HIGH,
            vibrationPattern: [0, 250, 250, 250],
            lightColor: '#FF231F7C',
          });
          console.log('Notification channel created: reminders');
        } else {
          console.log('Notification channel already exists:', existingChannel);
        }

        await Font.loadAsync({
          // Fonts
        });

        const handleNotificationResponse = async (response) => {
          console.log('Notification response received:', response);
      
          const { identifier, content } = response.notification?.request || {};
          const channelId = content?.data?.channelId || 'reminders';
          console.log(`Notification ID: ${identifier}`);
          console.log(`Notification Channel: ${channelId}`);
      
          const item = content?.data?.item;

          console.log('Received item data:', item);

          if (item) {
            const formattedItem = {
              id: item.id,
              name: item.name,
              description: item.description || 'No description',
              date: item.date,
              time: item.time,
              location: item.location || 'N/A',
              latitude: parseFloat(item.latitude),
              longitude: parseFloat(item.longitude),
              phone: item.phone || 'No phone',
              image: item.image,
              price: item.price || 'N/A',
              openedFromNotification: true,
          };

              await removeReminderData(item.id);
      
              if (!isNaN(formattedItem.latitude) && !isNaN(formattedItem.longitude)) {
                  setIsNavigating(true);
                  navigationRef.current?.navigate('Item Details', { item: formattedItem });
                  setTimeout(() => setIsNavigating(false), 1000);
              } else {
                  console.warn('Invalid coordinates received in notification');
              }
          } else {
              console.error('Notification data is missing or invalid', item);
          }
      };

        const subscription = Notifications.addNotificationResponseReceivedListener(handleNotificationResponse);

        return () => {
          subscription.remove();
        };
      } catch (e) {
        console.warn(e);
      } finally {
        setFontsLoaded(true);
        SplashScreen.hideAsync();
      }
    }

    loadResourcesAndDataAsync();
  }, []);

  if (!fontsLoaded) {
    return null;
  }

  return <Navigation />;
}

When I run in production, and look at the logs, this shows me:

2024-08-11 23:31:35.473 19652-19690 EGL_emulation           com.example.MyApplication  D  app_time_stats: avg=34.05ms min=10.96ms max=140.43ms count=28
2024-08-11 23:31:37.991 19652-19690 EGL_emulation           com.example.MyApplication  D  app_time_stats: avg=176.36ms min=14.18ms max=2028.39ms count=14
2024-08-11 23:31:39.013 19652-19690 EGL_emulation           com.example.MyApplication  D  app_time_stats: avg=30.25ms min=2.52ms max=98.53ms count=30
2024-08-11 23:31:39.202 19652-19707 ReactNativeJS           com.example.MyApplication  I  Parsed coordinates: Latitude = 44.77935, Longitude = 20.439291
2024-08-11 23:31:39.523 19652-19707 ReactNativeJS           com.example.MyApplication  I  Notification scheduled for event: Children's Summer Games with ID: bd4741d9-416f-4e3b-87b6-7aac3fa6e574
2024-08-11 23:31:41.458 19652-19690 EGL_emulation           com.example.MyApplication  D  app_time_stats: avg=123.84ms min=2.02ms max=1899.74ms count=19
2024-08-11 23:31:42.483 19652-19690 EGL_emulation           com.example.MyApplication  D  app_time_stats: avg=20.06ms min=2.49ms max=33.73ms count=39
2024-08-11 23:31:44.474 19652-19807 expo-notifications      com.example.MyApplication  D  Notification request "bd4741d9-416f-4e3b-87b6-7aac3fa6e574" will not trigger in the future, removing.
2024-08-11 23:31:44.946 19652-19690 EGL_emulation           com.example.MyApplication  D  app_time_stats: avg=130.94ms min=2.37ms max=2005.04ms count=18
2024-08-11 23:31:45.967 19652-19690 EGL_emulation           com.example.MyApplication  D  app_time_stats: avg=26.19ms min=4.42ms max=58.36ms count=33
2024-08-11 23:31:48.521 19652-19652 ReactNativeJS           com.example.MyApplication  D  [native] ExpoNotificationLifecycleListener contains an unmarshaled notification response. Skipping.
2024-08-11 23:31:48.731 19652-19707 ReactNativeJS           com.example.MyApplication  I  'Notification response received:', { notification: 
                                                                                                       { request: 
                                                                                                          { trigger: 
                                                                                                             { channelId: null,
                                                                                                               value: 1723411904202,
                                                                                                               repeats: false,
                                                                                                               type: 'date' },
                                                                                                            content: 
                                                                                                             { autoDismiss: true,
                                                                                                               title: 'Starting Soon!',
                                                                                                               badge: null,
                                                                                                               sticky: false,
                                                                                                               sound: 'default',
                                                                                                               body: 'Your event Children's Summer Games is starting soon.',
                                                                                                               subtitle: null },
                                                                                                            identifier: 'bd4741d9-416f-4e3b-87b6-7aac3fa6e574' },
                                                                                                         date: 1723411904459 },
                                                                                                      actionIdentifier: 'expo.modules.notifications.actions.DEFAULT' }
2024-08-11 23:31:48.731 19652-19707 ReactNativeJS           com.example.MyApplication  I  Notification ID: bd4741d9-416f-4e3b-87b6-7aac3fa6e574
2024-08-11 23:31:48.731 19652-19707 ReactNativeJS           com.example.MyApplication  I  Notification Channel: reminders
2024-08-11 23:31:48.732 19652-19707 ReactNativeJS           com.example.MyApplication  E  'Notification data is missing or invalid', undefined
2024-08-11 23:31:48.883 19652-19708 unknown:ReactNative     com.example.MyApplication  E  console.error: Notification data is missing or invalid undefined, js engine: hermes, stack:
                                                                                                    _construct@1:141787
                                                                                                    Wrapper@1:141441
                                                                                                    _callSuper@1:139426
                                                                                                    SyntheticError@1:140918
                                                                                                    reactConsoleErrorHandler@1:140579
                                                                                                    ?anon_0_@1:733473
                                                                                                    asyncGeneratorStep@1:120466
                                                                                                    _next@1:120723
                                                                                                    anonymous@1:120675
                                                                                                    anonymous@1:120596
                                                                                                    handleNotificationResponse@1:733873
                                                                                                    anonymous@1:1623892
2024-08-11 23:31:49.140 19652-19690 EGL_emulation           com.example.MyApplication  D  app_time_stats: avg=206.85ms min=15.57ms max=2618.55ms count=15
2024-08-11 23:31:50.145 19652-19690 EGL_emulation           com.example.MyApplication  D  app_time_stats: avg=31.36ms min=2.32ms max=67.14ms count=25
2024-08-11 23:31:50.703 19652-19657 MyApplication           com.example.MyApplication  W  Cleared Reference was only reachable from finalizer (only reported once)
2024-08-11 23:31:50.747 19652-19657 MyApplication           com.example.MyApplication  I  Background concurrent mark compact GC freed 8462KB AllocSpace bytes, 22(1008KB) LOS objects, 49% free, 11MB/23MB, paused 1.575ms,2.825ms total 180.853ms
2024-08-11 23:31:52.680 19652-19690 EGL_emulation           com.example.MyApplication  D  app_time_stats: avg=137.83ms min=13.51ms max=2026.10ms count=18
2024-08-11 23:31:53.683 19652-19690 EGL_emulation           com.example.MyApplication  D  app_time_stats: avg=20.53ms min=2.39ms max=39.92ms count=37

Why won’t my function capture the value of my input element?

I’m working on a freeCodeCamp Javascript project and I currently need to obtain the value given by the user on my input element. I’m practically certain I have my code correct, yet when testing it on freeCodeCamp or in a Code Pen I created the value keeps returning as undefined.

let cash = document.getElementById(“cash”).value;

const purchaseBtn = document.getElementById(“purchase-btn”);

purchaseBtn.addEventListener(“click”, () => {console.log(cash)});

Reseting an array results in undefined

I’m trying to create a “killfeed” script which is supposed to show “kills” in a feed with randomized names from an array.
I don’t want the same name to appear twice in the same feed, so I want to remove every name as it is picked from the array, but I also want to be able to reset the array with the original names.
I’ve figured out the mostpart, but I’m having issues with the reset part as after the “reset” I’m left with an “undefined” response.

const myNames = ["Niko", "Anomaly", "Kandis"];
let names = [...myNames];

function getRandomName() {
  if (names.length === 0) {
    resetNames();
  }
  let randomIndex = Math.floor(Math.random() * names.length);
  let randomName = names[randomIndex];
  names.splice(randomIndex, 1);
  return randomName;
}

function addKill() {
  kills = $("li").length + 1;
  let selectedName = getRandomName();
  $("#killfeed").append('<li><b class="ct">ne0lines</b> killed <i class="t">' + selectedName + '</i></li>');
}

function resetNames() {
  let names = [...myNames];
}

function resetKill() {
  $("ul").fadeOut(1000);
  setTimeout(function() {
    $("li").remove();
  }, 1000);
  $("ul").fadeIn();
  resetNames();
}
body {
  background-color: transparent;
  margin: 0px auto;
  overflow: hidden;
  text-decoration: none;
  font-size: 20px;
  font-family: rajdhani, sans-serif !important;
  letter-spacing: 1px;
  font-weight: 600;
  text-align: center;
}

ul {
  list-style: none;
}

li {
  display: table;
  margin: 0px auto;
  position: relative;
  clear: both;
  float: none;
  min-width: 100px;
  height: 32px;
  line-height: 32px;
  background: rgba(0, 0, 0, 0.5);
  border: 2px #b50000 solid;
  border-radius: 6px;
  padding: 0 10px;
  color: #fff;
  margin-top: 5px;
  right: -100%;
  animation: smooth-appear 1s ease forwards;
}

b {
  font-style: normal;
  font-weight: 600;
}

i {
  font-style: normal;
}

.ct {
  color: rgb(105, 180, 255);
}

.t {
  color: rgb(237, 208, 87);
}

@keyframes smooth-appear {
  to {
    right: 5px;
    opacity: 1;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<button onClick="javascript:addKill();">Add kill</button>
<button onClick="javascript:resetKill();">Reset</button>
<ul id="killfeed"></ul>

Need data from an html file to go to my main code.gs file

I am making a google apps script in which you give an image link and the desired width and height, takes the center color of the division, and puts it as the background color of the corresponding cell. I believe everything should be fine, but my color data is apparently not reaching my main function.

Honestly I’m new to this and not sure what is wrong. If I’m completely genuine, I took a good chunk of this code from Bing Copilot. Anyways, here’s the code.

Code.gs

function onOpen() {
  const ui = SpreadsheetApp.getUi();
  ui.createMenu('My Tools')
      .addItem('Rickroll', 'storePixelData')
      .addToUi();
}

function storePixelData(pixelData) {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  var widthDivisions = 25;
  var heightDivisions = 21;
  for (var y = 0; y < heightDivisions; y++) {
    for (var x = 0; x < widthDivisions; x++) {
      var color = pixelData[y][x];
      var hexColor = rgbToHex(color[0], color[1], color[2]);
      sheet.getRange(y + 1, x + 1).setBackground(hexColor);
    }
  }
}

function rgbToHex(r, g, b) {
  return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase();
}

Rickroll.html (hehe)

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    <canvas id="canvas" style="display:none;"></canvas>
    <script>
      function processImage(imageUrl, widthDivisions, heightDivisions) {
        return new Promise((resolve, reject) => {
          const img = new Image();
          img.crossOrigin = 'Anonymous';
          img.src = imageUrl;
          img.onload = () => {
            const canvas = document.getElementById('canvas');
            const ctx = canvas.getContext('2d');
            const width = img.width;
            const height = img.height;
            canvas.width = width;
            canvas.height = height;
            ctx.drawImage(img, 0, 0, width, height);
            
            const pixelData = [];
            const widthStep = width / widthDivisions;
            const heightStep = height / heightDivisions;
            
            for (let y = 0; y < heightDivisions; y++) {
              const row = [];
              for (let x = 0; x < widthDivisions; x++) {
                const centerX = Math.floor((x + 0.5) * widthStep);
                const centerY = Math.floor((y + 0.5) * heightStep);
                const imageData = ctx.getImageData(centerX, centerY, 1, 1).data;
                const r = imageData[0];
                const g = imageData[1];
                const b = imageData[2];
                row.push([r, g, b]);
              }
              pixelData.push(row);
            }
            resolve(pixelData);
          };
          img.onerror = reject;
        });
      }
      
      document.addEventListener('DOMContentLoaded', () => {
        const imageUrl = 'https://ibb.co/LC5B9Nj'; // Replace with image URL
        processImage(imageUrl, 25, 21).then(pixelData => {
          google.script.run.withSuccessHandler(() => {
            google.script.host.close();
          }).storePixelData(pixelData);
        }).catch(error => {
          console.error('Error processing image:', error);
        });
      });
    </script>
  </body>
</html>

Specifically, the error it gives me is an undefined error in this line:

var color = pixelData[y][x];

Shift Center of Mass with Bullet Physics/Ammo.js

I am using the JavaScript port of Bullet Physics, Ammo.js, with Three.js and would like to shift the center of mass of an object. In other words, I want move the center of mass to a specific point and therefore make that part of the object heavier.

The only similar question I could find was this one from 2007 and there is no working code or demo that would resolve the issue. I tried a similar approach to what the user initially attempted, with the same result: The object’s center gets moved, instead of just the center of mass.

const info = new Ammo.btRigidBodyConstructionInfo(mass, motionState, shape, localInertia);
const body = new Ammo.btRigidBody(info);

// My attempt, which unfortunately physically moves the object to that vector

body.setCenterOfMassTransform(new Ammo.btVector3(1, 0, 0));

If anyone knows how to achieve this, it would be greatly appreciated. Answers in other languages (like C++) are also welcome if I can translate the concepts/code to Ammo.js.

How does one clear a rectangle being drawn at mouse coordinates in javascript?

I’m trying to draw a rectangle at the mouse’s coordinates however I haven’t been able to get it to clear without clearing the other objects.

<!DOCTYPE html>
<html>
  <style>
     html, body {
    height: 100%;
    margin: 0;
  }

  body {
    display: flex;
    align-items: center;
    justify-content: center;
  }

  canvas {
    border: 1px solid orange;
    background: black;
  }
  </style>
  <head>
    <base target="_top">
  </head>
  <body>
<canvas width="1250" height="600" id="game">
    <script>
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
let mouseX = 0;
let mouseY = 0;

function loop(){
  ctx.clearRect(0,0,canvas.width,canvas.height);
  let levelMax = 5;
  let box = [];
  for (j=0;j<levelMax;j++){
    for (i=0;i<levelMax;i++){
          ctx.fillStyle = "lime";
        box.push({
          X : (75 * i),
          Y : 525 - (j*75),
          Width : 75,
          Height : 75
        });
        ctx.fillRect(box[(j*levelMax)+i].X, box[((j*levelMax)+i)].Y, box[i].Width, box[i].Height);
}
}
window.addEventListener("mousemove", (e)=>{
  let posX = e.offsetX;
  let posY = e.offsetY;
  ctx.fillRect(posX, posY, 50, 50);
});
}
requestAnimationFrame(loop);
    </script></canvas>
  </body>
</html>

I tried to use ctx.clearRect(0, 0, canvas.width, canvas.height); which didn’t clear the mouse’s squares or cleared the other squares but cleared old squares from the mouse as desired. I also tried to use ‘ctx.clearRect(e.offsetX, e.offsetY, 50, 50);’ which never really worked, either clearing the squares before they showed up and clearing the larger boxes if the mouse went over them, or just never cleared the mouse’s box.

Send data from react native to ttgo t-display using BLE

Problem:

I’m trying to send data from a React Native app to my TTGO T-Display using Bluetooth communication. However, whenever I send a string (e.g., “John”), the TTGO T-Display receives garbled data (e.g., e&g instead of “John”).

What I have tried:

I’ve experimented with different encoding methods and data types, but none seem to resolve the issue.

React Native Code:

    let connectedDevice = null;

    function stringToBase64(str) {
        return btoa(unescape(encodeURIComponent(str)));
    }

    try {
        const isReady = await prepareBluetooth();
        if (!isReady) {
            console.error("Bluetooth voorbereiding mislukt.");
            return;
        }

        const TTGO_T_DISPLAY_UUID = '4fafc201-1fb5-459e-8fcc-c5c9c331914b';
        const TTGO_T_DISPLAY_Characteristic_UUID = 'beb5483e-36e1-4688-b7f5-ea07361b26a8';

        const scanAndConnectDevice = new Promise((resolve, reject) => {
            manager.startDeviceScan(null, null, async (error, device) => {
                if (error) {
                    console.error(error);
                    reject(error);
                    return;
                }

                if (device.name === 'TTGO_T_Display') {
                    console.log('Apparaat gevonden: ', device.name);

                    try {
                        manager.stopDeviceScan();
                        const isConnected = await device.isConnected();
                        if (isConnected) {
                            console.log('Device already connected.');
                            resolve(device);
                            return;
                        }

                        connectedDevice = await device.connect();
                        console.log('Succesvol verbonden met ', device.name);

                        await connectedDevice.discoverAllServicesAndCharacteristics();
                        resolve(connectedDevice);

                    } catch (err) {
                        console.error('Fout bij verbinden met device:', err);
                        reject(err);
                    }
                }
            });
        });

        const device = await scanAndConnectDevice;

        if (color) {
            const colorRGB = convertToColor(color);
            if (Array.isArray(colorRGB) && colorRGB.length === 3) {
                const [r, g, b] = colorRGB;
                const colorInt = (r << 16) | (g << 8) | b;
                const colorHex = colorInt.toString(16).padStart(6, '0').toUpperCase();

                await device.writeCharacteristicWithResponseForService(
                    TTGO_T_DISPLAY_UUID,
                    TTGO_T_DISPLAY_Characteristic_UUID,
                    colorHex
                );

                console.log('Kleur verzonden naar TTGO T-display:', colorHex);
            } else {
                console.error('Ongeldige kleurarray:', colorRGB);
            }
        }

        if (voornaam) {
            try {
                console.log('Bezig met verzenden van voornaam:', voornaam);
                await device.writeCharacteristicWithResponseForService(
                    TTGO_T_DISPLAY_UUID,
                    TTGO_T_DISPLAY_Characteristic_UUID,
                    voornaam
                );
                console.log('Voornaam succesvol verzonden naar TTGO T-display:', voornaam);
            } catch (error) {
                console.error('Fout bij het verzenden van de voornaam:', error);
            }
        }

        if (medicijnNaam) {
            try {
                let encodedMedicijnNaam = stringToBase64(medicijnNaam);
                await device.writeCharacteristicWithResponseForService(
                    TTGO_T_DISPLAY_UUID,
                    TTGO_T_DISPLAY_Characteristic_UUID,
                    encodedMedicijnNaam
                );
                console.log('Medicijnnaam succesvol verzonden naar TTGO T-display:', medicijnNaam);
            } catch (error) {
                console.error('Fout bij het verzenden van de medicijnNaam:', error);
            }
        }

        if (notitie) {
            try {
                let encodedNotitie = stringToBase64(notitie);
                await device.writeCharacteristicWithResponseForService(
                    TTGO_T_DISPLAY_UUID,
                    TTGO_T_DISPLAY_Characteristic_UUID,
                    encodedNotitie
                );
                console.log('Notitie succesvol verzonden naar TTGO T-display:', notitie);
            } catch (error) {
                console.error('Fout bij het verzenden van de notitie:', error);
            }
        }

    } catch (error) {
        console.warn('Fout tijdens scannen en verbinden:', error);
    } finally {
        if (connectedDevice) {
            try {
                await connectedDevice.cancelConnection();
                console.log('Verbinding geannuleerd.');
            } catch (err) {
                console.error('Fout bij annuleren van de verbinding:', err);
            }
        }
    }
}

```scanAndConnect(null, null, "John", null);
TTGO T-Display Code:

```#include <BLEDevice.h>
   #include <BLEUtils.h>
#include <BLEServer.h>
#include <TFT_eSPI.h>

#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

TFT_eSPI tft = TFT_eSPI();
uint16_t currentColor = TFT_BLACK;

class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
        // Wanneer apparaat verbindt
    }

    void onDisconnect(BLEServer* pServer) {
        // Wanneer apparaat loskoppelt
    }
};

class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
        std::string value = pCharacteristic->getValue();
        if (value.length() > 0) {
            // Vergelijk ontvangen bytes met verwachte hex-waarden
            // (implement logic here)
        }
    }
};

void setup() {
    Serial.begin(9600);
    tft.begin();
    tft.setRotation(1);
    tft.fillScreen(currentColor);

    BLEDevice::init("TTGO_T_Display");
    BLEServer *pServer = BLEDevice::createServer();
    pServer->setCallbacks(new MyServerCallbacks());
    BLEService *pService = pServer->createService(SERVICE_UUID);
    BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID,
                                         BLECharacteristic::PROPERTY_WRITE
                                       );
    pCharacteristic->setCallbacks(new MyCallbacks());
    pService->start();
    BLEAdvertising *pAdvertising = pServer->getAdvertising();
    pAdvertising->start();
}

void loop() {
    // (implement loop logic here)
```}
Expected Behavior:

I expect that when I send the string "John" from my React Native app, the TTGO T-Display should receive and display "John".

Question:

Does anyone know why the data is getting garbled and how I can ensure that the data is correctly received and displayed on the TTGO T-Display?

Javascript Expandable Rows … First row expanded … need it closed on page load

I have an expandable table that I modified… Right now it functions very well, but the FIRST ROW is expanded on page load. And I need that first row to be closed. Javascript is below.

$(document).ready(function () {
  const expchartcontents = $('.expchart');

  expchartcontents.each((index, expchartcontents) => {
  let selecteditem = 0;

  let expchartItemIndex = -1;
  const changeTab = (index, item) => {
      var delay = 300;
      if (window.innerWidth < 980) {
        delay = 800;
      }
      if (expchartItemIndex !== index) {
            $(expchartcontents).find(".expchart-row")
                .eq(expchartItemIndex)
                .children(".expchartpane-subitem")
                .slideUp(delay);
            $(expchartcontents).find(".expchart-row")
                .eq(expchartItemIndex)
                .removeClass("clicked");
          
            $(expchartcontents).find(item)
                .children(".expchartpane-subitem")
                .slideDown(delay);
            $(expchartcontents).find(item)
                .addClass("clicked");
            expchartItemIndex = index;

      } else {
          $(expchartcontents).find(".expchart-row")
            .eq(expchartItemIndex)
            .children(".expchartpane-subitem")
            .slideUp(delay);
          $(expchartcontents).find(".expchart-row")
            .eq(expchartItemIndex)
            .removeClass("clicked");
          expchartItemIndex = -1;
      }
};
/* Click closes others */
$(expchartcontents).find(".expchart-row").each((index, item) => {
      $(expchartcontents).find(item).click(() => {
            changeTab(index, item);
            selecteditem = index;
      });
});
changeTab(0, $(expchartcontents).find(".expchart-row").eq(0)); 
  });
});

I don’t know javascript very well, so I’ve been trying various things. If I change the last line … it changes some of the opening states, but the 1st is still open.

changeTab(-1, $(expchartcontents).find(".expchart-row").eq(-1)); 
/^ does nothing (first row still expanded)  */
changeTab(0, $(expchartcontents).find(".expchart-row").eq(0)); 
/^ does nothing (first row still expanded) */
changeTab(1, $(expchartcontents).find(".expchart-row").eq(1));
/^ opens 2nd row, in addition to the 1st */ 
changeTab(2, $(expchartcontents).find(".expchart-row").eq(2)); 
/^ opens 3rd row, in addition to the 1st */ 

I’ve also tried changing the initial variables, hoping they’d change, but that didn’t help either…

let selecteditem = 0; /* tried -1, 1, 2, 3 ... no change */
let expchartItemIndex = -1; /* tried 0, 1, 2, 3 ... no change */

Here is a codepen for easier viewing…

https://codepen.io/jabbamonkey/pen/QWXqWVM

Create image carousel using only css

I have created the following code as animation. However, I want it as image carousel, so that after Image 1 leaves the screen then it comes after image 3.

At the moment the animation just starts again.

Any suggestions how to get the carousel effect?

I appreciate your replies!

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>AI Image Generator</title>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@700&display=swap" rel="stylesheet">
    <style>
        .scrolling-images-wrapper {
            overflow: hidden;
            position: relative;
            width: 100%;
            height: 220px;
        }

        .scrolling-images {
            display: flex;
            animation: scroll 20s linear infinite;
        }

        .scrolling-images img {
            width: 200px;
            height: 200px;
            margin-right: 16px;
        }

        @keyframes scroll {
            0% {
                transform: translateX(0);
            }
            100% {
                transform: translateX(calc(-100px * 5)); /* Number of images to show in one loop * image width */
            }
        }
    </style>

<style>
    @keyframes typing {
        from { width: 0; }
        to { width: 100%; }
    }

    @keyframes progress {
        0% { width: 0; }
        100% { width: 100%; }
    }

    @keyframes robot {
        0% { left: 0; }
        100% { left: calc(100% - 30px); }
    }
</style>
</head>

<body class="bg-gray-100 font-sans">



    <section class="scrolling-images-wrapper">
        <div class="scrolling-images">
            <img src="https://via.placeholder.com/200x200?text=Image1" alt="Image1">
            <img src="https://via.placeholder.com/200x200?text=Image2" alt="Image2">
            <img src="https://via.placeholder.com/200x200?text=Image3" alt="Image3">

        </div>
    </section>

</body>

</html>

Calling Javascript from a SSR Page Blazor .NET core

I have a .NET 8 Core Blazor page with Authentication. My App.razor contains the following html and code.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <base href="/" />
    <link href="https://fonts.googleapis.com/css2?family=Montserrat&display=swap" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Macondo&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="" id="userStylesheet" data-permanent />
    <link rel="stylesheet" href="css/CardFlip.css" />
    <link href="css/site.css" rel="stylesheet" />
    <link rel="stylesheet" href="css/cutealert.css" />
    <link rel="stylesheet" href="css/fontawesome.css" />
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <HeadOutlet @rendermode="RenderModeForPage" />
</head>

<body>
    <Routes @rendermode="RenderModeForPage" />

    <script>window.$ = window.jQuery = require('jquery');</script>
    <script src="js/all.min.js"></script>
    <script src="js/Jquery.js"></script>
    <script src="js/bootstrap.bundle.min.js"></script>
    <script src="js/ShowModal.js"></script>
    <script src="js/cute-alert.js"></script>
    <script src="js/jspdf.min.js"></script>
    <script src="js/html2canvas.js"></script>
    <script src="js/html2pdf.bundle.min.js"></script>
    <script src="_framework/blazor.server.js"></script>

</body>

</html>

@code {
    [CascadingParameter]
    private HttpContext HttpContext { get; set; } = default!;

    private IComponentRenderMode? RenderModeForPage => HttpContext.Request.Path.StartsWithSegments("/Account")
        ? null
        : InteractiveServer;
}

I have a global theme I am trying to apply to all of my pages and I do that with a javascript function.

function ChangeStyleSheet(newSheet) {
    var linkTag = document.getElementById('userStylesheet');
    linkTag.href = newSheet;
}

The problem is that I cannot seem to call this function when I am rendering in SSR. That is anytime I load in a page from /Account, it renders SSR. Other pages render in Interactive Server. I can easily call the javascript function using JSRuntime when rendered in Interactive server.

I found a microsoft page which discusses Javascript in SSR where it seems to create a component called PageScript and another js module which you create which I am unsure its purpose. Yet I still do not see in that example how I am supposed to call ChangeStyleSheet from an SSR page.

Does anyone have a solution? If I need to add more information, please let me know and I will certainly add it.