Vue 3 mobile event listeners and swipe

In Vue 3, I want to trigger a function when a user swipes left / right. (I made a calendar and interested in having months changed on swiping)

I found this package: https://github.com/robinrodricks/vue3-touch-events (npm install vue3-touch-events) but it’s not working and I get the following errors:

and imported the relevant packages in main.js:

import Vue from "vue";
import Vue3TouchEvents from "vue3-touch-events";

and in public/index.html:

    <script src="https://raw.githubusercontent.com/robinrodricks/vue3-touch-events/master/index.js"></script>

after that, in main.js
If registered as:

createApp(App)
  .use(Vue3TouchEvents)

then I get the error: “Maximum recursive updates exceeded in component …”
And the event won’t be fired.

If registered as

Vue.use(Vue3TouchEvents);

then I get the error “export ‘default’ (imported as ‘Vue’) was not found in ‘vue'”
And the event still won’t be fired

What’s wrong? How to implement it right or make a solution in another way?
(@starttouch and mobile event listeners seems to not be supported in Vue 3)

MoxieManager TinyMCE

I have purchased MoxieManager and successfully set it up.

I can navigate to the moxiemanager-php-pro directory and see the UI below:
enter image description here

However, through the TinyMCE textbox when clicking to open the UI I see the below error:

‘Authentication failed. Server returned HTTP status: 0’

The only error I see in console is

‘TypeError: undefined is not an object (evaluating
‘moxman.ui.FloatPanel’)’

Javascript unable to capture the mouse position in dedicated variables, when I can easily print it out

So, I am getting back into javascript coding, and I am resuming an older project. I am attempting to capture the mouse position in dedicated variables (mouseX and mouseY), for ease of use.

I have successfully managed to print out the mouse coordinates in real time, but when I try to place those coordinates into dedicated variables for ease of use, the program fails.

I believe this is most likely a simple syntax error, but I don’t know where else to look for what I’m doing wrong.

This code fragment works correctly:

document.addEventListener('mousemove', (event) => {
document.getElementById("fiddleText").innerHTML = (`Mouse X: ${event.clientX}, Mouse Y: ${event.clientY}`);

})

However, when I try to store the mouse position in two variables, like so:

document.addEventListener('mousemove', (event) => {

mouseX = ${ event.clientX };
mouseY = ${ event.clientY };
document.getElementByID("fiddleText").innerHTML = ('Mouse X: ' + mouseX + 'Mouse Y: ' + mouseY);
})

the program fails.

I’d like to imagine that my question can be answered using only the code shown above, but last time I believed that, I was mistaken. As such, I have pasted my full javascript program below.

Note: This program is a work-in-progress, and there is a comment header stating “this is the problem area”; ignore this for now, that is an unrelated issue. Right now, I’m just trying to get the mouse to work.

//canvas elements
var canvas = document.getElementById("SnekGamCanvas");
var ctx = canvas.getContext("2d");
canvas.addEventListener('click', function () { }, false);

/*
//some code from stack overflow: (https://stackoverflow.com/questions/9880279/how-do-i-add-a-simple-onclick-event-handler-to-a-canvas-element)
var elem = document.getElementById('canvas'),
    elemLeft = elem.offsetLeft + elem.clientLeft,
    elemTop = elem.offsetTop + elem.clientTop,
    context = elem.getContext('2d'),
    elements = [];

// Add event listener for `click` events.
elem.addEventListener('click', function (event) {
    var x = event.pageX - elemLeft,
        y = event.pageY - elemTop;

    // Collision detection between clicked offset and element.
    elements.forEach(function (element) {
        if (y > element.top && y < element.top + element.height
            && x > element.left && x < element.left + element.width) {
            alert('clicked an element');
        }
    });

}, false);

// Add element.
elements.push({
    colour: '#05EFFF',
    width: 150,
    height: 100,
    top: 20,
    left: 15
});

// Render elements.
elements.forEach(function (element) {
    context.fillStyle = element.colour;
    context.fillRect(element.left, element.top, element.width, element.height);
});
*/
//End of code from stack overflow


//some important variables
var px = canvas.width / 2;
var py = canvas.height / 2;

var snekColor = "#EC942D";

var clock = 0;

var mouseX = 0.5;
var mouseY = 0.5;

//classes

class clickButton {
    constructor(text, color, width, height, radius) {
        this.text = text;
        this.color = color;
        this.width = width;
        this.height = height;
        this.radius = radius;
    }

    drawButton(xpos, ypos) {
        ctx.strokeStyle = "#000000"
        ctx.fillStyle = this.color;

        roundRect(xpos, ypos, this.width, this.height, this.radius, true, true, this.color);

        ctx.fillStyle = "#000000";
        ctx.strokeStyle = "#000000";
        ctx.font = '40px san-serif';

        ctx.strokeText(this.text, xpos + 10, ypos + 40);
        ctx.fillText(this.text, xpos + 10, ypos + 40);

        //draw_Ball(303, 500, 50, snekColor);
    }

    clickOnButton() {

    }

}

//buttons

var startButton = new clickButton("Start Game", "#74B5ED", 200, 50, 20);

//images
var seel = new Image();
seel.onload = function () {
    ctx.drawImage(seel, 0, 0, canvas.width, canvas.height);
}
seel.src = "https://assets.pokemon.com/assets/cms2/img/pokedex/full/086.png"

var snek_title = new Image();
snek_title.onload = function () {
    ctx.drawImage(snek_title, 0, 0, canvas.width, canvas.height);
}
snek_title.src = "https://globin347.com/images/Snake%20Title.png"

//stuff about mouse moving

document.addEventListener('mousemove', (event) => {
    //document.getElementById("fiddleText").innerHTML = (`Mouse X: ${event.clientX}, Mouse Y: ${event.clientY}`);

    
    mouseX = ${ event.clientX };
    mouseY = ${ event.clientY };
    document.getElementByID("fiddleText").innerHTML = ('Mouse X: ' + mouseX + 'Mouse Y: ' + mouseY);
    
})

//begin
var gameState = 0;

function draw() {

    clock += 1;
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    //document.getElementById("fiddleText").innerHTML = ("Clock: " + clock);

    if (gameState == 0) {
        //this hasn't been implemented yet
        startMenu();
    }
    else if (gameState == 1) {
        //this hasn't been implemented yet either
        playGame();
    }
    else if (gameState == 2) {
        //ditto
        gameOver();
    }
    else {
        //something's wrong

        ctx.drawImage(seel, 0, 0, canvas.width, canvas.height);

        ctx.fillStyle = "#b30000";
        ctx.strokeStyle = "#000000";
        ctx.font = '140px san-serif';

        ctx.fillText('OH NO', 120, 120);
        ctx.strokeText('OH NO', 120, 120);

        ctx.fillText('IT BLOKE', 200, 630);
        ctx.strokeText('IT BLOKE', 200, 630);
    }

}
setInterval(draw, 10);

function startMenu() {
    ctx.drawImage(snek_title, 0, 0, canvas.width, canvas.height);

    /***********************************************
     * 
     * 
     * This is the problem area. When the next line, startButton.drawButton(100, 100) is commented out, the rest of the code workes normally.
     * However, if the line is not commented out, draw_Ball doesn't run, indicating that the program crashed somewhere in the button code.
     * I would like to reiterate that the button's functionality has not yet been implemented; I am only trying to get it to display.
     * 
     * 
     **********************************************/

    //startButton.drawButton((canvas.width / 2) - 100, (canvas.height * (4 / 5)));

    //flashing lights
    /*flashTime = timer % 100;
    if (timer % 2) {
        draw_Ball(200, 700, 50, snekColor);
    }*/

    draw_Ball(200, 700, 50, snekColor);
}

function playGame() {
    draw_Ball(200, 700, 50, snekColor);
    draw_Ball(400, 700, 50, snekColor);
    draw_Ball(300, 500, 50, snekColor);
}

function gameOver() {

}

//this function was stolen from stack overflow
function showImage(width, height, image_source, alt_text) {
    var img = document.createElement("img");
    img.src = image_source;
    img.width = width;
    img.height = height;
    img.alt = alt_text;

}

function draw_Ball(bx, by, size, ballColor) {
    ctx.beginPath();
    ctx.arc(bx, by, size, 0, (Math.PI * 2));
    ctx.fillStyle = ballColor;
    ctx.fill();
    ctx.strokeStyle = "#000000";
    ctx.stroke();
    ctx.closePath();
}

//This next function was taken from stack overflow

function roundRect(x, y, width, height, radius, stroke, fill, color) {
    ctx.beginPath();
    ctx.moveTo(x + radius, y);
    ctx.lineTo(x + width - radius, y);
    ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
    ctx.lineTo(x + width, y + height - radius);
    ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
    ctx.lineTo(x + radius, y + height);
    ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
    ctx.lineTo(x, y + radius);
    ctx.quadraticCurveTo(x, y, x + radius, y);
    if (stroke) {
        ctx.stroke();
    }
    if (fill) {
        ctx.fill();
    }
    ctx.closePath();
    return;
}

And, for good measure, my HTML and CSS files:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - Portfolio</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="~/css/site.css" />
</head>
<body class="background_gradient">
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-dark dark-bg border-bottom box_shadow mb-0">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">Portfolio</a>
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
                        </li>
                        <!--
                        <li class="nav-item">
                            <a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
                        </li>
                        -->
                        <li class="nav-item">
                            <a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Resume">Resume</a>
                        </li>
                        <!----
                        <li class="nav-item">
                            <a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Art3D">3D Art</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Art2D">2D Art</a>
                        </li>
                        <!---->
                        <li class="nav-item">
                            <a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Snake">Snake</a>
                        </li>
                        
                        <li class="nav-item">
                            <a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="CodeExamples">Code Examples</a>
                        </li>

                        <li class="nav-item">
                            <a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Ballad">Ballad of the Masked Bandits</a>
                        </li>
                        <!--
    <li class="nav-item">
        <a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="DataBaseHub">Database Hub</a>
    </li>
    --->
                        <!--
    <li class="nav-item">
        <a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Unavailable">???</a>
    </li>
        -->
                        <!--Temporary Links-->
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container-fluid" id="MainDiv">
        <main role="main" class="pb-0" style="width:100%">
            <!--Where the other code goes-->
            
                @{
                    ViewData["Title"] = "Snake Game";
                }
                
                <div class="container-fluid purple_gradient text-center">
                    <h1>Snake Game</h1>
                </div>
                <div class="buffer"></div>
                <div class="container">
                    <div class="fancy_text_box">
                        <div class="container buffer">
                            <div class="ghostly_text_box text-center">
                                <h1>By the power of Javascript, here is a playable snake game.</h1>
                                <div class="buffer"></div>
                                <h1 id="fiddleText">Give it a moment to load.</h1>
                            </div>
                
                            <div class="buffer"></div>
                
                            <div class="ghostly_text_box text-center">
                                <canvas onload="draw()" class="simple_text_box" id="SnekGamCanvas" width="1000" height="1000"></canvas>
                            </div>
                
                        </div>
                
                    </div>
                
                    <div class="text-center">
                        <div class="buffer"></div>
                
                        <a class="button glo_button big_r_button big_text" asp-area="" asp-controller="Home" asp-action="Index">Back to Home</a>
                
                        <div class="buffer"></div>
                    </div>
                
                    <!--The code be here but if you are reading this you probably already knew that-->
                    <script src="~/js/Snake.js"></script>
                
                </div>
                
        </main>
    </div>

    <footer class="border-top footer dark-bg text-light">
        <div class="container">
            &copy; 2021 - Portfolio - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
        </div>
    </footer>
    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>
    <script src="../jsc3d-master/jsc3d/jsc3d.js"></script>
    @RenderSection("Scripts", required: false)
</body>
</html>


/* Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
for details on configuring this project to bundle and minify static web assets. */

a.navbar-brand {
  white-space: normal;
  text-align: center;
  word-break: break-all;
}

/* Provide sufficient contrast against white background */
a {
  color: #0366d6;
}

.btn-primary {
  color: #fff;
  background-image: linear-gradient(30deg, #b6e2dd, #2a5efe);
  border-color: #1861ac;
}

/*Link colors*/
.nav-pills .nav-link.active, .nav-pills .show > .nav-link {
  color: #fff;
  background-color: #1b6ec2;
  border-color: #1861ac;
}

/* Sticky footer styles
-------------------------------------------------- */
html {
  font-size: 14px;
}
@media (min-width: 768px) {
  html {
    font-size: 16px;
  }
}

.border-top {
  border-top: 1px solid #e5e5e5;
}
.border-bottom {
  border-bottom: 1px solid #e5e5e5;
}

.box-shadow {
  box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
}

button.accept-policy {
  font-size: 1rem;
  line-height: inherit;
}

/* Sticky footer styles
-------------------------------------------------- */
html {
  position: relative;
  min-height: 100%;
}

body {
  /* Margin bottom by footer height */
  margin-bottom: 60px;
}
.footer {
  position: absolute;
  bottom: 0;
  width: 100%;
  white-space: nowrap;
  line-height: 60px; /* Vertically center the text there */
}

/* My Stuff
--------------------------------------------------------------------------
--------------------------------------------------------------------------
--------------------------------------------------------------------------
*/

/*This gives me more control over the exact dark background color*/
.dark-bg
{
    background-color: #161631;
}

.purple_gradient 
{
    /*The image used*/
    background-image: linear-gradient(#4b1ac4, #fff);

    height:100%;
    width:100%;

    background-position: center;
    background-repeat: no-repeat;
    background-size: cover;
}

.test_box_blue
{
    /* A container with a solid color and an outline */
    background-color: #2d1eb2;

    width: 100%;
    height: 100%;
    margin: 0px;

}

.test_box
{
    border:solid #000000;
}

#MainDiv
{
    padding:0;
    margin:0;

    left:0;
    top:0;

    width:100%;
    height:100%;
}

.tundra_backround
{
    background-image: url('../images/Tundra_Fixed.png');
    width:100%;
    height:100%;
}

.white_space_box
{
    height:50 px;
}

.background_gradient
{
    background-image:linear-gradient(320deg, #fff, #96cbde);
}

.glo_button
{
    min-width: 30%;
    height: 20%;
    border-radius: 25px;
    padding: 20px;
    margin: 10px;
    box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.19);
    transition-duration: 0.4s;
    border: 4px solid #000;
}

.big_r_button {
    background-color: #a10000;
    color: #fff;
}

.big_r_button:hover {
    color: #fff;
    background-color: #4e0505;
}

.big_b_button {
    background-color: #080e9f;
    color: #fff;
}

.big_b_button:hover {
    color: #fff;
    background-color: #161631;
}

.big_g_button {
    background-color: #0a7727;
    color: #fff;
}

.big_g_button:hover {
    color: #fff;
    background-color: #07340e;
}

.big_p_button {
    background-color: #6f1cbf;
    color: #fff;
}

.big_p_button:hover {
   color: #fff;
   background-color: #2a073e;

}

.buffer
{
    padding: 20px;
}

.big_text
{
    font-size: 60px;
    font-family:'Times New Roman', Times, serif;
    text-shadow: 2px 2px rgb(12 14 39 / 0.67);
}

.fancy_text_box{
    background-image: linear-gradient(300deg, #ece1c4, #c99e69);
    border-radius: 25px;
    border: 4px solid #5d3c08;
}

.simple_text_box{
    background-color: #fff;

    border: 2px solid #000;
}

.ghostly_text_box{
    background-color: rgb(255 255 255 / 0.60);
    border-radius: 25px;
    padding: 10px;
    border: 3px solid #000;
}

.thick_border{
    border: 4px solid #000;
}

.black_and_white_gradient{
    background-image: linear-gradient(310deg, #fff, #000);
}

.red_border{
    padding: 0px;
    margin: 0px;
    border: 4px solid #8f0000;
}

.model_box{
    border: 4px solid #000;
    background-color: #fff;
    border-radius: 25px;
}

.image_box{
    border: 4px solid #000;
    background-color: #fff;
}

.chain_image_box {
    border-top: 4px solid #000;
    border-left: 4px solid #000;
    border-right: 4px solid #000;
    border-bottom: 0px;
    background-color: #fff;
}

.margin_setter {
    margin: 20px;
    padding: 20px;
}

#model_display_1{

}

I apologize for asking such a simple question, but I don’t know where to look to find an existing answer.

Mapbox popups in a React app not showing up after deploying to Heroku

I have a Mapbox installed in my React app which shows up popups, but only when working in localhost. When I deploy to Heroku the styles look broken. They look a bit faded so I guess it’s the styles which are broken, but I’m a bit lost wondering what I could change. We are also using bootstrap to style some components.

Popup in localhost /
Popup in Heroku

This is the styles file in apps.css

.mapboxgl-popup-content{
  background: none !important;
  padding: 0 !important;
}

.popup-border {
  background: linear-gradient(to right, rgb(255, 189, 65), rgb(255, 200, 255));
  padding: 4px;
  border-radius: 10%;
  opacity: 100%;
}

.popup-content {
  margin: auto;
  color: black;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  border-radius: 10%;
  background-color: white;
  min-width: 250px;
  opacity: 85%;
}

.popup-title {
  padding: 0px 20px;
  align-items: center;
  justify-content: center;
  text-align: center;
}

.popup-description {
  margin: 0;
  padding: 0px 20px;
  align-items: flex-start;
  justify-content: center;
  text-align: center;
}

.popup-owner-attendees {
  display: flex;
  flex-direction: row;
  justify-content: space-evenly;
  text-align: center;
  padding: 0px 20px;
}

.popup-list-title {
  text-decoration: underline;
}
.orange-text {
  color: orange;
  border-bottom: 1px solid orange;
}

In case it helps, this is also the code for the popup inside the React component:

     {selectedEvent ? (
        <Popup
          latitude={selectedEvent.location[1]}
          longitude={selectedEvent.location[0]}
          onClose={() => {
            setSelectedEvent(null);
          }}
        >
          <div>
            <br />
            <h4>
              {selectedEvent.icon} {selectedEvent.title}
            </h4>
            <p>{selectedEvent.description}</p>
            <p>
              Host:
              {selectedEvent.owner
                ? "@" + selectedEvent.owner.username
                : "Anonymous"}
            </p>
            <p>
            {/* ATTENDEES IS NOT BEING POPULATED  */}
              Attendees:
              <ul>
                {selectedEvent.attendees.map((attendee) => {
                  return <li>{attendee.username}</li>;
                })}
              </ul>
            </p>
          </div>
        </Popup>
      ) : null}

How to implement pipe function with arg AND …funcs?

const replaceUnderscoreWithSpace = (value) => value.replace(/_/g, ' ')
const capitalize = (value) =>
    value
        .split(' ')
        .map((val) => val.charAt(0).toUpperCase() + val.slice(1))
        .join(' ');
const appendGreeting = (value) => `Hello, ${value}!`

const pipe = (value, ...funcs) => value => funcs.reduce((value, f) => f(value), value)

I`m trying to implement pipe function, but I can`t get how to make it work so it takes param “value” as argument.

Example

const result = pipe(
  "john_doe",
  replaceUnderscoreWithSpace,
  capitalize,
  appendGreeting,
);
 
alert(result); // Hello, John Doe!

Why am I getting error when using setAttribute() every time I type it?

So I am using Vanilla JavaScript, and I am having trouble using setAttribute(). It is giving me errors every time I try to use it. I am trying to make a challenge without using a lot of HTML just CSS and JS. Here is the code.

<script>
window.onload = function () {
    var el = document.querySelector("#home");
    el.setAttribute("href", "http://oyopages.com/p/61b8ab61666e4dc7d5f630e0.html");
} 
</script>

Is there a way to block while waiting for a websocket response in the browser?

Perhaps by (mis)using some legacy API?
Are there browser plugins that can do this?

I am in a controlled environment, so solutions involving browser plugins or browser modifications are welcome.

Background:
I have some JS running in an embedded JavaScript VM, using custom methods exposed from C++. These custom methods are synchronous (there is no need for them to be asynchronous).

For testing and development, I want to be able to run the same JS code in the browser. As the browser does not have my custom C++ methods, I need to call them remotely.
Today, I’m using a blocking XMLHttpRequest (deprecated in most browsers, but still works) to do this.

The problem is that making an HTTP-request has some overhead and is relatively slow (in the 20-50 ms range). WebSockets are much faster (roundtrip in a few ms), but as they are inherently asynchronous, I can’t use it to replace my blocking functions.

Puppeteer Select Table row/option

Working on some code that will select a table option that gets built out after an option is selected from a drop-down menu. Don’t have access to github atm to check puppeteer documentation so I’m looking for how to adapt a line similar to
let optionValue = await page.$$eval('option', options => options.find(o => o.innerText === "Quality")?.value)

await page.select('#selDept', optionValue); in order to select the proper table row using either the id tag or the innerText of either “Stephen_Test” or the hidden cell measure id “1640”. I believe selecting the measure id 1640 would be preferable so that I can also save that id as a variable that could be used elsewhere later on in the project if needed. I just don’t have prior experience with nodeJS/puppeteer to know how to adjust this line to what I’m looking for so any help is appreciated.

Current puppeteer code

const puppeteer = require('puppeteer');

(async () => {
    const browser = await puppeteer.launch({headless: false});
    
    const page = await browser.newPage();
    
    await page.authenticate({'username': username, 'password': password});
    
    await page.goto('http://10.10.4.80/index-test-sh.html') //this is an intranet site for the company I work at
    
    await page.waitForTimeout(4000);
    await page.waitForSelector('#selDept');
    
    await page.waitForTimeout(4000);
    let optionValue = await page.$$eval('option', options => options.find(o => o.innerText === "Quality")?.value)
    await page.select('#selDept', optionValue);
    
    await page.waitForTimeout(4000);
    let measureValue = await page.$$eval('td', td => td.find(t => t.innerText === "Stephen_Test")?.value)
    await page.select('#Output', measureValue);
    
    await page.waitForTimeout(4000);
    //await browser.close();
    
})();

Table is built with this loop:

for (var i = 0; i < arr.length; i++) {  
        txtTable = txtTable + "<tr id='row" + i + "'>"; //altered this to have unique row ID's
        txtTable = txtTable + "<td style='width:30%;'>" + arr[i].departmentName + "</td>";      
        txtTable = txtTable + "<td id='measureId" + arr[i].measureId + "' style='display:none; width:10%;'>" + arr[i].measureId + "</td>"; //altered this to include an id using measureId  
        txtTable = txtTable + "<td style='width:40%;'>" + arr[i].qmsMeasure + "</td>";      
        txtTable = txtTable + "<td style='width:20%;'>" + arr[i].measureSltOwner + "</td>";
        txtTable = txtTable + "</tr>";
        
    };//End Loop

HTML generated after option is selected (contains about 10 rows, just showing the one I want to select)

<div class="OptionTable DisplayScrollBar">
<table id="Output">
  <thead>
    <tr>
      <th style="width: 30%;">Department Name</th>
      <th style="width: 10%;display:none;">Report ID</th>
      <th style="width: 40%;">Measure Name</th>
      <th style="width: 20%;">SLT Measure Owner</th>
    </tr>
  </thead>
  <tbody>
    <tr id="row0">
      <td style="width:30%;">Quality</td>
      <td id="measureId1640" style="display:none; width:10%;">1640</td>
      <td style="width:40%;">Stephen_Test</td>
      <td style="width:20%;">null</td>
    </tr>
  </tbody>
</div>

How to prevent React component from re-rendering when I am changing routes?

I have React components: allUsersList and userDetail. In the first one I am fetching all of the users and displaying them and by clicking each of them I am changing route and going to the second component but when I click arrow to go back on browser first component starts fetching data and re-rendering again. Could you please tell me how an I prevent it from doing extra re-render?

This is the AllUsers component:

import React, {useEffect, useMemo} from 'react';
import { Link } from 'react-router-dom';
import { useSelector, useDispatch } from 'react-redux';
import {setAllUsers, setLoading, setPage} from '../redux/actions/actions';
import User from './User';
import '../styles/AllUsersList.css';

const AllUsersList = () => {
    const allUsers = useSelector(state => state.setAllUsersReducer);
    const page = useSelector(state => state.setPageReducer);
    const loading = useSelector(state => state.setLoadingReducer);
    const dispatch = useDispatch();
  

    const fetchAllUsers = () => {
       fetch(`${url}/${page}/15`)
            .then(res => res.json())
            .then(data => {
                dispatch(setAllUsers(data.list));
            })
            .catch(err => console.log('Error message: ', err))
    }

    useEffect(() => {
      fetchAllUsers();
    }, [page])

    const handleScroll = () => {
        dispatch(setPage());
    }

    window.onscroll = function () {
        if(window.innerHeight + document.documentElement.scrollTop === document.documentElement.offsetHeight) {
            handleScroll();
        }
    }


    return (
        <div className="allUsersList">
            {
                allUsers ? (
                    allUsers.map((user, index) => (
                        <Link key={user.id} to={`/user/${user.id}`}>
                            <User name={user.name} lastName={user.lastName} prefix={user.prefix} title={user.title} img={user.imageUrl}/>
                        </Link>
                    ))
                ) : (
                    <div> Loading... </div>
                )
            }
        </div>
    )
}

export default AllUsersList;

Here is UserDetails component:

import React, {useEffect} from 'react';
import {useParams} from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux';
import { setSelectedUser, removeUser, setSelectedUsersHistory } from '../redux/actions/actions';

export const UserDetails = () => {
    const selectedUser = useSelector(state => state.setSelectedUserReducer);
    const selectedUsersHistory = useSelector(state => state.setSelectedUsersHistoryReducer);
    const dispatch = useDispatch();
    const {userId} = useParams();
    const fetchUserDetails = () => {
        fetch(`${url}/${userId}`)
            .then(res => res.json())
            .then(data => {
                 dispatch(setSelectedUser(data));
              }
            )
            .catch(err => console.log('Error message: ', err))
    }

    useEffect(() => {
        if(userId && userId!=='') fetchUserDetails();
        
        return () => {
            dispatch(removeUser())
        }
    }, [userId])


    return (
        <div className="userDetails">
            {
                Object.keys(selectedUser).length === 0 ? (
                    <div>Loading...</div>
                ) : (
                    <div>{selectedUser.name}</div>
                )
            }
        </div>
    )
}

export default UserDetails;

And here is the App,js with routes:

import React from 'react';
import AllUsersList from './components/AllUsersList';
import UserDetails from './components/UserDetails';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';

function App() {

  return (
    <div className="App">
      <Router>
        <Switch>
          <Route path="/" exact component={AllUsersList} />
          <Route path="/user/:userId" exact component={UserDetails} />
        </Switch>
      </Router>
 
    </div>
  );
}

export default App;

Bootstrap – sticky navbar and smoothscroll – padding/margin-top

Trying to implement a bootstrap sticky navbar (fixed height of 81px) with smooth-scroll behavior.

The HTML site features section tags, such as <section class="section" id="news">, which works fine in order to jump to certain areas by using <a class="nav-link" href="#news">News</a> in the navbar. I am using the following CSS and JS technologies, loaded right at the beginning of the <body>:

So far it works: at the bootstrap specific --breakpoint-lg at 992px the navbar collapses into a burger menu. Now in order to compensate for the fixed-height navbar I added the following code to my custom.css (loaded after the bootstrap.min.css of course), according to a trick found at https://css-tricks.com/fixed-headers-on-page-links-and-overlapping-content-oh-my/

@media (max-width: 991px) {
  section {
    padding-top: 382px;
    margin-top: -382px;
  }
}

@media (min-width: 992px) {
  section {
    padding-top: 80px;
    margin-top: -80px;
  }
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l" crossorigin="anonymous">

This works fine on larger dimensions of the browser window width, but as soon as it’s loaded on smaller width windows (991px and below) – hence on almost all mobile devices – clicking the navbar-link jumps to a point slightly vertically offset. Any ideas why this happens? It seems my media-query for max-width: 991px is being ignored.

Lodash.cloneDeep: unable to edit property of cloned object [discord.js execute command]

I’m currently trying to make an ~execute command for my bot. This command will allow me to execute commands as other users, thereby allowing to provide better debugging.

An example of this would be something like:

Example of the ~execute command in use, on an already-working instance.

In essence, what I want/need to do in this command is:

  1. grab the message object
  2. clone the message object
  3. edit the cloned message object such that its author and member are different, but everything else remains the same.
  4. pass this new object through client.emit("messageCreate", <NewMessageObject>).

I’ve tried the following…

JSON.parse(JSON.stringify(…))

This one was actually the most promising, however, it did not copy over all the "special" stiff -- during my research, I learned that this method only works well for primitive data types.

const cloned = JSON.parse(JSON.stringify(message));
// the normal functions/methods such as message.reply and message.guild.members.fetch were undefined.

By “most promising”, I mean that this method actually copied the guild object and everything else.

Note that JSON method will loose any Javascript types that have no equivalent in JSON. For example: JSON.parse(JSON.stringify({a:null,b:NaN,c:Infinity,d:undefined,e:function(){},f:Number,g:false})) will generate {a: null, b: null, c: null, g: false} – @oriadam

Source: a comment on this question (What is the most efficient way to deep clone an object in JavaScript?)

Lodash’s cloneDeep()

I found this question (What is the most efficient way to deep clone an object in JavaScript?), and saw this. I tried it, however, it doesn’t seem to work. By “doesn’t seem to work”, I mean that when I attempt to reassign certain properties, it doesn’t do anything. Here’s my current code, which shuold hopefully make it easier to understand what I mean:

        // this is the code inside my command. I've removed the fluff to make it easier to read. It is inside an async function.
        const { cloneDeep } = require("lodash");
        const user = await client.config.fetchUser(args[0]); // works fine -- identifies user perfectly. eg User { id: '' ... }
        if (!user) return message.reply({ content: `Invalid user "${args[0]}"`, allowedMentions: { parse: [] } });
        console.log(cloneDeep(message)) // again, this bit is also fine - it logs a message object.
        const cloned = cloneDeep(message);
        cloned.author = user;
        console.log(cloned.author); // everything works fine - the user is changed fine.
        cloned.content = message.guild.prefix + args.slice(1).join(" ");
        cloned.emit = true;
        client.emit("messageCreate", cloned);

Note: the only 2 properties that were changed are: author and content. Everything else in the message object should remain the same, such as guild, channel, etc.

I’m getting this error:

TypeError: Cannot read properties of undefined (reading 'guilds') [index.js:478:15]

enter image description here

The error is pointing to this line in the messageCreate event:

    if (!message.guild || (message.author.bot && (!cst.includes("wl"))) || (message.system) || (message.webhookId)) return;

From what I gathered, in this context, the error basically meant that message.guild (and, in turn) cloned.guild was undefined. (as we were parsing the cloned object into the messageCreate event. This isn’t an issue with anything else, as all other commands work fine. Even ones done in dms.)

Next, I added console.log(cloned.guild) to the code, expecting a Guild object. Instead, I got the same error message: TypeError: Cannot read properties of undefined (reading 'guilds').

Simply adding cloned.guild = message.guild; has not seemed to fix the issue. It has resulted in the same error. I have checked the value of message.guild, and it is indeed a Guild object.

Here’s the final code which I’m currently working with:

./cmds/execute.js

const { Message } = require("discord.js");
const { cloneDeep } = require("lodash");

module.exports = {
    name: "execute",
    aliases: ["execute", "exec"],
    async run(client, message, args) {
        if (args.length < 2) return message.reply("You must specify a user and a command to execute as the user in order for this command to work!");
        const user = await client.config.fetchUser(args[0]);
        if (!user) return message.reply({ content: `Invalid user "${args[0]}"`, allowedMentions: { parse: [] } });
        const cloned = cloneDeep(message);
        cloned.author = user;
        cloned.content = message.guild.prefix + args.slice(1).join(" ");
        cloned.emit = true;
        // works FINE till here. For some reason, cloned.guild just doesn't work...
        cloned.guild = message.guild;
        client.emit("messageCreate", cloned);
    },
};

This is what a properly formed message object should look like:

<ref *1> Message {
  channelId: '911802238442287124',
  guildId: '911784758600679455',
  deleted: false,
  id: '920762096373891134',
  createdTimestamp: 1639597190708,
  type: 'DEFAULT',
  system: false,
  content: '~eval message',
  author: User {
    id: '501710994293129216',
    bot: false,
    system: false,
    flags: [UserFlags],
    username: 'Paradox',
    discriminator: '1234',
    avatar: 'fd6c2479694970c0a357155bd43860d4',
    banner: undefined,
    accentColor: undefined,
    debug: false, // this is a custom property that I've attached myself - isnt here by default. same with color and colors.
    color: 'RANDOM',
    colors: [Array]
  },
  pinned: false,
  tts: false,
  nonce: '920762095794913280',
  embeds: [],
  components: [],
  attachments: Collection(0) [Map] {},
  stickers: Collection(0) [Map] {},
  editedTimestamp: null,
  reactions: ReactionManager { message: [Circular *1] },
  mentions: MessageMentions {
    everyone: false,
    users: Collection(0) [Map] {},
    roles: Collection(0) [Map] {},
    _members: null,
    _channels: null,
    crosspostedChannels: Collection(0) [Map] {},
    repliedUser: null
  },
  webhookId: null,
  groupActivityApplication: null,
  applicationId: null,
  activity: null,
  flags: MessageFlags { bitfield: 0 },
  reference: null,
  interaction: null
}

And this is what the deepCloned one looks like:

<ref *1> Message {
  channelId: '911802238442287124',
  guildId: '911784758600679455',
  deleted: false,
  id: '920762763272392715',
  createdTimestamp: 1639597349709,
  type: 'DEFAULT',
  system: false,
  content: '~bal',
  author: User {
    id: '504619833007013899',
    bot: false,
    system: false,
    flags: UserFlags { bitfield: 0 },
    username: 'ephemeral',
    discriminator: '2341',
    avatar: '2f274547855bf700b44408c593d37cad',
    banner: undefined,
    accentColor: undefined
  },
  pinned: false,
  tts: false,
  nonce: '920762762311761920',
  embeds: [],
  components: [],
  attachments: Collection(0) [Map] {},
  stickers: Collection(0) [Map] {},
  editedTimestamp: null,
  reactions: ReactionManager { message: [Circular *1] },
  mentions: MessageMentions {
    everyone: false,
    users: Collection(0) [Map] {},
    roles: Collection(0) [Map] {},
    _members: Collection(0) [Map] {},
    _channels: null,
    crosspostedChannels: Collection(0) [Map] {},
    repliedUser: null
  },
  webhookId: null,
  groupActivityApplication: null,
  applicationId: null,
  activity: null,
  flags: MessageFlags { bitfield: 0 },
  reference: null,
  interaction: null,
  emit: true
}

PACKAGE.JSON DEPENDENCY VERSIONS:

  "dependencies": {
    "@keyv/mysql": "^1.1.4",
    "@keyv/sqlite": "^2.0.2",
    "babel-plugin-syntax-class-properties": "^6.13.0",
    "babel-plugin-transform-class-properties": "^6.24.1",
    "bootstrap": "^4.5.2",
    "delay": "^4.4.1",
    "discord.js": "^13.0.0",
    "discord.js-reaction-menu": "^1.0.2",
    "dotenv": "^8.2.0",
    "enmap": "github:eslachance/enmap#v3",
    "enmap-mongo": "^2.0.2",
    "express": "^4.17.1",
    "express-session": "^1.17.1",
    "helmet": "^4.1.1",
    "keyv": "^4.0.0",
    "lodash": "^4.17.21",
    "lodash.clonedeep": "^4.5.0",
    "mathjs": "^7.2.0",
    "moment": "^2.27.0",
    "mongochrome": "0.0.3",
    "mongoose": "^5.10.7",
    "morgan": "^1.10.0",
    "ms": "^2.1.3",
    "mysql": "^2.18.1",
    "node-fetch": "^2.6.0",
    "node-os-utils": "^1.2.2",
    "passport": "^0.4.1",
    "passport-discord": "^0.1.4",
    "pug": "^3.0.0",
    "quickmongo": "^2.0.1",
    "serve-favicon": "^2.5.0",
    "sqlite3": "^5.0.2",
    "statcord.js": "^3.1.0",
    "uptime-robot": "^1.3.0"
  }

node: v16.10.0

I’ve tried my best to construct a good question. Apologies if this is unclear. If any further information is required, please do let me know.

How do I submit value of a “custom” input in a form?

I’m wirting a CRUD application and I ran into this problem today:
There’s a form where user can set the entry’s priority (basically a number from 1 to 3). But instead of an input with type=”number” or anything similar, I created a “custom” input. It’s a small circle that changes colors when you click it (colors represent numbers from 1 to 3). My question is: how do I submit this value to the form?

The solution I came up with was to use an input with type=”hidden” and before the form is submitted, javascript changes the input’s “value” attribute to match the number selected in the “custom” input. This seems to be working but according to MDN type=”hidden” inputs are used for “data that cannot be seen or modified by users when a form is submitted”, so I’m guessing this is not a typical solution to this kind of problem. Is there some kind of agreed upon method for this problmes like this?