Chrome extension: Approach to persist prepended query parameter across the same domain?

I have extension which prepends certain query parameters to a URL after toggling an input box. But, it drops off when navigating to another page on the same domain.

My goal – I want to persist the query parameter ?active=true across the same domain. For example:

www.example.com?active=true
www.example.com/product/main?active=true
www.example.com/help?active=true

Heres what I have so far:

popup.html – Heres the Input I interact with to run JS script that adds the query parameter:

<input type="checkbox" name="query" id="queryParams">

popup.js – Heres the script that prepends query parameter

const queryParamaOptions = document.querySelector('#queryParams');

function toggleQueryParams(e) {
    chrome.tabs.query({ active: true, lastFocusedWindow: true }, (tabs) => {
        if (e.target.checked === false) {
            chrome.storage.local.set({
                query: false
            });
            return;
        } else {
            chrome.storage.local.set({
                query: true
            });

            // Heres where parameter is created
            const params = encodeURI('active=true');
            const url = tabs[0].url;
            const hashStart = url.indexOf('#') === -1 ? url.length : url.indexOf('#');
            const querySymbol = url.indexOf('?') === -1 ? '?' : '&';
            var newUrl = `${url.substring(
                0,
                hashStart
            )}${querySymbol}${params}${url.substring(hashStart)}`;

            // Refresh page with new URL
            chrome.tabs.update(tabs[0].id, { url: newUrl });
        }
    });
}

queryParamaOptions.addEventListener('click', (e) => toggleQueryParams(e));

Current thoughts

  • I am thinking to store the domain in localstorage when I first run toggleQueryParams
  • Use something like chrome.tabs.onUpdated to watch for url changes on changeInfo.url within the background script because the pop.up is closed at this point whilst navigating different pages
  • Use an if condition to check if the stored domain matches the current domain. If so then run toggleQueryParams

Any thoughts?

How to get the log and result of websocket async_to_sync calling

I have websocket and simply send the mesasges to channel_layer

from channels.layers import get_channel_layer
    channel_layer = get_channel_layer()
    async_to_sync(channel_layer.group_send)(
        '{}'.format(mychannelname),
        {
            "type": "chat_message",
            "message": "send you"
        }
    )

It seems works well and messages goes to client browser,
however I want to know if it works well or not from server.

Is it possible or can I get the number of clients connected to channel?

My consumers.py makes channels

import json

from channels.db import database_sync_to_async
from channels.generic.websocket import AsyncWebsocketConsumer


class ChatConsumer(AsyncWebsocketConsumer):
    
    async def connect(self):

        self.room_group_name = self.scope["url_route"]["kwargs"]["room_name"]

        await self.channel_layer.group_add(
            self.room_group_name,
            self.channel_name
        )
        await self.accept()
        await self.send(text_data=json.dumps({
            'channel_name': self.channel_name
        }))
    async def disconnect(self, close_code):
        print("some disconnect")
        await self.channel_layer.group_discard(
            self.room_group_name,
            self.channel_name
        )

    async def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']
        print("receive data",text_data_json)
    
        print("channel_name:",self.channel_name)
        print("group_name:",self.room_group_name)
        if text_data_json['type'] == "register":
            self.user_id = text_data_json['message']
        print("user_id is:",self.user_name)

        #res = await self.save_message_to_db(message)
        await self.channel_layer.group_send(
            self.room_group_name,
            {
                'type': 'chat_message',
                'message': "nicelydone",
            }
        )

    async def chat_message(self, event):
        print("someone call chat_message")
        message = event['message']
        await self.send(text_data=json.dumps({
            'message': message
        }))

HTMX runs script element before applying the DOM changes

I have a HTMX page with a websocket connection that serves OOB updates to DOM.

Whenever a file changes on server it sends a script tag that invokes a JS function:

<div hx-swap-oob="innerHTML" id="__dev_scratch"><script>devReloadTriggered();</script></div>

In case the file change produces an error, the server will send this update:

<div hx-swap-oob="innerHTML" id="__dev_scratch"><div id="dev-reload-error">Unable to resolve symbol: sss in this context</div><div id="dev-reload-error-ns">portal.response</div><script>devReloadTriggered();</script></div>

The devReloadTriggered script detects presence of these error text divs and shows an alert box.

This all works fine individually. The problem is when the error is removed, so when after the error text divs have been added, server sends again:

<div hx-swap-oob="innerHTML" id="__dev_scratch"><script>devReloadTriggered();</script></div>

In this case the error box is shown again, which would indicate that devReloadTriggered is ran again before divs with error are removed by HTMX. How do I prevent this? Why does it run the script before removing the divs?

Having a trouble with gulp-imagemin

I’m having a trouble with gulp-imagemin. When I test the minify-image task, it can’t run. I tried a lot of ways to fix it but every time it had a problem. Can someone help me to fix this? I need this very much.
how I import gulp & gulp-imagemin:

const gulp = require('gulp');
const imagemin = require('gulp-imagemin');

how I write the task:

// gulp.task('minifyimage', () =>
//     gulp.src('src/assets/img/*')
//         .pipe(imagemin())
//         .pipe(gulp.dest('dist/assets/img/'))
// );

gulp.task('minifyimage', async function () {
    return gulp
        .src('src/assets/img/*')
        .pipe(imagemin())
        .pipe(gulp.dest('dist/assets/img/'));
});

// export default () => (
//     gulp.src('src/images/*')
//         .pipe(imagemin())
//         .pipe(gulp.dest('dist/images'))
// );

// function imgSquash() {
//     return gulp
//         .src('src/assets/img/*')
//         .pipe(imagemin())
//         .pipe(gulp.dest('dist/assets/img/'));
// }

fix this problem. just fix this problem.
here is the problem:
enter image description here
PS C:UsersMatinDownloadsgulpApp> gulp optimize-images
[03:48:08] Loaded external module: C:UsersMatinAppDataRoamingnpmnode_modulesgulpnode_modulesinterpretcjs-stub
(node:23416) ExperimentalWarning: CommonJS module C:UsersMatinDownloadsgulpAppgulpfile.cjs is loading ES Module C:UsersMatinDownloadsgulpAppnode_modulesgulp-imageminindex.js using require().
Support for loading ES Module in require() is an experimental feature and might change at any time
(Use node --trace-warnings ... to show where the warning was created)
Error: require() cannot be used on an ESM graph with top-level await. Use import() instead. To see where the top-level await comes from, use –experimental-print-required-tla.

D3: Position marker does not follow graph when zooming and panning

I have a D3.js graph with a vertical red line that marks the value of variable x. The value of x is determined by a range slider on the page.

The problem is that when the graph is panned/zoomed, the vertical line does not move together with the graph’s scales and content.

I’ve tried various approaches, but to no avail. How can I get the vertical line to keep its position relative to the graph content, and still update its horizontal position based on the value of x?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Binet/Fibonacci</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/13.2.0/math.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.9.0/d3.min.js"></script>
    <style>
        body {
            font-family: Arial, sans-serif;
            text-align: center;
            margin: 20px;
        }

        #slider {
            margin: 20px;
            width: 80%;
        }

        svg {
            border: 1px solid black;
            margin-top: 20px;
        }
    </style>
</head>
<body>
    <input type="range" id="slider" min="0" max="30" step="0.02" value="0" />
    <p>Value of x: <span id="xValue">0.00</span></p>
    <p>Fibonacci number (y): <span id="yValue">0</span></p>
    <p>y real: <span id="yReal">0</span></p>
    <p>y imaginary: <span id="yImag">0</span></p>
    <p>y imaginary (decimal): <span id="yImagDec">0</span></p>

    <div>
        <label for="yImagMultip">y imaginary multiplier: </label>
        <input type="number" id="yImagMultip" value="1000" step="10" />
    </div>

    <svg width="800" height="400" id="chartArea"></svg>

    <script>
        const phi = math.bignumber((1 + Math.sqrt(5)) / 2);
        const psi = math.bignumber((1 - Math.sqrt(5)) / 2);

        function fibonacci(x) {
            const n = math.bignumber(x);
            const y = math.divide(
                math.add(
                    math.pow(phi, n),
                    math.multiply(-1, math.pow(psi, n))
                ),
                math.sqrt(5)
            );
            return y;
        }

        const slider = document.getElementById("slider");
        const xValue = document.getElementById("xValue");
        const yValue = document.getElementById("yValue");
        const yReal = document.getElementById("yReal");
        const yImag = document.getElementById("yImag");
        const yImagDec = document.getElementById("yImagDec");
        const yImagMultipInput = document.getElementById("yImagMultip");

        const svg = d3.select("#chartArea");
        const margin = { top: 20, right: 30, bottom: 30, left: 60 };
        const width = +svg.attr("width") - margin.left - margin.right;
        const height = +svg.attr("height") - margin.top - margin.bottom;

        const graphArea = svg.append("g")
            .attr("transform", `translate(${margin.left},${margin.top})`);

        let realPoints = [];
        let imaginaryPoints = [];
        let x; // x scale
        let y; // y scale
        let xAxis; // x axis
        let yAxis; // y axis
        let line; // line generator

        function updateData() {
            realPoints = [];
            imaginaryPoints = [];
            for (let x = 0; x <= 30; x += 0.01) {
                const yVal = fibonacci(x);
                realPoints.push({ x, y: math.re(yVal) }); // Real part
                const imaginaryPart = math.im(yVal); // Extract imaginary part
                imaginaryPoints.push({ x, y: imaginaryPart });
            }
        }

        function drawGraph() {
            // Update scales
            x = d3.scaleLinear()
                .domain([0, 30])
                .range([0, width]);

            y = d3.scaleLinear()
                .domain([-50, 250])
                .range([height, 0]);

            // Update axes
            xAxis = graphArea.selectAll(".x-axis").empty() ? graphArea.append("g").attr("class", "x-axis") : xAxis;
            yAxis = graphArea.selectAll(".y-axis").empty() ? graphArea.append("g").attr("class", "y-axis") : yAxis;

            xAxis.attr("transform", `translate(0,${height})`).call(d3.axisBottom(x));
            yAxis.call(d3.axisLeft(y));

            // Update or draw real curve
            line = d3.line()
                .x(d => x(d.x))
                .y(d => y(d.y));

            const realLinePath = graphArea.selectAll(".real-line")
                .data([realPoints]);

            realLinePath.enter()
                .append("path")
                .attr("fill", "none")
                .attr("stroke", "blue")
                .attr("class", "real-line")
                .merge(realLinePath)
                .attr("d", line);

            // Update or draw imaginary curve
            const imaginaryLinePath = graphArea.selectAll(".imaginary-line")
                .data([imaginaryPoints]);

            imaginaryLinePath.enter()
                .append("path")
                .attr("fill", "none")
                .attr("stroke", "orange")
                .attr("class", "imaginary-line")
                .merge(imaginaryLinePath)
                .attr("d", d3.line()
                    .x(d => x(d.x))
                    .y(d => y(d.y * +yImagMultipInput.value)));

            // Update vertical line
            updateVerticalLine();
        }

        function updateVerticalLine() {
            const currentX = +slider.value;
            const verticalLine = graphArea.selectAll(".current-line").data([currentX]);

            verticalLine.enter()
                .append("line")
                .attr("class", "current-line")
                .attr("stroke", "red")
                .attr("stroke-width", 1)
                .attr("stroke-dasharray", "4")
                .merge(verticalLine)
                .attr("x1", x(currentX))
                .attr("x2", x(currentX))
                .attr("y1", height)
                .attr("y2", 0);
        }

        function handleZoom(event) {
            const new_x = event.transform.rescaleX(x);
            const new_y = event.transform.rescaleY(y);

            xAxis.call(d3.axisBottom(new_x));
            yAxis.call(d3.axisLeft(new_y));

            graphArea.selectAll(".real-line")
                .attr("d", d3.line()
                    .x(d => new_x(d.x))
                    .y(d => new_y(d.y)));

            graphArea.selectAll(".imaginary-line")
                .attr("d", d3.line()
                    .x(d => new_x(d.x))
                    .y(d => new_y(d.y * +yImagMultipInput.value)));

            updateVerticalLine();
        }

        const zoom = d3.zoom()
            .scaleExtent([0.5, 20])
            .on("zoom", handleZoom);

        svg.append("rect")
            .attr("width", width)
            .attr("height", height)
            .style("fill", "none")
            .style("pointer-events", "all")
            .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
            .call(zoom);

        slider.addEventListener("input", function () {
            const x = parseFloat(this.value).toFixed(2);
            xValue.textContent = x;

            const yVal = fibonacci(x);
            yValue.textContent = math.format(yVal, { precision: 5 });
            yReal.textContent = math.format(math.re(yVal), { precision: 5 });
            const imaginaryPart = math.im(yVal);
            yImag.textContent = math.format(imaginaryPart, { precision: 5 });
            yImagDec.textContent = math.format(imaginaryPart, { precision: 15, notation: 'fixed' });
            
            if (imaginaryPart == 0) {
                yImag.textContent = "0";
                yImagDec.textContent = "0";
            }

            drawGraph(); // Refresh the graph
        });

        yImagMultipInput.addEventListener("input", drawGraph);

        updateData(); // Generate data first
        drawGraph(); // Draw the graph initially
    </script>
</body>
</html>

You may also notice that interacting with the page controls resets the zoom level. I should mention that this is not intentional. It’s a separate issue that I will probably need to ask a separate question about. But if anyone reading knows how to fix this, I welcome your feedback.

Optimizing Form Rendering with Multiple Tabs and Dynamic Form Items

I want to structure a form effectively. My goal is to create a page with five tabs, each containing 10 unique form items with different types, such as text, number, and select fields. I’ve built the structure by setting up a Tab and TabContent area, displaying the corresponding TabContent based on the active tab. Each tab’s 10 form items are defined in constants as objects with types, allowing the form component to render the appropriate form item based on the type. The layout displays correctly, but the rendering speed is slow. How can I improve the performance? Below is a partial code example showing the relevant sections. I’d greatly appreciate any suggestions for optimization.

import React, { useState, useMemo } from 'react';
import {
  Tabs as UITabs,
  Tab as UITab,
  TabContent as UITabContent,
  FormInput,
  FormSelect,
  FormInputNumber,
} from 'your-ui-library';

const FORM_LIST = [
  {
    id: 0,
    key: 'school',
    title: 'School',
    fieldsList: SCHOOL_FIELDS,
  },
  {
    id: 1,
    key: 'college',
    title: 'College',
    fieldsList: COLLEGE_FIELDS,
  },
  {
    id: 2,
    key: 'university',
    title: 'University',
    fieldsList: UNIVERSITY_FIELDS,
  },
];

export const UNIVERSITY_FIELDS = [
  {
    type: 'select',
    name: '1',
    label: 'Region',
    description: 'test',
    options: [
      { label: 'Korea', value: 'korean' },
      { label: 'India', value: 'india' },
    ],
    validationRules: { required: 'Role selection is required' },
  },
  {
    type: 'inputNumber',
    name: '2',
    label: 'Minimum Letters',
    validationRules: { required: 'Number is required' },
  },
];

// Tabs Component
const Tabs = ({ tabs, activeTab, onTabChange }) => {
  return (
    <UITabs orientation="vertical" onChangeTab={(newTab) => onTabChange(newTab)} outline>
      {tabs.map((tab) => (
        <UITab key={tab.id} id={tab.id} label={tab.title}>
          {tab.title}
        </UITab>
      ))}
    </UITabs>
  );
};

// TabContent Component
const TabContent = ({ activeTab, tabs }) => {
  const content = useMemo(() => {
    return tabs
      .filter((tab) => tab.id === activeTab)
      .map((tab) => (
        <UITabContent key={tab.id} value={tab.id} activeTabNum={activeTab}>
          <FieldRenderContent fields={tab.fieldsList} />
        </UITabContent>
      ));
  }, [activeTab, tabs]);

  return <>{content}</>;
};

// FieldRenderer Component
const FieldRenderer = ({ field }) => {
  switch (field.type) {
    case 'input':
      return (
        <FormInput
          name={field.name}
          label={field.label}
          description={field.description}
          validationRules={field.validationRules}
        />
      );
    case 'select':
      return (
        <FormSelect
          name={field.name}
          label={field.label}
          options={field.options}
          description={field.description}
          isClearable={true}
          validationRules={field.validationRules}
        />
      );
    case 'inputNumber':
      return <FormInputNumber name={field.name} label={field.label} validationRules={field.validationRules} />;
    default:
      return null;
  }
};

// FieldRenderContent Component
const FieldRenderContent = ({ fields }) => {
  return (
    <>
      {fields.map((field) => (
        <FieldRenderer key={field.name} field={field} />
      ))}
    </>
  );
};

// Main Component
const FormPage = () => {
  const [activeTab, setActiveTab] = useState(0);

  return (
    <div style={{ display: 'flex' }}>
      {/* Tabs */}
      <div style={{ marginRight: '16px' }}>
        <Tabs tabs={FORM_LIST} activeTab={activeTab} onTabChange={setActiveTab} />
      </div>

      {/* Tab Content */}
      <div>
        <TabContent activeTab={activeTab} tabs={FORM_LIST} />
      </div>
    </div>
  );
};

export default FormPage;

element id different from the element passed to the getElementById() method and the code still worked, why? [closed]

I am following a project and studying it, but I have a question, how is it working to access this id through the getElementById(‘quantidade’) method, given that the id in the HTML element is like ‘id=’quantidade0”? o 0 não estaria faltando em getElementById?
codding HTML

 <div id="produto0"
  class="d-flex flex-row justify-content-between align-items-center pt-lg-4 pt-2 pb-3 border-bottom mobile">
     <div class="d-flex flex-row align-items-center">
           <div><img src="https://images.unsplash.com/photo-1529374255404-311a2a4f1fd9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60"
                            width="150" height="150" alt="" 
  id="image"></div>
                    <div class="d-flex flex-column pl-md-3 pl-1">
                        <div>
                        <h6>COTTON T-SHIRT</h6>
                        </div>
                        <div>Art.No:<span class="pl-2">091091001</span></div>
                        <div>Color:<span class="pl-3">White</span></div>
                        <div>Size:<span class="pl-4"> M</span></div>
                    </div>
                </div>
                <div class="pl-md-0 pl-1"><b>R$50,00</b></div>
                <div class="pl-md-0 pl-2">
                    <span class="fa fa-minus-square text-secondary"></span>
                    <span class="px-md-3 px-1" id="quantidade0">0</span><span
                        class="fa fa-plus-square text-secondary"></span>
                </div>
                <div class="pl-md-0 pl-1"><b>R$</b> <span id="total0"></span></div>
                <div class="close">&times;</div>
            </div>

             <!----------------------------------------------------------------->
            <div id="produto1" class="d-flex flex-row justify-content-between align-items-center pt-4 pb-3 mobile">
                <div class="d-flex flex-row align-items-center">
                    <div><img
                            src="https://images.unsplash.com/photo-1529374255404-311a2a4f1fd9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60"
                            width="150" height="150" alt="" id="image"></div>
                    <div class="d-flex flex-column pl-md-3 pl-1">
                        <div>
                            <h6>WHITE T-SHIRT</h6>
                        </div>
                        <div>Art.No:<span class="pl-2">056289891</span></div>
                        <div>Color:<span class="pl-3">White</span></div>
                        <div>Size:<span class="pl-4"> XL</span></div>
                    </div>
                </div>
                <div class="pl-md-0 pl-1"><b>R$30,00</b></div>
                <div class="pl-md-0 pl-2">
                    <span class="fa fa-minus-square text-secondary"></span>
                    <span class="px-md-3 px-1" id="quantidade1">0</span><span
                        class="fa fa-plus-square text-secondary"></span>
                </div>
                <div class="pl-md-0 pl-1"><b>R$</b>
                    <span id="total1"></span></div>
                <div class="close">&times;</div>
            </div>

        </div>
    </div>

—————————————————-enter code here

javascript code

function adicionarItem(item){ 
var quantidade = document.getElementById('quantidade0' + item)
}

How to Programmatically Set a Date in a Date Picker that Blocks Input and Paste Actions?

I’m trying to automate setting a date in an HTML date picker input field using Puppeteer, but I’ve encountered a problem: the date picker does not allow me to type in special characters, nor does it allow me to paste a date directly into the field.

Here’s the structure of the date picker input field:

<div class="input-group decade_date">
  <input type="text" name="passport_issue_date" 
         class="decade form-control form-control valid" 
         onpaste="return false;" 
         required="" 
         data-toggle="tooltip" 
         id="id_passport_issue_date" 
         tabindex="22" 
         aria-required="true" 
         aria-invalid="false">
</div>

I’ve tried several approaches:

Setting the value attribute directly via JavaScript.
Using Puppeteer to type the date, character by character.
Dispatching custom events to simulate user input.
None of these approaches reflect any change in the input field, likely due to internal validation or JavaScript in the date picker library itself (it appears to be using datepicker2).

My Question:
How can I programmatically set a date in this date picker input field? Is there a workaround in Puppeteer to simulate date selection or bypass these restrictions?

Any insights or suggestions on how to overcome this issue would be greatly appreciated. Thanks in advance!

What did you try and what were you expecting?

I tried several methods to set the date programmatically:

Setting the value attribute directly: I used JavaScript in Puppeteer to set input.value = ‘2024/10/30’, expecting this to update the field with the correct date. However, the input didn’t change visibly on the page, likely because of restrictions in the date picker library.

Typing each character with Puppeteer’s page.type method: I attempted to type each character individually in the date format expected by the input. I anticipated this would mimic real user input, but no date appeared in the field. It seems the input is actively blocking non-numeric characters and possibly even keyboard events from automation tools.

Dispatching custom events: I dispatched input and change events after setting the value in JavaScript, expecting these events to trigger any attached listeners and update the date field. Unfortunately, the date picker did not respond to these events, suggesting it requires specific user actions.

Expectation:
My goal was to automate the date input process as if a user selected a date manually. Ideally, I’d like a solution that bypasses any library restrictions or triggers the date picker’s own event listeners to accept the date input.

Question:
Are there any workarounds that might trigger a proper date selection in date picker libraries like datepicker2?

RGraph filledAccumulative line chart tooltips not showing

I am trying to get tooltips to work on my RGraph that is using filledAccumulative:true – I can get tooltips to come out if I just pass in tooltips1 (but that only works with the lower values), but when I pass in [tooltips1, tooltips2] then I get nothing. Can anyone tell me why the following isn’t working?

const chart = new RGraph.Line({
  id: canvas.id,
  data: [minData, maxDataA],
  options: {
    filled: true,
    filledAccumulative: true,
    colors: ["transparent", "rgba(178,240,241,1)"],
    xaxisLabels: dateLabels,
    xaxisLabelsAngle: 0,
    xaxisLabelsSize: 8,
    gutterLeft: 50,
    gutterTop: 1,
    gutterBottom: 0,
    linewidth: 2,
    title: null,
    titleSize: 1,
    textAccessible: true,
    tooltips: [tooltips1, tooltips2],
    tooltipsEffect: "fade",
    tooltipsCssClass: "chart-tooltips",
    tooltipsHighlightStyle: "dot",
    yaxisLabelsSize: 8,
    yaxisScaleDecimals: yaxis.dp,
    yaxisScaleMin: yaxis.min,
    yaxisScaleMax: yaxis.max,
    yaxisLabelsCount: yaxis.stepNum,
    yaxis: true,
    marginLeft: 50,
    yaxisTitleSize: 8,
    yaxisTitle: unitNm,
    yaxisTitleOffsetx: 5,
  },
})
  .draw();

Can anyone tell me why the following isn’t working?

(The full runtime code can be seen below, or on jsfiddle):

const dateLabels = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
const minData = [4, 2, 5, 2, 7, 8, 9]
const maxData = [12, 10, 11, 8, 13, 14, 15]
let chartNm = "My Data"
let unitNm = "Performance %"

function getTooltipContent(index) {
  const minValue = minData[index]
  const maxValue = maxData[index]
  const dateLabel = dateLabels[index] || ""
  let pct = ""
  if (unitNm && unitNm.indexOf("%") > -1) pct = "%"
  let result =  `<h1>${chartNm} (${unitNm}) </h1><h2>${dateLabel}</h2>Min: ${minValue}${pct}<br>Max: ${maxValue}${pct} `;
  console.log('tooltip',index,result);
  return result;
}



const canvasId = "my-canvas"
let canvas =  document.getElementById(canvasId) || document.createElement("canvas")
if (!canvas.id) {
  canvas.id = canvasId;
  canvas.width = window.innerWidth - 40;
  canvas.height = 300;
  document.body.appendChild(canvas);
}


const maxDataA = maxData.map((maxValue, index) => {
  return maxValue - minData[index]
});

const tooltips1 = minData.map((_, index) => {
  return getTooltipContent(index)
})
const tooltips2 = maxData.map((_, index) => {
  return getTooltipContent(index)
})

const yaxis = { min: 0, max: 20, stepNum: 5, dp: 0 }
const chart = new RGraph.Line({
  id: canvas.id,
  data: [minData, maxDataA],
  options: {
    filled: true,
    //filledAccumulative: true,
    colors: ["transparent", "rgba(178,240,241,0.8)"],
    xaxisLabels: dateLabels,
    xaxisLabelsAngle: 0,
    xaxisLabelsSize: 8,
    gutterLeft: 50,
    gutterTop: 1,
    gutterBottom: 0,
    linewidth: 2,
    title: 'xxx', // Would be nice to remove the space that a title existed in
    titleSize: 0, // Would be nice to remove the space that a title existed in
    textAccessible: true,
    
    tooltips: [tooltips1, tooltips2],
    tooltipsEffect: "fade",
    tooltipsCssClass: "chart-tooltips",
    tooltipsHighlightStyle: "dot",
    
    yaxisLabelsSize: 8,
    yaxisScaleDecimals: yaxis.dp,
    yaxisScaleMin: yaxis.min,
    yaxisScaleMax: yaxis.max,
    yaxisLabelsCount: yaxis.stepNum,
    yaxis: true,
    marginLeft: 50,
    yaxisTitleSize: 8,
    yaxisTitle: unitNm,
    yaxisTitleOffsetx: 5,
  },
})
  .draw();
canvas {
    border:solid 1px red;
}
.chart-tooltips {
  text-align: left !important;
}
.chart-tooltips * {
  font-size: 11px;
  color: white !important;
  min-height: unset !important;
}
.chart-tooltips h1 {
  font-size: 13px !important;
  font-weight: 800;
  margin: 0;
  border-bottom: solid 1px white;
}
.chart-tooltips h2 {
  font-size: 12px !important;
  margin: 0 0 10px 0;
}
     <script src='https://cdnjs.cloudflare.com/ajax/libs/RGraph/606/RGraph.common.core.js'></script>
            <script src='https://cdnjs.cloudflare.com/ajax/libs/RGraph/606/RGraph.line.min.js'></script>
            <script src='https://cdnjs.cloudflare.com/ajax/libs/RGraph/606/RGraph.common.dynamic.min.js'></script>
            <script src='https://cdnjs.cloudflare.com/ajax/libs/RGraph/606/RGraph.common.key.min.js'></script>
            <script src='https://cdnjs.cloudflare.com/ajax/libs/RGraph/606/RGraph.common.tooltips.min.js'></script>
        

position: sticky Does not work inside a container with overflow-auto in a dynamically created table using Tailwind CSS + Preline JS [closed]

I’m working on a project where I’m dynamically creating a large table using JavaScript and Tailwind CSS. I need certain headers and columns to stay “sticky” while scrolling horizontally and vertically. However, I’m facing an issue:

When I wrap the table in a div with the overflow-auto class, the position: sticky property stops working for the headers and columns. If I remove the overflow-auto class, the sticky positioning works correctly, but I lose the scrollbars, which are necessary because of the table’s size.

Here’s my code:

<div class="bg-white border-t border-gray-200 overflow-auto">
    <table id="graph" class="w-full divide-y divide-gray-200">
        <thead class="bg-gray-50">
            <tr class="divide-x" id="table1-months-headers">
                <th class="sticky top-0 left-0 z-50 bg-gray-50"></th>
                <th class="sticky top-0 left-[50px] z-50 bg-gray-50"></th>
            </tr>
            <tr class="divide-x" id="table2-headers">
                <th scope="col" class="sticky top-[40px] left-0 z-50 bg-gray-50 border-t border-gray-200 px-2 text-center whitespace-nowrap">
                    <span class="text-xs font-semibold uppercase tracking-wide text-gray-800">ID</span>
                </th>
                <th scope="col" id="name" class="sticky top-[40px] left-[50px] z-50 min-w-[200px] bg-gray-50 border-t border-gray-200 px-2 text-start whitespace-nowrap">
                    <div class="flex items-center gap-1">
                        <span class="text-xs font-semibold uppercase tracking-wide text-gray-800">Name</span>
                    </div>
                </th>
                <!-- Other headers -->
            </tr>
        </thead>
        <tbody>
            <!-- Dynamically generated table rows -->
        </tbody>
    </table>
</div>

I’m generating table headers and cells dynamically. Here’s how I’m adding the headers:

const monthsHeaders = $('#table1-months-headers');

let tdHeaders = `
    <td class="px-2 text-center whitespace-nowrap bg-gray-50 border-b border-gray-200">
        <span class="text-xs font-semibold uppercase tracking-wide text-gray-800">Total</span>
    </td>
`;

monthsHeaders.append(tdHeaders);

months.forEach(month => {
    let td = `<td class="sticky top-0 z-20 px-6 py-2 text-center whitespace-nowrap bg-gray-50 border-b border-gray-200" colspan="${month.days}">
                <span class="upper-month text-xs font-semibold uppercase tracking-wide text-gray-800">${month.name}</span>
            </td>`;
    monthsHeaders.append(td);
});

const tableHeaders = $('#table2-headers');
tableHeaders.append(tdHeaders);

months.forEach(month => {
    for (let i = 1; i <= month.days; i++) {
        let th = `<th scope="col" class="sticky top-[40px] z-30 min-w-8 max-w-12 whitespace-nowrap bg-gray-50" data-date="${year}-${month.code}-${String(i).padStart(2, '0')}">
                    <span class="text-xs font-semibold uppercase tracking-wide">${i}</span>
                </th>`;
        tableHeaders.append(th);
    }
});

What I’ve tried so far:

Parent container adjustments: Ensured correct position properties (relative, static, etc.) on parent elements.
Changing overflow properties: Tried various combinations of overflow properties on parent elements, like overflow-x, overflow-y, but the issue persists.
Restructuring HTML: Tried different HTML structures to see if a different hierarchy would help, but no luck.

How to correctly handle method animate behavior from Animation API

I am handling 3 events (codepen): mouseenter scales the element, mousemove rotates and mouseleave resets to original position. Please, see video showing the problem. At the end of the video, the element does not return to its original position. I’ve noticed that this happens more often if you trigger an mousemove event very, very quickly within an element. Less frequently, it can also occur in the case of rapid alternation of mouseenter-mouseleave.

There is one condition and general clarification. This frames cleaner here overAnimation.cancel() in the mouseleave handler might seem unnecessary. But in my project this element is located in Vue <transition-group> component and I have to leave cleaner in case to not brake component’s own animation because without cancel() the component just refuse to play his animation.

<div class="item"></div> 
const itemRef = document.querySelector('.item')
let overAnimation = null

itemRef.addEventListener('mouseleave', (e) => {
    overAnimation = itemRef.animate([
        {
            transform: 'none',
        }
    ], {duration: 1000, fill: 'forwards'})

    overAnimation.onfinish = () => {
        overAnimation.cancel()
    }
})

itemRef.addEventListener('mousemove', (e) => {
    const x = e.offsetX
    
    overAnimation = itemRef.animate([
        {
            transform: `scale(1.6) rotate(${x}deg)`,
        }
    ], {duration: 1000, fill: 'forwards'})
})

itemRef.addEventListener('mouseenter', (e) => {
    overAnimation?.cancel()

    overAnimation = itemRef.animate([
        {
            transform: 'scale(1.6)',
        }
    ], {duration: 1000, fill: 'forwards'})
})
body {
    background: #55b0fa;
}
.item {
    width: 200px;
    height: 200px;
    margin: 100px auto;
    background-color: blue;
}

Nodemailer Works in Development but Fails in Production – How Can I Fix This?

I’m using Nodemailer in my Node.js app with Gmail’s SMTP to send emails. It works fine in my development environment, but in production, emails aren’t being sent. I’ve set up my environment variables and confirmed they are loaded correctly. Here’s the code:

const nodeMailer = require("nodemailer");

exports.sendEmail = async (options) => {
  const transporter = nodeMailer.createTransport({
    service: "gmail",
    auth: {
      user: process.env.SMPT_MAIL,
      pass: process.env.SMPT_PASSWORD,
    },
  });

  const mailOptions = {
    from: process.env.SMPT_MAIL,
    to: options.email,
    subject: options.subject,
    html: options.message,
  };

  await transporter.sendMail(mailOptions);
};

C# API Controller Returns 400, but fetch in JavaScript hows 422 Status Code – Why?

I’m testing my C# API endpoint and encountering a discrepancy between the status code I return in my controller and what I receive by using fetch. I have configured my C# controller to return a 400 Bad Request if a parameter value does not match the expected format. However, when I make a request with invalid parameters using fetch, response.status shows 422 Unprocessable Entity instead of 400.

Here’s the relevant code:
In my C# API, I’m checking if the category parameter is valid. If it’s not, I set up a ProblemDetails response with a 400 status code. When I fill in a false parameter, it does return the 400.

if (!string.IsNullOrEmpty(category) && category != "http://terminology.hl7.org/CodeSystem/observation-category|laboratory")
{
    return UnprocessableEntity(new ProblemDetails
    {
        Title = "Ongeldige parameter",
        Detail = "De enige toegestane waarde voor 'category' is 'http://terminology.hl7.org/CodeSystem/observation-category|laboratory'.",
        Status = 400
    });
}

response from c# endpoint

I’m using fetch-api to make the request. This code snippet shows how I’m sending the request and logging the response status.

async def make_request(params):
    response = await fetch('/api/request', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            url: document.getElementById('url').value,
            params: params
        })
    })

    data = await response.json()
    print(response.status)  # This shows 422 instead of 400
    return {
        'status': response.status,
        'data': data
    }

Why does the response.status in JavaScript show 422 instead of 400? Is this an issue with how UnprocessableEntity works in C# when setting a custom Status code, or could it be something specific to the fetch implementation in JS?

Comprehensive Crypto MLM Software Development Services

Introduction:

Cryptocurrency and blockchain technologies are transforming industries, providing unprecedented innovation and efficiency. One of the most promising applications of these technologies is in multi-level marketing, where crypto MLM platforms allow businesses to manage, distribute, and expand their networks with improved transparency and security.

Justtry Technologies leads the way in this change by offering holistic crypto MLM software development services aligned with the needs of modern business. Using the power of blockchain, Justtry Technologies helps organizations develop scalable and high-performance, secure MLM solutions over cryptocurrencies.

Tailor-Made Crypto MLM Solutions

Justtry Technologies specializes in building bespoke solutions to handle various MLM business models on board such as binary and matrix along with unilevel.
The software integrates multiple currencies for users; thus they can manage numerous transactions through crypto assets in a very simplified manner.

Intuitive interfaces allow easy onboarding and navigation for businesses and users.

Enhanced Security Features
Blockchains are inherently secure, but Justtry Technologies adds more encryption, multi-factor authentication, and real-time monitoring to the base.
All the transactions are recorded immutably in the blockchain so fraud cannot take place and thus makes it more transparent.

Scalable Infrastructure
Justtry Technologies develops its MLM software on a scalable infrastructure that supports the growth of businesses without losing speed.

The software can be easily expanded to accommodate large, rapidly growing networks with cloud support and modular architecture.

Smart Contract Integration
Justtry Technologies guarantees each transaction and payout to be automatic, transparent, and secure from error and fraud risks by making use of smart contracts.

Smart contracts allow the automating of commission calculation and distribution. This reduces MLM management work.

All-around Analytics and Reporting
Integrated analytics help users understand user behavior, revenue trends, and growth of the network.

Tracking KPIs becomes an easy task, detailed reporting is generated, and hence, data-driven decisions could be made to enhance the performance and profitability.

Wallet Integration
Justtry Technologies has wallet integrations of the most popular cryptocurrencies with wallet integrations, where it makes transactions easy and secure for the users. It allows users to conduct transacting, holding, and converting crypto assets right from the MLM platform in the form of multi-currency wallets.

Dedicated Support and Maintenance
Justtry Technologies ensures smooth operation of the software in terms of technical support during its lifecycle as the needs of business evolve.

The software receives frequent updates and maintenance in terms of security, updated regulatory compliance, and most current technological changes.

Conclusion:

As innovation continues in the crypto world, Justtry Technologies empowers MLM businesses to gain from blockchain. With its full-cycle crypto MLM software development service.

Justtry Technologies provide advanced Crypto MLM Software Development Services for security, transparency, and scalability of blockchain-based solutions. With customized features, smart contract integrations, and multi-currency support, this software delivers against a variety of MLM requirements. Advanced analytics, user-friendly interfaces, and support for continued operations ensure seamless network growth. Reach new heights in MLM business using the edge technology provided by Justtry.

in node.js ESM I want to stub an exported module thats the default

I have a very simple auth middleware with an export default () anonymous function:

export default () => async (req, res, next) => {
  try {
       // some auth implementation... does not matter
    } else {
      throw new Error('No "Bearer" token passed as header')
    }

    next()
  } catch (err) {
    next(err)
  }
}

I want to stub this in my unit tests to just continue with next().

import express from 'express';
import supertest from 'supertest';
import { router } from "express-file-routing"
import auth from '../../middlewares/auth.js';
import sinon from 'sinon'

describe("/foo", () => {
    let app, request;
    
    before(async () => {
        app = express();
        app.use("/", await router())
        request = supertest(app);
    });

    beforeEach(() => {
   
        sinon.stub(auth()).callsFake((req, res, next) => next());
        // tried also ...
        // sinon.replace(auth, 'default', () => (req, res, next) => next());
});
//... test continue

But these are not working. I am getting TypeError: sinon.stub(...).callsFake is not a function
or
TypeError: Cannot replace non-existent property default. Perhaps you meant sandbox.define()? when I try with sinon.replace