How do I give react router Outlet a className?

I’m using react with react router for the client-side routing.
I have a header, outlet, and footer.
What I want is to give the Outlet a classname so that every component get’s a margin-top.
Is there a way to do this or do I have to make a wrapper component surrounding the Outlet?

Map through an array – toggle first option, second to false

I want to write a function where if isActive.id === ‘singlesided’ then its status is toggled and at the same time ‘doublesided’ is set to false.
Idea is that singleSided and soubleSided cannot be true at the same time.
Managed to toggle the first option, but cannot find a way to set second to false…

setup.store.ts:

    const initialState: LightboxState = {
          isActive: [
           { id: 'singleSided', status: false },
           { id: 'doubleSided', status: false },
           { id: 'illuminated', status: false },
           { id: 'notIlluminated', status: false },
           { id: 'standing', status: false },
           { id: 'hanging', status: false },
      ],
}

export const LightboxStore = signalStore(
  { providedIn: 'root' },
  withState(initialState),
  withMethods((store) => ({
    activeStatus(statusId: string, statusFalse: string): void {
      patchState(store, {
        isActive: store.isActive().map((isActiveId) => {
          if (isActiveId.id === statusId) {
            return { ...isActiveId, status: !isActiveId.status };
          }
          return isActiveId;
        }),
      });
    },
  }))
);

I want to run it through a button click as:

store.activeStatus('singleSided', 'doubleSided')

where the first option is toggled(true/false) and second is set to false.

How to Add a Scrollbar to a Status Container When Content Exceeds 100% Height Without Setting a Fixed Height?

I’m working on a responsive layout where I want the .status container to have a scrollbar if its content exceeds the available space. However, I don’t want to set a fixed height for the .status container since the layout needs to be flexible and responsive. I’m looking for a solution primarily using HTML and CSS, but I’m open to JavaScript, TypeScript, or Angular solutions if necessary.

In this example, each .status container should display a scrollbar if the content exceeds the available height. However, I’m not sure how to achieve this without setting a fixed height.

Is there a way to make the .status container handle overflow correctly in this scenario?

Here is the code I’m working with:

<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title></title>
    <style>
        * {
            box-sizing: border-box;
        }

        html,
        body {
            margin: 0;
            width: 100%;
            height: 100%;
            background-color: red;
            color: #fff;
            text-align: center;
        }

        .container {
            padding: 20px;
            width: 100%;
            height: 100%;
            display: grid;
            grid-auto-rows: auto 1fr;
            row-gap: 20px;
        }

        .content-1 {
            width: 100%;
            height: 60px;
            background-color: yellow;
        }

        .content-2 {
            width: 100%;
            height: 100%;
            background-color: pink;
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
            gap: 20px;
        }

        .status {
            height: 100%;
            max-height: 100%;
            background-color: blue;
            padding: 5px;
            overflow-y: auto;
        }

        .card {
            width: 100%;
            height: 200px;
            background-color: green;
            margin-bottom: 10px;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="content-1"></div>
        <div class="content-2">
            <div class="status">
                <div>Status</div>
                <div class="card"></div>
                <div class="card"></div>
                <div class="card"></div>
                <div class="card"></div>
                <div class="card"></div>
                <div class="card"></div>
            </div>
            <div class="status">
                <div>Status</div>
            </div>
            <div class="status">
                <div>Status</div>
            </div>
            <div class="status">
                <div>Status</div>
            </div>
        </div>
    </div>
</body>
</html>

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.