Horizontal split resizing screen dynamic component in angular

I am creating a dynamic component that can contain multiple full-height panel components, where their widths can be resized and adjusted.

For example:

enter image description here

First of all, the container width must always be filled, you can’t have free space.

If I want to increase the size of A, it will decrease the size of B accordingly. If B has reached it’s minimum width, it will try and resize C, and so on till it can’t resize anyone else and the resize function will stop.

This works perfectly fine. However, now I want to do the same for decreasing width.
Let’s say I want to decrease the width of B, what happens now is that it will automatically increase the width of C, but what if B has reached it’s minimum width? it should try and decrease the previous siblings sizes, so A’s width should be decreased accordingly as much as possible.

This creates the effect of pushing panels when resizing.

when I say “decrease B’s width”, it means increasing C. same as if I want to increase A’s width and it will decrease everything else one after another until it cannot resize anymore and reached the max available space.

Stackblitz: https://stackblitz.com/edit/stackblitz-starters-ftujzx?file=src%2Fapp%2Fpages%2Fpages%2Fplatform%2Fhelpers%2Fproject.helper.ts

You can resize by hovering the side borders of every panel

What I did

MouseDown to initialize the resizing:

  @HostListener('mousedown', ['$event'])
  onMouseDown($event: MouseEvent): void {
    $event.preventDefault();
    if (!$event.target) {
      return;
    }

    if (!($event.target instanceof HTMLElement)) {
      return;
    }

    const target = $event.target as HTMLElement;

    if (target.className !== 'split-resize-toggle') { // Todo use the IDynamicHorizontalSplitChild abstraction to get the toggle element to make it dynamic
      return;
    }

    const id = target.id;
    if (!id) {
      return;
    }

    this.currentResizingId = id;
    this.currentResizingElement = this.containerCards.find(card => card.getUniqueId() === id)?.getElement();
    this.startX = $event.pageX;

    this.elementStartWidth = this.currentResizingElement?.clientWidth;
  }

mouseMove handles the resizing:

  @HostListener('mousemove', ['$event'])
  onMouseMove($event: MouseEvent): void {
    if (!this.currentResizingId || !this.currentResizingElement || !this.startX) {
      return;
    }
    $event.preventDefault();

    const currentWidth = this.currentResizingElement.clientWidth;
    let newWidth = currentWidth + $event.movementX;

    // Get computed styles for the current element
    const currentStyles = window.getComputedStyle(this.currentResizingElement);
    const currentMinWidth = parseFloat(currentStyles.minWidth) || 0;
    const currentMaxWidth = parseFloat(currentStyles.maxWidth) || Infinity;

    // Constrain the new width of the current element
    newWidth = Math.max(currentMinWidth, Math.min(newWidth, currentMaxWidth));

    let widthDelta = newWidth - currentWidth;

    if (widthDelta !== 0) {
      let remainingDelta = this.adjustNextSiblings(this.currentResizingElement, widthDelta);

      // If we couldn't distribute all the delta, adjust the current element's width
      if (remainingDelta !== 0) {
        newWidth = currentWidth + (widthDelta - remainingDelta);
        this.disposeResizeHelperProperties();
      }
    }

    // Update the current element's width
    this.currentResizingElement.style.width = `${newWidth}px`;
  }

And the adjustNextSiblings function that tries to resize the next siblings accordingly to fill up the free space.

private adjustNextSiblings(element: HTMLElement, delta: number): number {
    let currentElement = element.nextElementSibling as HTMLElement | null;
    let remainingDelta = delta;

    while (currentElement && remainingDelta !== 0) {
      const currentWidth = currentElement.clientWidth;
      const newWidth = currentWidth - remainingDelta;

      const styles = window.getComputedStyle(currentElement);
      const minWidth = parseFloat(styles.minWidth) || 0;
      const maxWidth = parseFloat(styles.maxWidth) || Infinity;

      const constrainedWidth = Math.max(minWidth, Math.min(newWidth, maxWidth));
      const actualDelta = currentWidth - constrainedWidth;

      currentElement.style.width = `${constrainedWidth}px`;
      remainingDelta -= actualDelta;

      currentElement = currentElement.nextElementSibling as HTMLElement | null;
    }

    return remainingDelta;
  }

The component name is DynamicHorizontalSplitContainerComponent

How can I get the opposite resizing (decreasing width) affect previous siblings + next siblings?

I have a feeling there is a shorter generic way to handle this, but I am over thinking.

passport js google getting original request param in callback

I’m attempting to get a url param /api/sso-login/google?mobile=true in the callback function. However the req returned is for the google auth and not the original request to the server. I have attemped to use req.session, however as stated the callback has a different req. Any advice on how to go about this?

stratergy:

passport.use(
  new GoogleStrategy(
    {
      clientID: process.env.GOOGLE_OAUTH_CLIENT_ID,
      clientSecret: process.env.GOOGLE_OAUTH_CLIENT_SECRET,
      callbackURL: process.env.BASE + '/api/sso-callback/google',
      passReqToCallback: true
    },
    function (request, accessToken, refreshToken, profile, done) {
      let parsedUser = {
        firstname: profile.name.givenName,
        lastname: profile.name.familyName,
        provider: 'google',
        email: profile.email
      }
      request.parsedUser = parsedUser
      return done(null, profile)
    }
  )
)

endpoint:

app.get('/api/sso-login/google',(req,res, next) => {
  req.session.isMobile = req.query.mobile
  next()
}, passport.authenticate('google', { scope: ['profile','email']}))

callback:

app.get('/api/sso-callback/google',passport.authenticate('google', { failureRedirect: '/api/sso-failed' }), loginWithSSO)

loginWithSSO:

async function loginWithSSO(req, res)  {
  try {
    let user = req.parsedUser
    .....login user....
    }
//req is from google auth rather than original req, so this is undefined
    if(req.session.isMobile) return res.status(200).redirect(`redirect1://oauth-callback?token=${token`)
    return res.status(200).redirect(process.env.BASE + `?token=${token}`)
  }
}

Is it possible in principle to force `setTimeout` to return a wrong timeout identifier integer with a race condition?

A.S.: This question is about the internals of how setTimeout and setInterval works, not about their typical usage.

When calling setTimeout in a browser, it returns a timeout ID that you are then supposed to use in clearTimeout. The timeout ID is an integer, and calling setTimeout twice in a row results in IDs that are sequential (see the demo below).

const timeoutIds = []

// generate a bunch of timeouts for entropy
for (let i = 0; i <= Math.random() * 100; i += 1) {
  setTimeout(() => {}, 0)
}

// generate two timeouts sequentially
timeoutIds.push(setTimeout(() => {}, 0))
timeoutIds.push(setTimeout(() => {}, 0))

// verify that they will always have sequential IDs
console.log({ timeoutIds })
console.assert(timeoutIds[1] === timeoutIds[0] + 1)

This suggests that there is a shared counter that is incremented every time setTimeout is called.

Since there is a shared counter, and setTimeout has an asynchronous side effect, this lead me thinking whether it is possible (at least, in principle) to break the counter and force it to issue a wrong timeout ID. Maybe, by passing a reference to the main thread’s setTimeout to a worker, or something as dirty?

const timeoutId1 = scheduleTimeoutSomehow(() => console.log(42))
const timeoutId2 = scheduleTimeoutSomehow(() => console.log(17))

clearTimeout(timeoutId2)
// console logs '17' eventually, and never logs '42'

How to filter and display a row when the search input matches the content within a collapsed in DataTables?

I’m using DataTables to manage a table where certain contents are in collapsible <tr> elements. Initially, these <tr> are hidden (display: none), and they only become visible when their corresponding button (Details) is pressed .

When using the DataTables search filter, I’d like the table to display the main row that contains the matching content that is in the hidden <tr> element, without requiring the user to click the “Details” button first.

Here is my current setup:

Each collapsible row has a unique ID, and I store the content of each row in a dictionary with the following structure:
{ ‘id_of_row’: [‘content1’, ‘content2’, ‘content3’, …] }
The goal is to search within the dictionary when the user types in the search box, and if a match is found in any of the dictionary elements, it uses the id_of_row and the corresponding main row with that id should be displayed.

Example Problem:

If I search for the term ‘requ’, nothing shows up because the corresponding content is inside a collapsed <tr>. However, if I manually expand the <tr> by clicking the “Details” button and make that content visible and if there is a match inside that content it will show up.

What I’ve Tried:

I use a dictionary that maps the main row’s ID to an array of content for that row. When the search input matches an element in the dictionary, I want the corresponding main row to be displayed, even if it’s content its inside a currently hidden element.
However, I can’t seem to get this to work as expected. The row is not being displayed when its content matches the search term unless it’s manually expanded.

Here is a simplified version of my current code:

@using Newtonsoft.Json
@{
// Sample machine names
var MachineNames = new List<string> { "Machine A", "Machine B", "Machine C" };

// Sample requests using anonymous objects
var requests = new[]
{
new { Id = 1, ContactName = "Client A", CompanyName = "Machine A", Status = "Pending", Msg = "Request 1" },
new { Id = 2, ContactName = "Client B", CompanyName = "Machine B", Status = "In Progress", Msg = "Request 2" },
new { Id = 3, ContactName = "Client C", CompanyName = "Machine C", Status = "Completed", Msg = "Request 3" }
};

// Sample dictionary data for matching the behavior of your original example
var requestDictionary = new Dictionary<int, string[]>
{
{ 1, new[] { "client a", "machine a", "pending", "request 1" } },
{ 2, new[] { "client b", "machine b", "in progress", "request 2" } },
{ 3, new[] { "client c", "machine c", "completed", "request 3" } }
};
}

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Collapsible Table with Custom Filter</title>

    <!-- Include jQuery -->
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>

    <!-- Include DataTables CSS & JS -->
    <link rel="stylesheet" href="https://cdn.datatables.net/1.10.21/css/jquery.dataTables.min.css">
    <script src="https://cdn.datatables.net/1.10.5/js/jquery.dataTables.min.js"></script>

    <style>
        table {
            width: 100%;
            border-collapse: collapse;
        }

        th, td {
            padding: 8px;
            text-align: left;
            border-bottom: 1px solid #ddd;
        }

        .show {
            display: table-row;
        }

        .dataTables_filter label {
            font-weight: bold;
            font-size: 1.2em;
        }

        .dataTables_filter input {
            margin-left: 10px;
            padding: 5px;
            border-radius: 5px;
            border: 1px solid #ccc;
        }

        #search-container {
            width: auto;
            padding: 5px;
            margin-bottom: 10px;
        }
    </style>
</head>

<body>
<h1>Collapsible Table with Custom Search Filter</h1>

<!-- Search filter -->
<div id="search-container"></div>

<!-- The table with collapsible rows -->
<table id="myTable" class="display table-flexible">
    <thead>
    <tr>
        <th>Request ID</th>
        <th>Client</th>
        <th>Machine</th>
        <th>Status</th>
        <th>Description</th>
    </tr>
    </thead>
    <tbody>
    @foreach (var request in requests)
    {
    <tr>
        <td>@request.Id</td>
        <td>@request.ContactName</td>
        <td data-id="@request.CompanyName">@request.CompanyName</td>
        <td>@request.Status</td>
        <td>
            <button class="btn btn-info btn-sm toggle-btn" data-target="#[email protected]">Details</button>
        </td>
    </tr>

    <tr id="[email protected]" class="details-row" style="display: none;">
        <td colspan="6">
            <div class="card custom-card-body details-card">
                <div class="detail-item">
                    <strong>Message:</strong>
                    <p class="tw-font-bold">@request.Msg</p>
                </div>
            </div>
        </td>
    </tr>
    }
    </tbody>
</table>

@section Scripts {
<script src="https://cdn.datatables.net/1.10.5/js/jquery.dataTables.min.js"></script>
<script>
    $(document).ready(function () {
       
        var requestDictionary = @Html.Raw(JsonConvert.SerializeObject(requestDictionary));

        console.log(requestDictionary); // Debugging purposes
        
        // Initialize DataTable
        var table = $('#myTable').DataTable({
            columnDefs: [{
                "defaultContent": "-",
                "targets": "_all"
            }],
            paging: false,
            ordering: false,
            info: false,
            dom: 'ft'
        });

        // Move search box to custom container
        $('#search-container').html($('.dataTables_filter'));

        // Custom search functionality using the requestDictionary
        function filterTable(searchTerm) {
            var rows = table.rows().nodes(); // Fetch all rows
            $(rows).each(function () {
                var $row = $(this); // The `tr` element

                // Extract requestId from the first column (adjust if necessary)
                var requestId = $row.find('td').first().text().trim();

                // Ensure requestId is a valid number
                requestId = parseInt(requestId, 10);
                if (isNaN(requestId)) {
                    return; // Skip rows without a valid requestId
                }

                // Check if requestId exists in the dictionary
                if (!requestDictionary.hasOwnProperty(requestId)) {
                    return;
                }

                var requestDetails = requestDictionary[requestId];
                console.log(requestDetails); // Debugging purposes

                // Check if any of the details contain the search term
                var match = requestDetails.some(function (detail) {
                    return detail.toLowerCase().includes(searchTerm.toLowerCase());
                });

                // Show or hide the row based on the search match
                if (match) {
                    console.log("HIT - Showing row for requestId:", requestId);
                    $row.css("display", "table-row");  // Set display to table-row
                } else {
                    console.log("MISS - Hiding row for requestId:", requestId);
                    $row.css("display", "none");  // Hide row
                }
            });
        }

        // Handle search input
        $('.dataTables_filter input[type="search"]').on('input', function () {
            var searchTerm = $(this).val().trim();
            filterTable(searchTerm);
        });

        // Attach event listeners for toggling rows
        $('.toggle-btn').on('click', function () {
            var target = $(this).data('target');
            $(target).fadeToggle(500);
        });
    });
</script>
}
</body>



Thank you for your time and attention!

Why does Prettier wrap my anonymous function with another anonymous function call and how do I turn it off?

Here is the original code:

namespace.namespace2 = new function() {/* logic here*/}

After using Prettier:

namespace.namespace2 = new (function() {/* logic here*/})();

Why? I want an option to disable this, but can’t find it documented anywhere.

I went into the Prettier playground area on their site, put in the code from the example above, and fiddled around with all settings, nothing worked.

I’ve then searched through the Prettier documentation, obviously tried to search for an answer, but I could only find posts unrelated to my issue.

Promise.allSettled returning status as “fulfilled” even though API call is failed and showing status as 404

I have a Promise.allSettled which takes two API. Even though the second API is failed and returned 404 the promise status shows ‘fulfilled’.

  async function loadLivePrerequisites() {
    try {
      const API_ENDPOINTS = getRequiredApis()

      // [0] -> join link, [1] -> user name
      const response = await Promise.allSettled(API_ENDPOINTS);

      const joinLink = response[0].status === "fulfilled" ? response[0].value.data : undefined
      setLiveDetails(joinLink)

      let userName: string;
      if(response[1].status === "fulfilled") {
        userName = response[1].value.data.name
      } else {
        userName = userNameGenerator(user.firstName, user.lastName)
      }
      setUserName(userName)
    } catch(error) { 
      console.log(error)
    }
  }

response:
screenshot

network error (404):
screenshot

I was expecting the status would be “rejected” and code inside the if statement would not be executed. Not sure if it is something wrong from my end or my lack of knowledge on how promise.allSettled work. Any help would be appreciated. Thank you in advance.

Playwright: how to connect existing chromium browser in MacBook

test("Open chrome with existing session", async ({}) => {
  const userDataDir =
    "/Users/SinhAb/Library/Application Support/Google/Chrome/";
  const browserContext = await chromium.launchPersistentContext(userDataDir, {
    channel: "chrome",
  });
  let page = browserContext.pages().at(0);
  if (!page) page = await browserContext.newPage();
  await page.goto("amazon.co.uk/");
  await page.waitForTimeout(5000);
});

This is the code I have used, for this, new window in existing browser panel is getting opened but the URL is blank, it’s showing “about:blank”.

I want to send a link, but the site looks bad when i send it. URL [closed]

The header menu duplicates and shows three different stores when I send the link to a friend. However, when I check it myself, everything looks normal. Is there a smart way to fix this through the URL? Maybe by setting some parameters or something similar? This is the URL: https://bondep.com/en-no/collections/emilia-ready-to-go/products/stud-combo-2

Thanks in advance!

I did not try anything because I am blanc. sorry

Tryed to post images but I have a bad reputation

Guessing game error. Wrote the logic perfectly, But it’s not working

The code just keep saying to insert larger number or smaller number. but don’t get it to the actual number and break, though the logic is fine in my opinion. Sometimes the console doesn’t print anything and it keeps roaming like infinite loop. Can anyone help me to understand what’s going on!??

//  Modify the guessing game you created to allow the user to guess within a dynamic range (e.g., "Guess a number between 50 and 150"). Ensure the user cannot enter a guess outside of this range.
while (true) {
  let randNumber = Math.floor(Math.random() * 101) + 50;
  let userGuess = prompt("Guess the Number: (50-150)");
  userGuess = parseInt(userGuess);
  if (!isNaN(userGuess) && userGuess >= 50 && userGuess <= 150) {
    if (userGuess == randNumber) {
      console.log("congrats! right guess");
      break;
    } else if (userGuess < randNumber) {
      console.log("Try large Number");
    } else if (userGuess > randNumber) {
      console.log("Try small number");
    }
  } else {
    console.log("Wrong input. Try a valid Number between (50-150)");
  }
}

requestAnimationFrame exceeds screen refresh rate

i use requestAnimationFrame in a js webgl project where i change the pixel color from black to white on each frame by accessing a texture that contains the content of the last frame ) but the framerate exceeds the Hz of my monitor and the flickering is inconsistent.
also i calculate the fps with the help of window.performance.now() and the framerate value looks like

n_fps: 200
n_fps: 333.3333333333333
n_fps: 250

i thought the requestAnimationFrame should sync the function call with the framerate of my monitor which is set to 239.96hz, but the flickering is inconsistent and the framerate sometimes exceeds 240fps, i cant figure out why but i suspect it has to do with v-sync.

Here some specs

OS

Distributor ID: Ubuntu

Description: Pop!_OS 22.04 LTS

GPU

lshw -c video

WARNING: you should run this program as super-user.

*-display

   description: VGA compatible controller

   product: Ellesmere [Radeon RX 470/480/570/570X/580/580X/590]

Monitor settings

xrandr –verbose

DisplayPort-0 connected primary 1920×1080+0+1200

TearFree: on
supported: off, on, auto

the important part of my js code looks like this

//...
const gl = canvas.getContext(
            'webgl2', 
            {
                desynchronized: false, //trying to force vsync?
            }
        ); 
///...
        function render() {
            nid = requestAnimationFrame(render);

            let n_ts_ms_now = window.performance.now();
            let n_ms_delta = n_ts_ms_now - n_ts_ms;

            // console.log(n_ms_delta)
            console.log(`n_fps: ${1000/n_ms_delta})`);
            n_ts_ms = n_ts_ms_now;
            n += 1;

            // if(n_ms_delta > n_ms_max){
                const nextTextureIndex = 1 - currentTextureIndex;



                gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffers[nextTextureIndex]);
                gl.viewport(0, 0, canvas.width, canvas.height);

                gl.useProgram(program);

                gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
                gl.enableVertexAttribArray(positionAttributeLocation);
                gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);

                gl.activeTexture(gl.TEXTURE0);
                gl.bindTexture(gl.TEXTURE_2D, textures[currentTextureIndex]);

                gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);

                // Swap textures
                currentTextureIndex = nextTextureIndex;

                // Render to the canvas
                gl.bindFramebuffer(gl.FRAMEBUFFER, null);
                gl.viewport(0, 0, canvas.width, canvas.height);
                gl.bindTexture(gl.TEXTURE_2D, textures[currentTextureIndex]);
                gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
                console.log(n)

            // }


        }
    ```

what i tried: 

- manually forcing/setting vsync with this command `xrandr --output DisplayPort-0 --set TearFree on`
- running chrome and firefox with vblank_mode=1 `vblank_mode=1 google-chrome` and then 


when i manually throttle the fps (commented out code) the flickering looks consistent.

How to open and read a json file on a server-hosted and local html file

Using HTML, CSS, and JS I have written a word chain game that uses JSON files to store game data for the many rounds of a single game. I wish to make it fairly user-friendly, so I want to make it possible to drag and drop the file onto the game window. I get a CORS error when running the HTML locally as one expects (it worked with --disable-web-security set). However, I get an error when running the game from the server:

Not allowed to load local resource: file:///C:/fakepath/<filename>.json

The HTML is very simple:

<input type="file" name="gameData" id="gameData"><button id="loadGame">Load Game</button><br><br>

The JS is the problem, I’m sure:

$("#loadGame").on("click", function() { // Load the game file, however it needs to be in the game directory to work!
    var filePath = $("#gameData").val().replace(/^.*[\/]/, '');
    // var filePath = $("#gameData").val();  // Version for online only game, maybe....
    consoleWrite(`File "${filePath}" loaded from game directory.`);
    $.getJSON(filePath, function(data) {
        round1 = data.round1;
        consoleWrite(`Round 1: ${round1}`);
        round2 = data.round2;
        consoleWrite(`Round 2: ${round2}`);
        round3 = data.round3;
        consoleWrite(`Round 3: ${round3}`);
        round4 = data.round4;
        consoleWrite(`Round 4: ${round4}`);

        extraRound1 = data.extraRound1;
        consoleWrite(`Extra 1: ${extraRound1}`);
        extraRound2 = data.extraRound2;
        consoleWrite(`Extra 2: ${extraRound2}`);
        extraRound3 = data.extraRound3;
        consoleWrite(`Extra 3: ${extraRound3}`);

        bonusRoundA = data.bonusRoundA;
        consoleWrite(`Bonus A: ${bonusRoundA}`);
        bonusRoundB = data.bonusRoundB;
        consoleWrite(`Bonus B: ${bonusRoundB}`);
        bonusRoundC = data.bonusRoundC;
        consoleWrite(`Bonus C: ${bonusRoundC}`);
    });
    consoleWrite(`Game loaded.`);
});

What must I change to allow the game to parse the file? Is there any way to read the file’s contents locally without uploading it to a server? I’d like it to be able to work locally and hosted on a server. The “less-user-friendly” workaround I thought of is to have the user copy and paste the contents of the file into a textbox; I’ve done stuff like that before, and while it works I’d rather keep with a simple file upload option. Any ideas?

DYMO Label Connect JavaScript Library – Barcode issue

I am using the Dymo connect SDK to print labels from our web application.
The customers are designing their labels in the Dymoconnect software (.dymo files) and upload it to our software.

All was working fine but one of our customers started using the barcode object.
It renders fine in print preview, but seems like it’s warped so how as the barcode reader will not read it. If we print directly from Dymoconnect it works fine.

This is an example of how it’s rendered, top is using the SDK, bottom is from the software:

https://i.sstatic.net/M2q7lgpB.png

I thought it might be related to one of the renderParamsXml options, but all documentation points to broken links…

How to locally test sub routes for a basic Javascript router in VSCode live server?

I have an AWS Cloudfront function that redirects urls to several different html pages hosted in S3 along the lines of this:

function handler(event) {
    var request = event.request;
    var uri = request.uri;

    if (uri.split('/')[1] == '') {
        request.uri = '/index.html';
    } else if (uri.split('/')[1] == 'contact'){
        request.uri = '/contact.html';
    } else if (uri.split('/')[1] == 'blog'){
        request.uri = '/blog.html';
    } else if (!uri.includes('.')) {
        request.uri = '/index.html';
    }
    return request;
}

This appears to work fine but I want to build the site locally with my 3 html files in the root directory but have sub routes point to them.

  1. http://127.0.0.1:5500/index.html
  2. http://127.0.0.1:5500/blog/index.html
  3. http://127.0.0.1:5500/contact/index.html

These are the sub routes:

www.example.com
www.example.com/index.html
route to: /index.html

www.example.com/foo
www.example.com/foo/123
www.example.com/foo/abc
www.example.com/foo/def/123
route to: /foo/index.html

www.example.com/bar
www.example.com/bar/123
www.example.com/bar/abc
www.example.com/bar/def/123
route to: /bar/index.html

Effectively I want to be able to use code similar to this to read the pathArray values to change the individual page like blog/hello would show the blog page hello whereas blog would show the blog list:

var pathArray = window.location.pathname.split('/');
document.write("pathArray[0]: " + pathArray[0] + "<br>");   
document.write("pathArray[1]: " + pathArray[1] + "<br>");   
document.write("pathArray[2]: " + pathArray[2] + "<br>");  
document.write("pathArray[3]: " + pathArray[3] + "<br>");   
if (pathArray[3] === undefined) {
    document.write("pathArray[3] === undefined: " + (pathArray[3] === undefined) + "<br>");   
} else {
    document.write("pathArray[3] === undefined: " + (pathArray[3] === undefined) + "<br>");  
}

My HTML is updating correctly to change colour with tailwind, but the browser only actually updates with the colour gray, not other colours, why?

I’m using JS, to update the background colour of an HTML element using tailwind.
It works with the colour gray, but not any other colour.

If I change yellow or green with gray, they update correctly, if I change gray with another colour, it doesn’t work correctly. So, the code is working fine, if I check console, it has the correct tailwind class, it’s just that the browser is not updating the colour displayed, unless it’s gray.

Any ideas why?

It also only updates with 200, so if it’s bg-gray-200 it changes colour, but if it’s anything else, it doesn’t.

Code below:

 for (let i = 0; i < 6; i++) {
            let letterColour = 'yellow'
            let box = row.children[i]
            let letter = currentGuess[i]
            let letterPosition = correctWord.indexOf(currentGuess[i])
            console.log(letterPosition)

            if (letterPosition === -1) {
                letterColour = "gray"
                let colour = "red"
                colourKeyboard(letter, colour)
            }
            else if (currentGuess[i] === correctWord[i]) {
                letterColour = "green"
                let colour = "green"
                colourKeyboard(letter, colour)
            }
 
            let backgroundColour = `bg-${letterColour}-200`
            console.log(backgroundColour)
            box.classList.add(backgroundColour)
            console.log(box)
        }