How to do custom plugin with custom parameters?

We have a TypeDoc custom plugin called CustomPlugin and I wish to pass custom parameters into that plugin, therefore it appears I cannot add its name as a string to the plugin option.

After running Appplication.bootstrapWithPlugins, I call the plugin as a function CustomPlugin(params). The issue I am having is my plugin requires that the JSON output has already been written and is accessible for use inside the plugin. The JSON output can only be called after convert is called and the project instance becomes available.

app.convert.addUnknownSymbolResolver has to be set before app.convert() is called or the plugin will fail to resolve these unknown symbols. I have set this inside the CustomPlugin.

This is a NX Monorepo with multiply projects inside and TypeDoc is called against many of them in the right order using dependsOn in nx.json.

const app = await Application.bootstrapWithPlugins({
  { ...options },
  [...readers]
});

// I need the generated **my-path.json** available in here to access the symbolIdMap
// We actually also use other projects **my-path.json** as well in here
// We build the projects in the right order using dependOn in the nx.json file
load(params); // CustomPlugin

const project = app.convert();

await app.generateJson(project, 'my-path.json');

I have implemented a double pass which works fine but was looking for other solutions.

Sound delay on the npm module node-wav-player

I’m using a typewriter effect and want to make a sound for every letter like the movie letter sound. I want to use the CMD program in Windows 11 to make a chatbot that runs with the command node chatbot.js. I don’t want it to run in the browser but in node.js. I have tryed to ask the ChatGPT but with no luck. I’m using the node-wav-player and it works; but the sound is delayed and not stabile. On the repo on GitHub they mention the require method; but I want the import method.

How to integrate N-Genius payment inline (on WooCommerce checkout) without redirecting to N-Genius page? [closed]

I am working on a custom integration of N-Genius payment gateway in my WordPress + WooCommerce site.

By default, the N-Genius flow redirects the customer to the N-Genius hosted payment page to enter card details.
But I want the payment form (card number, expiry, CVV) to appear inline / on-site / directly on my WooCommerce checkout page — without sending the user to the N-Genius page.

What I have tried:

I am already loading the N-Genius SDK on my checkout page.

I tried rendering the custom card fields, but WooCommerce checkout JavaScript interferes and prevents them from showing.

If I disable WooCommerce checkout scripts, the card fields work fine (but then checkout breaks).

I also attempted moving the N-Genius init script to wp_footer, but still no luck.

Support die/exit on FrankenPHP(Caddy) worker mode

My PHP app runs on a Caddy webserver, over a FrankenPHP container (Dunglas image). It runs in worker mode.

Unfortunately, it seems that workers prevent abrupted interruptions of the process. So is not possible to use die(); or exit();.
When using those to get debug output, FrankenPHP doesn’t stop but goes in an infinite loop of reloading the page (and re-logging the exception).

Is there any option/configuration to make the process effectively “die” or “exit” execution (and show me the debug data)?

PHP/Apache proxy somehow tells browser the content is mixed [closed]

I’ve been trying to make a proxy for a web-game I’ve been working on. The game’s engine demands all requests to the game’s server to be HTTPS, which I’m incapable of doing at the moment. To bypass that I’m using the proxy in the form of a php script on the web server the game’s client is hosted on. For some reason though, when the request to the proxy is made, proxy somehow tells browser that the resource it’s accessing is not on HTTPS. I’d like to avoid this behavior, but I don’t know whether it’s due to PHP or due to Apache. Proxy’s code is a basic cURL request to the game server ip, which is then simply echoed into the proxy’s page

Edit: here’s the proxy file’s code:

<?php
function curlPost($url, $data = NULL, $headers = []) {
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 5); //timeout in seconds
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_ENCODING, 'identity');

    
    if (!empty($data)) {
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    }

    if (!empty($headers)) {
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    }
    
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);

    $response = curl_exec($ch);
    if (curl_error($ch)) {
        trigger_error('Curl Error:' . curl_error($ch));
    }

    curl_close($ch);
    return $response;
}

echo curlPost("http://[server_ip]/" . ($_SERVER['REQUEST_METHOD'] == "POST" ? $_POST : $_GET)["resource"], json_encode($_SERVER['REQUEST_METHOD'] == "POST" ? $_POST : $_GET, JSON_FORCE_OBJECT));

Edit 2: The error browser throws is as follows:

The page at ‘https://[game_webpage]/’ was loaded over HTTPS, but
requested an insecure resource ‘http://[server_ip]’. This request has
been blocked; the content must be served over HTTPS.

Regex to only add missing quotes to HTML attributes?

The Missing Attribute Quotes Problem:

I have HTML emails with clearly copy/pasted code where the original… authors, failed to add double quotes around the values of some HTML attributes. This leads to the parser disregarding those attributes and breaking the emails.

Examples:

  • border=0
  • cellpadding=0
  • cellspacing=0
  • width=480

An example string to be fixed:

<table border=0 style="color: red;" title='Hello'></table>

An example of the string after being fixed:

<table border="0" style="color: red;" title='Hello'></table>

Determining the Regular Expression Logic

I know how to find and replace one or more consecutive characters. What I do not know is how to find and replace two sets of strings in a single regular expression and the whole grouping part:

$string = str_ireplace(array('_','--'),array('-','-'), '$string');

I believe the pattern logic should be:

  1. First if < been encountered but not >? (we are within an element).
  2. Second if the first space is encountered (the element name).
  3. Third if = has been encountered but also the next immediate character is not a quote.
  4. Fourth if after (.*?) (I think, for the value itself) is a space encountered?

Some Attempts:

I’ve been going through pages here on Stack and other websites for a few hours though no one, that I’ve come across, has even bothered to work out the logic forget about working on syntax. So with the logic worked out I have some small parts figured out:

  • preg_replace('/<(.*?)( )/u', '', $s) will replace the element (regardless of it’s tag name) but delete everything up to the first attribute. So I don’t know how to write “do nothing here but make sure it exists” so we’re only applying the expression to attributes assuming the HTML author at least got the < and > formatting correct.
  • preg_replace('/^=(.*?)( )$/u', '', $s) was my attempt to ^ start a match at = and end $ it with a space however this just deletes the entire string.

I can’t get the second part figured out. Then I presume there is a way to group the two individual expressions together.

Question:

How do I update my regular expression to append double quotes to HTML attributes only if they’re missing quotes?

Clarifications:

  1. I absolutely do not want to do anything else with regular expressions here. I believe my goal is reasonably simple (as opposed to something very expansive like this). I figured that the pattern is established enough and possibly not too complex for others with greater experience with regular expressions than I. If I can’t figure this out or get enough help I can just write my own parser just to resolve this issue.
  2. I attempted to use $dom = new DOMDocument; $dom->loadHTML($html); $xml = trim($dom->saveXml($dom)); and that did add the missing quotes, but this is HTML from email that triggered tons of errors from other malformed syntax problems so ultimately it was an interesting though non-viable approach.
  3. To keep it as simple as possible I’m content to ignore single quotes.
  4. If this gets figured out I should be able to easily adapt this to make a second version to replace single quotes with double quotes (or vice-versa) for parsing consistency.

Why Upon failure SQS does not place the failed message upon DLQ?

I am running this worker:

php -d memory_limit=-1 bin/console messenger:consume sqs_channel_manager -vv

And worker fails:

14:29:32 INFO      [messenger] Received message AppDomainEventChannelManagerChannelManagerEventHasReceived ["class" => "AppDomainEventChannelManagerChannelManagerEventHasReceived"]
14:29:32 WARNING   [messenger] Error thrown while handling message AppDomainEventChannelManagerChannelManagerEventHasReceived. Sending for retry #1 using 922 ms delay. Error: "Handling "AppDomainEventChannelManagerChannelManagerEventHasReceived" failed: " ["class" => "AppDomainEventChannelManagerChannelManagerEventHasReceived","message_id" => null,"retryCount" => 1,"delay" => 922,"error" => "Handling "AppDomainEventChannelManagerChannelManagerEventHasReceived" failed: ","exception" => SymfonyComponentMessengerExceptionHandlerFailedException^ { …}]
14:29:37 INFO      [messenger] Received message AppDomainEventChannelManagerChannelManagerEventHasReceived ["class" => "AppDomainEventChannelManagerChannelManagerEventHasReceived"]
14:29:37 WARNING   [messenger] Error thrown while handling message AppDomainEventChannelManagerChannelManagerEventHasReceived. Sending for retry #3 using 3676 ms delay. Error: "Handling "AppDomainEventChannelManagerChannelManagerEventHasReceived" failed: " ["class" => "AppDomainEventChannelManagerChannelManagerEventHasReceived","message_id" => null,"retryCount" => 3,"delay" => 3676,"error" => "Handling "AppDomainEventChannelManagerChannelManagerEventHasReceived" failed: ","exception" => SymfonyComponentMessengerExceptionHandlerFailedException^ { …}]
14:30:08 INFO      [messenger] Received message AppDomainEventChannelManagerChannelManagerEventHasReceived ["class" => "AppDomainEventChannelManagerChannelManagerEventHasReceived"]
14:30:08 CRITICAL  [messenger] Error thrown while handling message AppDomainEventChannelManagerChannelManagerEventHasReceived. Removing from transport after 5 retries. Error: "Handling "AppDomainEventChannelManagerChannelManagerEventHasReceived" failed: " ["class" => "AppDomainEventChannelManagerChannelManagerEventHasReceived","message_id" => null,"retryCount" => 5,"error" => "Handling "AppDomainEventChannelManagerChannelManagerEventHasReceived" failed: ","exception" => SymfonyComponentMessengerExceptionHandlerFailedException^ { …}]
14:30:08 INFO      [messenger] Rejected message AppDomainEventChannelManagerChannelManagerEventHasReceived will be sent to the failure transport SymfonyComponentMessengerBridgeDoctrineTransportDoctrineTransport. ["class" => "AppDomainEventChannelManagerChannelManagerEventHasReceived","transport" => "SymfonyComponentMessengerBridgeDoctrineTransportDoctrineTransport"]

The transports sqs_channel_manager is configured like this:

framework:
    messenger:
        failure_transport: failed
        transports:
            failed: 'doctrine://default?table_name=failed_messages'
            sqs_channel_manager:
              dsn: 'https://sqs.eu-north-1.amazonaws.com/XXXXXX/sqs_channel_manager_test'
              serializer: AppInfrastructureMessengerChannelManagerSerializer
              options:
                  access_key: '%env(AWS_ACCESS_KEY_ID)%'
                  secret_key: '%env(AWS_SECRET_ACCESS_KEY)%'
                  region: '%env(AWS_REGION)%'
                  queue_name: '%env(CHANNEL_MANAGER_QUEUE_NAME)%'

And is an SQS queue The queue has a redrive policy:

aws sqs get-queue-attributes --queue-url https://sqs.eu-north-1.amazonaws.com/XXXXXX/sqs_channel_manager_test --attribute-names RedrivePolicy
{
    "Attributes": {
        "RedrivePolicy": "{"deadLetterTargetArn":"arn:aws:sqs:eu-north-1:XXXXX:sqs_channel_manager_test_dlq","maxReceiveCount":1}"
    }
}

But upon failure message is not placed upon Deal letter queue:

aws sqs get-queue-attributes --queue-url https://sqs.eu-north-1.amazonaws.com/XXXXXXXX/sqs_channel_manager_test_dlq  --attribute-names ApproximateNumberOfMessages
{
    "Attributes": {
        "ApproximateNumberOfMessages": "0"
    }
}

Does failure_transport prevents the message to be placed upon DLQ? Setting failure_transport has no effect:

            sqs_channel_manager:
              failure_transport: null
              dsn: '%env(SQS_CHANNEL_MANAGER_TRANSPORT_DSN)%'
              serializer: AppInfrastructureMessengerChannelManagerSerializer
              options:
                  access_key: '%env(AWS_ACCESS_KEY_ID)%'
                  secret_key: '%env(AWS_SECRET_ACCESS_KEY)%'
                  region: '%env(AWS_REGION)%'
                  queue_name: '%env(CHANNEL_MANAGER_QUEUE_NAME)%'

Also I am using custom serializer:

<?php
declare(strict_types=1);

namespace AppInfrastructureMessenger;

use AppDomainEventChannelManagerChannelManagerEventHasReceived;
use SymfonyComponentMessengerEnvelope;
use SymfonyComponentMessengerStampRedeliveryStamp;
use SymfonyComponentMessengerStampTransportMessageIdStamp;
use SymfonyComponentMessengerTransportSerializationSerializerInterface;

class ChannelManagerSerializer implements SerializerInterface
{
    public function decode(array $encodedEnvelope): Envelope
    {
        $data = json_decode($encodedEnvelope['body'], true);

        if (json_last_error() !== JSON_ERROR_NONE) {
            throw new InvalidArgumentException(
                'Invalid JSON received from SQS: ' . json_last_error_msg()
            );
        }

        $envelope = new Envelope(new ChannelManagerEventHasReceived($data));

        if (isset($encodedEnvelope['headers']['stamps'])) {
            $stamps = unserialize(base64_decode($encodedEnvelope['headers']['stamps']));
            foreach ($stamps as $stamp) {
                $envelope = $envelope->with($stamp);
            }
        }

        return $envelope;
    }

    public function encode(Envelope $envelope): array
    {
        $event = $envelope->getMessage();

        $stampsToSerialize = [];

        foreach ($envelope->all() as $stampArray) {
            foreach ($stampArray as $stamp) {
                if ($stamp instanceof RedeliveryStamp || $stamp instanceof TransportMessageIdStamp) {
                    $stampsToSerialize[] = $stamp;
                }
            }
        }

        return [
            'body' => json_encode($event->channelManagerData, JSON_THROW_ON_ERROR),
            'headers' => [
                'stamps' => base64_encode(serialize($stampsToSerialize)),
            ],
        ];
    }
}

Does it affect a message entering DLQ? I am using Symfony 7.2, it this a known issue?

İs C sufficient for learning for beginners

I began learning programming since this September and a lot of people ı saw online recommending C for learning as its closer to hardware and learning it would make learning high level languages much easier. Should ı give a shot on C?

Some people also recommended Javascript and Python as they’re high on demand in the job market.

React Aria FileTrigger onSelect not firing on first file selection in Chrome iOS, subsequent selections trigger cancel event

I’m encountering an inconsistent event behavior with the FileTrigger component from @react-aria/components in a React application. The issue is observed specifically in ​​Chrome on iOS (version 140)​​ based on user analytics, and is difficult to reproduce.

Problem Description​​

After a user selects an image file:

​​First selection​​: The onSelect event handler does not fire at all.

​​Second and subsequent selections​​: The file dialog opens, but immediately after a file is selected, a cancel event is triggered follow by the button click event. The selected files are not processed, which no triggered the onSelect event.

Environment​​

  • ​​React​​: 18.x

  • Library​​: @react-aria/components(1.2.1)

  • ​​Browser & Platform​​: Chrome 140, iOS (iPhone/iPad)
    ​​
    ​​Simplified Code Example​​
    Here is a simplified version of the component focusing on the event handling:

import React, { useEffect, useRef } from 'react';
import { FileTrigger } from 'react-aria-components';

const UploadComponent = ({ onFileSelected }) => {
  const uploadInputRef = useRef(null);

  // This handler does not fired at all
  const handleFileSelect = (fileList) => {
    console.log('onSelect fired', fileList);
    if (fileList) {
      onFileSelected(Array.from(fileList));
    }
  };

  // This event fires immediately on subsequent selections
  const handleCancel = () => {
    console.log('Cancel event fired from user selection');
  };

  useEffect(() => {
    const currentInput = uploadInputRef.current;

    // this code will run after second upload
    currentInput?.addEventListener('cancel', handleCancel);

    return () => {
      currentInput?.removeEventListener('cancel', handleCancel);
    };
  }, []);

  return (
    <FileTrigger
      // didn't triggered 
      onSelect={handleFileSelect}
      acceptedFileTypes={['image/*', 'image/heic', 'image/heif']}
      allowsMultiple={true}
      ref={uploadInputRef}
    >
      {/* we got the click logs from this button */}
      <button onClick={() => {console.log('clicked');}}>Select Images</button>
    </FileTrigger>
  );
};

export default UploadComponent;

onSelect can be triggered, and got the file from user.

How to remove header ‘Host’ using supertest

I have condiiton in my http server that check if req.headers["host"] is undefined or not. I am using supertest and mocha to send GET request. I tried to use unset("Host"), but supertest still send header “Host”

http server:

const http_server = http.createServer(function (req, res) {
  console.log("http", req.method, req.url, req.headers);

  const url_path = url.parse(req.url, true).pathname;
  const query = url.parse(req.url, true).query;

  if (req.method === "GET" && req.headers["host"] !== undefined) {
    // force create session
    const session = getSession(req);
    console.log(`HOST === ${req.headers["host"]}`)

    res.removeHeader("Date");
    res.removeHeader("Transfer-Encoding");

    res.writeHead(302, {
      Location: getNewLocation(req.headers["host"], url_path, query),
      Connection: "close",
    });

    res.end();
    return;
  }

  handler(req, res);
});

test

  it("should return index.html", (done) => {
    request(http_server)
      .get("/")
      .unset("Host")
      .expect(200)
      .expect("Connection", "close")
      .expect("Etag", '"167-110-5f0633df"')
      .expect("Last-Modified", "Wed, 08 Jul 2020 21:00:15 GMT")
      .expect("Date", date_regex)
      .expect("Cache-Control", "no-cache")
      .expect("Expires", "0")
      .expect("Content-Type", "text/html")
      .expect("Content-Length", `<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="refresh" content="0; URL=/webpages/login.html" />
</head>
</html>
`.length)
      .expect(res => assert.strictEqual(res.text, `<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="refresh" content="0; URL=/webpages/login.html" />
</head>
</html>
`))
      .end(done)
  })

I am trying to remove header “Host”, so code would not fall into condition where it sends 302 status code

how do i create a sort function on a table?

The page is here for reference: https://songscape-helgasonpete.replit.app/artist/clarencewilliams.html

I have two tables that are activated by hitting the two buttons. But I want to be able to sort the information within those two tables. So under the “songs as writer” button – I want to be able to sort the information under the “Song” “Writer” “Originally By” headers alphabetically and information under the “Original Release” header by date.

Likewise under the “Songs as Performer” button – I want to be able to sort the information under the “Title” and “Performer” headers alphabetically, the information under the “Release Date” by date and the information under the “Streamcount” header numerically.

I tried creating two tables of differing data similar to the table I did on this link here: https://songscape-helgasonpete.replit.app/artist/bessiesmith.html. The table would be button activated.

I was able to get the buttons work, but I was unable to sort the table once I clicked on it. Here is the code for reference:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Clarence Williams</title>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
        integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

    <style>
        th {
            color: white;
        }
    </style>


  </head>
  <body>

<h1>Clarence Williams</h1>
<img src="/images/clarencewilliams.jpg"><br>
Born: October 8, 1898<br>
Died: November 6, 1965<br>
Rankings: <br>
<a href="https://songscape-helgasonpete.replit.app/statistics/writers.html">1st</a> most streamed writer<br>
<a href="https://songscape-helgasonpete.replit.app/statistics/performers.html">2nd</a> most streamed performer<br>
    <button type="button" onclick="updateDisplay('demo')">Songs As Writer</button>
    <button type="button" onclick="updateDisplay('demo2')">Songs As Performer</button>


    <table id="demo" style="display:none" class="specialTable table table-striped">
      <tr class="bg-info">
      <th id="songCol">Song</th>
      <th id="writerCol">Writer</th>
      <th id="originalperformerCol">Originally By</th>
      <th id="releaseCol">Original Release</th>
       </tr>

      <tr>
      <td><a href="https://songscape-helgasonpete.replit.app/work/gulfcoastblues.html">Gulf Coast Blues</a></td>
      <td><a href="https://songscape-helgasonpete.replit.app/artist/clarencewilliams.html">Clarence Williams</a></td>
      <td><a href="https://songscape-helgasonpete.replit.app/artist/bessiesmith+clarencewilliams.html">Bessie Smith - Clarence Williams at the Piano</a></td>
      <td>May 1923</td>
       </tr>

      <tr>
      <td><a href="https://songscape-helgasonpete.replit.app/work/babywontyoupleasecomehome.html">Baby, Won't You Please Come Home</a></td>
      <td><a href="https://songscape-helgasonpete.replit.app/artist/charleswarfield.html">Charles Warfield</a> <a href="https://songscape-helgasonpete.replit.app/artist/clarencewilliams.html">Clarence Williams</a></td>
      <td><a href="https://songscape-helgasonpete.replit.app/artist/bessiesmith+clarencewilliams.html">Bessie Smith - Clarence Williams at the Piano</a></td>
      <td>June 1923</td>
       </tr>

      </table>

      <table id="demo2" style="display:none" class="specialTable table table-striped">
      <tr class="bg-info">
      <th id="titleCol">Title</th>
      <th id="performerCol">Performer</th>
      <th id="releasetwoCol">Release Date</th>
      <th id="streamCol">Stream Count</th>
       </tr>

      <tr>
      <td><a href="https://songscape-helgasonpete.replit.app/performance/downheartedblues.html">Down Hearted Blues</a></td>
      <td><a href="https://songscape-helgasonpete.replit.app/artist/bessiesmith+clarencewilliams.html">Bessie Smith - Clarence Williams at the Piano</a></td>
      <td><a href="https://songscape-helgasonpete.replit.app/statistics/1923releases.html">May 1923</a></td>
      <td>1294462</td>
       </tr>

      <tr>
      <td><a href="https://songscape-helgasonpete.replit.app/performance/gulfcoastblues.html">Gulf Coast Blues</a></td>
      <td><a href="https://songscape-helgasonpete.replit.app/artist/bessiesmith+clarencewilliams.html">Bessie Smith - Clarence Williams at the Piano</a></td>
      <td><a href="https://songscape-helgasonpete.replit.app/statistics/1923releases.html">May 1923</a></td>
      <td>89052</td>
       </tr>

      <tr>
      <td><a href="https://songscape-helgasonpete.replit.app/performance/babywontyoupleasecomehome.html">Baby Won't You Please Come Home Blues</a></td>
      <td><a href="https://songscape-helgasonpete.replit.app/artist/bessiesmith+clarencewilliams.html">Bessie Smith - Clarence Williams at the Piano</a></td>
      <td><a href="https://songscape-helgasonpete.replit.app/statistics/1923releases.html">June 1923</a></td>
      <td>1832242</td>
       </tr>

      <tr>
      <td><a href="https://songscape-helgasonpete.replit.app/performance/ohdaddyblues.html">Oh Daddy Blues</a></td>
      <td><a href="https://songscape-helgasonpete.replit.app/artist/bessiesmith+clarencewilliams.html">Bessie Smith - Clarence Williams at the Piano</a></td>
      <td><a href="https://songscape-helgasonpete.replit.app/statistics/1923releases.html">June 1923</a></td>
      <td>37590</td>
       </tr>

      </table>




      <script>

      // Create a function to update your display area
      function updateDisplay(tableId) {

        // The function receives the id of the table to show (give each table a unique id, but the same class)

        // Set the display value of all tables with the target class to none
        document.querySelectorAll(".specialTable").forEach(el => {
          el.style.display = "none";
        });

        // Set the display value of the table with the target id to block
        document.getElementById(tableId).style.display = "block";

        $('#songCol').on('click', async function () {
            let newSortOrder;
            sortKey = "Song";
            if (lastSortOrder != "asc") {
                newSortOrder = "asc";
            } else {
                newSortOrder = "desc";
            }

            myArray = await performSort(myArray, sortKey, newSortOrder);
            buildtable(myArray);
        });

        $('#writerCol').on('click', async function () {
            let newSortOrder;
            sortKey = "Writer";
            if (lastSortOrder != "asc") {
                newSortOrder = "asc";
            } else {
                newSortOrder = "desc";
            }

            myArray = await performSort(myArray, sortKey, newSortOrder);
            buildtable(myArray);
        });

        $('#originalperformerCol').on('click', async function () {
            let newSortOrder;
            sortKey = "Originally By";
            if (lastSortOrder != "asc") {
                newSortOrder = "asc";
            } else {
                newSortOrder = "desc";
            }

            myArray = await performSort(myArray, sortKey, newSortOrder);
            buildtable(myArray);
        });

        $('#releaseCol').on('click', async function () {
            let newSortOrder;
            sortKey = "Original Release";
            if (lastSortOrder != "asc") {
                newSortOrder = "asc";
            } else {
                newSortOrder = "desc";
            }

            myArray = await performSort(myArray, sortKey, newSortOrder);
            buildtable(myArray);
        });

        $('#titleCol').on('click', async function () {
            let newSortOrder;
            sortKey = "Title";
            if (lastSortOrder != "asc") {
                newSortOrder = "asc";
            } else {
                newSortOrder = "desc";
            }

            myArray = await performSort(myArray, sortKey, newSortOrder);
            buildtable(myArray);
        });

        $('#performerCol').on('click', async function () {
            let newSortOrder;
            sortKey = "Performer";
            if (lastSortOrder != "asc") {
                newSortOrder = "asc";
            } else {
                newSortOrder = "desc";
            }

            myArray = await performSort(myArray, sortKey, newSortOrder);
            buildtable(myArray);
        });

        $('#releasetwoCol').on('click', async function () {
            let newSortOrder;
            sortKey = "Release Date";
            if (lastSortOrder != "asc") {
                newSortOrder = "asc";
            } else {
                newSortOrder = "desc";
            }

            myArray = await performSort(myArray, sortKey, newSortOrder);
            buildtable(myArray);
        });

        $('#streamCol').on('click', async function () {
            let newSortOrder;
            sortKey = "Stream Count";
            if (lastSortOrder != "asc") {
                newSortOrder = "asc";
            } else {
                newSortOrder = "desc";
            }

            myArray = await performSort(myArray, sortKey, newSortOrder);
            buildtable(myArray);
        });
      }

      </script>

      </body>


</html>

Loader in conditional statements is not showing after navigation or making new API calls

I had an API call for fetch products for wishlist and cart however since both share same UI I decided to do in single page component and at first refresh the loader is showing but after I navigation loader is not showing and Header and Product is different components.

Loader is not showing when I navigation between components as it took 0.1s for get data and I can’t see loader when I navigation through it

"use client";

import { useState, useEffect } from "react";
import { useParams } from "next/navigation";
import axios from "axios";
import Image from "next/image";
import { CircularProgress } from "@mui/material";

export default function ViewResouce() {
  const { resource } = useParams();
  const [isCart, setIsCart] = useState(false);
  const [resourcesData, setResourcesData] = useState<any[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [dataFind, setDataFind] = useState(false);

  useEffect(() => {
    if (!resource) {
      return;
    }

    if (resource === "cart") {
      setIsCart(true);
      return;
    }

    setIsCart(false);
  }, [resource]);

  useEffect(() => {
    if (!resource) {
      setIsLoading(false);
      setDataFind(false);
      setResourcesData([]);
      return;
    }

    setIsLoading(true);
    setDataFind(false);
    setResourcesData([]);

    const abortController = new AbortController();

    async function getResource() {
      try {
        const res = await axios.get(
          `/api/client/manage?resource=${resource}`,
          { signal: abortController.signal }
        );
        setResourcesData(res.data.data || []);
      } catch (e) {
        setResourcesData([]);
      } finally {
        setIsLoading(false);
        setDataFind(true);
      }
    }

    getResource();

    return () => {
      abortController.abort();
    };
  }, [resource]);

  if (isLoading && !dataFind) {
    return (
      <div
        className="d-flex justify-content-center align-items-center"
        style={{ height: "50vh" }}
      >
        <CircularProgress size={80} />
      </div>
    );
  }

  if (dataFind && !isLoading && resourcesData.length <= 0) {
    return (
      <div className="no-product-card">
        {isCart && (
          <Image
            src="/assests/no-items-cart.png"
            alt="no-products"
            width={400}
            height={400}
            style={{
              maxWidth: "100%",
              width: "auto",
              objectFit: "cover",
            }}
            loading="lazy"
            unoptimized
          />
        )}
        {!isCart && (
          <Image
            src="/assests/no-items-wishlist.png"
            alt="no-products"
            width={400}
            height={400}
            style={{
              maxWidth: "100%",
              width: "auto",
              objectFit: "cover",
            }}
            loading="lazy"
            unoptimized
          />
        )}
        <h6>No {isCart ? "Cart" : "Wishlist"} Items Found</h6>
      </div>
    );
  }

  if (dataFind && !isLoading && resourcesData.length > 0 && isCart) {
    return (
      <div className="main-resource-container">
        <h6>Your Cart Items</h6>
      </div>
    );
  }

  if (dataFind && !isLoading && resourcesData.length > 0 && !isCart) {
    return (
      <div className="main-resource-container">
        <h6>Your Wishlist Items</h6>
      </div>
    );
  }

  return null;
}

Loader in conditional statements is not showing after I navigation or new API calls in nextjs

I had an API call for fetch products for wishlist and cart however since both share same UI I decided to do in single page component and at first refresh the loader is showing but after I navigation loader is not showing and Header and Product is different components.

"use client";

import { useState, useEffect } from "react";
import { useParams } from "next/navigation";
import axios from "axios";
import Image from "next/image";
import { CircularProgress } from "@mui/material";

export default function ViewResouce() {
  const { resource } = useParams();
  const [isCart, setIsCart] = useState(false);
  const [resourcesData, setResourcesData] = useState<any[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [dataFind, setDataFind] = useState(false);

  useEffect(() => {
    if (!resource) {
      return;
    }

    if (resource === "cart") {
      setIsCart(true);
      return;
    }

    setIsCart(false);
  }, [resource]);

  useEffect(() => {
    if (!resource) {
      setIsLoading(false);
      setDataFind(false);
      setResourcesData([]);
      return;
    }

    setIsLoading(true);
    setDataFind(false);
    setResourcesData([]);

    const abortController = new AbortController();

    async function getResource() {
      try {
        const res = await axios.get(
          `/api/client/manage?resource=${resource}`,
          { signal: abortController.signal }
        );
        setResourcesData(res.data.data || []);
      } catch (e) {
        setResourcesData([]);
      } finally {
        setIsLoading(false);
        setDataFind(true);
      }
    }

    getResource();

    return () => {
      abortController.abort();
    };
  }, [resource]);

  if (isLoading && !dataFind) {
    return (
      <div
        className="d-flex justify-content-center align-items-center"
        style={{ height: "50vh" }}
      >
        <CircularProgress size={80} />
      </div>
    );
  }

  if (dataFind && !isLoading && resourcesData.length <= 0) {
    return (
      <div className="no-product-card">
        {isCart && (
          <Image
            src="/assests/no-items-cart.png"
            alt="no-products"
            width={400}
            height={400}
            style={{
              maxWidth: "100%",
              width: "auto",
              objectFit: "cover",
            }}
            loading="lazy"
            unoptimized
          />
        )}
        {!isCart && (
          <Image
            src="/assests/no-items-wishlist.png"
            alt="no-products"
            width={400}
            height={400}
            style={{
              maxWidth: "100%",
              width: "auto",
              objectFit: "cover",
            }}
            loading="lazy"
            unoptimized
          />
        )}
        <h6>No {isCart ? "Cart" : "Wishlist"} Items Found</h6>
      </div>
    );
  }

  if (dataFind && !isLoading && resourcesData.length > 0 && isCart) {
    return (
      <div className="main-resource-container">
        <h6>Your Cart Items</h6>
      </div>
    );
  }

  if (dataFind && !isLoading && resourcesData.length > 0 && !isCart) {
    return (
      <div className="main-resource-container">
        <h6>Your Wishlist Items</h6>
      </div>
    );
  }

  return null;
}

Thymeleaf page not rendering correctly on iOS when using LIFF SDK

Now I am having a problem:
I am building a chat application, when from the LINE app click on the start chat button, it will transfer the user to the chat website dedicated to them. Currently when processing on Android, everything is still displayed normally, but when I build on iOS, nothing is displayed.

Regarding the technology used, I use spring boot, thymeleaf combined with jQuery + LIFF SDK.

The process when init the screen I am processing: When init the screen for the first time, the backend will check the isInit variable passed is null, then it will return the html of that screen.
My Server:

  public String init(
      @RequestParam(value = "liffChannelId") String liffChannelId,
      @RequestParam(value = "messageChannelId") String messageChannelId,
      @RequestParam(value = "isInit", required = false) String isInit,
      @RequestParam(value = "idToken", required = false) String idToken,
      HttpServletRequest request, Model model) {
    if (Objects.isNull(isInit)) {
      return "s2013_chat";
    }

    ChatForm form = chatHelper.init(liffChannelId, messageChannelId, idToken, page, request);

    return "s2013_chat";
  }

And in my js:

$(document).ready(function () {
  const urlParams = new URLSearchParams(window.location.search);
  const isInit = urlParams.get("isInit");
  if (!isInit) {
    initLiffApp();
  }
});

function initLiffApp() {
  const messageChannelId = new URLSearchParams(window.location.search).get("messageChannelId");
  if (!messageChannelId) {
    alert("MessageChannelId is missing");
    return;
  }

  const liffChannelId = new URLSearchParams(window.location.search).get("liffChannelId");
  if (!liffChannelId) {
    alert("LiffChannelId is missing");
    return;
  }

  const liffId = new URLSearchParams(window.location.search).get("liffId");
  if (!liffId) {
    alert("LiffId is missing");
    return;
  }

  liff
    .init({
      liffId: liffId
    })
    .then(() => {
      const idToken = liff.getIDToken();
      if (!idToken) {
        alert("Failed to get ID Token");
        return;
      }
      sendToServer(liffChannelId, messageChannelId, idToken);
    })
    .catch(err => {
      console.error("LIFF init error", err);
    });
}

function sendToServer(liffChannelId, messageChannelId, idToken) {
  const redirectUrl = `/counseling/chat/client?liffChannelId=${encodeURIComponent(liffChannelId)}&messageChannelId=${encodeURIComponent(messageChannelId)}&isInit=1&idToken=${encodeURIComponent(idToken)}`;
  window.location.href = redirectUrl;
}

When returning for the first time, in js make a call to the liff server to get idToken and at this time will call back to the server 1 more time with isInit is true. At this time the backend will start processing. However, when building on iOS, I noticed that when init for the first time, it returns the screen UI without displaying anything (I think it’s due to the processing when isInit is null, it returns without calling liff anymore).

I tried commenting out the isInit variable check, and now the UI is displayed but does not receive any css and js events.

//if (Objects.isNull(isInit)) {
//   return "s2013_chat";
//}

I used Web Inspector on Safari browser to check and saw that the css and js files were loaded successfully, but the console log is reporting an error as shown.

enter image description here
enter image description here
enter image description here

Please help me with this problem, I have been trying to solve it for 3 days but still don’t know the reason why?

displaying and filtering images with a click event vanillajs

I want to dynamically display images and list items. I then want to filter the images based on the list item(genre) that is clicked. There are 2 images per list item. The list items are displayed in the middle of the page with one image on either side of the page.
I’ve created this function that I know is wrong but I’m not exactly sure where I’m going wrong. I don’t necessarily need the answer but let me know if I’m going in the right direction and if not, what errors I am making.

HTML

    <div class="content-wrapper-2">
      <div class="image-container-1"></div>
      <ul id="genre-list"></ul>
      <div class="image-container-2"></div>
    </div>

JS

const imageContainer1 = document.querySelectorAll('.image-container-1');
const imageContainer2 = document.querySelectorAll('.image-container-2');
const genreList = document.getElementById('genre-list');
const albums = [
  {
    id: 1,
    genre: 'Rock',
    image1: '/images/album-covers/jimihindrix-areyouexperienced.jpg',
    image2: '/images/album-covers/thedoors.jpg',
  },
  {
    id: 2,
    genre: 'Jazz',
    image1: '/images/album-covers/somethinelse.jpg',
    image2: '/images/album-covers/MilesDavis-BitchesBrew.jpg',
  },
  {
    id: 3,
    genre: 'Hiphop',
    image1: '/images/album-covers/mfdoom-mmfood.jpg',
    image2: '/images/album-covers/nas-illmatic.jpg',
  },
  {
    id: 4,
    genre: 'Soul',
    image1: '/images/album-covers/aliciakeys-diary.jpeg',
    image2: '/images/album-covers/ettajames-tellmama.jpg',
  },
  {
    id: 5,
    genre: 'Electronic',
    image1: '/images/album-covers/burial-tunes.jpg',
    image2: '/images/album-covers/björk-homogenic.jpg',
  },
  {
    id: 6,
    genre: 'Classic',
    image1: '/images/album-covers/sparks-kimonomyhouse.jpg',
    image2: '/images/album-covers/chakakhan-rufus.jpg',
  },

  {
    id: 7,
    genre: 'Pop',
    image1: '/images/album-covers/beatles-sgtpeppers.jpg',
    image2: '/images/album-covers/prince-purplerain.png.webp',
  },
];

const handleClick = (e) => {
  const clickedElement = e.target.id;
  albums.map((album) => {
    genreList.innerHTML = `<li id=${album.genre}>${album.genre}</li>`;
  });
  document.getElementById(`${albums.genre}`).addEventListener('click', () => {
    albums.filter((p) => {
      if (p.name === clickedElement) {
        imageContainer1.innerHTML = `<img src=${p.image1}/>`;
        imageContainer2.innerHTML = `<img src=${p.image2}/>`;
        
      }
    });
  });
};

document.addEventListener('DOMContentLoaded', (e) => {
  handleClick(e);
});