use externally loaded rot.js with typescript, without bundling?

I would like to use external rot-js with typescript, without bundlers.
IE load rot-js from e.g. dist/rot.js, and compile my own ts code with TSC.
This causes conflicts both for TSC, for tsconfig.json, and for type resolution during editing.

If I specify nodenext/node moduleResolution in tsconfig, editor can happily see types, but TSC will try to generate require-imports for node, which is wrong both for the externally loaded rot-js, and for our browser context.
If I don’t specify nodenext as module-resolution, I may not use

import * as ROT from "rot-js";

or

import { Display } from "rot-js"; 

Without nodeNext, I could instead do

import * as ROT from "./node_modules/rot-js/dist/rot.js";

but it doesn’t appear to work/editor can’t see types,
and also it emits an ‘import’ in the js output.

rot-jslib actually DOES contain *.d.ts files,
and even index.d.ts. But I can’t seem
to actually import declarations from them..?
Display is exported in index.d.ts,
but if I try to import it directly, I get TS2846,
which says that declaration files can only be imported with
import type.
IF I try to import Display with

import type

I get the error that values can’t be resolved through
import type, so I can’t do e.g.
new Display(…)

If I try to install typings for rot-js, I get a dummy package
which proudly claims, that it is not necessary because
rot-js already has everything and already has typescript source.

I also tried to use triple-slash /// reference path/types, but this doesn’t seem to work either.

Maddeningly, VSCode intellisense seems to ‘know’ the syntax/properties for rot-js stuff, but feigns ignorance when I try to e.g. jump to a symbol. So first it says ‘yeah, there is an object called Display, and it takes these arguments’, but next thing it says ‘a constructor for Display? I know nothing about that, who told you that?”

It feels like a labyrinth of endless combinations that invariably make something else not work.
I read through SOs suggested earlier questions on this topic, but sadly they are mostly unsatisfactorily answered variants of my question here.
Also, this is a general issue I have with typings for external modules when working with typescript tooling, so the question is broader than rot-js.

I guess I could write my own declares from scratch for rot-js, but surely the existing tooling is supposed to already work, in a way I haven’t been able to figure out yet?

To sum up the problem, I ‘just’ want the types to be resolved/enforced, without emitting weird imports or requires. And I cannot figure out if that should come from *.d.ts files, or from actual typescript files, or..

Typings tooling with javascript is really hard to wrap your head around, unless you just close your eyes and use webpack :-/

Stop notification from duplicating

I am working on a bell notification. Notifications should appear in notification pop up when clicked bell icon and when user scrolls to the bottom it should send get request to the backend and fetch older notifications.

  1. If theres global notification, it will stick as 1st notification and rest of the personal notification appear below it.
    2)The Personal notification (notification that is not global), older ones should appear in the bottom and newer ones should appear in the top (without having to refresh the page).

The problem: newer notifications appear in the top but the same notification appear in the bottom as well. Example:

current notification box :H,G,F

new notifications has been added to the database -> updated notification box: I,H,G,F,I

scrolls to the bottom and older notifications get loaded ->updated notification box :I,H,G,F,I,E,D,C

refeshes the page ->current notification box: I,H,G

scrolls to the bottom and older notifications get loaded -> current notification box: I,H,G,F,E,D

As shown in example it works fine when refreshed the page but it shows duplicated when its not. Also any advice for the code is welcomed.

 $(document).ready(function() {

        var pageNumber =1;
        var displayNotificationOnId = [];
        var newNotificationIds = [];
        var loading = false;
        var loadDelay = 4000;

        var bellClickedToOpen = true;


        function getNewNotifications() {

            $.ajax({
                type:'GET',
                url:'/notifications?page=' + pageNumber,
                success: function (data) {
                    populateNotifications(data.notifications);
                    data.notifications.forEach(function(dta){
                        if (!newNotificationIds.includes(dta.id)) {
                            newNotificationIds.push(dta.id)

                        }
                    })
                    console.log(data)
                },
                error: function(xhr, status, error) {
                    console.error('Error fetching new notifications:', error);
                }
            })
        }

        // $(document).ready(function() {
        $('#notificationDropdown').on('scroll', function() {
            var container = $(this);
            var scrollPosition = container.scrollTop();
            var containerHeight = container.innerHeight();
            var contentHeight = container[0].scrollHeight;

            var distanceBottom = contentHeight - (scrollPosition + containerHeight);

            var threshold = 50;
            // Check if the scroll position is near the bottom of the container
            if (distanceBottom <=threshold && !loading ) {

                loading = true


                $('#loading').show();
                console.log("inside if statement" + loading)

                setTimeout(function () {
                    console.log("reached bottom of the popup")
                    pageNumber +=1;
                    getNewNotifications(pageNumber); // Fetch new notifications when near the bottom
                    loading = false;
                    $('#loading').hide;

                }, loadDelay)

            }
        });
        // });


        function fetchNotificationCount () {
            $.ajax({
                url : '/notifications',
                method: 'GET',
                success: function (data) {
                    var notifications = data.notifications;
                    if(data.newNotificationsCount>0){
                        $('#notificationBadge').text(data.newNotificationsCount).show();
                        $("#readAll").removeClass("disabled-link");
                        console.log(">0" + data.newNotificationsCount);
                    } else {
                        $('#notificationBadge').hide();
                        $("#readAll").addClass("disabled-link");
                        console.log("else" + data.newNotificationsCount);
                    }
                    // $('#notificationBell').click(function() {
                    populateNotifications(notifications);

                }, error: function (xhr, status, error) {
                    console.error(error);
                }
            })
        }

        fetchNotificationCount();
        setInterval(fetchNotificationCount, 5000);


        function markSingleNotificationAsRead(id, read){

            console.log(id, read);


            var isUnread = read ===0;


            var buttonText = isUnread ? "Unread":"Read";

            var $button = $('.mark-as-read-btn[data-notification-id="' + id + '"]');

            $.ajax({
                url:`/notificationsRead/${id}`,
                method: 'POST',
                success: function(response) {
                    console.log("Notification marked as " + buttonText + " successfully");
                    $button.text(buttonText);

                },
                error:function (xhr, status, error) {
                    console.error('Error marking notification as read:', error);
                }
            })
        }

        function populateNotifications(notifications) {
            // var $notificationList = $('#notificationList');
            // $notificationList.empty(); // Clear existing notifications
            var globalNotificationDiv = $('#global-notification');
            var hasGlobalNotification = false;

            console.log(notifications);

            var globalNotifications = notifications.find(function (notification){
                return notification.type === 'global';
            })

            if (!globalNotifications) {
                // alert("hello")
                globalNotificationDiv.empty();
            }
            if(globalNotifications && !displayNotificationOnId.includes(globalNotifications.id)) {
                console.log(globalNotifications)
                // console.log(globalNotifications.expired)

                displayNotification(globalNotifications, true)
            }

            // notifications.forEach(function(notification) {

            for (var i=0; i<notifications.length; i++) {
                var notification = notifications[i];
                var buttonText = notification.read === 0 ? "Unread" : "Read";
                var notificationClass = notification.read === 0 ? "unread-notification" : "";

                if (!displayNotificationOnId.includes(notification.id)) {
                    displayNotification(notification, false);
                    console.log(displayNotificationOnId, notification.id);
                }
            }



            // });

            $('#notificationBell').click(function (){
                $('#notificationDropdown').show();

            })


        }



        function displayNotification (notification, isGlobal) {
            var $notificationList = $('#notificationList');
            var globalNotificationDiv = $('#global-notification');
            var greaterThanLargestId= false;

            var notificationRead = notification.read ===0 ? "unread-notification" : "";
            var disableClick = isGlobal ? "disable-globalNotification" : "";

            var daNotifications = `
                    <div class="list-group-item ${notificationRead} ${disableClick}"  >


                        <a  href= "${notification.url}" class="mainNotiHeader" data-notification-global="${notification.type}"   data-notification-id="${notification.id}" data-notification-read="${notification.read}" >
                            <div class = "notificationInfo">
                                <h4  class="list-group-item-heading">${notification.tool}</h4>
                                <p >${notification.created_at}</p>
                            </div>
                            <p class="list-group-item-text" >${notification.text}</p>
                        </a>



                    </div>

`;

            if (!displayNotificationOnId.includes(notification.id)) {

                for (var i = 0; i<displayNotificationOnId.length; i++){

                    if (notification.id >displayNotificationOnId[i]){
                        greaterThanLargestId = true;
                        break;
                    }

                }
                if (greaterThanLargestId) {


                    $notificationList.prepend(daNotifications);
                    greaterThanLargestId= false;
                    displayNotificationOnId.push(notification.id);


                }
            }

            if(isGlobal) {
                globalNotificationDiv.html(daNotifications);

            } else if (greaterThanLargestId === false) {
                console.log("!greaterThanLargestId: " +greaterThanLargestId  )
                $notificationList.append(daNotifications);
                displayNotificationOnId.push(notification.id);
                
            }
            if (isGlobal) {
                globalNotificationDiv.find('.disable-globalNotification').click(function (event){
                    event.preventDefault();
                })
            }

            console.log("line 494" + displayNotificationOnId);


        }

Next.js vercel open graph image rendering

I want to share user profile to socials, I want to do that by just pasting in a link and it will render this “card” and it looks nice and have some data inside. I am using nextjs and I have component in /api folder (I use page router version) for this and Open Graph image render. The problem is that because I need to get profile data first (I cannot pass it through params to /api component) and additionally I have to fetch some external images it takes sometimes 4-5 seconds to load the image. The problem is that when I paste a profile link to twitter and wait few seconds the “card” preview does not load. I have to paste it few times to actually load the data. I’ve tried to put all the images to my project files and fetch it instead of making external requests but it does not work because edge functions have limit to 2mb. I was able to speed image loading to like 3-4 seconds but its still not enough for twitter to load it correctly.
I have no idea how to fix this
and its a very important feature to let people just copy paste user link and get his statistics

Python + JavaScript good? [closed]

I learned python and I’m good on python but is python good choice to use it with JavaScript(React + Next.js)

And I use Python(Django + FastApi) as a backend lib

Is JavaScript(React+Next.js) good with Python(Django + FastApi) as freelancer

I tried to search about that thing and every web and video say “everything is good” but I need to search it for a free lance work

Bootstrap ‘needs-validation’ not Triggering on Form Submission

I have a PHP file index.php containing a form with Bootstrap’s needs-validation class, but it seems that the validation isn’t being triggered upon form submission. Here’s my index.php file:

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

<head>
    <?php include_once __DIR__ . '/src/php/head.php' ?>
    <link rel="stylesheet" href="style.css">
    <link rel="stylesheet" href="src/css/login.css">
</head>

<body>
    <div class="container">
        <div id="box">
            <h1>Login</h1>
            <form method="POST" action="src/php/login.php" class="row g-4 needs-validation" id="loginForm" novalidate>
                <div class="col-sm-12">
                    <label for="username" class="form-label">Benutzername: *</label>
                    <input type="text" class="form-control" id="username" name="username" required>
                    <div class="invalid-feedback">
                        Benutzername ist erforderlich
                    </div>
                </div>
                <div class="col-sm-12">
                    <label for="password" class="form-label">Passwort: *</label>
                    <input type="text" class="form-control" name="password" id="password" required>
                    <div class="invalid-feedback">
                        Passwort ist erforderlich
                    </div>
                </div>
                <button class="btn btn-primary rounded-pill px-3" type="submit">Login</button>
            </form>
            <div id="register">
                <a href="users/create">Registrieren</a>
            </div>
        </div>
    </div>
</body>
<?php include_once 'src/php/footer.php' ?>
<script src="src/js/login.js"> </script>

</html>

Additionally, here’s my head.php file:

<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href=https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css rel="stylesheet"
    integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">

And footer.php:

<script src=https://code.jquery.com/jquery-3.7.1.min.js
    integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
<script src=https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js
    integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous">
</script>

Despite having the needs-validation class on the form, it doesn’t seem to trigger validation when I submit the form. What could be causing this issue, and how can I fix it?

mistake in using id in react in html

слушайте вы случайно не знаете, как убрать ошибку? поставил на div id- что бы по клику кнопки осуществлялся переход на данное место в странице. но id выделяется как ошибка -Тип “{ children: (“” | Element | undefined)[]; id: string; className: string; }” не может быть назначен для типа “DetailedHTMLProps<HTMLAttributes, HTMLDivElement>”.
Свойство “id” не существует в типе “DetailedHTMLProps<HTMLAttributes, HTMLDivElement>”.ts(2322). пока локально все запущено, то все работает, хоть и выделяется красным. при билде выходит ошибка с этим id. не пойму как исправить. приложение на react typescript

не нагуглил ничего что бы помогло

How to make deeplink ionic for ios correct?

I was developing a hybrid mobile application for Android/iOS using Nuxt 3, TypeScript, and Ionic. My app serves as an online store. During the payment process, the application redirects users to the epay Halyk website, and when the ‘back’ button is pressed, it should lead back to our application.

This functionality works well on Android devices and in the Xcode emulator. However, when I build it for TestFlight and the App Store, it doesn’t work. I’m not sure why this issue is occurring.

      window.halyk.pay({
            ...response.data,
            backLink:        'https://m.smartdeal.kz',
            failureBackLink: 'https://m.smartdeal.kz',
            postLink:        response.data.postLink,
        });

Why setting the state inside a fetch callback (doesn’t) cause an infinite loop?

I have the following code snippet, and I expected it to result in an infinite loop due to a state update inside a fetch callback inside the body of the component without using ‘useEffect’. However, it’s not behaving as expected. Here’s the code:

function App() {
  const [cartContent, setCartContent] = useState(null);

  fetch("https://fakestoreapi.com/carts/6")
    .then((resp) => resp.json())
    .then((data) => {
      setCartContent("test");
    });

  console.log(cartContent);

  return <div className="cartContent">{cartContent}</div>;
}

export default App;

My understanding was that console.log(cartContent) should log the initial value of cartContent, then when setCartContent(“test”) is called inside the fetch callback, it should log “test”, and this process should repeat indefinitely, creating an infinite loop.

Could someone please help me understand why this code doesn’t result in an infinite loop as expected? Any insights or explanations would be greatly appreciated. Thank you!

How to use Webpack with Github actions to deploy multiple websites

I am building a fairly simple website using Webpack for customer_A. I would like to now use a template to allow me to build the same website for customer_B, customer_C etc. What would be a good Webpack tool to do this with for a simple HTML, CSS and JS website?

The second part is how is this best achieved. Is there a way that Webpack itself can be used to build multiple websites each with its own dist folder or would it be best to call Webpack in the Github actions pipeline multiple times in a for loop and pass in each customer’s specific parameters?

I have been using Webpack and JS for a few days now so don’t have much experience in this area.

Which algorithm to downsample a 2D array of values to save space in js

I’m working with 1D and 2D arrays containing values for plotting heatmaps.
Some datasets can containing thousands of values which represent millions of values in the matrix. I’d like to try some downsampling/compression methods with some parameters to save space on disk and still be able to plot everything.

I have 3 arrays, X and Y being 1D and Z being 2D (of dimension X*Y).

I already have a downsampling method, which basically removes every k-th value, it works on huge datasets but I could lose some valuable information without any smart processing.

React Highchart Reverse the order of tooltip data

In my code, I have a dataset rendered in bar format using a highchart. The current implementation of UI looks like this:
enter image description here

What i need is that in the tooltip, I need to revert the data info. Instead of ‘Follow’, then ‘Lead’, it should be like: ‘Lead’ and then ‘Follow’, along with their respective data values as per the bar chart.

Here is the code done so far:

App.js

import {
  DummyData,
  PercentageBarChart,
} from "./Component/Sparkline/ChartCollection";
function App() {
  const mapperValue = (chartDetails, header) => {
    switch (chartDetails.type) {
      case "area": {
        const options = {
          series: [
            {
              data: chartDetails.data,
              pointStart: 1,
            },
          ],
          tooltip: {
            headerFormat: `<span style="font-size:10px">${header}, Q{point.x}: </span><br/>`,
            pointFormat: "<b>{point.y}.000</b> USD",
          },
          chart: {
            type: chartDetails.type,
          },
        };
        return <SparkLine options={options} />;
      }
      case "bar": {
        const color =
          chartDetails?.stacked === "normal"
            ? ["#B5E3D8", "#66C8C2", "#118C7D", "#004C45"]
            : ["#F5E887", "#00A499"];
        const series = chartDetails.data.map((item, index) => {
          return {
            ...item,
            color: color[index],
          };
        });
        const options = PercentageBarChart({
          series,
          stacked: chartDetails?.stacked || "percentage",
          dataLabel: chartDetails?.dataLabel,
          name: header,
        });

        return (
            <SparkLine options={options} />
        );
      }
      default:
        return chartDetails.data.map((item) => {
          return `${item.name} || `;
        });
    }
  };

ChartCollection.js

export const DummyData = [
  {
    name: "AON",
    lead_follow: {
      type: "bar",
      data: [
        { name: "Follow", data: [72] },
        { name: "Lead", data: [28] },
      ],
      dataLabel: {
        visible: true,
      },
    },
    types: {
      type: "bar",
      stacked: "normal",
      data: [
        { name: "Open", data: [45] },
        { name: "Deleg", data: [120] },
        { name: "Pool", data: [31] },
      ],
      dataLabel: {
        visible: false,
      },
    },
    avg_cost_acquisition: 35,
    avg_cost_brokerage: 23,
  },
];
const disableDataLabel = ["Follow", "Lead"];
export const PercentageBarChart = (props) => {
  props.series.forEach((seriesItem) => {
    if (disableDataLabel.includes(seriesItem.name)) {
      seriesItem.dataLabels = {
        enabled: false, // Disable data labels for "New", "old", and "other"
      };
    }
  });

  const plotOptions =
    props.stacked === "percentage"
      ? {
          bar: {
            stacking: "percent",
            dataLabels: {
              enabled: props.dataLabel.visible,
              format: "{point.y:.0f}%",
              x: props?.series?.dataLabel?.x || null,
              y: props?.series?.dataLabel?.y || null,
              verticalAlign: "middle",
              inside: false,
              style: {
                fontSize: "0.75rem",
                textOutline: "0px",
              },
            },
          },
        }
      : {
          series: {
            stacking: "normal",
            dataLabels: {
              enabled: props.dataLabel.visible,
              style: {
                fontSize: "0.75rem",
                textOutline: "0px", // Remove outline to avoid overlapping
              },
            },
          },
        };

  return {
    chart: {
      backgroundColor: "transparent",
      borderWidth: 0,
      type: "bar",
      margin: [2, 0, 2, 0],
      width: 200,
      height: 50,
      style: {
        overflow: "visible",
      },
      skipClone: true,
    },
    title: {
      text: null,
    },
    credits: {
      enabled: false,
    },
    yAxis: {
      endOnTick: false,
      startOnTick: false,
      labels: {
        enabled: false,
      },
      title: {
        text: null,
      },
      tickPositions: [0],
    },
    legend: {
      enabled: false,
      align: "left",
      x: 10,
      verticalAlign: "top",
      layout: "horizontal",
      y: 0,
    },
    tooltip: {
      headerFormat: `<span style="font-size:10px">${props.name}</span><br/>`,
      pointFormatter: function () {
        console.log("inside point formattor", this);
        var point = this,
          series = point.series;
        return `<div style="align-items: baseline">${series.name} <hr style="display:inline-block; position: relative; top: 5px; width:${point.y}px; height: 10px; font-size: 10px" color=${point.color}> <b>${point.y}</b><br /></div>`;
      },
    },
    plotOptions: plotOptions,
    series: props.series || [],
  };
};

I tried to update the code in App.js like this:

//.......
    const options = PercentageBarChart({
          series,
          stacked: chartDetails?.stacked || "percentage",
          dataLabel: chartDetails?.dataLabel,
          name: header,
        });

        const modifiedOptions = JSON.parse(JSON.stringify(options));

        modifiedOptions["tooltipSeries"] = [...series].reverse();
        console.log({ modifiedOptions });
//......

and it prints the console of options as expected:

enter image description here

Then passing the modifiedOptions as props, instead of options, is also not working:
//…

 <SparkLine options={modifiedOptions} />

...//

If anyone can help fix the same, will be appreciated!

javascript removing element style after clicking other

I’m trying to remove attribute “selected” from span element when other span element (not the same div) is clicked
div1 span swatch clicked
another div1 span swatch clicked

How to remove attribute “selected” of span element in div_bottom1 while div1 another span is selected?

<script type="text/javascript">
            window.addEventListener('DOMContentLoaded',() => {
                const div1 = document.getElementById('div1');
                div1.addEventListener('click', (e) => {
                    const div1span = e.target.closest('span.swatch');
                    if (!div1span) return;
                    const dj = document.getElementById('div_bottom1');
                    const djp = document.getElementById('div_bottom2');
                    const dd = document.getElementById('div_bottom3');
                    if (div1span.matches('.div1swatch')) {
                        const clodj = dj.closest('span.selected');
                        const clodd = dd.closest('span.selected');
                        clodj.removeProperty('selected');
                        clodd.removeProperty('selected');
                    }
                });
</script>

It works till getting div1span.matches('.div1swatch') and then “Uncaught TypeError: Cannot read properties of null” error appear
div 2-4 are separate divs outside div1 and have style.display = "none"; set while div1span is switched

click on div1span sets style.display = "none"; to div_bottom2 and div_bottom3
click on div2span sets style.display = "none"; to div_bottom1 and div_bottom3
click on div3span sets style.display = "none"; to div_bottom1 and div_bottom2
is it related?

What I’m doing wrong? I’m javascript newbie, coding in php + html so far

Leaflet Map Rendering Issue with Large Non-Geographical Map

I’m currently developing a non-geographical map for my website using React, tailwindCSS and react-leaflet. The map is square-shaped and quite large, with each side measuring 10 million pixels. The image overlay is a square with white color. I’ve followed the guides provided by both react-leaflet and leaflet documentation on https://leafletjs.com/examples/crs-simple/crs-simple.html, where I defined a specific bound to map the image to the corresponding scale.

However, I’ve encountered a problem where the image is not initially displayed (though it does appear when zooming out). Specifically, the map tends to disappear when I reach a certain zoom level (although the marker still remains). For normal maps (which I takes from the tutorial and is geographical map), it works normally, so I did setup leaflet correctly.

Below is the code for the map I encountered issues with (note that I am using react-leaflet):

<MapContainer
                // whenReady={setMapRef}
                center={[this.state.lat, this.state.lng]}
                zoom={this.state.zoom}
                className="h-dvh z-10"
                bounds={bounds}
                // maxBounds={bounds}
                // maxZoom={10}
                zoomControl={false}
                minZoom={-1000}
                maxZoom={7}
                crs={CRS.Simple}
                // zoomSnap={0}
            // maxNativeZoom={7}



            >
                <ImageOverlay
                    url="https://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Blank_square.svg/2048px-Blank_square.svg.png"
                    bounds={bounds}
                    className="border box-border border-black"

                />
                <ZoomControl position="bottomleft" />
                <Marker position={[this.state.lat, this.state.lng]}>
                    <Popup>
                        This is the center
                    </Popup>
                </Marker>
                <Marker position={[51.5, +0.1]}>
                    <Popup>
                        This is the content
                    </Popup>
                </Marker>
            </MapContainer>

While inspecting the element through console, I’ve noticed that the glitch starts to occur when the map’s width and height exceed 10 million pixels to some extent, leading me to suspect that this might be the root of the issue. I tried to rectify this by setting the bounds to 20 million for each side, but the problem persists. I tried to look for leaflet documentation looking for anything related to zooms but to no avail. I’m at a loss as to how to resolve this issue and would greatly appreciate any assistance or suggestions. Thanks in advance!