Chrome permission for clipboard-write returns ‘granted’ but prompts user

I’m using the following code to check if the the navigator has permission to write to the clipboard:

window.onload = () => {
  navigator.permissions.query({ name: 'clipboard-write' }).then((permission) => {
    console.log(permission.state);
    if (permission.state === 'granted') {
      navigator.clipboard.writeText('sample text');
    }
  });
}

In Chrome, it returns “granted”, however I get a prompt “See text and images copied to the clipboard” with the option to “Allow” or “Block”. Shouldn’t it return “prompt” instead?

How to make specific elements inside custom modal appear above an overlay with higher z-index than the modal?

Context:

In my Blazor web app I am trying to implement a feature which will allow me to cover all elements, except some selected ones, with an overlay. Only selected (highlighted) elements should be visible above the overlay.

So far everything worked by changing the class of the elements I wanted to highlight dynamically to a highlighted class which has higher z-index than the overlay element.

The problem:

When I use my custom modal, the elements inside don’t appear in front of the overlay even when I apply the highlighted class.

Minimal example:

Here link to jsfiddle (same code as below): https://jsfiddle.net/hartmaj2/x1dg23m4/2/


<div class="overlay"> </div>
    
<div class="custom-modal-background">
    <div class="custom-modal" >
        <div class="modal-div">
          <div class="highlighted">
            I want to be in front of everything
          </div>
        </div>
    </div>
</div>

<div class="highlighted">
  I am in front of everything
</div>

<div>
  I am not in front of everything
</div>
.custom-modal-background {
    position: fixed;
    display: flex;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.5);
    align-items: center;
    justify-content: center;
    z-index: 1500; 
}
.custom-modal {
    position: relative;
    display: flex;
    background-color: white;
}

.overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0,0,0,0.5);
    z-index: 2000;
}

.highlighted {
    position: relative;
    background-color: yellow;
    z-index: 2100;
}

Suspect reasons:

I think that the reason is that the custom-modal-background and custom-modal elements have position: fixed which creates their own stacking context (this property is necessary for them to work properly). Removing the position: fixed property solves the problem but is not a solution for me (unless I find a way to implement my modal without needing this property)

What I have tried:

I tried using a Blazor bootstrap modal instead of my custom one but the problem wasn’t solved. Also Chat-GPT proposed moving the element inside DOM using JSInterop but I don’t know if that would be a scalable solution. (I would appreciate some thoughts about this also)

Question:

Is there a way to make the highlighted elements inside the custom-modal appear above the overlay elements?

I am looking for a solution that is scalable as I will be using it for many elements which I will mark as highlighted.

Many thanks!

How to listen to Enhanced Measurement events from js?

I want to pass Enhanced Measurement events from Google Analytics through an iframe. Specifically I want to capture events, such as form_start and form_submit, etc and then send them to the parent window via window.parent.postMessage.

I tried to log all the events pushed via the window.dataLayer.push, but it appears to me that enhanced measurement events don’t directly use it – I see the events firing in Tag Assistant but not in the console.

Is it possible for me to access those events through my JavaScript?

How can I create a subtotal percentage column?

In webdatarocks I have two main columns, amount and percentage, which are grouped by branch and department, so I can see the subtotals of these grouping criteria.
My problem comes when I want to create the “percentages” column, because the only aggregation function I have to create this column is “percent” which, if I understand correctly, represents a percentage of the grandtotal, not the subtotal.
I would need something like a “percentofparent” function, but I don’t see something like that available in WebDataRocks.

I’ve tried the 3 percentage aggregation functions but any of them worked, I’ve also tried to add this manually by manipulating the data, but I always need to calculate the percentages based on the ‘parent subtotal,’ which is a value I don’t have.

Uncaught (in promise) Error: Could not load file ‘/public/content-script.bundle.js’. It isn’t UTF-8 encoded. Using chrome.scripting.executeScript

Goal

I am trying to create a Chrome extension that will embed a CodeMirror Editor in the web page. I use vite for bundling the CodeMirror package and use chrome.scripting.executeScript to run my javascript file.

Setup

manifest.json

{
    "manifest_version": 3,
    "name": "Odoo Better Ide",
    "description": "Better Ide",
    "version": "1.0",
    "icons": {
        "16": "images/icon-16.png",
        "32": "images/icon-32.png",
        "48": "images/icon-48.png",
        "128": "images/icon-128.png"
    },
    "background": {
        "service_worker": "src/background.js",
        "type": "module"
    },
    "action": {
        "default_icon": {
            "16": "images/icon-16.png",
            "32": "images/icon-32.png",
            "48": "images/icon-48.png",
            "128": "images/icon-128.png"
        }
    },
    "permissions": ["activeTab", "scripting"]
}

background.js (for my service worker and check if the user clicks the extension icon)

chrome.runtime.onInstalled.addListener(() => {
    chrome.action.setBadgeText({
        text: "OFF",
    });
});

const odooUrl = "https://demo";
chrome.action.onClicked.addListener(async (tab) => {
    if (tab.url.startsWith(odooUrl)) {
        const prevState = await chrome.action.getBadgeText({ tabId: tab.id });
        const nextState = prevState === "ON" ? "OFF" : "ON";

        await chrome.action.setBadgeText({
            tabId: tab.id,
            text: nextState,
        });

        if (nextState === "ON") {
            chrome.scripting.executeScript({
                target: { tabId: tab.id },
                files: ["/dist/content-script.bundle.js"], // this is the bundled js file
            });
        } else if (nextState === "OFF") {
            console.log("Turned off");
        }
    }
});

content-script.js (will be bundled by vite rollup)

import { EditorView, basicSetup } from "codemirror";
import { python } from "@codemirror/lang-python";

const ideElem = document.querySelector(".o_field_code");
console.log(ideElem);

if (ideElem) {
    console.log(ideElem);
    const editorElem = initiazeEditorView(ideElem);
    console.log(editorElem);
}

function initiazeEditorView(ideElem) {
    let editor = new EditorView({
        extensions: [basicSetup, python()],
        parent: ideElem,
    });
    return editor;
}

vite.config.js

import { defineConfig } from "vite";
import { nodeResolve } from "@rollup/plugin-node-resolve";
import terser from "@rollup/plugin-terser";

export default defineConfig({
    build: {
        rollupOptions: {
            input: "src/content-script.js",
            output: {
                dir: "dist",
                entryFileNames: "content-script.bundle.js",
                format: "iife",
            },
            plugins: [nodeResolve(), terser()],
        },
    },
});

Problem/Issue

The extension is working properly but everytime I tried to run (click the extension icon) and execute the code:

chrome.scripting.executeScript({
    target: { tabId: tab.id },
    files: ["/dist/content-script.bundle.js"], // this is the bundled js file
});

It always shows me an error Uncaught (in promise) Error: Could not load file '/dist/content-script.bundle.js'. It isn't UTF-8 encoded.

When I opened the bundled file in VSCode it shows that it’s a “UTF-8”. I also tried the Save with encoding feature of VSCode but still no luck.

If you want to clone the repo here’s the link: https://github.com/dwarjie/odoo-better-ide

How to run a ABP project on linux app services in Azure?

I have been trying to run an angular ef-core ABP project on linux appservices in azure.
The httphost is working but the app service with angular is still serving the Default Microsoft screen. Any suggestions to trouble-shoot the issue? Is ABP compatible on linux?

Tried switching the app service stack between various .NET and Node version.
Ensured that the build files are reaching the app service via bash.
Tried giving the start command at the optional Startup Command field in app service configuration

How can I modify the 2048 game to support different board sizes in JavaScript? [closed]

I’m creating a version of the 2048 game and want to allow players to choose custom board sizes (e.g., 3×3, 5×5, etc.). The standard game uses a 4×4 grid, but I want the logic to dynamically adjust based on the selected size.

How should I modify the merging and movement logic to handle different board sizes seamlessly? Are there any specific pitfalls to avoid?

Architecture patterns for extendable MVC applications

I maintain a JS UI component library and a frontend web application following the general MVC architecture. There are basic views, complex views, and then controllers that bind the view logic to the model.

Basic components (views)

// The UI library is made of atomic components like the following one.
// 
// * This could be as well a React component, a native web component, or any other framework.
//   It accepts properties, renders a DOM element, and has a means of informing the world 
//   about user actions and that's all that matters. It's a framework-agnostic example.
// * Note: this is a pseudo-code to keep it simple. 
class ButtonView extends BaseView {
    constructor( type, cssClass, label ) {
        this.type = type;
        this.cssClass = cssClass;
        this.label = label;
        
        // ...
    }
    
    render() {      
        this.element = document.createElement( 'button' );
        
        // ...
        
        // Set DOM element attributes and children so it looks familiar
        // <button type="{ type }" class="{ cssClass }">{ label }</button>
        
        // ...
        
        this.element.addEventListener( 'click' ), () => {
            this.fire( 'click' );
        } );
    }   
}

Complex web application views

// The web application composes UI library views (e.g. simple buttons ☝️) 
// into complex user interfaces like forms, toolbars, etc.
//
// Note: this is a pseudo-code to keep it simple. 
class SomeFormView extends BaseView {
    // ...
    
    render() {      
        // Use the basic component to as a building block for the complex view.
        const button = new ButtonView( 'submit', 'foo', 'Send form' );
        
        button.on( 'click', () => {
            this.submitForm();      
        } );
        
        button.render();
    
        // ...inject the button into the form along with other components.
    }       
    
    submitForm() {
        this.fire( 'submit', { 
            /* Passing the form data along with the event */ 
        } );
    }
    
    // ...
}

Web application controllers

// The controller glues the topmost view layer and the model together.
// 
// Note: this is a pseudo-code to keep it simple. 
class SomeController {
    constructor() {
        this.someFormView = new SomeFormView();
        this.someFormView.render(); 
        this.someFormView.on( 'submit', ( data ) => {
            this.onSubmit( data );
        } );
    }
    
    onSubmit( data ) {
        // E.g. save data to a database. It doesn't really matter.
    }
}

Problem

My business requirement is to make the above MVC architecture as open-ended and extendable as possible by integrators. Here are some details:

  • The web application runs in a web browser.
  • The integrators need an API to:
    • Change the template (add/remove attributes, children, behaviors) for basic components like mentioned ButtonView.
    • Change the template (add/remove attributes, children, behaviors) for complex views like mentioned SomeFormView.
    • Remove, replace, or inject an extra logic to the SomeController. This is especially useful when they have already customized the views the controller would glue to the model.
  • The customization must be possible in the runtime (e.g. right before the application starts on the client). Build-time module replacement and similar solutions are, sadly, off the table.
    • As a side note, there’s an underlying plugin system the integrators can use to extend the application. So there’s a central extension point.

I’m looking for good examples: existing frameworks, books, academic papers or just any sort of inspiration. It does not have to be web-based. I assume that native application developers who allow for 3rd-party plugins (extensions) are facing the same set of problems that I am.

Nothing pops into my head aside from:

  • splitting views and controllers into atomic chunks (e.g. methods)
  • providing some sort of view/controller registry the integrator may hook into before the UI is rendered (and displayed) to swap classes.

Are ideas?

Simulate a Web Site’s auto form fill

It’s can be hard to understand cause of my english. But, here’s my question.

Web sites filling inputs in the form elements after taking responses from GET or POST requests. I want to automate it in HTML Agility Pack. How to convert the scripts that web sites using to fill inputs a method or something?

I’m tried to fill every input by manuel but it’s hard a bit.

string respTrafik = _driver.GetData(adress, "", "").Result;
                HtmlAgilityPack.HtmlDocument dc = new HtmlAgilityPack.HtmlDocument();
                dc.LoadHtml(respTrafik);

_driver is one of my modified classes. GetData method uses httpwebrequest class. After this process i need to fill a form in dc. Then i will post that form to a url.

In normal browsers, scripts filling all inputs automatically. I need to find a way to get that algorithm and use it with HAP.

Using TamperMonkey to change the text that is loaded after the page is loaded

So this is the JS selector of the element i want to change document.querySelector("#sSGrid > table > tbody > tr.k-state-selected > td:nth-child(7)")
this grid has a text element in it that i want to change lets call it Test
Yet i seem to not be able to change it no matter what i try can anyone help me i really suck at javascript but need to change this

I tried using scripts i found in the internet such as mutation observers or waiting 3 seconds or waiting for page to load yet it seems like this thing just wont work.

This element is in a table and when i load the scripts after the page fully loads it seems like it works just that i cant automate it.

Obj loader collect group vertices

I have nice working obj script but with small bug.
I made group detect rule by adding in blender name with “COLLIDER” and it is a simply non rotated cube.
I also have group detect part.

But i saw in console log that some of (looks like random choose) group always have
all vertices of object.

See printscreen with console logs:
enter image description here

My Obj loader:

'use strict';
import {world} from './matrix-world';

export class constructMesh {

    constructor(objectData, inputArg) {
        this.inputArg = inputArg;
        this.objectData = objectData;
        this.create(objectData, inputArg);
        this.setScale = (s) => {
            this.inputArg.scale = s;
            initMeshBuffers(world.GL.gl, this.create(this.objectData, this.inputArg));
        };
    }

    create = (objectData, inputArg, callback) => {
        if(typeof callback === 'undefined') callback = function() {};
        let initOrientation = [0, 1, 2];
        var verts = [],
            vertNormals = [],
            textures = [],
            unpacked = {};
        // unpacking stuff
        unpacked.verts = [];
        unpacked.norms = [];
        unpacked.textures = [];
        unpacked.hashindices = {};
        unpacked.indices = [];
        unpacked.index = 0;
        // array of lines separated by the newline
        var lines = objectData.split('n');

        // test group catch data bpund or center
        var objGroups = [];
        // update swap orientation
        if(inputArg.swap[0] !== null) {
            swap(inputArg.swap[0], inputArg.swap[1], initOrientation);
        }

        var VERTEX_RE = /^vs/;
        var NORMAL_RE = /^vns/;
        var TEXTURE_RE = /^vts/;
        var FACE_RE = /^fs/;
        var WHITESPACE_RE = /s+/;

        for(var i = 0;i < lines.length;i++) {
            var line = lines[i].trim();
            var elements = line.split(WHITESPACE_RE);
            elements.shift();

            if(VERTEX_RE.test(line)) {
                // if this is a vertex
                verts.push.apply(verts, elements);

                if(objGroups.length > 0) {
                    objGroups[objGroups.length - 1].groupVert.push(elements)
                }

            } else if(NORMAL_RE.test(line)) {
                // if this is a vertex normal
                vertNormals.push.apply(vertNormals, elements);
            } else if(TEXTURE_RE.test(line)) {
                // if this is a texture
                textures.push.apply(textures, elements);
            } else if(FACE_RE.test(line)) {
                // if this is a face
                /*
                    split this face into an array of vertex groups
                    for example:
                        f 16/92/11 14/101/22 1/69/1
                    becomes:
                        ['16/92/11', '14/101/22', '1/69/1'];
                    */
                var quad = false;
                for(var j = 0, eleLen = elements.length;j < eleLen;j++) {
                    // Triangulating quads
                    // quad: 'f v0/t0/vn0 v1/t1/vn1 v2/t2/vn2 v3/t3/vn3/'
                    // corresponding triangles:
                    //      'f v0/t0/vn0 v1/t1/vn1 v2/t2/vn2'
                    //      'f v2/t2/vn2 v3/t3/vn3 v0/t0/vn0'
                    if(j === 3 && !quad) {
                        // add v2/t2/vn2 in again before continuing to 3
                        j = 2;
                        quad = true;
                    }
                    if(elements[j] in unpacked.hashindices) {
                        unpacked.indices.push(unpacked.hashindices[elements[j]]);
                    } else {
                        var vertex = elements[j].split('/');

                        if(typeof inputArg.scale == "number") {
                            unpacked.verts.push(+verts[(vertex[0] - 1) * 3 + initOrientation[0]] * inputArg.scale);
                            unpacked.verts.push(+verts[(vertex[0] - 1) * 3 + initOrientation[1]] * inputArg.scale);
                            unpacked.verts.push(+verts[(vertex[0] - 1) * 3 + initOrientation[2]] * inputArg.scale);
                        } else {
                            unpacked.verts.push(+verts[(vertex[0] - 1) * 3 + initOrientation[0]] * inputArg.scale.x);
                            unpacked.verts.push(+verts[(vertex[0] - 1) * 3 + initOrientation[1]] * inputArg.scale.y);
                            unpacked.verts.push(+verts[(vertex[0] - 1) * 3 + initOrientation[2]] * inputArg.scale.z);
                        }

                        // vertex textures
                        if(textures.length) {
                            unpacked.textures.push(+textures[(vertex[1] - 1) * 2 + 0]);
                            unpacked.textures.push(+textures[(vertex[1] - 1) * 2 + 1]);
                        }
                        // vertex normals
                        unpacked.norms.push(+vertNormals[(vertex[2] - 1) * 3 + 0]);
                        unpacked.norms.push(+vertNormals[(vertex[2] - 1) * 3 + 1]);
                        unpacked.norms.push(+vertNormals[(vertex[2] - 1) * 3 + 2]);
                        // add the newly created vertex to the list of indices
                        unpacked.hashindices[elements[j]] = unpacked.index;
                        unpacked.indices.push(unpacked.index);
                        // increment the counter
                        unpacked.index += 1;
                    }
                    if(j === 3 && quad) {
                        // add v0/t0/vn0 onto the second triangle
                        unpacked.indices.push(unpacked.hashindices[elements[0]]);
                    }
                }
            } else {
                if(line.indexOf('# ') != -1) {
                    // console.log('obj loader comment:', line)
                } else if(line.indexOf('mtllib') != -1) {
                    // console.log('obj loader MTL file:', line)
                } else if(line.indexOf('g ') != -1) {
                    // console.log('obj loader group :', line)
                    var nameOFGroup = line.split(' ')[1]
                    if(nameOFGroup.indexOf('COLLIDER') != -1) {
                        console.log('obj loader group [SPECIAL CASE COLLIDER]:', nameOFGroup)
                        objGroups.push({
                            groupName: nameOFGroup,
                            groupVert: []
                        })
                    }
                }
            }
        }
        this.vertices = unpacked.verts;
        this.vertexNormals = unpacked.norms;
        this.textures = unpacked.textures;
        this.indices = unpacked.indices;

        if(objGroups.length > 0) {
            this.groups = objGroups;
        } else {
            this.groups = null;
        }
        callback();
        return this;
    };

}

var Ajax = function() {
    // this is just a helper class to ease ajax calls
    var _this = this;
    this.xmlhttp = new XMLHttpRequest();

    this.get = function(url, callback) {
        _this.xmlhttp.onreadystatechange = function() {
            if(_this.xmlhttp.readyState === 4) {
                callback(_this.xmlhttp.responseText, _this.xmlhttp.status);
            }
        };
        _this.xmlhttp.open('GET', url, true);
        _this.xmlhttp.send();
    };
};

export var downloadMeshes = function(nameAndURLs, completionCallback, inputArg) {
    var semaphore = Object.keys(nameAndURLs).length;
    var error = false;
    if(typeof inputArg === 'undefined') {
        var inputArg = {
            scale: 1,
            swap: [null]
        };
    }
    if(typeof inputArg.scale === 'undefined') inputArg.scale = 1;
    if(typeof inputArg.swap === 'undefined') inputArg.swap = [null];
    var meshes = {};
    for(var mesh_name in nameAndURLs) {
        if(nameAndURLs.hasOwnProperty(mesh_name)) {
            new Ajax().get(
                nameAndURLs[mesh_name],
                (function(name) {
                    return function(data, status) {
                        if(status === 200) {
                            meshes[name] = new constructMesh(data, inputArg);
                        } else {
                            error = true;
                            console.error('An error has occurred and the mesh "' + name + '" could not be downloaded.');
                        }
                        // the request has finished, decrement the counter
                        semaphore--;
                        if(semaphore === 0) {
                            if(error) {
                                // if an error has occurred, the user is notified here and the
                                // callback is not called
                                console.error('An error has occurred and one or meshes has not been ' + 'downloaded. The execution of the script has terminated.');
                                throw '';
                            }
                            // there haven't been any errors in retrieving the meshes
                            // call the callback
                            completionCallback(meshes);
                        }
                    };
                })(mesh_name)
            );
        }
    }
};

var _buildBuffer = function(gl, type, data, itemSize) {
    var buffer = gl.createBuffer();
    var arrayView = type === gl.ARRAY_BUFFER ? Float32Array : Uint16Array;
    gl.bindBuffer(type, buffer);
    gl.bufferData(type, new arrayView(data), gl.STATIC_DRAW);
    buffer.itemSize = itemSize;
    buffer.numItems = data.length / itemSize;
    return buffer;
};

export var initMeshBuffers = function(gl, mesh) {
    mesh.normalBuffer = _buildBuffer(gl, gl.ARRAY_BUFFER, mesh.vertexNormals, 3);
    mesh.textureBuffer = _buildBuffer(gl, gl.ARRAY_BUFFER, mesh.textures, 2);
    mesh.vertexBuffer = _buildBuffer(gl, gl.ARRAY_BUFFER, mesh.vertices, 3);
    mesh.indexBuffer = _buildBuffer(gl, gl.ELEMENT_ARRAY_BUFFER, mesh.indices, 1);
};

export var deleteMeshBuffers = function(gl, mesh) {
    gl.deleteBuffer(mesh.normalBuffer);
    gl.deleteBuffer(mesh.textureBuffer);
    gl.deleteBuffer(mesh.vertexBuffer);
    gl.deleteBuffer(mesh.indexBuffer);
};

/**
 * @description
 * Construct sequence list argument for downloadMeshes.
 * This is adaptation for blender obj animation export.
 * For example:
 *    matrixEngine.objLoader.downloadMeshes(
            matrixEngine.objLoader.makeObjSeqArg(
                {
                    id: objName,
                    joinMultiPahts: [
                        {
                            path: "res/bvh-skeletal-base/swat-guy/seq-walk/low/swat",
                            id: objName,
                            from: 1, to: 34
                        },
                        {
                            path: "res/bvh-skeletal-base/swat-guy/seq-walk-pistol/low/swat-walk-pistol",
                            id: objName,
                            from: 35, to: 54
                        }
                    ]
                }),
            onLoadObj
        );
 */
export const makeObjSeqArg = (arg) => {
    // Adaptation for blender (animation) obj exporter.
    var local = {};
    function localCalc(arg, noInitial = false) {
        var zeros = '00000';
        var l = {};
        var helper = arg.from;
        for(let j = arg.from, z = 1;j <= arg.to;j++) {
            if(z > 9 && z < 99) {
                zeros = '0000';
            } else if(z > 99 && z < 999) {
                zeros = '000';
            } // no need more then 999
            if(helper == arg.from && noInitial === false) {
                l[arg.id] = arg.path + '_' + zeros + z + '.obj';
            } else {
                l[arg.id + (helper - 1)] = arg.path + '_' + zeros + z + '.obj';
            }
            helper++;
            z++;
        }
        return l;
    }

    if(typeof arg.path === 'string') {
        local = localCalc(arg);
    } else if(typeof arg.path === 'undefined') {
        if(typeof arg.joinMultiPahts !== 'undefined') {
            console.log("ITS joinMultiPahts!");
            var localFinal = {};
            arg.joinMultiPahts.forEach((arg, index) => {
                if(index === 0) {
                    localFinal = Object.assign(local, localCalc(arg));
                } else {
                    localFinal = Object.assign(local, localCalc(arg, true));
                }
            });
            console.log("joinMultiPahts LOCAL => ", localFinal);
            return localFinal;
        }
    }
    return local;
}

Any suggestion ?

Resizing a div that has a transform: how to play with the top/left/width properties such that it remains in one place?

I am trying to make my shape stay in place when performing a resize. Unfortunately, the following code:

element.style.left =
        initialPositionsTransformed.originalXPosition -
        Math.abs(distanceX) +
        "px";

element.style.top = initialPositionsTransformed.originalYPosition + "px";

element.style.width = originalElementWidth + Math.abs(distanceX) + "px";

while performing said resize, doesn’t work. I can’t find a way to make my top value change in such a way that (visually speaking) the shape wouldn’t move. If you go to the codesandbox, you can see the movement is weird.

I tried to make it so that the top value is initialPositionsTransformed.originalYposition + distanceX, but this still pushes it.

Is there a formula that would take the resize value from my horizontal resize, use that, and then make it so my shape doesn’t move? In other words, I’d like the shape to be anchored to the bottom-right (in this case). The only thing that should increase here is its width, which should shoot up to the top-left.

how can select many items by don’t close FormControl in MUI

const MonthPicker = ({ monthsList, selectedMonths, setSelectedMonths }) => {`

! main function for select items
const handleChange = (event) => {
const {
target: { value },
} = event;

  setSelectedMonths(typeof value === "string" ? value.split(",") : value);
};

const MenuProps = {
  // Prevent the menu from closing when selecting a menu item
  MenuProps: {
    disableAutoFocusItem: true,
  },
};

 return (
  <FormControl
    sx={{width: "100%",
      "& .MuiInputLabel-root": {
        fontSize: "1rem",
        color: Colors.dark,
      },
      "& .MuiSelect-root": {
        fontSize: "0.8rem",
      },
    }}
       size="small">
      <InputLabel id="month-picker-label">Oyni Tanlash</InputLabel>
      <Select
      multiple
      labelId="month-picker-label"
      id="month-picker"
      value={selectedMonths}
      onChange={handleChange}
      input={<OutlinedInput label="Oyni Tanlash" />}
      renderValue={(selected) => selected.join(", ")}
      MenuProps={MenuProps}>
      {monthsList.map((month) => (
        <MenuItem
          key={month.id}
          value={month.name}
          sx={{
            padding: "4px 8px",
            display: "flex",
            alignItems: "center",
            gap: "8px",}}
          // Prevent the menu from closing when clicking on a menu item
          onClick={(event) => event.stopPropagation()}>
          <Checkbox
            checked={selectedMonths.includes(month.name)}
            sx={{ color: Colors.blue_nbu, padding: 0 }}
            size="small"
          />
          <ListItemText
            primary={month.name}
            sx={{ fontSize: "0.8rem", margin: 0 }}
          />
        </MenuItem>
        ))}
       </Select>
     </FormControl>
   );
`};

i use own function of mui component but can not fix bug , my code works : user select month name and form send item name to array immediately , but i will make collect all of elected month names and send array after selection

Is it possible to animate a radio button on selection change without using JavaScript?

I’m making a selection bar for an app by using heavily styled radio buttons so I can make sure there can just be one element selected at a time and also using handy styling tricks so I had to code less. However, now I’m trying to animate them, using a slight ease whenever the selected button changes. I have changed the background color whenever an element is selected and I want it to move it linearly along the line until it reaches the new position of the element that should have the background color. Is that possible with just CSS and HTML? Or do I need to add a bit of JavaScript to make it work? And if yes, how exactly?

I tried many things, like adding the background color on different places, I tried different ways of animating, but nothing worked out the way I liked. I managed to get an animation where the form would collapse when I switched buttons, so it isn’t impossible to trigger an animation on input change.

Here’s my code (I’ve tried to make it slightly more generic so other people can benefit from this too:)

<script lang="ts">
    import './example.css';

    export let options: "OPTION1" | "OPTION2" | "OPTION3" = "OPTION1";

    const handleClick = () => {
        const option1 = document.getElementById('option1') as HTMLInputElement;
        const shortBreak = document.getElementById('option2') as HTMLInputElement;
        const longBreak = document.getElementById('option3') as HTMLInputElement;

        if (option1.checked) {
            options = "OPTION1";
        } else if (option2.checked) {
            options = "OPTION2";
        } else if (option3.checked) {
            timerType = "OPTION3";
        }

        console.log(`debug> option selected: ${options}`);
    }
</script>

<div class="options">
    <form>
        <label>
            <input type="radio" id="option1" name="options" checked on:click={handleClick}>
            <span>Option 1</span>
        </label>
        <label>
            <input type="radio" id="option2" name="options" on:click={handleClick}>
            <span>Option 2</span>
        </label>
        <label>
            <input type="radio" id="option3" name="options" on:click={handleClick}>
            <span>Option 3</span>
        </label>
    </form>
</div>
input[type="radio"] {
    display: none;
}

form {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: nowrap;
    overflow: hidden;
    background-color: #242424;
    color: white; /* needed for debugging, otherwise you can't really visualize what happens */
    border-radius: 10px;
    padding-left: 5px;
    padding-right: 5px;
}

label {
    display: flex;
    align-items: center;
    cursor: pointer;
    max-width: 300px;
    white-space: nowrap;
    overflow: hidden; 
    text-overflow: ellipsis;
    border-radius: 10px;
    margin: 0; 
}

form > label:not(:first-child) {
    margin-left: 5px;
}

*, *::before, *::after {
    box-sizing: border-box;
}

input[type="radio"]:checked + span {
    background-color: #747bff;
    padding: 10px;
    border-radius: 10px;
    margin: 0;
}

label span {
    margin-left: 0;
}

PS. Some other thing I was encountering was that there was a slight gap between the form and the label if I’d select the first element. It would be nice if you guys could also help me with that.