I am trying to make a dot placement on an image, but whenever the screen is resized the dot placement changes its location

The point is pointing on the phones camera, but whenever the screen is resized the position of the dot changes. I want to make sure that whenever the screen is resized the dot isn’t going all over the place, instead it remains pointing on the phone’s camera. Does anyone have any clue what I am doing wrong here?

CSS code

.spec::before { /* TO MODIFY THE SPECS WRITINGS OF THE HEADER PHOTOS */
    content: '';
    background: var(--secondary);
    width: 6em;
    height: 1px;
    position: absolute;
    bottom: -2.2em;
    left: 50%;
}

.phone .spec::before {
    transform:
        translateX(-145%) rotate(-45deg);
}

.tablet .spec::before {
    transform:
        translateX(-50%) rotate(45deg);
}

.dot {
    position: absolute; 
    bottom: -5em;
    height: 1.8em;
    width: 1.8em;
    border: 1px var(--primary) solid;
    border-radius: 50%;
    animation: expand 1s ease-in-out infinite;
}

.phone .dot {left: -30%;} 
.phone .dot {bottom: -240%;}/* change the dot placement */
.tablet .dot {left: 65%;}

.dot::before, .pagination a::before {
    content: '';
    background: var(--accent);
    width: 50%;
    height: 50%;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    border-radius: inherit;
}

Typescript DiscordJS bot audio stops working after a few seconds of playing

I am currently facing an issue with playing audio through a bot I made for discord.
The bot downloads a song from youtube using ytdl-core and then plays it, but the song stops after a few seconds of playing.

Here is my “play.ts” file, which includes the play command:
(apologies for the messy code, I am just trying to put something together here.)

import { CommandInteraction, SlashCommandBuilder } from "discord.js";
import { getVoiceConnection, createAudioPlayer, createAudioResource, NoSubscriberBehavior } from '@discordjs/voice';
import { join } from "path";
import ytdl from 'ytdl-core';
import fs from 'fs';

export const data = new SlashCommandBuilder()
    .addStringOption(option =>
        option.setName("link")
            .setDescription("Link to the audio source to be played.")
            .setRequired(true)
    )
    .setName("play")
    .setDescription("Plays audio from given URL.");

export async function execute(interaction: CommandInteraction) {
    if (!interaction.guildId) {
        return interaction.reply("Something went really, really wrong.");
    }

    const url = interaction.options.getString("link");
    const connection = getVoiceConnection(interaction.guildId);

    if (!connection) {
        return interaction.reply("Bot is not currently in a voice channel. Join one before using this command.");
    }

    const audioplayer = createAudioPlayer({
        behaviors: {
            noSubscriber: NoSubscriberBehavior.Pause,
        },
    });

    const download = ytdl(url, { filter: 'audioonly' });
    const writestream = fs.createWriteStream('audio.mp4');
    const pathtoresource = join('audio.mp4');
    // console.log(pathtoresource);

    download.pipe(writestream);

    const resource = createAudioResource(pathtoresource, {
        inlineVolume: true,
        metadata: {
            title: "SONG",
        },
    });

    audioplayer.play(resource);
    connection.subscribe(audioplayer);

    return interaction.reply(`Playing from: ${url}`);
}

It should play the audio after downloading the song, but it sometimes plays a few seconds of the song, other times nothing at all. (maybe because the download isn’t done in time to play, but I don’t know how to make it wait for the ytdl download.)

Any help is much appreciated!
(once again, apologies for the messy code, I am still learning)

Can’t use promises in Puppeteer

I’m new to Javascript and obviously to Puppeteer Library.

I know what async programming is and I’ve been playing around with it in Javascript but when I try to use it with Puppeteer I get errors.

This is my index.js file:

(async () => {

  const browser = await puppeteer.launch({
    headless: false,
  });

  // Disable Facebook notifications
  const context = await browser.defaultBrowserContext();
  await context.overridePermissions('https://www.facebook.com', ['geolocation', 'notifications']);

  const page = await browser.newPage();
  const logger = await myLog.logger;

  console.log('About to use function.');
  await utils.webAction(
    logger, 'Enter Facebook',
    (() => (page.goto(constants.linkHomepage, {waitUntil: ['domcontentloaded', 'networkidle2']})))
  );
  console.log('Content loaded');

  // User Login
  await utils.webAction(
    logger, 'Wait for loginEmail element',
    (() => (page.waitForSelector(constants.cssLoginEmail, {visible: true}))),
  );
  // Using a fake (incorrect) xpath to trigger the "catch" block
  await utils.webAction(
    logger, 'Enter user email using incorrect xpath', utils.webType,
    page, "Fake user", "fake xpath/css"  // Arguments of `webType`
  );

})();

And utils.js file:

module.exports = {

  webAction: function (logger, msg, func, ...args)
  {
    return new Promise((resolve) => {
      let actionMessage, actionLevel;
      try
      {
        func(...args);
        actionMessage = msg;
        actionLevel = 'info';
      }
      catch (error)
      {
        actionMessage = "Error while executing " + msg + " function.n---n" + error.message + "n---";
        actionLevel = 'error';
      }
      finally
      {
        logger.log({
          level: actionLevel,
          message: actionMessage
        })
      }
      console.log('Inside resolve Promise');
      resolve('Fullfilment value of Promise');
      console.log('Last line if resolve body');
    })
  },

  // Type into input field
  webType: function (page, text, xpath)
  {
    page.type(
      xpath, text,
      {delay: getRandomIntInRange(constants.minSpeed, constants.maxSpeed)}
    );
  },

};

I created webAction function because I want the code to look cleaner and also to keep track of where the program crash (I’m open to other ways to achieve this).

This is the error I’m getting:

About to use function.
info: Enter Facebook {"timestamp":"2024-01-18 16:43:59"}
Inside resolve Promise
Last line if resolve body
Content loaded
info: Wait for loginEmail element {"timestamp":"2024-01-18 16:43:59"}
Inside resolve Promise
Last line if resolve body
info: Enter user email using incorrect xpath {"timestamp":"2024-01-18 16:43:59"}
Inside resolve Promise
Last line if resolve body
/home/user/Projects/Javascript/Facebook/node_modules/puppeteer-core/lib/cjs/puppeteer/common/CallbackRegistry.js:85
            this._reject(callback, new Errors_js_1.TargetCloseError('Target closed'));
TargetCloseError: Protocol error (Runtime.callFunctionOn): Target closed
    at CallbackRegistry.clear (/home/user/Projects/Javascript/Facebook/node_modules/puppeteer-core/lib/cjs/puppeteer/common/CallbackRegistry.js:85:36)
    at CdpCDPSession._onClosed (/home/user/Projects/Javascript/Facebook/node_modules/puppeteer-core/lib/cjs/puppeteer/cdp/CDPSession.js:113:25)
    at Connection.onMessage (/home/user/Projects/Javascript/Facebook/node_modules/puppeteer-core/lib/cjs/puppeteer/cdp/Connection.js:132:25)
    at WebSocket.<anonymous> (/home/user/Projects/Javascript/Facebook/node_modules/puppeteer-core/lib/cjs/puppeteer/node/NodeWebSocketTransport.js:52:32)
    at callListener (/home/user/Projects/Javascript/Facebook/node_modules/ws/lib/event-target.js:290:14)
    at WebSocket.onMessage (/home/user/Projects/Javascript/Facebook/node_modules/ws/lib/event-target.js:209:9)
    at WebSocket.emit (node:events:514:28)
    at Receiver.receiverOnMessage (/home/user/Projects/Javascript/Facebook/node_modules/ws/lib/websocket.js:1192:20)
    at Receiver.emit (node:events:514:28)
    at Receiver.dataMessage (/home/user/Projects/Javascript/Facebook/node_modules/ws/lib/receiver.js:560:14) {
  cause: ProtocolError
      at <instance_members_initializer> (/home/user/Projects/Javascript/Facebook/node_modules/puppeteer-core/lib/cjs/puppeteer/common/CallbackRegistry.js:96:14)
      at new Callback (/home/user/Projects/Javascript/Facebook/node_modules/puppeteer-core/lib/cjs/puppeteer/common/CallbackRegistry.js:100:16)
      at CallbackRegistry.create (/home/user/Projects/Javascript/Facebook/node_modules/puppeteer-core/lib/cjs/puppeteer/common/CallbackRegistry.js:32:26)
      at Connection._rawSend (/home/user/Projects/Javascript/Facebook/node_modules/puppeteer-core/lib/cjs/puppeteer/cdp/Connection.js:91:26)
      at CdpCDPSession.send (/home/user/Projects/Javascript/Facebook/node_modules/puppeteer-core/lib/cjs/puppeteer/cdp/CDPSession.js:78:33)
      at next (/home/user/Projects/Javascript/Facebook/node_modules/puppeteer-extra-plugin-stealth/evasions/sourceurl/index.js:34:41)
      at CdpCDPSession.send (/home/user/Projects/Javascript/Facebook/node_modules/puppeteer-extra-plugin-stealth/evasions/sourceurl/index.js:75:16)
      at #evaluate (/home/user/Projects/Javascript/Facebook/node_modules/puppeteer-core/lib/cjs/puppeteer/cdp/ExecutionContext.js:211:50)
      at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
      at async ExecutionContext.evaluateHandle (/home/user/Projects/Javascript/Facebook/node_modules/puppeteer-core/lib/cjs/puppeteer/cdp/ExecutionContext.js:178:16)
}

Node.js v18.17.0

I want to be able to use webAction function so i you have any idea of how i can fix the error you are more than welcomed.

In the output it says that it entered Facebook correctly but this is not true, as as soon as the browser opened it closed immediately!
And obviously it doesn’t complete correctly the order statements (waitForSelector & utils.webType) so can someone explain me what is happening and how to be able to run this code without any error.

Thanks in advanced!

NestJS connect to websocket inside route

I looked at implementing WebSocket connection in NestJs but most places are importing module in AppModule or if don’t they just don’t work.

My case is I have route making POST request to some random endpoint on the internet and the response from this endpoint is websocket URL. I need to connect to that URL and wait for data. After i get this data I send It as my route response.

what I did is

let socket: Socket | undefined;
    if (websocketUrl) {
      socket = io(websocketUrl, { secure: true, reconnection: true, rejectUnauthorized: false });

      await new Promise<void>((resolve, reject) => {
        socket?.on("connect", () => resolve(console.log("connected")));
        socket?.on("connect_error", (error: Error) => reject(error));
      });
    }

    if (socket) {
      return new Promise<void>((resolve, reject) => {
        console.log("in promise");
        if (socket?.connected) {
          socket.on("onMessage", (data: any) => {
            console.log(data);

            try {
              if (data.type === "failed") {
                reject(new Error("Rejected"));
              } else {
                const stringData = data.payload.redirect;
                console.log(stringData);
                resolve(stringData);
              }
            } catch (err) {
              reject(err);
            }
          });

          socket.on("error", (error: Error) => {
            socket.off("onMessage");
            reject(new Error(`Websocket error ${error.message}`));
          });

          socket.on("disconnect", () => {
            socket.off("onMessage");
            reject(new Error("Websocket closed"));
          });
        } else {
          reject(new Error("Websocket is not connected"));
        }
      });
    } else {
      throw new Error("Websocket connection failed.");
    }

unfortunately when I’m running my function server throws error

XHR Polling Error

multiple grids in css

im trying to design a simple website, where i have multiple completely independent grids, and im wondering how i can make sure that each item goes in the correct grid

this is grid 1:
#grid1 {
  display: grid;
   grid-template-columns: 33% 33% 33%;
  grid-template-rows: 600px;
  column-gap: 100px;
}

 .grid1_items {
   height: 500px;
  width: 400px;
  background-color: #80b2d0;
  border: 2px solid #115e8d;
  border-radius: 16px;
  text-align: center;
  color: white;
  grid-area: auto;
}

this is grid 2:
#grid2 {
  display: grid;
  grid-template-columns: 33% 33% 33%;
  grid-template-rows: 600px;
  column-gap: 100px;
}

.grid2_items {
  font-size: 35px;
  color: black;
  font-weight: bold;
  font-family: "gill sans" , sans-serif;
  text-align: left;
  margin-bottom: 10px;
}

how do i make sure grid1_items go in grid1 rather than grid2 and the same for grid2_items?

Role Select Menu | Discord.js

I have ran into a problem with my selectMenu code. There’s no error in the console, but the slash command won’t show up. Maybe there’s problem in the code? I’ve spent over 30 minutes trying to the problem and yet I couldn’t find it.

require('dotenv').config();
const { RoleSelectMenuBuilder, ActionRowBuilder, ComponentType } = require('discord.js');

const data = {
    name: 'show-roles',
    description: 'Show roles using role select menu.',
};

/**
 * 
 * @param {Object} param0 
 * @param {import('discord.js').ChatInputCommandInteraction} param0.interaction
 */

async function run({ interaction }) {
    const roleMenu = new RoleSelectMenuBuilder()
        .setCustomId(interaction.id)
        .setMinValues(0)
        .setMaxValues(3);

    const actionRow = new ActionRowBuilder().setComponents(roleMenu);

    const reply = await interaction.reply({ components: [actionRow]});

    const collector = reply.createMessageComponentCollector({
        componentType: ComponentType.RoleSelect,
        filter: (i) => i.user.id === interaction.user.id && i.customId === interaction.id, time: 60_000,
    });

    collector.on('collect', (interaction) => {
        if  (!interaction.values.length) {
            interaction.reply('You have emptied your selection.');
            return;
        }

        interaction.reply(
            `You have now selected: ${interaction.values.join(', ')}`);
    })
}

module.exports = { data, run };

try {
    console.log(`----- YOUR'RE GOOD TO GO! -----`)
} catch (error) {
    console.log(`ERROR: ${error}`);
};```


I tried to make a role menu selector but the slash command for it doesn't work. I'd like to find a solution how to fix this problem

Shopify or Javascript Debugging

Situation:

When running the new module (#c-orderNote if you want to look at the code. Contains all script, css & html used for the module) #c-orderNote module

It works in my Shopify CLI locally but the moment I move it to the live site it starts throwing this error which is part of the theme script that has nothing to do with the new module that I have made.Error on live site

enter image description here

I’m having an issue with a cart form submitting consistently.

Currently this is how this page is code. Either using the cart page OR cart Ajax drawer.

  1. I have a input box for customers to select their delivery option.

  2. There is a textbox for customers so they can put in their own notes(optional).

  3. Javascript is used to combine the options selected(from step 1 and 2) into the hidden textbox(id=”CartSpecialInstructions”) inside the form that has name=”note” which should always submit with the form.

   <textarea 
    name="note" 
    id="CartSpecialInstructions" 
    class="t4s-cart-note__input" 
    placeholder="How can we help you?" spellcheck="false">
   </textarea>

Possible solutions:

  • What was a good video/blog on How to debug scripts when you have multiple running in tandum?
    OR
  • Did you see a reason why the two would be conflicting?

express locallibrary tutorial author names missing from book list

I’m trying to build some knowledge in back end development (because I need it!) after spending a few years on front end, and after a short intro’ into Basic Node and Express from the fantastic FreeCodeCamp Curriculum I’m now trying to follow the MDN Express Locallibrary Tutorial . Everything was going well until the Book List page.

When I click on the All Books link the app should render a list of all the books along with the names of the author of each book. I’m getting the list of books OK, but the author names are missing.

I’m not getting any error messages per se, however, when I hover over the allBooks variable in the async handler (I’m using VS Code) I notice that the author value seems somewhat amiss as there is a question mark after the author key and the value has Types.ObjectID followed by null | undefined

const allBooks: Omit<Document<unknown, {}, {
    title: string;
    summary: string;
    isbn: string;
    genre: Types.ObjectId[];
    author?: Types.ObjectId | null | undefined;
}> & {
    title: string;
    summary: string;
    isbn: string;
    genre: Types.ObjectId[];
    author?: Types.ObjectId | null | undefined;
} & {
    ...;
}, never>[]

Now, I typed most of the code up by hand initially, just to get used the format and syntax of using Mongoose ODM along with PugJS template engine and after a day or so of failing to find the source of the problem I’ve been through the tutorial from the start and copied & pasted the code into each of the individual files in the app and I still have the exact same problem.

There are many questions posted on this forum regarding the tutorial, but none specific to this case. I did find that this problem had occurred before though: Author’s Name Not Rendering but that appears to have been fixed back in 2020. I noticed during the git Hub discussion that there were concerns over the state of the DB at the time. With that in mind, I dropped all tables from the Mongo DB and re-populated it with the original data, because I thought there may have been a chance that I had corrupted the data at some point. That hasn’t fixed the problem and I’m not sure where to go from here. I feel that if I just ignore the problem, it’s not going to go away, and could well come back and bite me later down the trail.

What I did find was that if I use #{book.author} instead of #{book.author.name} in the book_list.pug file then the app renders the authors’ _Id from the database. This tells me it has to be something to do with the virtual type name which is defined on the AuthorSchema but, that’s as far as my skills will take me. I’m just not familiar enough with this stack tech to know how to fix this.

My code for the app is below.

Models

author.js

const mongoose = require("mongoose");
const Schema = mongoose.Schema;

const AuthorSchema = new Schema({
  first_name: { type: String, required: true, maxLength: 100 },
  family_name: { type: String, required: true, maxLength: 100 },
  date_of_birth: { type: Date },
  date_of_death: { type: Date },
});

AuthorSchema.virtual("name").get(function () {
  // To avoid erros where an author doesn't have a family name or first name
  // we want to make sure we handle the exception by returning an empty string for that case

  let fullname = "";
  if (this.first_name && this.last_name) {
    fullname = `${this.family_name}, ${this.first_name}`;
  }

  return fullname;
});

// Virtual for author's URL returns an absolute URL
// we'll use this property in our templates whenever we want to get a link for an author
AuthorSchema.virtual("url").get(function () {
  // We don't want to use arrow functions because we'll need to us this object
  return `/catalog/author/${this._id}`;
});

// Export the `Author` model
module.exports = mongoose.model("Author", AuthorSchema);

book.js

const mongoose = require("mongoose");

const Schema = mongoose.Schema;

const BookSchema = new Schema({
  title: { type: String, required: true },
  author: { type: Schema.Types.ObjectId },
  summary: { type: String, required: true },
  isbn: { type: String, required: true },
  genre: [{ type: Schema.Types.ObjectId, ref: "Genre" }],
});

//  Virtual for book's URL
BookSchema.virtual("url").get(function () {
  // We don't want to use arrow functions as we'll need the `this` object
  return `/catalog/book/${this._id}`;
});

module.exports = mongoose.model("Book", BookSchema);

Controllers

bookController.js

// book controller
// The controllers use the `express-async-handler module` which will
// catch any exceptions thrown in our route handler functions,
// this needs to be installed using `npm install express-async-handler`

const Book = require("../models/book");
const Author = require("../models/author");
const Genre = require("../models/genre");
const BookInstance = require("../models/bookinstance");

const asyncHandler = require("express-async-handler");
const author = require("../models/author");

exports.index = asyncHandler(async (req, res, next) => {
  // Get details of books, book instances, authors and genre counts (in parallel)
  const [
    numBooks,
    numBookInstances,
    numAvailableBookInstances,
    numAuthors,
    numGenres,
  ] = await Promise.all([
    Book.countDocuments({}).exec(),
    BookInstance.countDocuments({}).exec(),
    BookInstance.countDocuments({ status: "Available" }).exec(),
    Author.countDocuments({}).exec(),
    Genre.countDocuments({}).exec(),
  ]);

  res.render("index", {
    title: "Local Library Home",
    book_count: numBooks,
    book_instance_count: numBookInstances,
    book_instance_available_count: numAvailableBookInstances,
    author_count: numAuthors,
    genre_count: numGenres,
  });
});

// Display list of all books.
exports.book_list = asyncHandler(async (req, res, next) => {
  const allBooks = await Book.find({}, "title author")
    .sort({ title: 1 })
    .populate("author")
    .exec();

  res.render("book_list", { title: "Book List", book_list: allBooks });
});

// Display detail page for a specific book.
exports.book_detail = asyncHandler(async (req, res, next) => {
  res.send(`NOT IMPLEMENTED: Book detail: ${req.params.id}`);
});

// Display book create form on GET.
exports.book_create_get = asyncHandler(async (req, res, next) => {
  res.send("NOT IMPLEMENTED: Book create GET");
});

// Handle book create on POST.
exports.book_create_post = asyncHandler(async (req, res, next) => {
  res.send("NOT IMPLEMENTED: Book create POST");
});

// Display book delete form on GET.
exports.book_delete_get = asyncHandler(async (req, res, next) => {
  res.send("NOT IMPLEMENTED: Book delete GET");
});

// Handle book delete on POST.
exports.book_delete_post = asyncHandler(async (req, res, next) => {
  res.send("NOT IMPLEMENTED: Book delete POST");
});

// Display book update form on GET.
exports.book_update_get = asyncHandler(async (req, res, next) => {
  res.send("NOT IMPLEMENTED: Book update GET");
});

// Handle book update on POST.
exports.book_update_post = asyncHandler(async (req, res, next) => {
  res.send("NOT IMPLEMENTED: Book update POST");
});

authorController

const Author = require("../models/author");
const asyncHandler = require("express-async-handler");

// Display list of all Authors.
exports.author_list = asyncHandler(async (req, res, next) => {
  res.send("NOT IMPLEMENTED: Author list");
});

// Display detail page for a specific Author.
exports.author_detail = asyncHandler(async (req, res, next) => {
  res.send(`NOT IMPLEMENTED: Author detail: ${req.params.id}`);
});

// Display Author create form on GET.
exports.author_create_get = asyncHandler(async (req, res, next) => {
  res.send("NOT IMPLEMENTED: Author create GET");
});

// Handle Author create on POST.
exports.author_create_post = asyncHandler(async (req, res, next) => {
  res.send("NOT IMPLEMENTED: Author create POST");
});

// Display Author delete form on GET.
exports.author_delete_get = asyncHandler(async (req, res, next) => {
  res.send("NOT IMPLEMENTED: Author delete GET");
});

// Handle Author delete on POST.
exports.author_delete_post = asyncHandler(async (req, res, next) => {
  res.send("NOT IMPLEMENTED: Author delete POST");
});

// Display Author update form on GET.
exports.author_update_get = asyncHandler(async (req, res, next) => {
  res.send("NOT IMPLEMENTED: Author update GET");
});

// Handle Author update on POST.
exports.author_update_post = asyncHandler(async (req, res, next) => {
  res.send("NOT IMPLEMENTED: Author update POST");
});

Routes

catalog.js

// Import the Express application & create a router
const express = require("express");
// The routes are all set up on the router which is then exported
const router = express.Router();

// Require controller modules.
const book_controller = require("../controllers/bookController");
const author_controller = require("../controllers/authorController");
const genre_controller = require("../controllers/genreController");
const book_instance_controller = require("../controllers/bookinstanceController");

/// BOOK ROUTES ///

// GET catalog home page.
router.get("/", book_controller.index);

// GET request for creating a Book. NOTE This must come before routes that display Book (uses id).
router.get("/book/create", book_controller.book_create_get);

// POST request for creating Book.
router.post("/book/create", book_controller.book_create_post);

// GET request to delete Book.
router.get("/book/:id/delete", book_controller.book_delete_get);

// POST request to delete Book.
router.post("/book/:id/delete", book_controller.book_delete_post);

// GET request to update Book.
router.get("/book/:id/update", book_controller.book_update_get);

// POST request to update Book.
router.post("/book/:id/update", book_controller.book_update_post);

// GET request for one Book.
router.get("/book/:id", book_controller.book_detail);

// GET request for list of all Book items.
router.get("/books", book_controller.book_list);

/// AUTHOR ROUTES ///

// GET request for creating Author. NOTE This must come before route for id (i.e. display author).
router.get("/author/create", author_controller.author_create_get);

// POST request for creating Author.
router.post("/author/create", author_controller.author_create_post);

// GET request to delete Author.
router.get("/author/:id/delete", author_controller.author_delete_get);

// POST request to delete Author.
router.post("/author/:id/delete", author_controller.author_delete_post);

// GET request to update Author.
router.get("/author/:id/update", author_controller.author_update_get);

// POST request to update Author.
router.post("/author/:id/update", author_controller.author_update_post);

// GET request for one Author.
router.get("/author/:id", author_controller.author_detail);

// GET request for list of all Authors.
router.get("/authors", author_controller.author_list);

/// GENRE ROUTES ///

// GET request for creating a Genre. NOTE This must come before route that displays Genre (uses id).
router.get("/genre/create", genre_controller.genre_create_get);

//POST request for creating Genre.
router.post("/genre/create", genre_controller.genre_create_post);

// GET request to delete Genre.
router.get("/genre/:id/delete", genre_controller.genre_delete_get);

// POST request to delete Genre.
router.post("/genre/:id/delete", genre_controller.genre_delete_post);

// GET request to update Genre.
router.get("/genre/:id/update", genre_controller.genre_update_get);

// POST request to update Genre.
router.post("/genre/:id/update", genre_controller.genre_update_post);

// GET request for one Genre.
router.get("/genre/:id", genre_controller.genre_detail);

// GET request for list of all Genre.
router.get("/genres", genre_controller.genre_list);

/// BOOKINSTANCE ROUTES ///

// GET request for creating a BookInstance. NOTE This must come before route that displays BookInstance (uses id).
router.get(
  "/bookinstance/create",
  book_instance_controller.bookinstance_create_get
);

// POST request for creating BookInstance.
router.post(
  "/bookinstance/create",
  book_instance_controller.bookinstance_create_post
);

// GET request to delete BookInstance.
router.get(
  "/bookinstance/:id/delete",
  book_instance_controller.bookinstance_delete_get
);

// POST request to delete BookInstance.
router.post(
  "/bookinstance/:id/delete",
  book_instance_controller.bookinstance_delete_post
);

// GET request to update BookInstance.
router.get(
  "/bookinstance/:id/update",
  book_instance_controller.bookinstance_update_get
);

// POST request to update BookInstance.
router.post(
  "/bookinstance/:id/update",
  book_instance_controller.bookinstance_update_post
);

// GET request for one BookInstance.
router.get("/bookinstance/:id", book_instance_controller.bookinstance_detail);

// GET request for list of all BookInstance.
router.get("/bookinstances", book_instance_controller.bookinstance_list);

// Export the router
module.exports = router;

index.js

var express = require("express");
var router = express.Router();

/* GET home page. */
// router.get("/", function (req, res, next) {
//   res.render("index", { title: "Express Yourself!" });
// });

// GET home page.
router.get("/", function (req, res) {
  res.redirect("/catalog");
});

module.exports = router;

Views

book_list.pug

extends layout

block content
  h1= title
  if book_list.length
    ul
      each book in book_list
        li
          a(href=book.url) #{book.title}
          |  (#{book.author.name})

  else
    p There are no books.

index.pug

extends layout

block content
  h1= title
  p Welcome to #[em LocalLibrary], a very basic Express website developed as a tutorial example on the Mozilla Developer Network.

  h1 Dynamic content

  p The library has the following record counts:

  ul
    li #[strong Books:] !{book_count}
    li #[strong Copies:] !{book_instance_count}
    li #[strong Copies available:] !{book_instance_available_count}
    li #[strong Authors:] !{author_count}
    li #[strong Genres:] !{genre_count}

layout.pug

doctype html
html(lang='en')
  head
    title= title
    meta(charset='utf-8')
    meta(name='viewport', content='width=device-width, initial-scale=1')
    link(rel="stylesheet", href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css", integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N", crossorigin="anonymous")
    script(src="https://code.jquery.com/jquery-3.5.1.slim.min.js", integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj", crossorigin="anonymous")
    script(src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js", integrity="sha384-+sLIOodYLS7CIrQpBjl+C7nPvqq+FbNUBDunl/OZv93DB7Ln/533i8e/mZXLi/P+", crossorigin="anonymous")
    link(rel='stylesheet', href='/stylesheets/style.css')
  body
    div(class='container-fluid')
      div(class='row')
        div(class='col-sm-2')
          block sidebar
            ul(class='sidebar-nav')
              li
                a(href='/catalog') Home
              li
                a(href='/catalog/books') All books
              li
                a(href='/catalog/authors') All authors
              li
                a(href='/catalog/genres') All genres
              li
                a(href='/catalog/bookinstances') All book-instances
              li
                hr
              li
                a(href='/catalog/author/create') Create new author
              li
                a(href='/catalog/genre/create') Create new genre
              li
                a(href='/catalog/book/create') Create new book
              li
                a(href='/catalog/bookinstance/create') Create new book instance (copy)

        div(class='col-sm-10')
          block content

Application

app.js

const createError = require("http-errors");
const express = require("express");
const path = require("path");
const cookieParser = require("cookie-parser");
const logger = require("morgan");

// Import the routes
var indexRouter = require("./routes/index");
var usersRouter = require("./routes/users");
const catalogRouter = require("./routes/catalog"); //Import routes for "catalog" area of site

const app = express();

// DB connection
// Set up mongoose connection
// NB: just for dev purposes. Do this more safely for production
const mongoose = require("mongoose");
mongoose.set("strictQuery", false);
const mongoDB =
  "mongodb+srv://username:[email protected]/local_library?retryWrites=true&w=majority";

main().catch((err) => console.log(err));
async function main() {
  await mongoose.connect(mongoDB);
}

// view engine setup
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "pug");

app.use(logger("dev"));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());

// make Express serve all the files in the .public directory
app.use(express.static(path.join(__dirname, "public")));

app.use("/", indexRouter);
app.use("/users", usersRouter);
app.use("/catalog", catalogRouter); // Add catalog routes to middleware chain.

// catch 404 and forward to error handler
app.use(function (req, res, next) {
  next(createError(404));
});

// error handler
app.use(function (err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get("env") === "development" ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render("error");
});

module.exports = app;

www

#!/usr/bin/env node

/**
 * Module dependencies.
 */

var app = require('../app');
var debug = require('debug')('express-locallibrary-tutorial:server');
var http = require('http');

/**
 * Get port from environment and store in Express.
 */

var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);

/**
 * Create HTTP server.
 */

var server = http.createServer(app);

/**
 * Listen on provided port, on all network interfaces.
 */

server.listen(port);
server.on('error', onError);
server.on('listening', onListening);

/**
 * Normalize a port into a number, string, or false.
 */

function normalizePort(val) {
  var port = parseInt(val, 10);

  if (isNaN(port)) {
    // named pipe
    return val;
  }

  if (port >= 0) {
    // port number
    return port;
  }

  return false;
}

/**
 * Event listener for HTTP server "error" event.
 */

function onError(error) {
  if (error.syscall !== 'listen') {
    throw error;
  }

  var bind = typeof port === 'string'
    ? 'Pipe ' + port
    : 'Port ' + port;

  // handle specific listen errors with friendly messages
  switch (error.code) {
    case 'EACCES':
      console.error(bind + ' requires elevated privileges');
      process.exit(1);
      break;
    case 'EADDRINUSE':
      console.error(bind + ' is already in use');
      process.exit(1);
      break;
    default:
      throw error;
  }
}

/**
 * Event listener for HTTP server "listening" event.
 */

function onListening() {
  var addr = server.address();
  var bind = typeof addr === 'string'
    ? 'pipe ' + addr
    : 'port ' + addr.port;
  debug('Listening on ' + bind);
}

I left out files that I think are irrelevant, but let me know if I missed something and I’ll post it.

Thanks to anyone who casts there eyes over this, I appreciate the time it takes.

Prevent draggable items to overlap

I’m developing a game in React-native. I have an array of objects (tile) that are absolutely positioned on render. The snap points are a grid of 2 rows with 16 columns.

Width, height and coordinates are a property of the object. Occasionally my objects overlap each other on drag release. I don’t know exactly how it happens but I’m assuming it happens when I drag an item from the second row (y > 0) to the first row (y === 0) initially. I’ve been stuck on it for a while now and cannot figure it out.

The below is my function to handle the chain reaction. When a tile is moved to an occupied snap point, all other tiles in the chain should be moved either to the left / right and to the beginning / end of a row.

See screen recording: video

  // Function to handle chain reaction
  const handleChainReaction = (newTiles, movedTile) => {
    let tilesToCheck = [movedTile];

    while (tilesToCheck.length > 0) {
      let currentTile = tilesToCheck.shift();

      let occupiedIndex;
      do {
        occupiedIndex = newTiles.findIndex(
          (t) =>
            t.x === currentTile.x &&
            t.y === currentTile.y &&
            t.key !== currentTile.key
        );

        if (occupiedIndex !== -1) {
          let displacedTile = { ...newTiles[occupiedIndex] };
          displacedTile.x += TILE_WIDTH; // Move the tile to the right

          // Check for horizontal boundary
          if (displacedTile.x >= CONTAINER_WIDTH) {
            displacedTile.x = 0;
            displacedTile.y += TILE_HEIGHT;

            // Check for vertical boundary
            if (displacedTile.y >= TOTAL_HEIGHT) {
              displacedTile.y = 0;
            }
          }

          newTiles[occupiedIndex] = displacedTile;

          // Add the displaced tile to the check queue
          tilesToCheck.push(displacedTile);
        }
      } while (occupiedIndex !== -1);
    }

    return newTiles;
  };

Pan responder:

  const panResponder = useMemo(
    () =>
      PanResponder.create({
        onStartShouldSetPanResponder: () => true,
        onPanResponderMove: (e, gestureState) => {
          const newX = initialPan.x + gestureState.dx;
          const newY = initialPan.y + gestureState.dy;
          pan.setValue({ x: newX, y: newY });
        },
        onPanResponderRelease: (e, gestureState) => {
          const finalX = initialPan.x + gestureState.dx;
          const finalY = initialPan.y + gestureState.dy;
          const closestSnapPoint = findClosestSnapPoint(
            finalX,
            finalY,
            snapPoints
          );

          let newTiles = [...tiles]; // Clone the tiles array
          const movedTileIndex = newTiles.findIndex(t => t.key === tile.key);
          let movedTile = { ...newTiles[movedTileIndex], x: closestSnapPoint.x, y: closestSnapPoint.y };
          newTiles[movedTileIndex] = movedTile;
          newTiles = handleChainReaction(newTiles, movedTile);

          checkGroups(newTiles);

          // Animate to the closest snap point
          Animated.spring(pan, {
            toValue: { x: closestSnapPoint.x, y: closestSnapPoint.y },
            useNativeDriver: false,
            friction: 30,
            tension: 60,
          }).start();

          // Update the initial position for the next drag
          initialPan.x = closestSnapPoint.x;
          initialPan.y = closestSnapPoint.y;
        },
      }),
    [tiles]
  );

Snaps:

    for (let row = 0; row < 2; row++) {
      for (let col = 0; col < 16; col++) {
        const x = col * TILE_WIDTH;
        const y = row * TILE_HEIGHT;
        snaps.push({ x, y });
      }
    }

Example tile object:

{"color": "blue", "groupIndex": 0, "groupLength": 0, "isInGroup": false, "key": "n13-cblue", "label": 13, "number": 13, "x": 576.675, "y": 53.823}

Why is my JavaScript loading perfectly on desktop but not on mobile?

Disclaimer: I built this page six years ago and can hardly remember a damn thing about its construction anymore. I was faking it as a dev back then out of necessity but it’s not my field.

URL: https://franzbakery.com/HTML/locations

Issue: The location finder data loads just fine at desktop widths, but not mobile. Device/browser doesn’t matter. When I load the page at >767px and then shrink it to mobile view the data remains, but when I refresh (at mobile width) no data loads. The data comes from a JSON file, so perhaps the JS is fine but the JSON data won’t load on mobile..?

What I’ve tried: Frankly not much beyond poking around the files and trying to identify an obvious culprit. I’m just not versed enough in JS anymore (you could easily argue that I never was to begin with), and I’m posting here in hopes that the fix is obvious to someone that knows what they’re doing.

I can provide any specific code or additional info that might be helpful, but the issue is page-level, so there isn’t any particular code block to highlight.

Thanks so much for reading.

The contact form is still getting submitted after implementing ‘preventDefault’ in JavaScript

“I have a contact form that I only want to submit when the fields are validated. However, there are instances where it works, and other times, blank data is sent. I’ve implemented ‘preventDefault’ to avoid the form from being submitted, but the issue persists randomly. For validation, I’ve used the JavaScript code provided below. Additionally, upon successful validation and submission by the user, the form redirects to another page.

HTML Code:

<form class="registration-form">
   <div class="form-group mb-3">
      <label class="sr-only" for="form-name">First name</label>
      <input type="text" name="form-name" id="form-name" placeholder="Your Full Name"
         class="form-name form-control-lg form-control" id="form-name">
      <div class="valid-feedback valid-invalid">Valid</div>
      <div class="invalid-feedback valid-invalid">Please Enter a valid Name</div>
   </div>
   <div class="form-group mb-3">
      <label class="sr-only" for="form-email">Email</label>
      <input type="text" name="form-email" id="form-email" placeholder="Email Address"
         class="form-email form-control-lg form-control" id="form-email">
      <div class="valid-feedback valid-invalid">Valid.</div>
      <div class="invalid-feedback valid-invalid">Please Enter a valid Email Address</div>
   </div>
   <div class="form-group mb-3">
      <label class="sr-only" for="form-phone">Phone</label>
      <input type="text" name="form-phone" id="form-phone" placeholder="Mobile Number"
         class="form-phone form-control-lg form-control" id="form-phone">
      <div class="valid-feedback valid-invalid">Valid.</div>
      <div class="invalid-feedback valid-invalid">Please Enter a valid Phone Number</div>
   </div>
   <button type="submit" id="formSubmit"
      class="btn btn-primary btn-lg btn-block mt-2 shadow-lg">Submit
   Now</button>
</form>

JS code:

document.addEventListener("DOMContentLoaded", function () {
  (function () {
    emailjs.init("ignore");
  })();

  const button = document.getElementById("formSubmit");
  const name = document.getElementById("form-name");
  const email = document.getElementById("form-email");
  const phone = document.getElementById("form-phone");
  button.addEventListener("click", function (e) {
    e.preventDefault();
    const data = {
      name: name.value.trim(),
      email: email.value.trim(),
      phone: phone.value.trim(),
    };

    if (name.value.trim() === "") {
      name.classList.remove("is-valid");
      name.classList.add("is-invalid");
    } else {
      name.classList.remove("is-invalid");
      name.classList.add("is-valid");
    }

    if (
      email.value
        .trim()
        .toLowerCase()
        .match(
          /^(([^<>()[]\.,;:s@"]+(.[^<>()[]\.,;:s@"]+)*)|.(".+"))@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}])|(([a-zA-Z-0-9]+.)+[a-zA-Z]{2,}))$/
        ) &&
      email.value.trim() !== ""
    ) {
      email.classList.remove("is-invalid");
      email.classList.add("is-valid");
    } else {
      email.classList.remove("is-valid");
      email.classList.add("is-invalid");
    }

    if (
      phone.value.trim().match(/^(0|91)?[6-9][0-9]{9}$/) &&
      phone.value.trim !== ""
    ) {
      phone.classList.remove("is-invalid");
      phone.classList.add("is-valid");
    } else {
      phone.classList.remove("is-valid");
      phone.classList.add("is-invalid");
    }

    if (
      name.value.trim() !== "" &&
      phone.value.trim().match(/^(0|91)?[6-9][0-9]{9}$/) &&
      phone.value.trim !== "" &&
      email.value
        .trim()
        .toLowerCase()
        .match(
          /^(([^<>()[]\.,;:s@"]+(.[^<>()[]\.,;:s@"]+)*)|.(".+"))@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}])|(([a-zA-Z-0-9]+.)+[a-zA-Z]{2,}))$/
        ) &&
      email.value.trim() !== ""
    ) {
      emailjs
        .send("ignore", "ignore", data)
        .then(function (res) {});
      window.location = "https://example.com";
    }
  });
});

Nested For loop to create a flexbox grid, not working

I am currently working on the odin project’s Etch-A-Sketch project. I’m trying to create a flexbox grid of divs to fit inside my set container. My first attempt was a single for loop that created the enough divs based on the input being squared, but the flex wouldn’t wrap properly. Instead of creating a 16×16 grid, it would make 15 across and then 17/18 down, with space on the right side and bottom of the container.

I decided to try a new method of creating a set number of row divs with the set number of column divs inside each row. I thought having a nested for loop to create the rows with the set number of columns inside each row would work, but currently it only makes one row with one column div. Can someone help me with what I am missing?

const containerEl = document.getElementById('container');
let col = document.createElement('div');
let row = document.createElement('div');

function createGrid(input) {
    for(i = 0; i < input; i++) {
        
        row.classList.add('row');
        containerEl.appendChild(row);

        for(j = 0; j < input; j++) {
            
            col.classList.add('col');
            row.appendChild(col);
        }
        
    }
}

col.addEventListener('mouseover', function() {
    col.style.backgroundColor = 'black';
});

createGrid(16);
body {
    background-color: burlywood;
    
}

#heading {
    font-size: 100px;
    font-weight: 900;
    color: brown;
    text-align: center;
    padding: 60px;
}

#container {
    background-color: white;
    height: 960px;
    width: 960px;
    margin: auto;
}

.row {
    display: flex;
}

.col {
    border: 1px solid black;
    flex: 1;
}
<div id="heading">Etch-A-Sketch</div>
<div id="container"></div>

Issues with Splitting GeoJSON Path

Hello Stack Overflow Community,

I am working on a React application using React-Leaflet for mapping functionalities. I’m facing an issue with dynamically splitting a GeoJSON LineString path based on a slider value and then rendering this splitted path.

My GeoJSON data consists of multiple LineString features. I’m trying to split these LineStrings dynamically when a slider value changes. The slider represents a time scale (minutes), and the idea is to display only the portion of the path that corresponds to the slider’s current value.

When I place a marker on the map, it automatically finds the nearest point on a GeoJSON path, which becomes the start of the path segment I want to display. The slider I use then determines the end of this segment. Essentially, the marker sets the starting point by finding the closest path point, and the slider lets me adjust where this segment ends, allowing me to dynamically visualize specific portions of the path.

The issue with my application always rendering the same split path segment, regardless of the marker or slider position, likely stems from the fact that it’s only considering the first feature of the GeoJSON data. This means that each time I try to split and display a path segment based on the marker’s location and the slider’s value, the code is repeatedly using the first set of coordinates from the first feature in the GeoJSON file, ignoring subsequent features and their coordinates. As a result, the same path segment is displayed every time, without responding to changes in the marker or slider positions.

I’d like to mention that the code snippet I’m sharing is part of a larger experimentation process. I’m aware that it might seem unconventional or ‘messy’ as I’ve been trying out various approaches to solve this issue, including some trial-and-error methods. The main objective here is to pinpoint the root cause of the problem, and any refinement of the code will be part of future iterations. I appreciate your understanding and am looking forward to your insights and suggestions!

    function getMarkerIndex(markerPosition, sliderValue) {
        console.log('sliderValue:', sliderValue); 

        const sliderValueNumber = sliderValue[0];
        console.log('sliderValueNumber:', sliderValueNumber);

        const flattenedCoordinates = IsarDaten2.features.flatMap(feature => feature.geometry.coordinates);
        console.log('flattenedCoordinates:', flattenedCoordinates);

        const totalCoordinates = flattenedCoordinates.reduce((total, coords) => total + coords.length, 0);
        console.log('totalCoordinates:', totalCoordinates);

        let startIndex = flattenedCoordinates.findIndex(coords => coords[0] === markerPosition[0] && coords[1] === markerPosition[1]);
        console.log('startIndex:', startIndex);

        let endIndex = Math.round(sliderValueNumber * (totalCoordinates - 1));
        console.log('endIndex:', endIndex);

        if (startIndex > endIndex) {
            [startIndex, endIndex] = [endIndex, startIndex];
        }

        let splitPart = flattenedCoordinates.slice(startIndex, endIndex);

        const data = splitPart.map(([lng, lat], index, array) => {
            const value = index / (array.length - 1);
            return { lat, lng, value };
        });
        console.log('data:', data);

        setSplitLine(data);
    }

Gradient Position has nothing to do with the marker position

I’ve already attempted over 10 different solutions to address the issue in my application, including automatically reformatting the GeoJSON, manually adjusting its format, and even converting the data into a MultiLineString, but these efforts have not resolved the problem.

How to load Spotify authorisation login page in a popup?

I’m trying to open Spotify’s login page in a new popup window so that user can give my application permission to access their spotify data. I’m making a server side request to the Spotify and then sending the receiving HTML from the server to the client as per the auth flow.

The issue arises when I try to open the popup and I see nothing but three loading dots. The code I received from spotify is working as I have tested it in isolation and my popup code is also working but I can’t get both of them to work together.

HTML

<html>
  <head>
    <title> Dashboard </title>
  </head>
  <body>
    <button id='myBtn'>Click</button>
  </body>
</html>

JS

const btn = document.getElementById('myBtn');



btn.addEventListener('click', function(){
  
  const popupWindow = window.open('',  'popup', "width=600,height=450,scrollbars=no");

  const codeData = `<!DOCTYPE html>
<html id="app" lang="en" dir="ltr">
<head>
  <meta charset="utf-8">
  <title>Login - Spotify</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
  <base href="/">
  <link rel="icon" href="https://accounts.scdn.co/sso/images/favicon.ace4d8543bbb017893402a1e9d1ac1fa.ico">
  <script defer src="https://accounts.scdn.co/sso/js/indexReact.80b656d1587f8f6dc120.js" sp-bootstrap></script>
  <meta id="bootstrap-data" sp-bootstrap-data='{"phoneFeatureEnabled":true,"previewEnabled":false,"user":false,"tpaState":"AQAUyYkSh59ZWwsaoxktt0QP0peVoqudQySwwaRggIRzjIDvJXSPb1XkA+h2SMWxsB4S7lHzObldMs9cX00OyB2SBsLzsgtTmYjqR1Ep6pTiDLfTa8LwlUu7mfJr2i2ZilhhGkRzXztEVTtBeyl1JvTF2OS7QqA/bOYdFtz6yQPiJ7dA5LKaOdJQi6gIqWzfGqIXnTyxxx9Ok/uRa2YSzaPtUPGrjRAx1Z4pkUTc6QmEPJbl+fn+QiJT9LTUrIWw/0rmCj61J0EIY30wX5lFftxu7GWLorgOcG+iGluxKqGMP0dG41j8nKRZzFqV40MlgAoJOk8KYSYZ8Q4Xeeejvug+hVAQylQ1f3o98E+/KC19RPhfrENshoyNm9Xhz+aV+n3qXrTkSE/2wh0JDSVc+uK+vT0sk44eBji9FSnl2C+N+Pmn16uCOBvDaUFm+MLEdTgIwncGT6EmFamF7+JwHkf6j7aeySj6rr7NSkZBWrUivkmRi2Lsfw9B2Z5LGRtXxtAC9k/h2uhDNq9RW/WMxt6PBQEIH5AzbN8P35Ns8thrBSIr/ajViJXQ8q9rckEYMOCfsP3wABSWarVkPd8L2H5EitFYK6e5usTlEW3w3/kALZ9T+1I9LLrGIOt8XQGtvR+F1daROn83bt/oKkDuHvHYx4bX7+NnWHJHKoX2Dahta1q16auFoppSolY/XBVdCGO1J9RePaoOMja7Pj2L0LfKrePy7zse0n+0xiMQ9oZtXQ==","geoLocationCountryCode":"IN","state":"","flowCtx":"dac5b50d-741f-4095-b401-fa87bfd499f4:1705629847","BON":["0","0",-1672731924]}' sp-component="login" sp-translations-data='eyJlcnJvclRpdGxlIjoiRXJyb3IiLCJsb2dpblRpdGxlIjoiTG9naW4iLCJmb3Jnb3RZb3VyUGFzc3dvcmRVc2VybmFtZSI6IkZvcmdvdCB5b3VyIHBhc3N3b3JkPyIsImRvbnRIYXZlQW5BY2NvdW50IjoiRG9uJ3QgaGF2ZSBhbiBhY2NvdW50PyIsImlucHV0VXNlcm5hbWUiOiJFbWFpbCBhZGRyZXNzIG9yIHVzZXJuYW1lIiwiaW5wdXRFbWFpbE9yVXNlcm5hbWUiOiJFbWFpbCBvciB1c2VybmFtZSIsImlucHV0UGFzc3dvcmQiOiJQYXNzd29yZCIsImNoZWNrYm94UmVtZW1iZXJNZSI6IlJlbWVtYmVyIG1lIiwiZXJyb3JGb3JtRGVmYXVsdCI6Ik9vcHMhIFNvbWV0aGluZyB3ZW50IHdyb25nLCBwbGVhc2UgdHJ5IGFnYWluIG9yIGNoZWNrIG91dCBvdXIgPGhlbHBMaW5rPmhlbHAgYXJlYTwvaGVscExpbms+IiwiZXJyb3JJbnZhbGlkQ3JlZGVudGlhbHMiOiJJbmNvcnJlY3QgdXNlcm5hbWUgb3IgcGFzc3dvcmQuIiwiZXJyb3JJbnZhbGlkQ3JlZGVudGlhbHNJbXByb3ZlZCI6IkluY29ycmVjdCBlbWFpbCBhZGRyZXNzLCB1c2VybmFtZSBvciBwYXNzd29yZC4iLCJlcnJvclVua25vd24iOiJPb3BzISBTb21ldGhpbmcgd2VudCB3cm9uZywgcGxlYXNlIHRyeSBhZ2FpbiBvciBjaGVjayBvdXQgb3VyIDxoZWxwTGluaz5oZWxwIGFyZWE8L2hlbHBMaW5rPiIsImVycm9yVHJhbnNpZW50IjoiQW4gZXJyb3IgaGFzIG9jY3VycmVkIHByb2Nlc3NpbmcgeW91ciBsb2dpbi4gUGxlYXNlIHRyeSBhZ2Fpbi4iLCJlcnJvckZhY2Vib29rQWNjb3VudCI6IllvdSBkbyBub3QgaGF2ZSBhIFNwb3RpZnkgYWNjb3VudCBjb25uZWN0ZWQgdG8geW91ciBGYWNlYm9vayBhY2NvdW50LiBJZiB5b3UgaGF2ZSBhIFNwb3RpZnkgYWNjb3VudCwgcGxlYXNlIGxvZyBpbiB3aXRoIHlvdXIgU3BvdGlmeSBjcmVkZW50aWFscy4gSWYgeW91IGRvIG5vdCBoYXZlIGEgU3BvdGlmeSBhY2NvdW50LCA8bGlua1dpdGhIcmVmPnNpZ24gdXA8L2xpbmtXaXRoSHJlZj4uIiwiZXJyb3JTZXJ2ZXJFcnJvciI6IkFuIGVycm9yIGhhcyBvY2N1cnJlZCBwcm9jZXNzaW5nIHlvdXIgcmVxdWVzdC4gUGxlYXNlIHRyeSBhZ2Fpbi4iLCJlcnJvclVzZXJuYW1lUmVxdWlyZWQiOiJQbGVhc2UgZW50ZXIgeW91ciBTcG90aWZ5IHVzZXJuYW1lIG9yIGVtYWlsIGFkZHJlc3MuIiwiZXJyb3JVc2VybmFtZUludmFsaWRDaGFyYWN0ZXJzIjoiRm9yYmlkZGVuIGNoYXJhY3RlcihzKSB7Zm9yYmlkZGVuQ2hhcnN9IGluIHVzZXJuYW1lLiIsImVycm9yUGFzc3dvcmRSZXF1aXJlZCI6IlBsZWFzZSBlbnRlciB5b3VyIHBhc3N3b3JkLiIsImVycm9yTm9JbnRlcm5ldENvbm5lY3Rpdml0eSI6IlByb2JsZW0gY29ubmVjdGluZy4gQ2hlY2sgeW91ciBpbnRlcm5ldCBjb25uZWN0aW9uIGFuZCB7dHJ5QWdhaW5MaW5rfS4iLCJlcnJvclRyeUFnYWluIjoidHJ5IGFnYWluIiwibG9nSW4iOiJMb2cgSW4iLCJsb2dJblRvU3BvdGlmeSI6IkxvZyBpbiB0byBTcG90aWZ5Iiwic2lnblVwRm9yU3BvdGlmeSI6IlNpZ24gdXAgZm9yIFNwb3RpZnkiLCJvciI6Im9yIiwibG9naW5Ub0NvbnRpbnVlIjoiVG8gY29udGludWUsIGxvZyBpbiB0byBTcG90aWZ5LiIsImVycm9yVmFsaWRhdGlvbkludmFsaWRDb2RlIjoiVGhpcyBjb2RlIGlzIGludmFsaWQuIENoZWNrIHRoZSBTTVMgYW5kIHRyeSBhZ2Fpbi4iLCJlcnJvclN1Ym1pdFRvb2tUb29Mb25nVG9DcmVhdGUiOiJJdCB0b29rIHRvbyBsb25nIHRvIGNvbXBsZXRlIHlvdXIgcmVxdWVzdC4gVHJ5IGFnYWluLiIsImVycm9yQXBwbGVBY2NvdW50IjoiWW91IGRvIG5vdCBoYXZlIGEgU3BvdGlmeSBhY2NvdW50IGNvbm5lY3RlZCB0byB5b3VyIEFwcGxlIElELiBJZiB5b3UgaGF2ZSBhIFNwb3RpZnkgYWNjb3VudCwgcGxlYXNlIHRyeSBsb2cgaW4gd2l0aCB5b3VyIFNwb3RpZnkgZW1haWwgb3IgdXNlcm5hbWUuIElmIHlvdSBkbyBub3QgaGF2ZSBhIFNwb3RpZnkgYWNjb3VudCwgcGxlYXNlIHNpZ24gdXAuIiwiY29udGludWVXaXRoQXBwbGUiOiJDb250aW51ZSB3aXRoIEFwcGxlIiwiY29udGludWVXaXRoRmFjZWJvb2siOiJDb250aW51ZSB3aXRoIEZhY2Vib29rIiwiY29udGludWVXaXRoUGhvbmVOdW1iZXIiOiJDb250aW51ZSB3aXRoIHBob25lIG51bWJlciIsImNvbnRpbnVlV2l0aEdvb2dsZSI6IkNvbnRpbnVlIHdpdGggR29vZ2xlIiwiZXJyb3JHb29nbGVBY2NvdW50IjoiWW91IGRvIG5vdCBoYXZlIGEgU3BvdGlmeSBhY2NvdW50IGNvbm5lY3RlZCB0byB5b3VyIEdvb2dsZSBBY2NvdW50LiBJZiB5b3UgaGF2ZSBhIFNwb3RpZnkgYWNjb3VudCwgcGxlYXNlIHRyeSBsb2cgaW4gd2l0aCB5b3VyIFNwb3RpZnkgZW1haWwgb3IgdXNlcm5hbWUuIElmIHlvdSBkbyBub3QgaGF2ZSBhIFNwb3RpZnkgYWNjb3VudCwgcGxlYXNlIHNpZ24gdXAuIiwicmVjYXB0Y2hhTGVnYWxOb3RpY2UiOiJUaGlzIHNpdGUgaXMgcHJvdGVjdGVkIGJ5IHJlQ0FQVENIQSBhbmQgdGhlIEdvb2dsZSA8Z29vZ2xlUHJpdmFjeVBvbGljeUxpbms+UHJpdmFjeSBQb2xpY3k8L2dvb2dsZVByaXZhY3lQb2xpY3lMaW5rPiBhbmQgPGdvb2dsZVRlcm1zTGluaz5UZXJtcyBvZiBTZXJ2aWNlPC9nb29nbGVUZXJtc0xpbms+IGFwcGx5LiIsImxvZ2luV2l0aG91dFBhc3N3b3JkIjoiTG9nIGluIHdpdGhvdXQgcGFzc3dvcmQiLCJtYWdpY19saW5rX3BvcHVwX2hlYWRlciI6IkhhdmluZyB0cm91YmxlIGxvZ2dpbmcgaW4/IiwibWFnaWNfbGlua19wb3B1cF9ib2R5IjoiV2Ugc2VudCBhbiBlbWFpbCB3aXRoIGEgbGluayB0aGF0IHdpbGwgbG9nIHlvdSBpbiB3aXRob3V0IGEgcGFzc3dvcmQuIiwiZGlhbG9nX19hY3Rpb25fcmV0cnlfbG9naW4iOiJUcnkgYW5vdGhlciBwYXNzd29yZCJ9'>
  <style>
    body {
      background-color: #121212;
      margin: 0;
    }
    #root {
      min-height: 100vh;
    }
    .loading-indicator-container {
      height: 100vh;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    .loading-indicator-container * {
      box-sizing: border-box;
    }
    .loading-indicator {
      content: "";
      width: 56px;
      inline-size: 56px;
      block-size: 12.4px;
      height: 12.4px;
      overflow-clip-margin: content-box;
      overflow: hidden;
    }
    .loading-indicator circle {
      fill: white;
      animation: loading-indicator-kf 1.32s linear infinite;
      transform-origin: center center;
      opacity: 0.5;
    }
    .loading-indicator circle:nth-of-type(2) {
      animation-delay: 0.1s;
    }
    .loading-indicator circle:nth-of-type(3) {
      animation-delay: 0.2s;
    }
    @keyframes loading-indicator-kf {
      0% {
        animation-timing-function: cubic-bezier(1, 0, 0.7, 1);
        opacity: 0.5;
        transform: scale(1);
      }
      40% {
        animation-timing-function: cubic-bezier(0.3, 0, 0, 1);
        opacity: 0.75;
        transform: scale(1.3);
      }
      72.5% {
        animation-timing-function: linear;
        opacity: 0.5;
        transform: scale(1);
      }
      100% {
        opacity: 0.5;
        transform: scale(1);
      }
    }
  </style>
</head>
<body>
<div id="root">
  <div class="loading-indicator-container">
    <svg class="loading-indicator" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 1 100" xml:space="preserve" role="progressbar" aria-valuetext="Loading">
      <circle stroke="none" cx="-140" cy="50" r="32"></circle>
      <circle stroke="none" cx="0" cy="50" r="32"></circle>
      <circle stroke="none" cx="140" cy="50" r="32"></circle>
    </svg>
  </div>
</div>
</body>
</html>
`;
  const codeData2 = `<html><body><h1>MissingOut</h1></body></html>`
  popupWindow.document.write(codeData);  
});

Checkout this codepen to see the issue for yourself. I have tested the code in isolation, checked the consoles and the network tab but I can’t figure out why the Spotify HTML code is being changed to loading dots code in the popup.