Server side rendering – vite + reactjs + express

I am trying to server side render my vite + react application. I followed vite documentation to create the server and now everything seems to run correctly. I am new to server side rendering so I have some doubts. When i see my page source when the app initially renders, it is showing the correct page source as expected. But if I interacts with my app and loads another view, the page source is not updated. Is this the normal behaviour, or is there anything i can do to get the updated page source whenever I change my view from the client side.

This is my server.js

import fs from "node:fs/promises";
import express from "express";

global.window = {};

// Constants
const isProduction = process.env.NODE_ENV === "production";
const port = process.env.PORT || 5173;
const base = process.env.BASE || "/";

// Cached production assets
const templateHtml = isProduction
  ? await fs.readFile("./dist/client/index.html", "utf-8")
  : "";
const ssrManifest = isProduction
  ? await fs.readFile("./dist/client/.vite/ssr-manifest.json", "utf-8")
  : undefined;

// Create http server
const app = express();

// Add Vite or respective production middlewares
let vite;
if (!isProduction) {
  const { createServer } = await import("vite");
  vite = await createServer({
    server: { middlewareMode: true },
    appType: "custom",
    base,
  });
  app.use(vite.middlewares);
} else {
  const compression = (await import("compression")).default;
  const sirv = (await import("sirv")).default;
  app.use(compression());
  app.use(base, sirv("./dist/client", { extensions: [] }));
}

// Serve HTML
app.use("*", async (req, res) => {
  try {
    const url = req.originalUrl.replace(base, "");

    let template;
    let render;
    if (!isProduction) {
      // Always read fresh template in development
      template = await fs.readFile("./index.html", "utf-8");
      template = await vite.transformIndexHtml(url, template);
      render = (await vite.ssrLoadModule("/src/entry-server.tsx")).render;
    } else {
      template = templateHtml;
      render = (await import("./dist/server/entry-server.js")).render;
    }

    const rendered = await render(url, ssrManifest);

    const html = template
      .replace(`<!--app-head-->`, rendered.head ?? "")
      .replace(`<!--app-html-->`, rendered.html ?? "");

    res.status(200).set({ "Content-Type": "text/html" }).end(html);
  } catch (e) {
    vite?.ssrFixStacktrace(e);
    console.log(e.stack);
    res.status(500).end(e.stack);
  }
});

// Start http server
app.listen(port, () => {
  console.log(`Server started at http://localhost:${port}`);
});

My vite.config is as follows

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import viteTsconfigPaths from "vite-tsconfig-paths";
// import macrosPlugin from 'vite-plugin-babel-macros'
import svgrPlugin from "vite-plugin-svgr";
// import path from 'path'
import { splitVendorChunkPlugin } from "vite";

// https://vitejs.dev/config/
// How to migrate from CRA to vite: https://cathalmacdonnacha.com/migrating-from-create-react-app-cra-to-vite

import dns from "dns";

dns.setDefaultResultOrder("verbatim");

export default defineConfig({
  define: {
    "process.env": {},
  },
  resolve: {
    alias: [
      {
        find: "stream",
        replacement: `stream-browserify`,
      },
    ],
  },
  plugins: [
    react({
      babel: {
        presets: ["@babel/preset-typescript"],
        plugins: [
          "@babel/plugin-transform-typescript",
          [
            "babel-plugin-styled-components",
            {
              ssr: false,
              pure: true,
              displayName: true,
              fileName: false,
              minify: false,
              transpileTemplateLiterals: false,
            },
          ],
        ],
      },
    }),
    viteTsconfigPaths(),
    svgrPlugin(),
    splitVendorChunkPlugin(),
  ],
  build: {
    outDir: "build",
    cssCodeSplit: false,
  },
  ssr: {
    noExternal: ["styled-components", "@emotion/*"],
    // noExternal: [],
  },
  server: {
    open: true,
    port: 5173,
  },
  preview: {
    port: 8000,
  },
});

My entry-client.tsx

import React from "react";
import { Provider } from "react-redux";
import { store } from "@store/index";
import ReactDOM from "react-dom/client";
import App from "./App";

ReactDOM.hydrateRoot(
  document.getElementById("root") as HTMLElement,
  <Provider store={store}>
    <App />
  </Provider>
);

My entry-server.tsx

import React from "react";
import ReactDOMServer from "react-dom/server";
import { Provider } from "react-redux";
import { store } from "@store/index";
import App from "./App";

export function render() {
  const html = ReactDOMServer.renderToString(
    <Provider store={store}>
      <App />
    </Provider>
  );
  return { html };
}

Can not use Playwright to login on JS?

const { test, expect } = require('@playwright/test');
test.only('Login 1', async ({ page }) => {
  await page.goto('my login page');
  await page.fill('input[name="userId"]', 'my userId');
  await page.fill('input[name="password"]', 'my password');
  await page.locator('#idPasswordInputForm a.input_area_btn_01').click({timeout: 30000});
})

I use above code to test login on my page automatically. However, after it runs to this line: await page.locator('#idPasswordInputForm a.input_area_btn_01').click({timeout: 30000}); on debug mode, It stuck on this step: waiting for scheduled navigations to finish.

Login on my page still works fine if I login manually.

Have I mistake something and how to fix it?

NextJS – Not able to get cookie in route.ts

I am using NextJS App Router.
When I try to get token from cookies in my api route, it returns nothing.

/app/api/profile/route.ts

import { NextResponse } from "next/server";
import { cookies } from "next/headers";

const getCookie = async (name: string) => {
 return cookies().get(name)?.value ?? "";
};

export async function GET(request) {
 const token = await getCookie("accessToken");  
 console.log(token); // I can't log the token here
 return NextResponse.json(user.data, { status: 200 });
}

layout.tsx

const test123 = await fetch("http://localhost:3000/api/profile");

However, when I do the same in layout.ts, it works.

layout.tsx

...
import { cookies } from "next/headers";

const getCookie = async (name: string) => {
 return cookies().get(name)?.value ?? "";
};

export default async function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
 const token = await getCookie("accessToken");
 console.log(token) // I can successfully log the token here!

 return (
   ...
  );
}

How to fix it?

Update 1
I set the cookies from my NestJS backend when it sends the response to my NextJS frontend, if that matters

  async login(@Body() loginDto: LoginDto, @Response() res: ExpressResponse) {
    const loginRes = await this.authService.login(loginDto.token);

    res.cookie('accessToken', loginRes?.accessToken, {
      expires: new Date(new Date().getTime() + 1 * 60 * 60 * 1000), // 1 hr
      sameSite: 'strict',
      httpOnly: true,
    });

    return res.send(loginRes);
  }

” Is causing undefined errors in my project

Yes, I do know that is an escape character. I am writing a code for a keyboard, and I have to have the key , of course. Now, the problem is, that this key must have a data attribute, which I put as \. Then, when the keys are updated, the JS changed the value to undefined, and everything goes downhill from there. Here is my code:

<html>
  <head>
    <style>
      /* Style the keyboard container */
      #keyboard {
        display: flex;
        flex-wrap: wrap;
        justify-content: center;
        align-items: center;
        margin: 20px auto;
        width: 80%;
        max-width: 800px;
        border: 2px solid #ccc;
        border-radius: 10px;
        padding: 10px;
      }

      /* Style the keyboard keys */
      kbd {
        display: inline-flex;
        justify-content: center;
        align-items: center;
        margin: 5px;
        width: 40px;
        height: 40px;
        border: 1px solid #ccc;
        border-radius: 5px;
        box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
        background-color: #fff;
        font-family: Arial, sans-serif;
        font-size: 18px;
        font-weight: bold;
        color: #333;
        cursor: pointer;
      }

      /* Style the special keys */
      kbd[data-key="tab"],
      kbd[data-key="enter"] {
        width: 80px;
      }

      kbd[data-key="caps"],
      kbd[data-key="backspace"] {
        width: 100px;
      }

      kbd[data-key="shift"] {
        width: 120px;
      }

      kbd[data-key="space"] {
        width: 240px;
      }

      /* Style the active keys */
      kbd.active {
        background-color: #ccc;
      }

      /* Style the output text area */
      #output {
        display: block;
        margin: 20px auto;
        width: 80%;
        max-width: 800px;
        height: 100px;
        border: 2px solid #ccc;
        border-radius: 10px;
        padding: 10px;
        font-family: Arial, sans-serif;
        font-size: 18px;
        color: #333;
        resize: none;
      }
    </style>
  </head>
  <body>
    <!-- Create the keyboard container -->
    <div id="keyboard">
      <!-- Create the keyboard keys -->
      <kbd data-key="`">`</kbd>
      <kbd data-key="1">1</kbd>
      <kbd data-key="2">2</kbd>
      <kbd data-key="3">3</kbd>
      <kbd data-key="4">4</kbd>
      <kbd data-key="5">5</kbd>
      <kbd data-key="6">6</kbd>
      <kbd data-key="7">7</kbd>
      <kbd data-key="8">8</kbd>
      <kbd data-key="9">9</kbd>
      <kbd data-key="0">0</kbd>
      <kbd data-key="-">-</kbd>
      <kbd data-key="+">+</kbd>
      <kbd data-key="backspace" data-exclude="true">Backspace</kbd>
      <kbd data-key="tab" data-exclude="true">Tab</kbd>
      <kbd data-key="q">q</kbd>
      <kbd data-key="w">w</kbd>
      <kbd data-key="e">e</kbd>
      <kbd data-key="r">r</kbd>
      <kbd data-key="t">t</kbd>
      <kbd data-key="y">y</kbd>
      <kbd data-key="u">u</kbd>
      <kbd data-key="i">i</kbd>
      <kbd data-key="o">o</kbd>
      <kbd data-key="p">p</kbd>
      <kbd data-key="[">[</kbd>
      <kbd data-key="]">]</kbd>
      <kbd data-key="\"></kbd>
      <kbd data-key="caps" data-exclude="true">Caps Lock</kbd>
      <kbd data-key="a">a</kbd>
      <kbd data-key="s">s</kbd>
      <kbd data-key="d">d</kbd>
      <kbd data-key="f">f</kbd>
      <kbd data-key="g">g</kbd>
      <kbd data-key="h">h</kbd>
      <kbd data-key="j">j</kbd>
      <kbd data-key="k">k</kbd>
      <kbd data-key="l">l</kbd>
      <kbd data-key=";">;</kbd>
      <kbd data-key="'">'</kbd>
      <kbd data-key="enter" data-exclude="true">Enter</kbd>
      <kbd data-key="shift" data-exclude="true">Shift</kbd>
      <kbd data-key="z">z</kbd>
      <kbd data-key="x">x</kbd>
      <kbd data-key="c">c</kbd>
      <kbd data-key="v">v</kbd>
      <kbd data-key="b">b</kbd>
      <kbd data-key="n">n</kbd>
      <kbd data-key="m">m</kbd>
      <kbd data-key=",">,</kbd>
      <kbd data-key=".">.</kbd>
      <kbd data-key="/">/</kbd>
      <kbd data-key="shift" data-exclude="true">Shift</kbd>
      <kbd data-key="space" data-exclude="true">Space</kbd>
    </div>
    <!-- Create the output text area -->
    <textarea id="output" placeholder="Type something..."></textarea>
  </body>
  <!-- Add the JavaScript code -->
  <script>
    // Get the keyboard container element
    const keyboard = document.getElementById("keyboard");

    // Get the output text area element
    const output = document.getElementById("output");

    // Get all the keyboard keys elements
    const keys = keyboard.querySelectorAll("kbd");

    // Define a variable to store the shift key state
    let shift = false;

    // Define a variable to store the caps lock key state
    let caps = false;

    // Loop through the keys and add event listeners
    for (let key of keys) {
      // Get the data-key attribute value
      let dataKey = key.getAttribute("data-key");

      // Add a click event listener
      key.addEventListener("click", function () {
        // Check which key was clicked
        switch (dataKey) {
          // If backspace, delete the last character
          case "backspace":
            output.value = output.value.slice(0, -1);
            break;
          // If tab, insert a tab character
          case "tab":
            output.value += "t";
            break;
          // If enter, insert a newline character
          case "enter":
            output.value += "n";
            break;
          // If shift, toggle the shift key state
          case "shift":
            shift = !shift;
            key.classList.toggle("active");
            break;
          // If caps, toggle the caps lock key state
          case "caps":
            caps = !caps;
            key.classList.toggle("active");
            break;
          // If space, insert a space character
          case "space":
            output.value += " ";
            break;
          // Otherwise, insert the key value
          default:
            // Check if shift or caps are active
            if (shift || caps) {
              // Insert the uppercase key value
              output.value += dataKey.toUpperCase();
            } else {
              // Insert the lowercase key value
              output.value += dataKey.toLowerCase();
            }
            // If shift is active, deactivate it
            if (shift) {
              shift = false;
              keyboard
                .querySelector('kbd[data-key="shift"]')
                .classList.remove("active");
            }
        }
      });
    }

    // Define an object to store the key values for each mode
    const keyValues = {
      normal: {
        "`": "`",
        1: "1",
        2: "2",
        3: "3",
        4: "4",
        5: "5",
        6: "6",
        7: "7",
        8: "8",
        9: "9",
        0: "0",
        "-": "-",
        "+": "+",
        q: "q",
        w: "w",
        e: "e",
        r: "r",
        t: "t",
        y: "y",
        u: "u",
        i: "i",
        o: "o",
        p: "p",
        "[": "[",
        "]": "]",
        "\": "\",
        a: "a",
        s: "s",
        d: "d",
        f: "f",
        g: "g",
        h: "h",
        j: "j",
        k: "k",
        l: "l",
        ";": ";",
        "'": "'",
        z: "z",
        x: "x",
        c: "c",
        v: "v",
        b: "b",
        n: "n",
        m: "m",
        ",": ",",
        ".": ".",
        "/": "/",
      },
      shift: {
        "`": "~",
        1: "!",
        2: "@",
        3: "#",
        4: "$",
        5: "%",
        6: "^",
        7: "&",
        8: "*",
        9: "(",
        0: ")",
        "-": "_",
        "+": "=",
        q: "Q",
        w: "W",
        e: "E",
        r: "R",
        t: "T",
        y: "Y",
        u: "U",
        i: "I",
        o: "O",
        p: "P",
        "[": "{",
        "]": "}",
        "\": "|",
        a: "A",
        s: "S",
        d: "D",
        f: "F",
        g: "G",
        h: "H",
        j: "J",
        k: "K",
        l: "L",
        ";": ":",
        "'": '"',
        z: "Z",
        x: "X",
        c: "C",
        v: "V",
        b: "B",
        n: "N",
        m: "M",
        ",": "<",
        ".": ">",
        "/": "?",
      },
      caps: {
        "`": "`",
        1: "1",
        2: "2",
        3: "3",
        4: "4",
        5: "5",
        6: "6",
        7: "7",
        8: "8",
        9: "9",
        0: "0",
        "-": "-",
        "+": "+",
        q: "Q",
        w: "W",
        e: "E",
        r: "R",
        t: "T",
        y: "Y",
        u: "U",
        i: "I",
        o: "O",
        p: "P",
        "[": "[",
        "]": "]",
        "\": "\",
        a: "A",
        s: "S",
        d: "D",
        f: "F",
        g: "G",
        h: "H",
        j: "J",
        k: "K",
        l: "L",
        ";": ";",
        "'": "'",
        z: "Z",
        x: "X",
        c: "C",
        v: "V",
        b: "B",
        n: "N",
        m: "M",
        ",": ",",
        ".": ".",
        "/": "/",
      },
    };

    // Define a function to update the key values
    function updateKeys() {
      // Loop through the keys
      for (let key of keys) {
        // Check the data-exclude attribute
        let exclude = key.getAttribute("data-exclude");
        if (exclude) {
          // Skip the key
          continue;
        }
        // Get the data-key attribute value
        let dataKey = key.getAttribute("data-key");
        // Check which mode is active
        if (shift) {
          // Set the key value to the shift mode value
          key.textContent = keyValues.shift[dataKey];
          key.dataset.key = keyValues.shift[dataKey];
        } else if (caps) {
          // Set the key value to the caps mode value
          key.textContent = keyValues.caps[dataKey];
          key.dataset.key = keyValues.caps[dataKey];
        } else {
          // Set the key value to the normal mode value
          key.textContent = keyValues.normal[dataKey];
          key.dataset.key = keyValues.normal[dataKey];
        }
      }
    }

    // Call the updateKeys function initially
    updateKeys();

    // Add a click event listener to the shift key
    keyboard
      .querySelector('kbd[data-key="shift"]')
      .addEventListener("click", function () {
        // Update the key values after toggling the shift mode
        updateKeys();
      });

    // Add a click event listener to all the keys besides the shift key, so that after one is pressed, shift is turned off
    for (let key of keys) {
      if (key !== keyboard.querySelector('kbd[data-key="shift"]')) {
        key.addEventListener("click", function () {
          shift = false;
          keyboard
            .querySelector('kbd[data-key="shift"]')
            .classList.remove("active");
          updateKeys();
        });
      }
    }

    // Add a click event listener to the caps lock key
    keyboard
      .querySelector('kbd[data-key="caps"]')
      .addEventListener("click", function () {
        // Update the key values after toggling the caps lock mode
        updateKeys();
      });
  </script>
</html>

https://jsfiddle.net/oxmzsrqe/

I tried several things, amoung which were:

  • Using one escape character ().
  • Using multiple escape characters (\\).
  • Using HTML entities (&#92; and others)
  • Changing my JS code to handle undefined, convert data to a string, and many other things.

Is there a way to make an application that runs in a nodejs terminal?

I want to create a node.js application than runs entirely in an external terminal, similar to C#. I want to be able to type in the application with responses. I have not been able to find an answer that looks like what I want to do.

For C#, there is a dedicated type of application called “Console Application”, and I wanted to know if there is a way to do the same in node.

Is there a way to generate a dynamic average line on my line chart?

I would like to generate a dynamic average line on my line chart. The line that is being generated is however not a straight line which means there is a problem in my code.

My chart looks like this:

chart

I used the following code to generate my chart:

I would like to get the average of $tit.

function drawChart() {
      var data = google.visualization.arrayToDataTable([
        ['id', 'TIT', 'AVERAGE'],
        <?php
        $query = "select * from engine2";
        $res = mysqli_query($conn, $query);
        while ($data = mysqli_fetch_array($res)) {
          $id = $data["id"];
          $tit = $data["tit1"];
          
          $tit_array[] = $tit; 
          $avg = array_sum($tit_array) / count($tit_array); //this is the average i want to use
          
        ?>
          ['<?php echo $id; ?>', <?php echo $tit; ?>,<?php echo $avg; ?>],
        
        <?php 
      } 
      ?>
      ]);

      var options = {
        title: 'T5',
        // curveType: 'function',
        legend: {
          position: 'bottom'
        }
      };

      var chart = new google.visualization.LineChart(document.getElementById('curve_chart3'));

      chart.draw(data, options);
    }
  </script>

GPU JS loop works incorrect

I wrote this JS for CPU before which works correcly. Now need to do it over GPU; but inner loop doesnt work correctly; result canvas always in grays, why?

const dist = 4
const target = document.getElementById("target")
const gpu = new GPU()
const conv = function (cnv,dist,w,h) {
    const px = this.thread.x
    const py = this.thread.y
    var pixel = cnv[py][px]
    var pixel1 = cnv[py][px]
    var score = -1
    for (var cy=-dist; cy <= dist; cy++) {
        for (var cx=-dist; cx <= dist; cx++) {
            const x = px+cx
            const y = py+cy
            if (x >= 0 && x < w && y >= 0 && y < h) {
                var pixel2 = cnv[py][px]
                const error = Math.sqrt(
                    Math.pow((pixel1[0]*255)-(pixel2[0]*255),2)+
                    Math.pow((pixel1[1]*255)-(pixel2[1]*255),2)+
                    Math.pow((pixel1[2]*255)-(pixel2[2]*255),2))
                if (score < error) {
                    score = error
                    pixel= pixel2
                }
            }
        }
    }
    this.color(
        ((pixel[0]*255)-(pixel1[0]*255)+128)/255,
        ((pixel[1]*255)-(pixel1[1]*255)+128)/255,
        ((pixel[2]*255)-(pixel1[2]*255)+128)/255
    )
}
const kernel = gpu.createKernel(conv)
    .setConstants({ width: target.width, height: target.height })
    .setGraphical( true )
    .setOutput([ target.width, target.height ])
kernel(target,dist,target.width,target.height)
document.body.appendChild(kernel.canvas)

How to sort order multiple columns using antd Table?

I want to display the active sort button on 2 columns of the antd Table. When I click on the “Sort Users” option, the sort button of the “Books” column becomes deactivated.
This is column of table

    {
      title: "Book",
      dataIndex: "books",
      sorter: true,
      sortDirections: ["descend"],
    },
    {
      title: "User",
      dataIndex: "user",
      sorter: true,
      sortDirections: ["descend"],
    }

enter image description here

How can I display both “Sort Books” and “Sort Users” buttons in an active state at the same time?

How to make theme more darker while opening pop-up

Recently, I’ve created pop-up on my portfolio website. And then, I’m using Bootstrap class to make own website more easier. So, I want to make back object more darker to make the pop-up object more pronounced, while opening pop-up. But some back object doesn’t turn into darker theme. Please refer to below URL to know my problem precisely.

My portfolio website

I tried:

  • Assign same id to the objects that I want to make more darker, and then, make it more
    darker while opening the pop-up
const theme = ['theme-change1', 'theme-change2', 'theme-change3', 'theme-change4', 'theme-change5', 'theme-change6', 'theme-change7', 'theme-change8', 'theme-change9',];

function showPopUp() {
  document.getElementById('pop-up').style.display = "block";
  document.body.style.backgroundColor = "rgba(0, 0, 0, .5)";
  document.getElementById('class-remover').classList.remove('bg-light'); 
  for(let i = 0; i < theme.length; i++){
    document.getElementById(theme[i]).style.backgroundColor = "rgba(0, 0, 0, .5)";
  }
}

function hidePopUp() {
  document.getElementById('pop-up').style.display = "none";
  document.body.style.backgroundColor = "white"; 
  document.getElementById('class-remover').classList.add('bg-light');
   for(let i = 0; i < theme.length; i++){
    document.getElementById(theme[i]).style.backgroundColor = "white";
  }
}      

And my current code is below.

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fi=no">
  <title>HirotoTakao - About</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
  <link rel="stylesheet" href="./my-portfolio.css">
  <script src="./my-portfolio.js"></script>
</head>
<body>
  <div class="pop-up-div" id="pop-up">
    <section class="main-pop-up">
      <video src="../underwater-motion.mp4" height="100%" width="100%" controls></video>
    </section>
    <footer class="footer-pop-up">
       <button onclick="hidePopUp()" class="btn btn-primary">Exit</button>
    </footer>
  </div>
  <div class="main-page">
    <nav class="navbar navbar-expand-lg navbar-light bg-light" id="class-remover">
      <a class="navbar-brand" href="#">HirotoTakao</a>
      <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>
      <div class="collapse navbar-collapse" id="navbarSupportedContent">
        <ul class="mr-auto"></ul>
        <ul class="navbar-nav pull-right">
          <li class="nav-item active">
            <a class="nav-link" href="#">About<span class="sr-only">(current)</span></a>
          </li>
          <li class="nav-item active">
            <a class="nav-link" href="../contact/contact.html">Contact</a>
          </li>
        </ul>
      </div>
    </nav>
      <div class="card card-margin">
        <div class="card-header header-font" id="theme-change5"> 
          Hobby
        </div>
        <ul class="list-group list-group-flush">
          <li class="list-group-item" id="theme-change1">Programming</li>
          <li class="list-group-item" id="theme-change2">Collecting snappy-on tags<br>
          <img src="../snapy-on tag.jpg" class="snappy-on-tag" alt="">
          </li>
        </ul>
        </div>    
  
  <div class="card card-margin" style="width: 100%;">
    <div class="card-header header-font" id="theme-change3">
      Skills
   </div>
   <ul class="list-group list-group-flush">
       <div class="list-group-item" style="border:solid 1px white;" id="theme-change3">
          <table>
            <tr>
              <th>Language</th>
              <td>HTML, CSS, Javascript</td>
            </tr>
            <tr>
              <th>Engines, Frameworks, Libraries</th>
              <td>Node.js, Express.js, JQuery</td>
            </tr>
            <tr>
              <th>Tools, OS</th>
              <td>Linux, Windows, Bootstrap, MySQL, PostgreSQL, Git</td>
            </tr>
          </table>   
       </div>
  </div>
      <div class="card-margin" style="width:100%; border:solid 1px rgba(0,0,0,.125); border-radius:.25rem;">
        <div class="card-header header-font">
          Favorite something
        </div>
        <ul class="list-group list-group-flush" id="theme-change4">
          <li class="list-group-item">
            <span>Favorite Youtube: <a href="https://www.youtube.com/@zelihaakpinar/videos" class="link-adjustment">Zeliha Akpinar</a></span>
            <br><span>Favorite Character: <a href="https://gup.fandom.com/wiki/Anchovy" class="link-adjustment">Anchovy</a></span>
          </li>
        </ul>
      </div>
      <div style="margin-bottom:50px;">
        <h1 class="display-4 text-center" style="margin-bottom:32px;">My Works</h1>
        <div style="display:flex;">
          <div class="card" style="width: 18rem; margin-right:13px;" id="theme-change6">
            <a href="https://openprocessing.org/sketch/2158648"><img class="card-img-top" src="../underwater-motion.png" alt="Card image cap"></a>
            <div class="card-body" id="theme-change7">
              <h5 class="card-title">Underwater-Motion(p5.js)</h5>
              <p class="card-text">none</p>
              <button class="btn btn-primary" onclick="showPopUp()">Play Demo Video</button>
            </div>
          </div>
          <div class="card" style="width: 18rem;" id="theme-changer8">
            <a href="https://github.com/hirototakao/meaning-teller"><img class="card-img-top" src="../Slack_logo_new.png" alt="Card image cap"></a>
            <div class="card-body" id="theme-changer9">
              <h5 class="card-title" style="margin-top:13px;">Meaning-teller(Slack API)</h5>
              <p class="card-text">none</p>
              <a href="https://github.com/hirototakao/meaning-teller" class="btn btn-primary">View code</a>
            </div>
          </div>
        </div>
      </div>
  </div>
</body>
</html>

Javascript:


function showPopUp() {
  document.getElementById('pop-up').style.display = "block";
  document.body.style.backgroundColor = "rgba(0, 0, 0, .5)";
  document.getElementById('class-remover').classList.remove('bg-light'); 
  document.getElementById('theme-change1').style.backgroundColor = "rgba(0, 0, 0, .5)";
  document.getElementById('theme-change2').style.backgroundColor = "rgba(0, 0, 0, .5)";
  document.getElementById('theme-change3').style.backgroundColor = "rgba(0, 0, 0, .5)";
  document.getElementById('theme-change4').style.backgroundColor = "rgba(0, 0, 0, .5)";
  document.getElementById('theme-change5').style.backgroundColor = "rgba(0, 0, 0, .5)";
  document.getElementById('theme-change6').style.backgroundColor = "rgba(0, 0, 0, .5)";
  document.getElementById('theme-change7').style.backgroundColor = "rgba(0, 0, 0, .5)";
  document.getElementById('theme-change8').style.backgroundColor = "rgba(0, 0, 0, .5)";
  document.getElementById('theme-change9').style.backgroundColor = "rgba(0, 0, 0, .5)";
}

function hidePopUp() {
  document.getElementById('pop-up').style.display = "none";
  document.body.style.backgroundColor = "white"; 
  document.getElementById('class-remover').classList.add('bg-light');
  document.getElementById('theme-change1').style.backgroundColor = "white";
  document.getElementById('theme-change2').style.backgroundColor = "white";
  document.getElementById('theme-change3').style.backgroundColor = "white";
  document.getElementById('theme-change4').style.backgroundColor = "white";
  document.getElementById('theme-change5').style.backgroundColor = "white";
  document.getElementById('theme-change6').style.backgroundColor = "white";
  document.getElementById('theme-change7').style.backgroundColor = "white";
  document.getElementById('theme-change8').style.backgroundColor = "white";
  document.getElementById('theme-change9').style.backgroundColor = "white";
}

How do you append to an object array by searching a different array for a object and returning a different object in javascript?

Similar to a vlookup in excel. I have 2 object arrays in javascript. I want to look up an object from array #1 in array #2 and push an object from array #2 to the array #1. I want this to happen for each value in array #1. This way I can have a single array with all of the information I want in one place.

for example,

    let array1 = [
        {"first":"Ana","last":"Anderson","id":"0001"},
        {"first":"Bob","last":"Brown","id":"0002"},
        {"first":"Charlie","last":"Clark","id":"0003"},
        {"first":"Danielle","last":"Dunn","id":"0004"}
    ]

    let array2 = [
        {"age":"38","id":"0002","eyeColor":"hazel","hieght":"5.5"},
        {"age":"45","id":"0001","eyeColor":"brown","hieght":"5"},
        {"age":"23","id":"0003","eyeColor":"blue","hieght":"6"}
    ]

How do I make an array that would display the following?
I have been trying a for loop with indexof and push

let array3 = [
        {"first":"Ana","last":"Anderson","id":"0001","age":"45","eyeColor":"brown","hieght":"5"},
        {"first":"Bob","last":"Brown","id":"0002","age":"38","eyeColor":"hazel","hieght":"5.5"},
        {"first":"Charlie","last":"Clark","id":"0003","age":"23","eyeColor":"blue","hieght":"6"},
        {"first":"Danielle","last":"Dunn","id":"0004","age":"","eyeColor":"","hieght":""}
    ]

Highlight text without JQuery

I’m not good at JavaScript and I found a snippet in order to highlight text using JQuery Color. It conflicts with Lightbox2 and I want to convert the snippet to JavaScript. Here’s my code:

function highlight(elemId){
  var elem = $(elemId);
  elem.css("backgroundColor", "#ffffff"); // hack for Safari
  elem.animate({ backgroundColor: '#ffffaa' }, 0);
  setTimeout(function(){$(elemId).animate({ backgroundColor: "#ffffff" }, 3000)},1000);
}

if (document.location.hash) {
  highlight(document.location.hash);
}
$('a[href*="#"]').click(function() {
  var elemId = '#' + $(this).attr('href').split('#')[1];
  requestAnimationFrame(highlight(elemId));
});

How can I convert the code from JQuery to JavaScript?

Using RxJS fromEvent and @ViewChild vs keyup event and RxJS Subject for input field value changes

I have a simple component that performs a search using the values typed into a Search box. I found two different ways to code this and they both work.

Method 1 uses fromEvent from RxJS and sets up an observable to capture input field value changes using the @ViewChild reference to the input element.

Method 2 captures the input field value changes using the keyup event and feeds the new value to an RxJS Subject.

Most of the examples I found on Stackoverflow and other sites use @ViewChild for this type of scenario. Is there any reason to use one method over the other or is it a matter of personal choice?

METHOD 1

app.component.html

<input type="text" #search placeholder="Search" />
<li *ngFor="let state of states$ | async">
  {{ state.text }}
</li>

app.component.ts

export class AppComponent implements OnInit {
  @ViewChild('search', { static: true }) search: ElementRef;
  states$: Observable<any[]>;

  constructor(private dataService: DataService) {}

  ngOnInit(): void {
    this.states$ = fromEvent(this.search.nativeElement, 'input').pipe(
      map((event: any) => event.target.value),
      debounceTime(500),
      distinctUntilChanged(),
      switchMap((searchText: string) => this.dataService.getData(searchText))
    );
  }
}

METHOD 2

app.component.html

<input
  type="text"
  (keyup)="searchStringChange(getValue($event))"
  placeholder="Search"
/>
<li *ngFor="let state of states$ | async">
  {{ state.text }}
</li>

app.component.ts

export class AppComponent implements OnInit {
  states$: Observable<any[]>;
  private searchText$ = new Subject<string>();

  constructor(private dataService: DataService) {}

  ngOnInit(): void {
    this.states$ = this.searchText$.pipe(
      debounceTime(500),
      distinctUntilChanged(),
      tap({ next: (searchText: string) => console.log(searchText) }),
      switchMap((searchText: string) => this.dataService.getData(searchText))
    );
  }

  searchStringChange(userInput: string) {
    this.searchText$.next(userInput);
  }

  getValue(event: Event): string {
    return (event.target as HTMLInputElement).value;
  }
}

Creating a feedback system using HTML, JavaScript, and MongoDB

I wanted to create an employee feedback system which collects feedback and save it to my MongoDB database. Below are the two codes for back-end is below.

This is a JavaScript code which serves as the server:

const express = require('express');
const mongoose = require('mongoose');
const path = require('path');

const app = express();
const port = process.env.PORT || 3000;

// Serve static files (HTML, CSS, JS)
app.use(express.static(path.join(__dirname, 'public')));

// Use express.json() to parse JSON bodies
app.use(express.json());

// Connect to MongoDB (make sure to have MongoDB installed and running)
mongoose.connect('mongodb://localhost:27017/feedbackDB', {
    useNewUrlParser: true,
    useUnifiedTopology: true,
});

mongoose.connection.on('error', (err) => {
    console.error('MongoDB connection error:', err);
});

// Create a mongoose schema for feedback
const feedbackSchema = new mongoose.Schema({
    text: String,
});

const Feedback = mongoose.model('Feedback', feedbackSchema);

// API endpoint to save feedback
app.post('/api/feedback', async (req, res) => {
    const feedbackText = req.body.text;

    if (!feedbackText) {
        return res.status(400).json({ error: 'Feedback text is required.' });
    }

    try {
        const newFeedback = new Feedback({
            text: feedbackText,
        });

        await newFeedback.save();
        res.status(201).json({ message: 'Feedback saved successfully.' });
    } catch (error) {
        console.error('Error saving feedback to the database:', error);
        res.status(500).json({ error: 'Error saving feedback to the database.' });
    }
});

// Catch-all middleware for handling other routes
app.get('*', (req, res) => {
    res.sendFile(path.join(__dirname, 'public', 'employee_feedback.html'));
});

app.listen(port, () => {
    console.log(`Server is running on http://localhost:${port}`);
});

I believe the problem is from the server which is the code I have provided above.

Is there any way I can more efficiently use something instead of if statements?

if (turn === 1) {
          if(X1 === true && X2 === true && X3 === false && O3 === false && turn === 1) {
            document.getElementById("3").innerHTML = 'O';
          O3 = true
          turn--
          }
          if(X1 === true && X3 === true && X2 === false && O2 === false && turn === 1) {
            document.getElementById("2").innerHTML = 'O';
          O2 = true
          turn--
          }
          if(X2 === true && X3 === true && X1 === false && O1 === false && turn === 1) {
            document.getElementById("1").innerHTML = 'O';
          O1 = true
          turn--
          }
          if(X3 === true && X4 === true && X5 === false && O5 === false && turn === 1) {
            document.getElementById("5").innerHTML = 'O';
          O5 = true
          turn--
          }
          if(X3 === true && X5 === true && X7 === false && O7 === false && turn === 1) {
            document.getElementById("7").innerHTML = 'O';
          O7 = true
          turn--
          }
          if(X4 === true && X5 === true && X6 === false && O6 === false && turn === 1) {
            document.getElementById("6").innerHTML = 'O';
          O6 = true
          turn--
          }
          if(X7 === true && X8 === true && X9 === false && O9 === false && turn === 1) {
            document.getElementById("9").innerHTML = 'O';
          O9 = true
          turn--
          }
          if(X7 === true && X9 === true && X8 === false && O8 === false && turn === 1) {
            document.getElementById("8").innerHTML = 'O';
          O8 = true
          turn--
          }
          if(X8 === true && X9 === true && X7 === false && O7 === false && turn === 1) {
            document.getElementById("7").innerHTML = 'O';
          O7 = true
          turn--
          }
          if(X1 === true && X4 === true && X7 === false && O7 === false && turn === 1) {
            document.getElementById("7").innerHTML = 'O';
          O7 = true
          turn--
          }
          if(X1 === true && X7 === true && X4 === false && O4 === false && turn === 1) {
            document.getElementById("4").innerHTML = 'O';
          O4 = true
          turn--
          }
          if(X7 === true && X4 === true && X1 === false && O1 === false && turn === 1) {
            document.getElementById("1").innerHTML = 'O';
          O1 = true
          turn--
          }
          if(X2 === true && X5 === true && X8 === false && O8 === false && turn === 1) {
            document.getElementById("8").innerHTML = 'O';
          O8 = true
          turn--
          }
          if(X2 === true && X8 === true && X5 === false && O5 === false && turn === 1) {
            document.getElementById("5").innerHTML = 'O';
          O5 = true
          turn--
          }
          if(X5 === true && X8 === true && X2 === false && O2 === false && turn === 1) {
            document.getElementById("2").innerHTML = 'O';
          O2 = true
          turn--
          }
          if(X3 === true && X6 === true && X9 === false && O9 === false && turn === 1) {
            document.getElementById("9").innerHTML = 'O';
          O9 = true
          turn--
          }
          if(X3 === true && X9 === true && X6 === false && O6 === false && turn === 1) {
            document.getElementById("6").innerHTML = 'O';
          O6 = true
          turn-- 
          }
          if(X9 === true && X6 === true && X3 === false && O3 === false && turn === 1) {
            document.getElementById("3").innerHTML = 'O';
          O3  = true
          turn--
          }
          if(X5 === true && X7 === true && X3 === false && O3 === false && turn === 1) {
            document.getElementById("3").innerHTML = 'O';
          O3 = true
          turn--
          }
          if(X5 === true && X3 === true && X7 === false && O7 === false && turn === 1) {
            document.getElementById("7").innerHTML = 'O';
          O7 = true
          turn--
          }
          if(X7 === true && X3 === true && X5 === false && O5 === false && turn === 1) {
            document.getElementById("5").innerHTML = 'O';
          O5 = true
          turn--
          }
          if(X1 === true || X2 === true || X3 === true || X4 === true || X5 === true || X6 === true || X7 === true || X8 === true || X9 === true && turn === 1) {
            if(O5 === false && X5 === false && turn === 1){
          document.getElementById("5").innerHTML = 'O';
          O5 = true
          turn--} else {
          if(X1 === false && O1 === false && turn === 1){
              document.getElementById("1").innerHTML = 'O';
          O1 = true
          turn--
          }
          if(X2 === false && O2 === false && turn === 1){
              document.getElementById("2").innerHTML = 'O';
          O2 = true
          turn--
          }
          if(X3 === false && O3 === false && turn === 1){
              document.getElementById("3").innerHTML = 'O';
          O3 = true
          turn--
          }
          if(X4 === false && O4 === false && turn === 1){
              document.getElementById("4").innerHTML = 'O';
          O4 = true
          turn--
          }
          if(X5 === false && O5 === false && turn === 1){
              document.getElementById("5").innerHTML = 'O';
          O5 = true
          turn--
          }
          if(X6 === false && O6 === false && turn === 1){
              document.getElementById("6").innerHTML = 'O';
          O6 = true
          turn--
          }
          if(X7 === false && O7 === false && turn === 1){
              document.getElementById("7").innerHTML = 'O';
          O7 = true
          turn--
          }
          if(X8 === false && O8 === false && turn === 1){
              document.getElementById("8").innerHTML = 'O';
          O8 = true
          turn--
          }
          if(X9 === false && O9 === false && turn === 1){
              document.getElementById("9").innerHTML = 'O';
          O9 = true
          turn--
          }
         
          }
          
          }
       
          }

I have insanely long lines of code for Tic-Tac-Toe to check if the player is about to win and I can’t figure out if there is anyway to shorten it. I know I can use loops and arrays to shorten it but I can’t figure out how to apply them. This is just a small portion of my code so some of the variable might me confusing. Just be glad I didn’t paste the whole thing on. You would be having nightmares about if statements.

I learned how to use arrays and loops when I started but the websiteI used (codecademy) didn’t show me how to apply it to anything but printing out certain words in an array.