How to made separate popups for each element in array using JS?

I have an array with products in it. Each product is a separate block (card) on the page which appears after user uses checkboxes on the same page. The product cards are buttons. What I need to do is that when user clicks on any product card it opens a popup which is linked to said card. Like if user clicks on ‘product1 card’ it opens ‘product1 popup’, ‘product2 card’ opens ‘product2 popup’ etc.

I’m new to JS so i would appreciate any help, thanks!

Here is how I tried to do it, but it doesn’t work.

// Creating an array and put an individual popup code as 'popupHtml'
function showProducts(selectedValues) {
  const resultsList = document.querySelector('.results__list');
  const products = [
    {
      id: 'giorgiocasa',
      name: 'Giorgiocasa',
      values: ['cont', 'high', 'mirgroup'],
      popupHtml: `<div class="popup__container">
         <button class="popup__close-button" type="button"></button> 
         <img src="./images/giorgiocasa2.png" class="popup__image" alt="giorgiocasa"> 
         <div class="popup__text"> 
          <p class="popup__title">Giorgiocasa</p> 
          <a class="popup__link" href="#">Официальный сайт</a> 
          <p class="popup__description">Представительство: <span>MIRGROUP</span></p> 
          <p class="popup__subtitle">Условия работы</p> 
          <p class="popup__description">Скидка: 50%
            <br>Предоплата: 50%
            <br>Сроки производства: 45 рабочих дней
          </p> 
        </div> 
      </div>`
    },
    {
      id: 'piermaria',
      name: 'Piermaria',
      values: ['classic', 'midHigh', 'mirgroup'],
      popupHtml: `<div class="popup__container">
         <button class="popup__close-button" type="button"></button> 
         <img src="./images/giorgiocasa2.png" class="popup__image" alt="giorgiocasa"> 
         <div class="popup__text"> 
          <p class="popup__title">Piermaria</p> 
          <a class="popup__link" href="#">Официальный сайт</a> 
          <p class="popup__description">Представительство: <span>MIRGROUP</span></p> 
          <p class="popup__subtitle">Условия работы</p> 
          <p class="popup__description">Скидка: 50+3%
            <br>Предоплата: 50%, заказ до 2000 евро - 100%
            <br>Сроки производства: 45 рабочих дней
          </p> 
        </div> 
      </div>`
    },
];
  let matchingProducts = [];
// Creating and adding a product card or 'no results' to the page
if (selectedValues.length === 0) {
    const noResultsHtml = '<p class="results__text">НЕТ РЕЗУЛЬТАТОВ</p>';
    resultsList.innerHTML = noResultsHtml;
    return;
  }

  products.forEach(function(product) {
  let matchCount = 0;
  selectedValues.forEach(function(value) {
  if (product.values.includes(value)) {
  matchCount++;
  }
  });
  if (matchCount === selectedValues.length) {
  matchingProducts.push(product);
  }
  });
  
  resultsList.innerHTML = '';
  

  if (matchingProducts.length === 0) {
  const noResultsHtml = '<p class="results__text">НЕТ РЕЗУЛЬТАТОВ</p>';
  resultsList.insertAdjacentHTML('beforeend', noResultsHtml);
  } else {
  let html = '';
  matchingProducts.forEach(function(product) {
  html += `<li>
              <button class="results__card" type="button" id="${product.id}"><span class="results__card-text">${product.name}</span></button>
            </li>`;
  });
  resultsList.insertAdjacentHTML('beforeend', html);
  }
  }
// results__card are all button tags
const buttons = document.querySelectorAll('.results__card');

// Trying to open a popup linked to the specific product card after click 
buttons.forEach((button) => {
  button.addEventListener('click', () => {
    const popupContent = button.dataset.popupHtml;
    
    const popup = document.createElement('div');
    popup.classList.add('popup-container');
    popup.innerHTML = popupContent;

    const container = document.querySelector('.popup');
    container.appendChild(popup);
  });
});

const resultsCards = document.querySelectorAll('.results__card');

resultsCards.forEach(function(card) {
  card.addEventListener('click', function() {
    const productId = this.dataset.productId;
    const product = products.find(function(p) {
      return p.id === productId;
    });

// My popup opens with popup_opened class and closes with adding popup_closed class.
    const popup = document.querySelector('.popup');
    popup.innerHTML = product.popupHtml;
    popup.classList.remove('popup_closed');
    popup.classList.add('popup_opened');
  });
});

chart js rotate label text on radar chart – is it possible?

I have Chart js radar diagram with 24 labels.

I need to rotate every next label text to 15 degrees from previous: ‘Label 1’ is on the top and it’s vertical, ‘Label 2’ rotated on 15 degrees clockwise etc.

Is there some option for this?

Here’s the code:

import React from 'react';
import { Radar } from 'react-chartjs-2';
import { Chart as ChartJS, RadialLinearScale, PointElement, LineElement, Filler, Tooltip, Legend } from 'chart.js';

const data = {
    labels: [ 'Label 1', 'Label 2', 'Label 3', 'Label 4', 'Label 5', 'Label 6', 'Label 7', 'Label 8', 'Label 9', 'Label 10', 'Label 11', 'Label 12', 'Label 13', 'Label 14', 'Label 15', 'Label 16', 'Label 17', 'Label 18', 'Label 19', 'Label 20', 'Label 21', 'Label 222', 'Label 23', 'Label 24' ],
    datasets: [
        {
            label: 'Dataset 1',
            data: [65, 59, 90, 81, 56, 65, 59, 90, 81, 56, 65, 59, 90, 81, 56, 65, 59, 90, 81, 56,],
            backgroundColor: 'rgba(255, 99, 132, 0.2)',
            borderColor: 'rgba(255, 99, 132, 1)',
            borderWidth: 1,
        },
    ],
};

const options: any = {
    scales: {
        r: {            
            ticks: {
                display: false 
            },
            angleLines: {
                display: true,
                color: '#90B7DA',
                borderDash: [11, 10],
                borderDashOffset: 5,
                lineWidth: 1
            },
            angle: 115,
            suggestedMin: 0,
            suggestedMax: 100,
            pointLabels: {
                font: {
                    family: 'Open Sans',
                    size: 10,
                    weight: '300',
                },
                color: '#90B7DA',
                
            }
        }
    },
    plugins: {
        legend: {
            display: false,
        }
    },

};

const RadarChart = () => (

    <Radar data={data} options={options} />
);

export default RadarChart;

How work with github api to retrieve a repository’s readme file?

I am trying to work with github api to get access to raw README.md file using /repos/{owner}/{repo}/readme, I am able to make the call using thunderclient in vscode and seeing the raw file.
enter image description here

but when I am making the same call from within my react application I am receiving a json object of this form

{
  "name": "README.md",
  "path": "README.md",
  "sha": "...",
  "size": 9,
  "url": "https://api.github.com/repos/anubhavadarsh/Litaci/contents/README.md?ref=master",
  "html_url": "https://github.com/anubhavadarsh/Litaci/blob/master/README.md",
  "git_url": "https://api.github.com/repos/anubhavadarsh/Litaci/git/blobs/592c92302634be24522f96f3ed6649f389f1aa0d",
  "download_url": "https://raw.githubusercontent.com/anubhavadarsh/Litaci/master/README.md",
  "type": "file",
  "content": "IyBMaXRhY2kKn",
  "encoding": "base64",
  "_links": {
    "self": "https://api.github.com/repos/anubhavadarsh/Litaci/contents/README.md?ref=master",
    "git": "https://api.github.com/repos/anubhavadarsh/Litaci/git/blobs/592c92302634be24522f96f3ed6649f389f1aa0d",
    "html": "https://github.com/anubhavadarsh/Litaci/blob/master/README.md"
  }
}

PS: I tried with a public repository that is not mine and I am able to get the raw readme, but my own repository still returns this.

lobby scan using name lookup tool [closed]

I state that I am a neophyte. Is it possible to create a tool that scans a game lobby, like the poker one, where there are 1vs1 matches? Having a table with nicknames of players, the tool should detect by scanning the tables when these (players) sign up.
If yes, how? surely the tool works on the client and not on the server. I thought about a possible use of mysql, ocr.

thanks

in the lobby they use this kind of tool, and even having found the nick, they self-register against it in a few thousandths of a second.

Exactly when (in which NodeJS event loop phase) are a Readable stream’s “data”, “close” and “end” events emitted?

I thought I got a complete understanding of NodeJS event loop and its phases, but apparently not.

When are the handlers of the “data”, “close” and “end” event handlers executed? In which event loop phase or task queue?

The question is straightforward, but let me explain what I expect and what I don’t understand.

Let’s consider the following code (Node 19).

const stream = require('stream');

const readable = new stream.Readable({ read() {} });

// 1st PUSH
setImmediate(() => console.log('Immediate log 1'));
process.nextTick(() => console.log('Next tick log 1'));
queueMicrotask(() => console.log('Microtask log 1'));
readable.push(Buffer.from([1]));
console.log('Pushed data # 1');

// 2nd PUSH
setImmediate(() => console.log('Immediate log 2'));
process.nextTick(() => console.log('Next tick log 2'));
queueMicrotask(() => console.log('Microtask log 2'));
readable.push(Buffer.from([2]));
console.log('Pushed data # 2');

console.log('Attaching handlers....');
readable.on('data', data => console.log('Data received:', data))
    .on('end', () => console.log('End received'))
    .on('close', () => console.log('Close received'))
console.log('Handlers attached');

// 3RD PUSH
setImmediate(() => console.log('Immediate log 3'));
process.nextTick(() => console.log('Next tick log 3'));
queueMicrotask(() => console.log('Microtask log 3'));
readable.push(Buffer.from([3]));
console.log('Pushed data # 3');

// 4TH PUSH
setImmediate(() => console.log('Immediate log 4'));
process.nextTick(() => console.log('Next tick log 4'));
queueMicrotask(() => console.log('Microtask log 4'));
readable.push(Buffer.from([4]));
console.log('Pushed data # 4');

// NULL PUSH
setImmediate(() => console.log('Immediate log null'));
process.nextTick(() => console.log('Next tick log null'));
queueMicrotask(() => console.log('Microtask log null'));
readable.push(null);
console.log('Pushed null');

console.log('----END OF MAIN CODE----');

And here’s the output:

Pushed data # 1
Pushed data # 2
Attaching handlers....
Handlers attached
Pushed data # 3
Pushed data # 4
Pushed null
----END OF MAIN CODE----
Next tick log 1
Next tick log 2
Data received: <Buffer 01>
Data received: <Buffer 02>
Data received: <Buffer 03>
Data received: <Buffer 04>
Next tick log 3
Next tick log 4
Next tick log null
End received
Close received
Microtask log 1
Microtask log 2
Microtask log 3
Microtask log 4
Microtask log null
Immediate log 1
Immediate log 2
Immediate log 3
Immediate log 4
Immediate log null

I don’t understand how can be the 3rd and 4th data event handlers executed before my 3rd and 4th nextTick handlers event though I push data after I add my handlers to the nextTick queue.

For me, it’s like not the .push() but the .on('data') call somehow inserts a “listener-like” stuff into the nextTick queue, and it stays there in that place for all future data events. So anything I push to the nextTick queue after attaching the data event handler will be executed after the event handler, as you can see. It doesn’t make sense to me; I’d expect the .push() call to push the data event handler to the end of the nextTick queue.

What do I misunderstand here?

The “end” and “close” event handlers seem to make sense to me, since – as I can see – the .push(null) call pushes the handler to the end of the nextTick queue. However, initially I thought that – at least the “close” handler – is executed in the separate macrotask queue of close handlers, which comes after the immediate queue, but seemingly it’s not the case, am I right?

Combining all tabs in a google sheet

I’ve got a large google sheet with multiple tabs. Each tab contains a different “deal” and a list of salesfolks and what their commission percentage is for that deal, as well as their total cash commission. Each “deal” tab is structured identically, the only information that changes is

  1. Which salespeople are on the deal
  2. What their commission % is for the deal (1 person could have different percentages on different deals)

I want to create a separate sheet, or separate tab, whichever is easier, that shows every salesperson and what their total cash take-home was across all deals.

To do this, I somehow need to do a simple lookup across tabs. This is simple enough if you know all the tab names such as in this example, but in my scenario new tabs are being constantly added. So, while I can standardize the tab names, move them into their own sheet, etc. I will always have 1 tab/sheet per deal (though each tab will follow the same format).
Is there any way to merge data across all tabs in a google sheet without explicitly stating each tab name in the formula? I’m a decent programmer so perhaps App Scripts could help with this if it’s not possible with built-in formulas?

**TL;DR: **Merging data across all tabs dynamically in GSheets, is it possible?

Node.JS migration to 18.14.1 version issue: error:0308010C:digital envelope routines::unsupported

I have migrated from node.js 16.15.0 to 18.14.1.

Right now, I am having an error coming from babel-loader.js in a custom framework (just FYI for the react based advice) :

enter image description here

This is what I am having in the place where issue is coming:

var filename = function filename(source, identifier, options) {
  var hash = crypto.createHash("md4");
  var contents = JSON.stringify({
    source: source,
    options: options,
    identifier: identifier
  });

  hash.update(contents);

  return hash.digest("hex") + ".json.gz";
 };

As I understand, the origin of the issue comes from Webpack using the MD4 algorithm in its build process, which is no longer supported in the latest Node.js version. So I have updated the webpack version to 5.75.0 (doesn’t help at all) and also I decided to patch the babel-loader dependency, by switching the algorithm from md4 to md5:

var filename = function filename(source, identifier, options) {
  var hash;
  try {
    hash = crypto.createHash("md4");
  } catch (e) {
    console.warn('Crypto "md4" is not supported anymore by this Node version');
    hash = crypto.createHash("md5");
  }
  var contents = JSON.stringify({
    source: source,
    options: options,
    identifier: identifier
  });

  hash.update(contents);

  return hash.digest("hex") + ".json.gz";
};

I am not having this error anymore, BUT the content is not being rendered and I am having a lot of issues in the console. I believe it’s because I changed the way of hashing, but I also have to do the proper un-hashing in babel-loader.js. Will be super grateful for any advices on it

p.s.: please don’t advise to downgrade the node.js version

How do i convert an array of objects into 1 object in typescript

I have an array of objects like this:

myArray = [
    {itemOneKey: 'itemOneValue', itemTwoKey: 'itemTwoValue'},
    {itemThreeKey: 'itemThreeValue'}
];

I wish to turn it to a single object like this:

myObject = {
    itemOneKey: 'itemOneValue',
    itemTwoKey: 'itemTwoValue',
    itemThreeKey: 'itemThreeValue'
}

in TypeScript. Anyone have a clue how I can go about to achieve this?

loadAsync in JSZip is not waiting to get completed

I am using JSZip library on browser UI and having a “content” which I am passing as body for creating a zip.

var contentDiff: async function(content){
      zip = await JSZip.loadAsync(content, {base64: true});
      return zip.files;
},//other functions below this

Now, I am new but this “zip.files” comes as undefined in a later method call, even after calling await.
Kindly suggest what is missing in this js.

I tried different variations of async await and promises, but all in vain.

How to make slot conditionally rendered?

<template>
    <div class="carousel">
        {{ index}}
                <slot></slot>
         <button @click="next">Next</button>
    </div>

</template>
<script setup>
import { useSlots, onMounted, ref, onUpdated, provide} from 'vue';

const slots = useSlots()
const index = ref(0)
function next(){
    index.value = index.value + 1 == slots.default().length ? 0 : index.value + 1;
}
onUpdated(() => {
  const currentSlide = ref(slots.default()[index.value])
})
</script>

I’m creating my own carousel. I have const currentslide that equals the first object in my array by default.

I have to figure out how to provide and inject this const to my slot “Slide” and then make it conditionally rendered. It means that the current slide that is shown in my carousel is 0 by default but I can change by clicking on the button next

<template>
    <div class="slide">

        <slot/>
    </div>
    
</template>
<script>

</script>

Display JSON Data by Category. Not all categories are visible

There are separate categories on my page. But it is not possible to exclude all categories.

index.html:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Display JSON Data by Category</title>
</head>
<body>
  <label for="category-select">Filter by Category:</label>
  <select id="category-select">
    <option value="all">All</option>
    <option value="fruits">Fruits</option>
    <option value="vegetables">Vegetables</option>
    <option value="dairy">Dairy</option>
  </select>

  <div id="category-container"></div>

  <script src="app.js"></script>
</body>
</html>

app.js:

// Wait for the DOM to finish loading
document.addEventListener("DOMContentLoaded", function() {

  // Get references to the category select element and category container element
  var categorySelect = document.getElementById("category-select");
  var categoryContainer = document.getElementById("category-container");

  // Attach an event listener to the category select element
  categorySelect.addEventListener("change", function() {
    // Get the selected category
    var category = categorySelect.value;

    // Send an AJAX request to the server to get the data for the selected category
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        // Parse the JSON response
        var data = JSON.parse(xhr.responseText);

        // Filter the data by the selected category
        if (category) {
          data = data.filter(function(item) {
            return item.category == category;
          });
        }

        // Build the HTML to display the filtered data
        var html = "";
        data.forEach(function(item) {
          html += "<h2>" + item.name + "</h2>";
          html += "<p>" + item.description + "</p>";
        });

        // Update the category container with the HTML
        categoryContainer.innerHTML = html;
      }
    };
    xhr.open("GET", "app.php?category=" + encodeURIComponent(category), true);
    xhr.send();
  });

});

data.json:

[
  {
    "name": "Apple",
    "description": "A sweet fruit that is good for you.",
    "category": "fruits"
  },
  {
    "name": "Broccoli",
    "description": "A nutritious vegetable that is high in fiber.",
    "category": "vegetables"
  },
  {
    "name": "Milk",
    "description": "A dairy product that is a good source of calcium.",
    "category": "dairy"
  },
  {
    "name": "Carrot",
    "description": "A root vegetable that is crunchy and delicious.",
    "category": "vegetables"
  },
  {
    "name": "Banana",
    "description": "A delicious fruit that is high in potassium.",
    "category": "fruits"
  }
]

app.php:

<?php

// Read the contents of the data.json file
$data = file_get_contents('data.json');

// Decode the JSON data into an array of items
$items = json_decode($data, true);
$itm = json_encode($items);

// Check if the category parameter is set and filter the items by category
if (isset($_GET['category'])) {
    if($_GET['category']!=="all"){
    $category = $_GET['category'];
    $items = array_filter($items, function($item) use ($category) {
        return $item['category'] == $category;
    });
    }
}

// Set the content type header to indicate that we are sending JSON data
header('Content-Type: application/json');

// Send the filtered items as JSON data
if($_GET['category']!=="all"){
echo json_encode(array_values($items));
}else{
    echo $itm;
}

This code reads the contents of the data.json file, decodes the JSON data into an array of items, filters the array by category if the category parameter is set, and then sends the filtered items as JSON data to the web page.

If I select a specific category:
working

If I select the “All” category:
not working

I want to see all categories.

Where did I go wrong? Thank you!

How does this link work that uses <a with no href and id instead?

I am trying to understand the way the links on a page are working because I like the design.

This is the live page:

https://www.infohio.org/resources/g68

This is how the links are set up in the source code:

<a  style='color: #202020' class='resourcelink'  id="resourcelinktitle61570">
  <div class='zoo-teaser-title uk-margin-small'> Book Nook </div>
  <div class='zoo-teaser-desc uk-margin-small'> Explore, create, and share video book trailers. Includes recommended web tools for creating book trailers, lesson plans, and other teacher resources. Lexile reading levels included.</div>
</a>

I’ve never seen a link like this. Can someone explain how it’s working?

I tried recreating the code on a page on my local machine and can’t get the links to work.