Why is this function causing so many bugs?

Trying to build a cart page for an e-commerce site with a cart “preview window” that when clicked, opens and closes the window. I have noticed a few bugs within this function and have a feeling the same bug is causing these issues. event listeners are on another file pasted below

import { viewCartWindow } from “/static/js/supplyshop/pageactions/CatalogAction.min.js”
import { removeBtn } from “/static/js/supplyshop/pageactions/CatalogAction.min.js”
import { addToCart } from “/static/js/supplyshop/pageactions/CatalogAction.min.js”

window.addEventListener(‘click’, viewCartWindow)

window.addEventListener(‘click’, removeBtn)

window.addEventListener(‘click’, addToCart)

  1. The first click on the view cart button removes an item from cart and shows an empty cart message. This button should only show/hide the cart preview window.
    2.After an item has been removed, the view cart button stops working and no longer hides the window on click

Could this be happening because of the way I wrote the viewCartWindow function? Is the if statement missing something or is there a better way to write it so these bugs don’t occur?

let cartContainer = document.querySelector('.cart-window')
function viewCartWindow() {
    if (cartContainer.style.display === 'none') {
        cartContainer.style.display = 'block'
    } else {
        cartContainer.style.display = 'none'
    }
}

function replaceContent(el) {
    let msg = 'Your cart is currently empty.'
    let textNode = document.createTextNode(msg)
    el.appendChild(textNode)
    el.classList.add('empty-message')
}

function removeBtn() {
    let cartItem = document.querySelector('.cart-item')
    let div = document.querySelector('.div')    

    if (cartContainer.style.display === 'block') {
        cartItem.remove()
    } else {
        cartContainer.style.display = 'block'
        cartItem.remove()
    }

    replaceContent(div)
}
.empty-cart-msg {
  font-size: 1.3rem;
  color: white;
  text-align: center;
  position: relative;
  background-color: #111;
  border: none;
}

.hidden {
  display: none;
}
.catalog-h1 {
  display: inline;
  color: #111;
  text-align: center;
  font-size: 1.5rem;
  position: relative;
  left: 45.5%;
}
.column {
  float: left;
  width: 15%;
  padding: 10px;
  height: max-content; 
  margin: 5px;
  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
  border-radius: 2%;
  background-color: #aeabab;
}

.row {
  margin: 2% 0% 2% 2%;
  position: relative;
}

.row:after {
  content: "";
  display: table;
  clear: both;
}
.item-name {
  color: black;
  font-weight: 300;
  text-align: center; 
}
.item-img {
  width: 100%;
  height: 100%;
  border-radius: 2%;
}

/* search box */
#search-bar {
  float: right;
  padding: 6px;
  right: 15%;
  position: relative;
  /* margin-right: 16px; */
  border: solid 2px #aeabab;
  font-size: 17px;
}

#ul-results {
  display: flex;
  flex-direction: column;
  padding: 5px;
  /* margin-right: 2%; */
  /* float: right;
  position: relative; */

}

.li-result {
  width: 30%;
  padding: 10px 0;
  text-align: center;
  list-style-type: none;
  color: black;
  background-color: white;
  border: #797575 1px solid;
}

.li-result:hover {
  background-color: #c7c2c2;
  cursor: pointer;
}

.view-cart {
  color: white;
  float: right;
  position: relative;
  left: 12%;
  padding: 5px 5px 5px 5px;
  border: #111 solid 1px;
  text-decoration: none;
  border-radius: 5px 5px 5px 5px;
  background-color: #797575;
  font-size: 1rem;
}

.view-cart:visited {
  text-decoration: none;
}
.view-cart:hover {
  background-color: #333;
  cursor: pointer;
}

.left-arrow {
  width: 10%;
  height: auto;
  text-align: center;
  font-size: 1.3rem
}

.right-arrow {
  width: 10%;
  height: auto;
  text-align: center;
  font-size: 1.3rem
  
}

.page-buttons {
  display: flex;
  flex-wrap: nowrap;
  margin: 0 8%;
  font-size: larger;
}

.btn-container {
  display: flex;
  position: relative;
  margin-left: 36%;
}

.detailsBtn {
  width: fit-content;
  height: fit-content;
}

/* Categories Catalog */

.background {
  background-color: black;
  padding: 2% 0 2% 2%;
}

.main-link {
  color: white;
  float: right;
  padding-right: 2%;
}

.header {
  text-align: center;
  font-weight: 100;
  font-size: 1.8rem;
}

li.category {
  list-style: none;
  color: white;
  margin: 5px 0;
}

.cat-link:link {
 color: white;
}

.cat-link:hover {
  color: yellow;
  font-size: 1.2rem;
}

.cart-window {
  width: 26% !important;
  position: absolute;
  left: 72%;
  top: 15%;
  border: solid 1px black;
  padding: 10px 20px;
}

h2 {
  text-align: center;
}

.cart-wrapper {
  overflow-y: auto;
  max-height: 350px;
}

.total {
  text-align: right;
  padding: 5%;
}

.checkout-btn {
  display: block;
  width: 100%;
  text-align: center;
  cursor: pointer;
  border: solid 3px black;
  font-size: larger;
  padding: 10px;
  color: black;
  text-decoration: none;
  position: relative;
  margin-bottom: 5%;
}

.checkout-btn:hover {
  background-color: black;
  color: white;
}

.view-cart-link {
  /* width: 95%; */
  position: relative;
  cursor: pointer;
  font-size: large;
  margin: 3%;
  padding: 10px;
  color: black;
  left: 32%;

}

.cart-item {
  display: grid;
  grid-template-columns: 3fr 6fr 1fr;
  padding: 5% 2%;
  border-bottom: solid 1px lightgray;
}

.cart-item img {
  width: 100%;
}

.cart-item .details {
  padding-left: 10%;
}

.text-color {
  color: black;
}

.cart-preview {
  text-align: center;
}

.border-bottom:after {
  content: ""; 
  display: block;
  margin: 0 auto; 
  width: 85%; 
  padding-top: 10px; 
  border-bottom: 1px solid black; 
}

.cancel {
  height: fit-content;
  cursor: pointer !important;
  z-index: 1;
  background-color: white;
}

.empty-message {
  background-color: white;
  font-size: 1.3rem;
  color: black;
  text-align: center;
}
<button class='view-cart' type='button'>View Cart </button>
<!-- view cart window-->
<div class='cart-window' style>
  <h2 class='cart-preview text-color border-bottom'>Cart Preview</h2>
  <div class='cart-wrapper div'>

    <div class='cart-item'>
      <img src="https://developers.elementor.com/docs/assets/img/elementor-placeholder-image.png" alt="">
      <div class='details'>
        <h3 class='text-color'>Item Name</h3>
        <p class='text-color'>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p>
        <p class='text-color quantity'>Qty: 1</p>
      </div>
      <span class='cancel'><i class="fa-solid fa-x"></i></span>
    </div>


  </div>
  <div class='total'>Total Items(s): 1</div>

  <a href=" {% url 'supplyshop:cart-management'  %}" class='checkout-btn'>Checkout</a>
       
</div>

How to hide html element from jquery from modal

I have modal and i populate the content using jquery. I want to hide some

based on results i get but I couldn’t solve the problem.

Here is the modalbody

        var modalBody = '<div class="row"> <div class="col-md-6" id="map" ></div><div class="col-md-6" id="myhidden"><b><p class="forestry">Diploma in Forestry = '+data.std_forestry+'</p></b><b><p>Diploma in Animal Science = '+data.std_animal+'</p></b><b><p>Diploma in Civil = '+data.std_civil+'</p></b><b><p>Diploma in Pharmacy = '+data.std_pharmacy+'</p></b></div></div>' 

I want to p tag of class forestry if data.std_forestry returns null or 0. I tried this

      $(".forestry").hide();
     $(".modal-body").html(modalBody); 

before showing modal. But it is not helping. Any suggestion will be highly appreciated. Thanks in advance.

Include CSS and Javascript in specific Modx page

I am trying to include a very simple snippet of CSS and JavaScript to a Modx page that lists recent newsletters from MailChimp:

<style type="text/css">
.display_archive {font-family: arial,verdana; font-size: 12px;}
.campaign {line-height: 125%; margin: 5px;}
</style>
<script language="javascript" src="//smcoe.us11.list-manage.com/generate-js/?u=XXXXX&fid=YYYYY&show=10" type="text/javascript"></script>

The <script> tag is returning a document.write() that outputs a list of links.

Unfortunately it looks like TinyMCE blocks <style> and <script> tags and this code is not being added. What is the best way to add this code chunk to a specific page?

I found this page that shows ways to add code to the <head> or <body> tags, but I am looking to insert the code on a specific part of the page (since it does document.write, the placement is important.

I was thinking an alternative is to create a snippet that does:

$response = file_get_contents('https://smcoe.us11.list-manage.com/generate-js/?u=XXXXX&fid=YYYYY&show=10')
// remove "document.write"
// unescape slashes
return $clean_html;

But this does not seem like it would be the best method.

Woocommerce – Javascript not working on review-order.php

I’m trying to add an accordion to my checkout with javascript and I can’t seem to get javascript to work inside the “woocommerce-checkout-review-order-table” class.

as soon as I remove this class the javascript fires and the accordion element works. I believe this is because Ajax refreshes the checkout with the “woocommerce-checkout-review-order-table” class?

Is there a best practice to get javascript to work inside an AJAX? I’m not too great with either :/

Clockify – unable to pull data to google spreadsheet using Javascript

I am struggling to pull reported data in Clockify to google spreadsheet, here’s the code I am trying to trigger.

function getClockifyReport() {
  const headers = {
    "headers": {
      "X-Api-Key": "[APIKEY]",
      "content-type": "application/json",
      "Accept": "*/*"
    }
  };
  
  const workspaceId = "WORKSPACE_ID";
  
  const url = `https://reports.api.clockify.me/v1/workspaces/${workspaceId}/reports/detailed?userGroupIds=all&projectIds=all&clientIds=all&billable=null&invoiced=null&approved=null&sortByDate=null&sortAscending=null&page=1&pageSize=50&considerDurationFormat=null&roundingMinutes=null&formatted=false`;
  
  const response = UrlFetchApp.fetch(url, headers);
  const data = JSON.parse(response.getContentText());
  
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet 1");
  sheet.clear();
  sheet.appendRow(["Description", "Start Time", "End Time", "Duration", "User", "Client", "Project"]);

  data.timeEntries.forEach((entry) => {
    sheet.appendRow([
      entry.description,
      entry.timeInterval.start,
      entry.timeInterval.end,
      entry.timeInterval.duration,
      entry.user.name,
      entry.client.name,
      entry.project.name
    ]);
  });
}

If you’d like to test the script, open a google spreadsheet > Extensions > apps script.
Clockify documentation: https://docs.clockify.me/

What am I doing wrong?

Tried adjusting the code like 100 times and spent hours of research without any luck on solving this.

I am expecting to pull all available reported data in clockify by users, and automate the reporting process in google spreadsheets.

How to return to Anchor in JavaScript

I have simply for loop with function. If i click on button (.custom-read-more) loop adds class called active and if i click the button again the class is removed. Simply toggle function.

My little issue is that if i click the button. Content is shown and if i click again content is hidden. When i hide the content user’s view is at the footer of the page. I’d like return user back. For example back to anchor.

  let more = document.querySelectorAll('.custom-read-more');
  for (let i = 0; i < more.length; i++) {
    more[i].addEventListener('click', function () {
      more[i].parentNode.classList.toggle('active');
      more[i].classList.toggle('active');
    });
  }

Is it possible tell JS every even click return back to anchor or use if statement something like if ($('.custom-read-more').hasClass('active')){"return to anchor"}

Maybe dumb question but my programing journey just begun. 🙂

Error Uncaught TypeError: Cannot read properties of undefined (reading ‘unshift’) at HTMLFormElement.

I’m doing a javascript course and I followed all the steps but it keeps giving this error.
I already researched a lot on the internet about it, I looked at several posts and it was saying that probably some variable would be null but I already used the console.log and alert and I saw that all the variables are being filled.
I rewrote the page several times to see if I was missing something but without success

Uncaught TypeError: Cannot read properties of undefined (reading 'unshift')

this is my code:

const myModal = new bootstrap.Modal("#transaction-modal");
let logged = sessionStorage.getItem("logged");
const session = localStorage.getItem("session");
let data = {
    transactions: []
};

checkLogged();

document.getElementById("logout-button").addEventListener("click", logout);

document.getElementById("transactions-button").addEventListener("click", function () {
    window.location.href = 'transactions.html';
});

document.getElementById("transaction-form").addEventListener('submit', function (e) {
    e.preventDefault();

    const value = parseFloat(document.getElementById('value-input').value);
    const description = document.getElementById('description-input').value;
    const date = document.getElementById('date-input').value;
    const type = document.querySelector('input[name="type-input"]:checked').value;

    data.transactions.unshift({
        value: value, type: type, description: description, date: date
    });

    saveData(data);
    e.target.reset();
    myModal.hide();

    getCashIn();
    getCashOut();
    getTotal();

    alert("Lançamento adicionado com sucesso!");

});

function checkLogged() {
    if (session) {
        sessionStorage.setItem("logged", session);
        logged = session;
    }

    if (!logged) {
        window.location.href = 'index.html';
        return;
    }

    const dataUser = localStorage.getItem(logged);
    if (dataUser) {
        data = JSON.parse(dataUser);
    }

}

function logout() {
    sessionStorage.removeItem("logged");
    localStorage.removeItem("session");

    window.location.href = 'index.html';
}

function getCashIn() {
    const transactions = data.transactions;

    const cashIn = transactions.filter((item) => item.type === "1");

    if (cashIn.length) {
        let cashInHtml = ``;
        let limit = 0;

        if (cashIn.length > 5) {
            limit = 5;
        } else {
            limit = cashIn.length;
        }

        for (let index = 0; index < limit; index++) {
            cashInHtml += `
            <div class="row mb-4">
                <div class="col-12">
                    <h3 class="fs-2">R$ ${cashIn[index].value.toFixed(2)}</h3>
                    <div class="container p-0">
                    <div class="row">
                        <div class="col-12 col-md-8">
                        <p>${cashIn[index].description}</p> 
                        </div>
                        <div class="col-12 col-md-3 d-flex justify-content-end">
                        <span>${cashIn[index].date}</span> 
                        </div>
                    </div>
                    </div>
                </div>
            </div>
        `

        }

        document.getElementById('cash-in-list').innerHTML = cashInHtml;
    }
}

function getCashOut() {
    const transactions = data.transactions;

    const cashOut = transactions.filter(item => item.type === "2");

    if (cashOut.length) {
        let cashOutHtml = ``;
        let limit = 0;

        if (cashOut.length > 5) {
            limit = 5;
        } else {
            limit = cashOut.length;
        }

        for (let index = 0; index < limit; index++) {
            cashOutHtml += `
            <div class="row mb-4">
                <div class="col-12">
                    <h3 class="fs-2">R$ ${cashOut[index].value.toFixed(2)}</h3>
                    <div class="container p-0">
                    <div class="row">
                        <div class="col-12 col-md-8">
                        <p>${cashOut[index].description}</p> 
                        </div>
                        <div class="col-12 col-md-3 d-flex justify-content-end">
                        <span>${cashOut[index].date}</span> 
                        </div>
                    </div>
                    </div>
                </div>
            </div>
        `

        }

        document.getElementById('cash-out-list').innerHTML = cashOutHtml;
    }
}

function getTotal() {
    const transactions = data.transactions;
    let total = 0;

    transactions.forEach((item) => {
        if (item.type === "1") {
            total += item.value;
        } else {
            total -= item.value;
        }
    })

    document.getElementById('total').innerHTML = `R$ ${total.toFixed(2)}`;
}

function saveData(data) {
    localStorage.setItem(data.login, JSON.stringify(data));
}

n this is my html page, i don’t know but could it be her?

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

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Nikel - Codaí</title>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"
        integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css">
    <link rel="stylesheet" href="./css/styles.css">
</head>

<body id="app">
    <header>
        <nav class="navbar navbar-expand navbar-light bg-white">
            <div class="container-fluid">
                <a class="navbar-brand" href="#">
                    <img src="./assets/images/nikel-small-logo.png" class="img-fluid" alt="nikel logo image" />
                </a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse"
                    data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent"
                    aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="collapse navbar-collapse justify-content-end" id="navbarSupportedContent">
                    <div class="d-flex menu">
                        <a href="home.html"><button class="btn" type="button"><i
                                    class="bi bi-house-door-fill fs-4 color-secondary"></i></button></a>
                        <a href="transactions.html"><button class="btn" type="button"><i
                                    class="bi bi-currency-exchange fs-4"></i></button></a>

                        <div class="dropdown">
                            <button class="btn" type="button" data-bs-toggle="dropdown" aria-expanded="false"><i
                                    class="bi bi-person-circle fs-4"></i></button>
                            <ul class="dropdown-menu logout" aria-labelledby="dropdownMenuButton1">
                                <li><button id="logout-button" class="dropdown-item">Sair</button></li>
                            </ul>
                        </div>
                    </div>
                </div>
            </div>
        </nav>
    </header>
    <main>
        <div class="container-lg">
            <div class="row">
                <div class="col-8 d-flex mt-4 justify-content-start align-items-center">
                    <div>
                        <i class="bi bi-cash-coin color-primary icon-detail"></i>
                        <span class="fs-2 bg-white" id="total">R$ 0,00</span>
                    </div>
                </div>
                <div class="col-4 d-flex mt-4 justify-content-end">
                    <div class="text-center">
                        <img src="./assets/images/coins-small.png" class="img-fluid" alt="coins image" />
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="col-12 info shadow-lg">
                    <div class="container">
                        <div class="row">
                            <div class="col-6"><span class="fs-4 align-middle">Entradas </span> <i
                                    class="bi bi-arrow-down-circle fs-2 align-middle"></i></div>
                            <div class="col-6"><span class="fs-4 align-middle">Saídas </span> <i
                                    class="bi bi-arrow-up-circle fs-2 align-middle"></i></div>
                            <div class="col-12 my-2">
                                <hr />
                            </div>
                        </div>
                        <div class="row">
                            <div class="col-6">
                                <div class="container p-0" id="cash-in-list">

                                </div>
                            </div>
                            <div class="col-6">
                                <div class="container p-0" id="cash-out-list">

                                </div>
                            </div>

                            <div class="col-12 mb-4">
                                <button type="button" class="btn button-default" id="transactions-button">Ver
                                    todas</button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <button class="btn button-float" data-bs-toggle="modal" data-bs-target="#transaction-modal"><i
                    class="bi bi-plus"></i></button>
        </div>
        <!-- Modal -->
        <div class="modal fade" id="transaction-modal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1"
            aria-labelledby="staticBackdropLabel" aria-hidden="true">
            <div class="modal-dialog">
                <div class="modal-content">
                    <div class="modal-header">
                        <h5 class="modal-title" id="staticBackdropLabel">Adicionar lançamento</h5>
                        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                    </div>
                    <form id="transaction-form">
                        <div class="modal-body">
                            <div class="mb-3">
                                <label for="value-input" class="form-label">Valor</label>
                                <input type="number" step="any" class="form-control" id="value-input">
                            </div>
                            <div class="mb-3">
                                <label for="description-input" class="form-label">Descrição</label>
                                <input type="text" class="form-control" id="description-input">
                            </div>
                            <div class="mb-3">
                                <label for="date-input" class="form-label">Data</label>
                                <input type="date" class="form-control" id="date-input">
                            </div>
                            <div class="mb-3">
                                <div class="form-check form-check-inline">
                                    <input class="form-check-input" type="radio" name="type-input" id="type-input1"
                                        value="1" checked>
                                    <label class="form-check-label" for="type-input1">Entrada</label>
                                </div>
                                <div class="form-check form-check-inline">
                                    <input class="form-check-input" type="radio" name="type-input" id="type-input2"
                                        value="2">
                                    <label class="form-check-label" for="type-input2">Saída</label>
                                </div>
                            </div>
                        </div>
                        <div class="modal-footer">
                            <button type="button" class="btn btn-secondary button-cancel"
                                data-bs-dismiss="modal">Cancelar</button>
                            <button type="submit" class="btn button-default">Adicionar</button>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </main>

    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
        integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p"
        crossorigin="anonymous"></script>
    <script src="./js/home.js"></script>
</body>

</html> 

What changes do I need to make to fix this? Any help is appreciated.
I already try a downgrade version of bootstrap bundle.

Can not reset addEventListener executables

I am working on the Etch a Sketch project for The Odin Project, a grid of squares that are colored with mouseover events.
The grid has 3 levels of nested divs.
The grid rows and squares have been created in JavaScript, each square in the grid is a div given a class of .grid__square, nested in divs for each row.
The div with the id #grid__container is the parent of the row div and is the grid container.

The problem, once the coloring is turned on, I can’t figure out how to turn coloring off when the mouse button is released, mouseup.

The objective is to color a square if 2 events are satisfied, 1. mouse button down, and 2. mouse over square.
The code provided will correctly start to color squares if the 2 events are satisfied, button down and mouse over. I’m using a forEach loop to monitor each square in the object squares.

// create function to build grid of squares to fill #grid__container
function createGridOfNumSquares(num) {
  document.querySelector(`#grid__container`).remove();
  const gridContainer = document.createElement("div");
  gridContainer.id = `grid__container`;
  document.querySelector(`#body__container`).appendChild(gridContainer);
  for (let i = 0; i < num; i++) {
    // for rows of squares
    let row = document.createElement(`div`);
    row.classList.add(`grid__row`);
    row.id = `row${i}`;
    document.querySelector(`#grid__container`).appendChild(row);
    for (let j = 0; j < num; j++) {
      // for columns of squares
      let square = document.createElement(`div`);
      square.classList.add(`grid__squares`);
      square.id = `row${i}__col${j}`;
      document.querySelector(`#row${i}`).appendChild(square);
    }
  }
  colorSquare();
}

// color in squares (class = grid__squares) with class background colors
// color in when mousedown and mouseover square
function colorSquare() {
const squaresContainer = document.querySelector(`#grid__container`);
const squares = document.querySelectorAll(`.grid__squares`);
squares.forEach(square => {
    squaresContainer.addEventListener(`mousedown`, () => {
      square.addEventListener(`mouseover`, () => {
        square.classList.add(`black`);
      });
    });
  })
;};

Setting state with Pinia using Options API

I have this store defined in the options API:

import { defineStore } from "pinia";
import AxiosBeerOffice from "@/services/axiosBeerOffice";

const uri = {
  getNavbarItems: "/navbarItems",
};

export const useNavbarStore = defineStore({
  id: "navbar",
  state: () => ({
    navbarItems: [],
  }),
  actions: {
    getNavbarItems: async () => {
      const response = await AxiosBeerOffice.get(uri.getNavbarItems, true);
      const { data } = response;
      this.navbarItems = data;
    },
  },
});

The problem is when I call the getNavbarItems actions, the line that set the value to navbarItems throws me this error:

enter image description here

I really don’t understand what is going on here. Any help will be good.

How to implement engine sound in js

I am making a 2d game and for I’ve been trying to find a way to implement engine sound.
I have the rpm gauge and the calculation of the speed. I tried having audio files from a real car engine and having one for each 250rpm but it didn’t work out well.. I also tried
https://github.com/Antonio-R1/engine-sound-generator
But I couldn’t make it to work on my app. Do you guys have any suggestions on how I could add the engine sound?

https://github.com/programmingkitten/balkan-legends

Connect the SVG file to the content

I use WordPress.

I want to make the bottom of the message box curved.

For this purpose, I placed an SVG file inside the body of the box and gave it the style (position: absolute;) and placed it at the bottom of the box.

In order for the SVG file not to be placed on the message box, I directed it outside the box so that it looks like the box and the SVG file are one.

My problem is when the body size of the whole page changes. In this case, a space is created between the SVG file and the body of the box.

I used (@media ) and (%) but to no avail. That is, with the smallest change in screen size, two elements are separated.

Is there a way to keep these two elements from separating when the page is resized?

Or is there a way to make the SVG file stick to the body style?

.box_main {
    width: 80%;
    margin: 3rem auto 5rem;
    background: #eee;
    position: relative;
}

.box_main h2 {
    text-align: center;
    font-size: 50px;
    padding: 25px 0 0;
}

.box_main p {
    font-size: 20px;
    padding: 0 20px 10px;
}

.box_main svg {
    position: absolute;
    bottom: -25px;
    fill: #eee;
}
    <div class="box_main">

        <h2> Title </h2>

        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Rem repellendus eos vitae natus harum repudiandae
            impedit repellat veniam, hic recusandae!</p>

        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 48">
            <path d="M0,0V48S131.13,7,243.67,7,424.36,45,585.43,45c133.43,0,174-20,214.57-26.81V0Z" />
        </svg>
        
    </div>

Getting a null value instead of the input selected value in React

I’m updating an existing code base that calculates the total based on the option selected from the drop down lists. However, it’s currently not making any calculations and hence the total is not changing. From my troubleshooting, the productId is suppose to be changing, and it’s currently not.

Where productId was defined using useState set to null initially. And this is the parent component called JobFormContainer

import React, { useState, useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import Utils from 'lib/utils';
import { JobForm } from 'components/Forms';
import { createJob, getJob, updateJob } from 'redux/slices/jobReducer';
import { getProducts } from 'redux/slices/productReducer';

export const JobFormContainer = ({ notify }) => {
  const products = useSelector((state) => state.products.products);

  const allPositionTypes = [
    { value: 'Full Time', label: 'Full Time' },
    { value: 'Part Time', label: 'Part Time' },
    { value: 'Contract', label: 'Contract' },
  ];
  const travelTypes = ['none', '0%-25%', '25%-50%', '50%-75%', '75%+'];
  const telecomuteOptions = ['No', 'Yes'];
  const total = Utils.getProductTotal(productId)
  console.log('productId', productId);
  console.log('total', total);

  useEffect(() => {
    if (slug) {
      setAction('edit');
      dispatch(getJob({ slug }));
    } else {
      // get store products;
      dispatch(getProducts());
      setJobDetails({ ...jobDetails });
    }
  }, [productId]);

  const jobFormatter = ({
    url = '',
    products = [],
    travel = false,
    jobLength = 0,
    payRate = 0,
    state = '',
    country = '',
    city = '',
    productId = null,
    description = '',
    applyEmail = '',
    title = '',
    jobLoaded = false,
    telecomute = false,
    areaCode = '',
    zipcode = '',
    countries = [],
    regions = [],
    salary = 0,
    positionTypes = [],
  }) => {
    return {
      travel: travel?.value,
      state: state?.value,
      country: country?.value,
      city,
      productId,
      description,
      title,
      zipcode,
      salary,
      apply_email: applyEmail,
      apply_url: url,
      area_code: areaCode,
      pay_rate: payRate,
      job_length: jobLength,
      telecommuting_position: telecomute?.value,
      position_types: positionTypes?.map((v) => v.value),
    };
  };

  const handleSubmit = (values) => {
    if (hasJobCredits()) {
      dispatch(createJob({ job: jobFormatter(values) }))
        .then(() => {
          notify('success', 'Job successfully created.');
          history.push({ pathname: '/dashboard/jobs' });
        })
        .catch((error) => notify('error', 'Job not created successfully.'));
    }
  };

  const hasJobCredits = () => !!user?.job_credits.length;

  const proceedToCheckout = (productId, job) => {
    const { quantity } = Utils.getProduct(productId);
    const currentCart = Utils.getCart();
    const updateCart = {
      ...currentCart,
      job,
      productId,
      quantity,
    };
    Utils.setCart(updateCart);
    history.push('/employers/store/checkout');
  };

  const handleUpdate = (values) => {
    dispatch(updateJob({ job: values, employer: user }))
      .then(() => {
        notify('success', 'Job successfully updated.');
        history.push({ pathname: '/dashboard/jobs' });
      })
      .catch((error) => notify('error', 'Job not updated successfully.'));
  };

  const handleItemClick = (position) => {
    const positionTypes = position?.map((pos) => pos.value);
    setJobDetails({ positionTypes: positionTypes });
  };

  return (
    <JobForm
      user={user}
      job={job}
      handleItemClick={handleItemClick}
      isNew={action === 'new'}
      hasJobCredits={!!user?.job_credits.length}
      handleOnSumbit={handleSubmit}
      handleCancel={handleCancel}
      handleUpdate={handleUpdate}
      setProductId={setProductId}
      total={total}
      allPositionTypes={allPositionTypes}
      travelTypes={travelTypes}
      telecomuteOptions={telecomuteOptions}
      createPending={createPending}
      updatePending={updatePending}
      proceedToCheckout={proceedToCheckout}
      products={products}
    />
  );
};

export default JobFormContainer;

Component where the select option is defined and state is set to what it’s been selected. It’s a child of the JobFormContainer called JobForm.jsx

import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { Link } from 'react-router-dom';
import { Row, Col, FormGroup, ControlLabel } from 'react-bootstrap';
import {
  TextField,
  NumberField,
  SelectField,
  RegionsField,
  CountriesField,
} from 'components/FormHelpers';
import { Editor } from 'components/Editor';
import { Loader } from 'components/Loader';
import { getRegions } from 'redux/slices/localeReducer';
import Utils from 'lib/utils';
import {
  ButtonStyle,
  Label,
  StyledFormControl,
  FieldContainer,
} from 'components/Styles';
import {
  Container,
  SectionTitle,
  DescriptionLabel,
  CategoryLabel,
  CategoryFieldContainer,
  LimitedAccess,
  EditorWrapper,
} from './styles';
import { Formik, Field, Form, useField } from 'formik';

const ActionButtons = ({
  isNew,
  hasJobCredits,
  createPending,
  handleUpdate,
  handleCancel,
  updatePending,
  values,
}) => (
  <>
    <CreateJob
      isNew={isNew}
      hasJobCredits={hasJobCredits}
      handleCancel={handleCancel}
      createPending={createPending}
    />
    <UpdateJob
      isNew={isNew}
      hasJobCredits={hasJobCredits}
      handleUpdate={handleUpdate}
      handleCancel={handleCancel}
      updatePending={updatePending}
      values={values}
    />
  </>
);

const CreateJob = ({ isNew, hasJobCredits, handleCancel, createPending }) =>
  isNew &&
  hasJobCredits && (
    <Row style={{ marginBottom: 100 }}>
      <Col md={3}>
        <ButtonStyle
          type='submit'
          style={{ marginLeft: 14 }}
          className='btn btn-primary'
        >
          Post Job
        </ButtonStyle>
        <ButtonStyle
          type='button'
          style={{ marginLeft: 14 }}
          className='btn btn-primary'
          onClick={handleCancel}
        >
          Cancel
        </ButtonStyle>
        <div
          style={{
            display: 'flex',
            alignItems: 'center',
            height: '4rem',
          }}
        >
          <Loader width='25px' height='25px' show={createPending} />
        </div>
      </Col>
    </Row>
  );

const UpdateJob = ({
  isNew,
  values,
  handleUpdate,
  handleCancel,
  updatePending,
}) =>
  !isNew && (
    <Row style={{ marginBottom: 100 }}>
      <Col md={3}>
        <ButtonStyle
          type='button'
          style={{ marginLeft: 14 }}
          className='btn btn-primary'
          onClick={() => handleUpdate(values)}
        >
          Update
        </ButtonStyle>
        <ButtonStyle
          type='button'
          style={{ marginLeft: 14 }}
          className='btn btn-primary'
          onClick={handleCancel}
        >
          Cancel
        </ButtonStyle>
        <div
          style={{
            display: 'flex',
            alignItems: 'center',
            height: '4rem',
          }}
        >
          <Loader width='25px' height='25px' show={updatePending} />
        </div>
      </Col>
    </Row>
  );

const CheckOutSection = ({
  isNew,
  hasJobCredits,
  products,
  setFieldValue,
  values,
  total,
  handleCancel,
  setProductId,
}) =>
  isNew &&
  !hasJobCredits && (
    <section>
      <Row>
        <Col md={6}>
          <SectionTitle>Checkout</SectionTitle>
        </Col>
      </Row>
      <Row>
        <Col md={6}>
          <FormGroup>
            <label>Job Posts</label>
            <FieldContainer>
              <SelectField
                options={
                  products
                    .filter((p) => p.category !== 'subscription')
                    .map((p) => ({ ...p, label: p.name })) || []
                }
                style={{ background: 'initial', height: 54 }}
                name='productId'
                onChange={() => {
                  // setFieldValue('productId', values.productId);
                  setProductId(values.productId);
                }}
                value={values.productId}
                required
              />
            </FieldContainer>
          </FormGroup>
        </Col>
        <Col md={6}>
          <Label>Order Total:</Label>
          <FieldContainer
            style={{
              position: 'relative',
              top: 14,
              marginBottom: 40,
            }}
          >
            {total}
          </FieldContainer>
        </Col>
      </Row>
      <Row>
        <Col>
          <LimitedAccess className='clearfix'>
            +Includes LIMITED access to our resume database!
          </LimitedAccess>
        </Col>
      </Row>
      <Row>
        <Col>
          <ButtonStyle
            type='submit'
            style={{ marginLeft: 14 }}
            className='btn btn-primary'
          >
            Checkout
          </ButtonStyle>
          <ButtonStyle
            type='button'
            style={{ marginLeft: 14 }}
            className='btn btn-primary'
            onClick={handleCancel}
          >
            Cancel
          </ButtonStyle>
        </Col>
      </Row>
      <Row>
        <Col md={6}>
          <SectionTitle>Pricing Information</SectionTitle>
          <div className='main_div'>
            <div className='price_table'>
              {products &&
                products
                  .filter((p) => p.category !== 'subscription')
                  .map((option, i) => {
                    if (option.display === undefined) {
                      return <p key={i}>{option.name}</p>;
                    }
                    return <p key={i}>{option.display}</p>;
                  })}
            </div>
            <div className='price_table big'>
              <p>
                <strong>Need More Jobs?</strong>
                &nbsp;
                <Link className='green_btn' to='/#'>
                  Contact Us
                </Link>
              </p>
            </div>
          </div>
        </Col>
        <Col md={6}>
          <SectionTitle>Special Offer:</SectionTitle>
          <p className='left'>
            Get Free Limited Access to QuirkyCoders's resume and social profile
            database with each job post!
            <br />
            <span>(Access is restricted to 10 candidate profile views)</span>
          </p>
        </Col>
      </Row>
    </section>
  );

export const JobForm = ({
  user,
  job,
  travelTypes,
  handleItemClick,
  telecomuteOptions,
  isNew,
  hasJobCredits,
  handleOnSumbit,
  handleCancel,
  handleUpdate,
  total,
  allPositionTypes,
  updatePending,
  createPending,
  products,
  productId,
  setProductId,
}) => (
  <Container>
    <SectionTitle>
      Job Postings
      {user && (
        <div className='pull-right'>
          job post credits: {user.job_credits.length}
        </div>
      )}
    </SectionTitle>
    {
      <Formik
        initialValues={{
          products: job?.products || [],
          travel: job?.travel || 'No',
          jobLength: job?.jobLength || 0,
          payRate: job?.payRate || 0,
          state: job?.state || '',
          country: job?.country || '',
          city: job?.city || '',
          productId: job?.productId || '',
          description: job?.description || '',
          applyEmail: job?.applyEmail || '',
          title: job?.title || '',
          telecomute: job?.telecomute || 'No',
          zipcode: job?.zipcode || undefined,
          salary: job?.salary || 0,
          positionTypes: job?.positionTypes.map((pt) => pt.name) || [],
          slug: job?.slug,
        }}
        enableReinitialize={true}
        onSubmit={(values) => handleOnSumbit(values)}
      >
        {({
          form,
          values,
          handleChange,
          handleBlur,
          handleSubmit,
          setFieldValue,
          setFieldTouched,
          errors,
          touched,
        }) => (
          <Form name='jobpostForm' onSubmit={handleSubmit} noValidate>
            <section>
              <Row>
                <Col sm={6}>
                  <TextField
                    placeholder='ex: Ruby on Rails Developer'
                    title='Title'
                    name='title'
                    onChange={handleChange}
                    value={values.title}
                  />
                </Col>
              </Row>
              <Row>
                <Col md={12}>
                  <FormGroup>
                    <DescriptionLabel componentClass={ControlLabel}>
                      Description
                    </DescriptionLabel>
                    <EditorWrapper>
                      <Editor
                        onChange={handleChange}
                        value={values.description}
                      />
                    </EditorWrapper>
                  </FormGroup>
                </Col>
              </Row>
            </section>
            <section>
              <Row>
                <Col md={12}>
                  <SectionTitle>Application Method</SectionTitle>
                </Col>
              </Row>
              <Row>
                <Col md={12}>
                  <TextField
                    placeholder='[email protected]'
                    title='Email'
                    name='applyEmail'
                    onChange={handleChange}
                    value={values.applyEmail}
                    required
                  />
                </Col>
              </Row>
            </section>
            <section>
              <Row>
                <Col md={12}>
                  <SectionTitle>Location</SectionTitle>
                </Col>
              </Row>
              <Row>
                <Col md={6}>
                  <CountriesField
                    title='Country'
                    name='country'
                    id='country'
                    onChange={setFieldValue}
                    onBlur={setFieldTouched}
                    value={values.country}
                    error={errors.country}
                    touched={touched.country}
                    label
                  />
                </Col>
                <Col md={6}>
                  <RegionsField
                    title='State or Region'
                    name='state'
                    onChange={handleChange}
                    onBlur={handleBlur}
                    value={values.state}
                    label
                  />
                </Col>
              </Row>
              <Row>
                <Col md={6}>
                  <TextField
                    placeholder='Charlotte'
                    title='City'
                    name='city'
                    onChange={handleChange}
                    value={values.city}
                  />
                </Col>
                <Col md={6}>
                  <NumberField
                    placeholder='12345'
                    title='Zipcode'
                    name='zipcode'
                    onChange={handleChange}
                    value={values.zipcode}
                    required
                  />
                </Col>
              </Row>
            </section>
            <section>
              <Row>
                <Col md={12}>
                  <SectionTitle>Compensation & Travel</SectionTitle>
                </Col>
              </Row>
              <Row>
                <Col md={4}>
                  <FormGroup>
                    <CategoryLabel>Position Types</CategoryLabel>
                    <CategoryFieldContainer>
                      <SelectField
                        options={allPositionTypes}
                        name='positionTypes'
                        placeholder='Select Position Type'
                        defaultValue={[...new Set(values.positionTypes)].map(
                          (position) => ({
                            value: position,
                            label: position,
                          })
                        )}
                        onChange={() =>
                          setFieldValue('positionTypes', values.positionTypes)
                        }
                        isMulti
                        isSearchable
                      />
                    </CategoryFieldContainer>
                  </FormGroup>
                </Col>
                <Col md={4}>
                  <FormGroup>
                    <CategoryLabel>Pay Rate</CategoryLabel>
                    <CategoryFieldContainer>
                      <StyledFormControl
                        title='Pay Rate'
                        type='number'
                        placeholder='55'
                        className='form-control'
                        name='payRate'
                        onChange={handleChange}
                        value={values.payRate}
                        required
                      />
                    </CategoryFieldContainer>
                  </FormGroup>
                </Col>
                <Col md={4}>
                  <FormGroup>
                    <CategoryLabel>Length (Months)</CategoryLabel>
                    <CategoryFieldContainer>
                      <StyledFormControl
                        type='number'
                        placeholder='12'
                        className='form-control'
                        name='jobLength'
                        onChange={handleChange}
                        value={values.jobLength}
                      />
                    </CategoryFieldContainer>
                  </FormGroup>
                </Col>
              </Row>
              <Row>
                <Col md={4}>
                  <TextField
                    style={{ background: 'initial', height: 54 }}
                    placeholder='70000'
                    name='salary'
                    title='Salary(p.a)'
                    onChange={handleChange}
                    value={values.salary}
                    label
                    required
                  />
                </Col>
                <Col md={4}>
                  <SelectField
                    options={travelTypes.map((v) => ({ label: v, value: v }))}
                    name='travel'
                    title='Travel'
                    value={values.travel}
                    label
                    required
                  />
                </Col>
                <Col md={4}>
                  <SelectField
                    options={telecomuteOptions.map((v) => ({
                      label: v,
                      value: v,
                    }))}
                    name='telecomute'
                    title='Telecomute'
                    value={values.telecomute}
                    label
                    required
                  />
                </Col>
              </Row>
              <ActionButtons
                isNew={isNew}
                hasJobCredits={hasJobCredits}
                createPending={createPending}
                updatePending={updatePending}
                handleUpdate={handleUpdate}
                handleCancel={handleCancel}
                values={values}
              />
            </section>
            <CheckOutSection
              isNew={isNew}
              hasJobCredits={hasJobCredits}
              products={products}
              total={total}
              setFieldValue={setFieldValue}
              values={values}
              handleCancel={handleCancel}
              setProductId={setProductId}
            />
          </Form>
        )}
      </Formik>
    }
  </Container>
);

export default JobForm;

File where the calculation for total is been done called Utils.js. Since this is not a React component, I really don’t understand how to pass the productId to the required function

export default class Utils {
  static getDefaultProductOption = () => {
    return [{ display: 'Purchase in Bulk and Save!', value: 0 }];
  };

  static getProducts = () => {
    var products = [{ display: 'Purchase in Bulk and Save!', value: 0 }];
    let cachedProducts = localStorage.getItem('p_data') || '[]';
    JSON.parse(cachedProducts).map((product, index) =>
      products.push({
        display: product.name,
        id: product.id,
        quantity: product.quantity,
        value: product.cost,
        details: product,
        created_at: product.created_at,
        description: product.description,
        sku: product.sku,
        updated_at: product.updated_at,
      })
    );

    products.push({ total: localStorage.getItem('_total'), value: 0 });
    return products;
  };

  static getProductTotal = (productId, quantity = null) => {
    console.log('productId', productId);
    let total;
    const product = this.getProduct(productId);
    if (product.quantity) {
      total = product
        ? parseInt(product.quantity, 10) * parseInt(product.value, 10)
        : 0;
    } else {
      total = product
        ? parseInt(product.quantity, 10) * parseInt(product.value, 10)
        : 0;
    }
    return Utils.currencyFormatter(total, 2);
  };

  static getProduct = (productId) => {
    return this.getProducts().filter(
      (product) => product.id === parseInt(product.quantity, 10)
    )[0];
  };

  static getProductByQuantity = (quantity) => {
    return this.getProducts().filter((product) => {
      return (
        product.quantity === parseInt(quantity, 10) ||
        (product.quantity >= 5 && parseInt(quantity, 10) >= 5)
      );
    })[0];
  };

}

When I console.log(productId) in the above Utils.js file, it’s given null instead of changing to the option selected value. Any hint on how I can make progress will be deeply appreciated.

Detect when pages has loaded via Javascript when using window.open

I looked at other solutions here in SO 1, 2 but none of the solutions work for me. Consider following code:

<!DOCTYPE html>
<html>
  <head>
    <title>Opening window with JS</title>
    <script>
      const openWindow = () => {
        const win = window.open('', '_blank', 'top=20, left=20, width=200, height=200');
        win.document.addEventListener('DOMContentLoaded', () => {
          console.info('Child window loaded');
          win.document.body.style.background = 'hotpink';
        });
      }

      document.addEventListener('DOMContentLoaded', (_) => {
        document.getElementById('open').addEventListener('click', (_) => openWindow())
      })
    </script>
  </head>
  <body>
    <button id="open">Open window</button>
  </body>
</html>

When the window is opened, I don’t see anything logged into the console and background of the page is not changed.

I also tried adding this to my <script> tag:

const openWindow = () => {
  const win = window.open('', '_blank', 'top=20, left=20, width=200, height=200');
  win.onload = () => {
    console.info('Child window loaded');
    win.document.body.style.background = 'hotpink';
  };
}

document.addEventListener('DOMContentLoaded', (_) => {
  document.getElementById('open').addEventListener('click', (_) => openWindow())
})

That doesn’t work either. So next step was to try embedding JS into the HTML of the newly opened window (the </script> is not a typo, it has to be escaped in literal):

      const openWindow = () => {
      const win = window.open('', '_blank', 'top=20, left=20, width=200, height=200');
      win.document.write = `
      <!DOCTYPE html>
      <html>
        <head>
          <title>Child window</title>
          <script>
            const handleOnLoad = () => {
              console.info('Child window loaded');
              window.body.style.background = 'hotpink';
            }
          </script>
        </head>
        <body onload="handleOnLoad">
        </body>
      </html>
      `;
      }

    document.addEventListener('DOMContentLoaded', (_) => {
      document.getElementById('open').addEventListener('click', (_) => openWindow())
    })

However that doesn’t bring me any closer. How do I proceed?

How to retrieve the Object data from JSON with Fetch [duplicate]

I’m using fetch to read data from a local JSON file like this:

var obj;

    fetch('./contacts.json')
        .then(res => res.json())
        .then(data => {
        obj = data;
        })
        .then(() => {
        console.log(obj);
        });

console.log shows an Object with all the data from the JSON file just how I want it to retrieve from the json file. So far so good.
However, when I try to access obj outside of the fetch statement, it’s empty/undefined; like this:

var obj;

    fetch('./contacts.json')
        .then(res => res.json())
        .then(data => {
        obj = data;
        })
        .then(() => {
        console.log(obj);
        });

console.log(obj)

How can I make the data from the json file accessible, e.g. to access the first element of obj with obj[0]? Isn’t this the whole purpose of fetch? Am I missing a return statement?

Google Apps Script local Addon development with live reload

I am developing a Google Apps Script editor add-on with the following setup:

src
|__ client
|__ gas
esbuild.config.js
tsconfig.json
package.json

src/client is a Svelte app for the add-on UI.
src/gas is Google Apps Script code developed.
esbuild.config.js has two build processes. The client is bundled into one single html file index.html. The gas code is bundled in one single javascript file Code.js.

During development (with esbuild –watch mode), every time I save my code, both index.html and Code.js are created and pushed automatically to Google server via clasp.

How can I enable live reload so that every time I save my code, I see the change automatically in my Add-on on Google server?

This project is able to do that using webpack and React. However I am not sure to understand conceptually how. Even after checking the code base.

For now, I am able:

  • To push my code to Google server for every save in my editor
  • To enable live reload locally with esbuild in-house dev server and a server sent event listener in the final build.
  • To create a valid certificate with mkcert to enable HTTPS

But I’m not able trigger a reload on Google server. Neither for the UI index.html nor for the apps script code Code.js.