Why is this conditional rendering not working?

I’m practicing memory game and working on a logic where if two cards are flipped and they are not equal value then flip back to hide the value. Basically,{trackFlip[idx] && cell} is the part in question. I even console.logged the trackFlip object from flipBack function to check to make sure the clicked card value is set to false, and they are, but this conditional rendering still fails. When two unmatched values still display on the screen instead of disappearing. Not sure what’s wrong with the logic. https://codesandbox.io/s/frontend-eval-memory-game-ts-8yyfmq?file=/src/App.tsx:0-2438

import "./styles.css";
import React, { useState, useEffect } from "react";

const generateRandomNumbers = (totalNums: number) => {
  let halfNums = totalNums / 2;
  let count = 0;
  let arr = [];
  for (let i = 0; i < halfNums; i++) {
    arr.push(i);
  }
  arr = [...arr, ...arr];
  let j = arr.length;
  while (--j > 0) {
    let temp = Math.floor(Math.random() * (j + 1));
    [arr[temp], arr[j]] = [arr[j], arr[temp]];
  }

  return arr;
};

interface Hash {
  [key: number]: boolean;
}

function createFlipTracker(j: number) {
  let hash: Hash = {};
  for (let j = 0; j < 36; j++) {
    hash[j] = false;
  }

  return hash;
}

export default function App() {
  const [board, setBoard] = useState(generateRandomNumbers(36));
  const [trackFlip, setTrackFlip] = useState(createFlipTracker(36));
  const [solved, setSolved] = useState<number[]>([]);

  const handleClick = (num: number, idx: number) => {
    let copiedTrackFlip = { ...trackFlip };
    if (copiedTrackFlip[idx]) {
      copiedTrackFlip[idx] = false;
      setTrackFlip(copiedTrackFlip);
    } else {
      copiedTrackFlip[idx] = true;
      setTrackFlip(copiedTrackFlip);
    }
    let flippedCell = Object.keys(copiedTrackFlip).filter(
      (val) => copiedTrackFlip[Number(val)] === true
    );
    console.log(flippedCell);
    function flipBack(x: number, y: number) {
      copiedTrackFlip[x] = false;
      copiedTrackFlip[y] = false;
      console.log(copiedTrackFlip);
      setTrackFlip(copiedTrackFlip);
    }
    if (flippedCell.length === 2) {
      let [x, y] = flippedCell;
      if (board[Number(x)] !== board[Number(y)]) {
        setTimeout(() => {
          flipBack(Number(x), Number(y));
        }, 1000);
      } else {
        setTimeout(() => {
          flipBack(Number(x), Number(y));
          let copiedSolved = [...solved];
          copiedSolved.push(Number(x));
          copiedSolved.push(Number(y));
          setSolved(copiedSolved);
        }, 1000);
      }
    }
  };

  const handleWinner = (idx: number) => {
    if (solved.includes(idx)) {
      return "solvedCell";
    }
  };

  return (
    <div className="board-container">
      {board.map((cell, idx) => {
        return (
          <div
            className={`cell ${handleWinner(idx)}`}
            data-cell={idx}
            onClick={() => handleClick(cell, idx)}
          >
            {trackFlip[idx] && cell}
          </div>
        );
      })}
    </div>
  );
}

How to await an async function that is inside an inline function

I have some code with this structure:

$w('#repeater').forEachItem(() => {
    a();
});

b();

This repeats “a” for each item in the repeater and then goes on to do “b”.

Now I need to await “a” which means I need to make the inline function for each item async like so:

$w('#repeater').forEachItem(async () => {
    await a();
});

b();

Now the problem is that “b” runs first. I tried adding “await” in front of the first line, but it doesn’t do anything. How do I get it to wait for “forEachItem” to all complete before moving on?

How to pass database variables from PHP to a JavaScript function?

I’m trying to create a website which can retrieve data from a MySQL database in an HTML table and then using a JavaScript function user can save the contact details by pressing the save button to their phone. I have written the following code using HTML, PHP and created a JavaScript function at the end but unable to pass the database variables in place of name: "John Smith", phone: "555-555-5555", email: "[email protected]" so user can save data from the database instead of hardcoded data.

My code so far

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

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta http-equiv="X-UA-Compatible" content="ie=edge" />
  <title>Employee's Contact</title>
  <!---Custom CSS File--->
  <link rel="stylesheet" href="style.css" />

</head>

<body>
  <section class="container">
    <header>Search for Contacts</header>

    <!-- <img src="jet.png" alt=""> -->
    <form action="displayContact.php" method="GET">
      <label for="contact">Employee ID: </label><br>
      <input type="number" name="employee_id" placeholder="enter employee id"><br><br>

      <button type="submit" value="list" name="genlist" class="btn">Generate Contact</button>&nbsp;&nbsp;<button id="save-btn">Save Contact</button><br><br>
    </form>

    <?php

    $serverAddress = "localhost";
    $serverUsername = "root";
    $serverPassword = "";
    $serverDB = "dlt";

    $connection = mysqli_connect($serverAddress, $serverUsername, $serverPassword, $serverDB);


    if (mysqli_connect_errno()) {
      die("Failed to connect " . mysqli_connect_errno());
    }

    if (isset($_GET['genlist'])) {

      $employee_id = $_GET['employee_id'];

      $query = "SELECT fullname, company, email, phone, socialpro FROM employee where employee_id = '$employee_id'";
      $result = mysqli_query($connection, $query);

      // check if we found any row of data

      if (mysqli_num_rows($result) > 0) {
        echo "<table>";
        echo "<tr><th style='width:200px;text-align:left'>Full Name</th> <th style='width:100px;text-align:left'>Company</th>  <th style='width:100px;text-align:left'>Email</th><th style='width:200px;text-align:left'>Phone</th><th style='width:200px;text-align:left'>Social Profile</th></tr>";
        while ($row = mysqli_fetch_array($result)) {
          echo "<tr><td>" . $row["fullname"] . "</td> <td>" . $row["company"] . "</td> <td>" . $row["email"] . "</td> <td>" . $row["phone"] . "</td> <td>" . $row["socialpro"] . "</td></tr>";
        }
        echo "</table>";
      } else {
        echo "there are no results from your search.";
      }

      mysqli_close($connection);
    }


    ?>

    <script>
      var saveBtn = document.getElementById("save-btn");
      saveBtn.addEventListener("click", function() {
        // Get the contact information from the website
        var contact = {
          name: "John Smith",
          phone: "555-555-5555",
          email: "[email protected]"
        };
        // create a vcard file
        var vcard = "BEGIN:VCARDnVERSION:4.0nFN:" + contact.name + "nTEL;TYPE=work,voice:" + contact.phone + "nEMAIL:" + contact.email + "nEND:VCARD";
        var blob = new Blob([vcard], {
          type: "text/vcard"
        });
        var url = URL.createObjectURL(blob);

        const newLink = document.createElement('a');
        newLink.download = contact.name + ".vcf";
        newLink.textContent = contact.name;
        newLink.href = url;

        newLink.click();
      });
    </script>

    </div>
  </section>
</body>

</html>

output

enter image description here

Player Webpage Project

Need help. I am currently making a webpage player for my subordinates. However, I can’t put them in GitHub and deploy it due to the audio/mp3 files are too large. Now I’m having problem on how I can incorporate or embed it from Google Drive or from YouTube to my page.

Here is my sample HTML code

    <div class="box" src="images/carpenters.mp4">
        <div class="image">
            <div class="play">
                <i class="fas fa-play"></i>
            </div>
            <img src="images/carpenters.jpg" alt="">
        </div>
        <div class="content">
            <h3>Best of Carpenters</h3>
        </div>
    </div>

and this is my script

let closePlayer = document.querySelector('#close-player');
let musicPlayer = document.querySelector('.music-player');
let boxContainer = document.querySelector('.container .box-container');

    closePlayer.onclick = () =>{
    closePlayer.classList.toggle('fa-times');
    musicPlayer.classList.toggle('active');
    boxContainer.classList.toggle('active');
}

let boxes = document.querySelectorAll('.container .box-container .box');

boxes.forEach(box =>{

    box.onclick = () =>{
        let src = box.getAttribute('src');
        let text = box.querySelector('.content h3').innerText;
        closePlayer.classList.add('fa-times');
        musicPlayer.classList.add('active');
        boxContainer.classList.add('active');
        musicPlayer.querySelector('h3').innerText = text;
        musicPlayer.querySelector('audio').src = src;
        musicPlayer.querySelector('audio').play();
    }

});

Get combine validation of Switch and Currency to show correct pricing

I am currently working on a pricing page which is getting very tricky. I am just a beginner in JS but getting through it. My task is to show the prices of a SAAS product on the pricing table. The trick is to show prices in different currencies and Annually/Quarterly. I wrote a code that takes the State of a Switch(Annually/Quarterly) and checks which Currency button is clicked. And it is working fine but it is not working in reverse. Toggling Switch does nothing because I am not getting a way to check which currency is clicked and what is the state of Switch or vice-versa at the same time. The code works fine until I interact with the switch.
I wrote the below code:

`//JS Starts
$(document).ready(function () {
$('#usdBtn').click(function()
{
var switchh = document.getElementById('mycheckbox');
    if (switchh.checked)
    {
        console.log("Switch is Checked");
      currMnUsd();
    } else{
      console.log("Switch is not Checked");
      currAnnUsd();
    }
});
  
  $('#eurBtn').click(function()
{
var switchh2 = document.getElementById('mycheckbox');
    if (switchh2.checked)
    {
        console.log("Switch is Checked");
      currMnEur();
    } else{
      console.log("Switch is not Checked");
      currAnnEur();
    }
});
  
    $('#gbpBtn').click(function()
{
var switchh3 = document.getElementById('mycheckbox');
    if (switchh3.checked)
    {
        console.log("Switch is Checked");
      currMnGbp();
    } else{
      console.log("Switch is not Checked");
      currAnnGbp();
    }
});

function currAnnUsd(){
  document.getElementById("start-price").textContent = "$20";
    document.getElementById("mid-price").textContent = "$30";
}
  
function currAnnEur(){
  document.getElementById("start-price").textContent = "Eur25";
    document.getElementById("mid-price").textContent = "Eur35";
}

function currAnnGbp(){
  document.getElementById("start-price").textContent = "40 GBP";
    document.getElementById("mid-price").textContent = "50 GBP";
}
  
function currMnUsd(){
  document.getElementById("start-price").textContent = "$25";
    document.getElementById("mid-price").textContent = "$40";
}
  
function currMnEur(){
  document.getElementById("start-price").textContent = "Eur30";
    document.getElementById("mid-price").textContent = "Eur40";
}

function currMnGbp(){
  document.getElementById("start-price").textContent = "45 GBP";
    document.getElementById("mid-price").textContent = "50 GBP";
}
  });
//JS Ends
`

I have added the HTML and CSS if that helps

<!-- HTML Starts -->
<label class="switch">
  <input id="mycheckbox" name="checkbox" type="checkbox">
  <span class="slider round"></span>
</label>
<button id="usdBtn">USD</button>
<button id="eurBtn">EUR</button>
<button id="gbpBtn">GBP</button>

<div id="start-price">$20</div>
<div id="mid-price">$30</div>
<!-- HTML Ends -->

/*CSS Starts*/
/* The switch - the box around the slider */
.switch {
  position: relative;
  display: inline-block;
  width: 60px;
  height: 34px;
}

/* Hide default HTML checkbox */
.switch input {
  opacity: 0;
  width: 0;
  height: 0;
}

/* The slider */
.slider {
  position: absolute;
  cursor: pointer;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: #ccc;
  -webkit-transition: .4s;
  transition: .4s;
}

.slider:before {
  position: absolute;
  content: "";
  height: 26px;
  width: 26px;
  left: 4px;
  bottom: 4px;
  background-color: white;
  -webkit-transition: .4s;
  transition: .4s;
}

input:checked + .slider {
  background-color: #2196F3;
}

input:focus + .slider {
  box-shadow: 0 0 1px #2196F3;
}

input:checked + .slider:before {
  -webkit-transform: translateX(26px);
  -ms-transform: translateX(26px);
  transform: translateX(26px);
}

/* Rounded sliders */
.slider.round {
  border-radius: 34px;
}

.slider.round:before {
  border-radius: 50%;
}
/*CSS Ends*/

As I mentioned I am not a pro but I learnt from StackOverflow. I tried adding eventListeners to the Switch but it is only working for one currency only.

how to map json data into object

Question – How can mapp json data into objects? json can be found here

Details – I was able to connect to api and get the json data. Now i want to map 2 array data.hourly.time[] & data.hourly.temperature_2m[] into 1 DataTable? I need datatable inorder to display json data into google charts api Below is a example of datable format that I am trying to create using 2 arrays from json data

javascript code

  $.ajax({
        url: FullURL,
        dataType: "JSON",
        success: function (data) {
            
            alert(data.hourly.time[1] + "_" + data.hourly.temperature_2m[1]);
            
            var data = new google.visualization.DataTable();
            data.addColumn('number', 'X');
            data.addColumn('number', 'Dogs');
            data.addRows([
                [0, 0], [1, 10], [2, 23], [3, 17], [4, 18], [5, 9],
                [6, 11], [7, 27], [8, 33], [9, 40], [10, 32], [11, 35],
                [12, 30], [13, 40], [14, 42], [15, 47], [16, 44], [17, 48],
                [18, 52], [19, 54], [20, 42], [21, 55], [22, 56], [23, 57],
                [24, 60], [25, 50], [26, 52], [27, 51], [28, 49], [29, 53]
            ]);

Unexpected behavior when dividing in JavaScript

I was trying to find the square roots of the following equation 3x^2 – 2x – 8 so I created these functions:

const delta = (a, b, c) => Math.sqrt(Math.pow(b, 2) - 4 * a * c);

function bhaskara(a, b = 0, c = 0) {
  if (delta(a, b, c) > -1) {
    let root = [2];

    console.log(`The discriminant is =${delta(a, b, c)}`) //10
    console.log(`The numerator is = ${-b + delta(a, b, c)}`) //12
    console.log(`The denominator is = ${2 * a}`) //6

    root[0] = (-b + delta(a, b, c)) / 2 * a;
    console.log(root[0])

    root[1] = (-b - delta(a, b, c)) / 2 * a;

    return root;
  } else {
    return "The discriminant is a negative number";
  }
}
let answer = bhaskara(3, -2, -8);
console.log(answer);

The answer:

[ 18, -12 ]

Why am I getting root[0] equal to 18 when I run the code if I’m clearly dividing the numerator (12) by 2 * a (2 * 3 = 6)? And, of course, why am I getting a -12 as well?

How do I set a state to a value in localStorage?

There is a button that toggles dark and light mode, and the state of what mode the page is on is saved in localStorage. However, I cannot change the initial value of the state (dark) and I don’t know why. This is done in a useEffect function but no matter what the value of dark is, it is always set to its initial value of false.

How do I set the value of the localStorage to the dark state?

function Mode() {
    const [dark, setDark] = useState(false);

    // localStorage.removeItem("dark");

    const onClick = () => {
        if (dark) {
            setDark(false);
            document.querySelector("body").classList.remove("dark");
        } else {
            setDark(true);
            document.querySelector("body").classList.add("dark");
        }
        localStorage.setItem("dark", dark);
    };

    const localDark = JSON.parse(localStorage.getItem("dark"));

    useEffect(() => {
        if (localDark !== null) {
            setDark(!JSON.parse(localStorage.getItem("dark"))); // this is what does not change the value of dark
            onClick();
        }
    }, []);

    return (
        <div onClick={onClick} className="mode">
            {dark ? <Light /> : <Dark />}
        </div>
    );
}

executeScript error in Vite React extension

I am having an issue with the executeScript function with using Vite React chrome extension tools with CRXJS

I am receiving the error message “Uncaught (in promise) Error: could not get url” when trying to use it.

The initial injection of the content.tsx file from the manifest.json is working fine, but the error is occurring when I call chrome.scripting.executeScript.

my manifest.json

{
  "manifest_version": 3,
  "name": "CRXJS React Vite Example",
  "version": "0.0.1",
  "action": { "default_popup": "index.html" },
  "content_scripts": [
    {
      "js": ["src/content.tsx"],
      "matches": ["*://*.github.com/*"]
    }
  ],
  "background": { "service_worker": "src/background.ts"},
  "permissions": ["webRequest", "webNavigation", "tabs", "activeTab", "scripting"],
  "host_permissions": ["<all_urls>"],
  "web_accessible_resources": [
    {
      "resources": ["src/assets/*"],
      "matches": ["https://*/*"]
    }
  ]
}

Here is my use of chrome.scripting in background.ts:

const inject = (tabId) => {
  chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
    if (tabs[0].url?.includes("some/search/string")) {
      const jsFiles = chrome.runtime.getManifest().content_scripts[0].js;
      chrome.scripting.executeScript({
          target: { tabId },
          files: jsFiles,
        })
        .then(() => {
          console.log("injected");
        });
    }
  });
};

I also tried with files: ["content.tsx"], or files: ["src/content.tsx"], but I received the error: “Uncaught (in promise) Error: Could not load file: ‘src/content.tsx'” on chrome dev tools

The only way to not have Could not load file error is to put the bundled file name taken from chrome.runtime.getManifest().content_scripts[0].js (“src/content.tsx-loader.js”)

How can I write a code in JS that deletes the existing output by disappearing it letter by letter, than writing the another one

Here’s the code i’ve written, where when i write a word into e search field, it appends it in the element “word” by displaying it letter by letter. But, the problem is, that i don’t know how to write the code that when i write another word in the search field, it deletes the word that appear to element “Word”, then writes the new one i’ve written.

let text = document.getElementById("txt");
let elem = document.getElementsByClassName("target")[0];
let word = elem.querySelector(".word");
let btn = document.getElementsByClassName("btn")[0];
let error = document.querySelector('#error');
i = 0;

        word.style.color = "#ffe100";
        btn.addEventListener("click", function init() { 
             if (text.value == "") {
                 error.style.opacity = '1.0';
             } else {
                 error.style.opacity = '0.0';
                 let save = word.textContent += text.value.charAt(i); 
                 i++;
             }
            if (i < text.value.length) {
                window.setTimeout(init, 100);
            }
        }); 
            

I’ve try many of alternatives, but there’s no result.

Getting elements by id or class in pure JS

I’m pretty new to JavaScript and I was wondering if there is a way to get elements from different websites and store them in array.

For example in Python with Selenium it would be something like this


arr = []

arr.append(driver.find_element(By.CLASS_NAME, "class_name_value")

Obiviusly not full code, just an example.

So i want to connect to some website, and grab all elements with same class, i wasn’t able to find anything on the internet.

Is there a way to select one question one after the other from an array of questions in JS

I’M building a quiz app using HTML, CSS and JS. I have all the questions as an object in an array, but issue is, I want to be able to display one question for the user to answer follow by the next question. and can’t that. I really really need help. I have been struggling for some days now.

var score = 0;
var maxQuestions = 0;

var questions = [
{ question: " javaScript is an....... language?",
    anwsers: [ "object-oriented", "object-based", "procedural", "none of the above"],
    correct: 1
    
},
{ question: "which of the following keywords is used a define variable in javaScript",
    anwsers: [ "var", "let", "both A and B", "none of the above"],
    correct: 2

  
}, 
{
    question: "which of the following methods is used to HTML elements using javaScript",
    anwsers: ["getElementsById", "getElementByClassName", "both A and B", "none of the above"] ,
    correct: 1
    
}
];

function showQuestion(questions){
    let ques = document.getElementById('questions');
    let qDiv = document.createElement('div');
    let p = document.createElement('p');
    p.textContent = questions[2]['question'];
    ques.appendChild(qDiv);
    qDiv.appendChild(p);

    let atl = document.querySelectorAll('.alts');
    atl.forEach(function(element, index){
        element.textContent = questions[2].anwsers[index];
        nextQuestion();

        element.addEventListener('click', function() {
            if(questions[2].correct === index) {
                console.log('correct answer');
            } else {
                console.log('wrong answer');
            }
        })
    })  
};

showQuestion(questions);
var btn = document.getElementById('btn');
btn.addEventListener('click', function() {
    console.log('clicked');
});

function nextQuestion() {
    if (maxQuestions !== questions.length) {
        
    }
}

Unwanted tiling effect in HTML5 canvas when zooming

I’m using html5 canvas to manipulate individual pixels. The canvas is zoomable and draggable, and each pixel is a rectangle, basically I do the following:

 pixels.forEach(p => {
     context.fillStyle = p.color;
     context.fillRect(toScreenX(p.x), toScreenY(p.y), 1*scale, 1*scale);
 });

where toScreenX and toScreenY determine the position of the rectangle based on the position of the pixel and the actual scale and offset.

When the zoom scale is 1, everything is okay as shown on picture below:

no zooming

However, when I start to zoom in, thin white lines start to appear between pixels, and the picture gets distorted as shown in the two figure below:
enter image description here

Here’s a short video about the effect: https://imgur.com/a/dvEaZIy
I also tried to use context.putImageData instead of fillRect but for individual pixels, it gets terribly slow.

Layered elements with oncontextmenu bindings

Repro: https://jsfiddle.net/ssabc/cL6qxn1r/13/

I have a background element and a foreground element (you can think of it as a dialog popup on top of a canvas). When the user right-clicks on the foreground I would like to prevent the context menu from appearing in the background.

I tried binding a handler for the foreground’s context menu and returning false from it to no avail:

document.getElementById('above').oncontextmenu = function(e) {
    e.preventDefault();
    return false;
}

As you can see in the JSFiddle, the oncontextmenu-event triggers on both elements. Here’s a screenshot showing event firing in the background no matter which element is right-clicked

Is there any way to prevent the background event from firing?

Changing the style of an element after it is appended doesn’t trigger transition from the style that it was appended with

Reproducing this took me a night, this is the most tidy version I could came up
with.

Its pretty easy to explain the behaviour:

  1. to change the flow, an element in the DOM is appended to a different location
  2. positioning it isn’t based on the flow, so the style is changed after too

No problem with it. Check the demo. For a naked eye:
swap – changes numbers in right.
append – matches numbers in left with numbers in right.
positions – sorts elements by the numbers with animation
swap_append_positions – does the 3 above but instant (the problem)
swap_append_positions_timeout – does the 3 above normally (dirty fix)

couldn’t make a runnable snippet, there wasn’t the button so, here’s the fiddle. would be great if someone could edit this question

$.swap_append_positions.onclick = e => {
    $.swap.click()
    $.append.click()
    $.positions.click() // doesn't work
}

$.swap_append_positions_timeout.onclick = e => {
    $.swap.click()
    $.append.click()
    setTimeout(() => $.positions.click(), 4) // works
}

  • Letter in blue represent the actual element.
  • Number in the right (innerText) is the index in the array.
  • Number in the left is the index for ol which represents the child’s index in flow.

The 3 steps

  • swap – takes the first element in the array and moves it to the end
    (also reflects the index in the innerText)
  • append – appends and reorganizes the elements in the order in the array.
  • positions – fixes the positions to match the flow.

This 3 steps is what I needed. Indeed, they work when you press them one-by-one.

But lets press these 3 at once

  • swap_append_positions – presses swap append
    positions synchronously.
  • swap_append_positions_timeout – presses swap append
    synchronously and then schedules setTimeout for positions.

Weirdly, swap_append_positions doesn’t work. Intuitively, to me it’s like

when you append and change the style in the “same cycle” there’s no chance to
“render” the element with the old styles as the “cycle” hasn’t ended yet, so it
be like waiting to be rendered. but before it is rendered with the old style,
we set a new style. so it will be rendered like it’s appended with a new style
and there was no “previous” style for this element to do a transition from.

in short, old state was ignored because I appended it. Don’t get me wrong, I’m
not changing anything, just re-appending it. Only after it, I update to new
state. But it ignores the old.

The solution I want

I had no idea why was the transition wasn’t working and didn’t expected that
doing it synchronously would be the problem but somehow I figured it out.
Now I have no idea how to make it work.
I need the properties to be set before the swap_append_positions_timeout is
returned. It’s like an “update” function for my project.
Don’t tell me the ways to get around this nor offer logic to work asynchronously.

I just need to append with the old styles and set the new styles synchronously
which would do a transition from old to new. Obviously, that’s not the case.

So if you have something to explain this behaviour than my fool’s assumption, I’d
like to hear please. If you have a solution, that’d be great. Else, thanks for the
effort that you have read till there.

Thank you all in advance.