How to Programmatically Activate a Pseudo-Class on an Element?

I am working on a React project and need to simulate the hover state on a button without user interaction. Our design system defines certain styles within pseudo-classes, such as hover, and I would like to apply these styles programmatically for demonstration purposes in an environment like Storybook.

Problem: I want to activate the :hover pseudo-class on React components (specifically buttons) so that they display the hover effect as if the user were hovering over them with their mouse. These styles are defined within our theme, and I cannot directly alter this definition.

Question: Is there any way to programmatically activate pseudo-classes such as :hover, :active, :focus, etc., in JavaScript or React? If so, how can this be done without modifying the original definitions of the pseudo-classes in CSS?

What I’ve Tried: I attempted to use mouse events like mouseover through dispatchEvent, but this did not work.

const buttonRef = useRef(null);

useEffect(() => {
  const button = buttonRef.current;
  const event = new MouseEvent('mouseover', {
    view: window,
    bubbles: true,
    cancelable: true
  });
  button.dispatchEvent(event);
}, []);

I aim to force the hover state on multiple buttons simultaneously, such that they remain with the hover style applied until I deactivate it.

Thanks in advance for your time! 🙂

Problem sending json data from js file to .NET controller through ajax post

So, I am trying to get from the client (js) to the server (.net controller) a json string through an ajax post. For some reason, which I cannot understand, it arrives into the controller, but the list is empty (count = 0).

  • JS Code
    btnAddMovie.addEventListener("click", () => {
        console.log(datesDict);

        var dataToSend = formatDataToSend();
        console.log(dataToSend);
        console.log(JSON.stringify(dataToSend));


        $.ajax({
            type: "POST",
            url: "SubmitMovieAdd",
            data: JSON.stringify(dataToSend),
            contentType: "application/json",
            success: function (response) {
                console.log(response);
            },
            error: function (request, status, error) {
                console.log(request.responseText);
            }
        });
    });

    function formatDataToSend() {
        var jsonToSend = [];

        for (const [key, value] of Object.entries(datesDict)) {
            jsonToSend.push({
                date: key,
                hours: value
            });
        }

        return jsonToSend;
    }

In datesDict (dictionary) there are some values like this:
datesDict = 14/05/2024: [’15:00:00′, ’12:00:00′]

In dataToSend it appears like this:
dataToSend = 0: {date: ’14/05/2024′, hours: Array(2)}

Final json.stringify => [{“date”:”14/05/2024″,”hours”:[“15:00:00”, “12:00:00”]}]

  • Controller
    [HttpPost("MyAdminDashBoard/MovieAdd/SubmitMovieAdd")]
    public IActionResult SubmitMovieAdd(List<MovieAddJsonAppModel> json)
    {
        return Content(json.Count().ToString());
    }
  • Model
    public class MovieAddJsonAppModel
    {
        public string Date { get; set; }
        public List<string> Hours { get; set; }
    }

Can you help me please solve this issue? Thank you:)

How to update zoom on an image when the user scrolls to a different section of the page?

I’m zooming in on an image when user scrolls on the page. In my case, I zoom to letter L when user scrolls to div id= “par3” and zooms out when it reaches to the end of div. I am using IntersectionObserver to check if #par3 is in view.

Now I want to add a new zoom with background-position: 22% 33%; when user scrolls to div id = par4 and zoom out when user is at the end of the div. How can I update/add to this code?

const d1 = document.querySelector(".d1");
const par3 = document.querySelector("#par3");
let toPar3 = false;
const par3InitialY = par3.offsetTop;
document.addEventListener("scroll", (evt) => {
  const r = scrollY - par3InitialY;
  const s = r < 0 ? 1 : 1 + r / 200;
  d1.style.backgroundSize = (toPar3 ? s : 1) * 100 + "%";
});
const observer = new IntersectionObserver((entries) => entries.forEach((entry) => (toPar3 = entry.isIntersecting)));
observer.observe(par3);
body {
  height: 200vh;
}

.d1 {
    width: 50%;
    aspect-ratio: 2/1;
    position: sticky;
    top: 0;
    background-image: url(http://picsum.photos/id/451/1500/750);
    background-size: 100%;
    background-position: 72% 43%;
    transition: background-size 0.5s ease; /* Smooth transition */
  }
<div>
  <div id="par1">
    <p>Paragraph1 sit amet, consectetur adipiscing elit. Maecenas tempor nunc mauris, sit amet placerat tortor lobortis dapibus. Nam lectus eros, maximus ac magna vel, congue consequat eros. Fusce id pretium diam. Cras sit amet pharetra ante. Sed quis commodo
      quam, vel facilisis ipsum. Vestibulum sodales iaculis arcu, et fringilla nisi ullamcorper sed. Donec interdum sit amet est non accumsan. Donec non augue feugiat, fermentum nunc non, convallis est. Cras vel ligula nec odio faucibus ultricies. Sed
      vulputate tortor eget pretium convallis. Cras interdum elit eget mi porta suscipit. Morbi ut velit diam. Etiam finibus eros et efficitur rutrum. Quisque viverra metus ac eleifend imperdiet. Quisque pretium ut purus vitae tempus. Duis varius risus
      congue velit faucibus, sed interdum purus consectetur.</p>
  </div>
  <div class="d1"></div>
  <div id="par2">
    <p>Paragraph2 Cras volutpat velit non mi sagittis condimentum. Cras tempor aliquet turpis sed pretium. Nunc aliquet sodales turpis quis ultrices. Duis auctor accumsan enim, quis maximus ex malesuada a. Donec a felis ut erat tempus euismod non vel neque.
      Proin lectus massa, sagittis at imperdiet nec, consequat ut neque. Sed vel placerat neque, vel varius urna. Vivamus interdum euismod urna a accumsan. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p>
  </div>
  <div id="par3">
    <p>Paragraph3 Nulla rhoncus aliquam mauris, eu pretium dolor auctor in. Maecenas a sollicitudin dolor, eget commodo quam. Proin et dui sed ligula vulputate egestas. Quisque eget augue vitae purus placerat pharetra. Aliquam rhoncus convallis lorem, sed
      facilisis odio blandit scelerisque. Vivamus viverra urna ac nulla interdum, eget ullamcorper leo maximus. Mauris nec feugiat enim. Nam congue, dui sit amet vestibulum posuere, leo mauris fermentum lorem, eget bibendum velit nunc quis leo.</p>


  </div>
  <div id="par4">
    <p>Paragraph4 Sed sed cursus leo. Nam molestie eleifend leo, nec fermentum risus maximus ac. Pellentesque eget placerat ipsum. Vestibulum tempor quam justo. Fusce dapibus turpis non ante faucibus suscipit. Fusce rhoncus eleifend ipsum et lacinia. Curabitur
      nec congue arcu. Mauris dignissim magna ligula. Nullam ultrices, metus sit amet ultrices porttitor, turpis ligula interdum enim, eu pellentesque purus quam ut arcu. Nullam aliquet vitae tortor vel tincidunt. Fusce maximus lacus diam, sed elementum
      ligula condimentum vel. Sed consequat orci ac nunc gravida, at accumsan magna porttitor.</p>

    <p>Mauris vulputate quam ac purus laoreet, nec ultrices eros placerat. Fusce id nisi ex. Nunc ornare tellus nisl, suscipit fermentum quam sodales sit amet. Ut ex magna, tempor nec ex sed, ornare ornare sem. Proin gravida turpis urna, vitae posuere purus
      consequat sit amet. Donec laoreet tempor massa. Praesent porta mauris vitae neque condimentum, non volutpat felis eleifend.</p>

    <p>Aliquam aliquam a est eget cursus. Ut eu tempus justo, rutrum dapibus ex. In hac habitasse platea dictumst. Nulla ornare nisi sit amet arcu semper maximus. Praesent eu augue eget mi sodales sodales. Praesent sodales neque malesuada, euismod est in,
      lobortis turpis. Nam blandit facilisis mauris. Ut ac ex rhoncus, ornare velit ac, aliquam nibh. Quisque euismod mauris quis nisl consectetur vulputate. Pellentesque mattis, tellus ut dictum dictum, urna ligula sodales magna, euismod malesuada ipsum
      quam nec elit.</p>

    <p>Duis sit amet eros non est lacinia posuere et et ex. Proin in dui ornare ex eleifend pharetra. Etiam eros urna, euismod eget porttitor et, tempor quis turpis. Nullam sollicitudin suscipit lorem, maximus pellentesque turpis dictum sed. Integer fringilla
      gravida tellus sit amet facilisis. Pellentesque vel porta justo. Proin vehicula eget tortor ut condimentum. Phasellus interdum urna a condimentum dapibus. Sed commodo elit a metus vestibulum, ac vehicula mi tincidunt. Duis ante quam, posuere eget
      purus et, mollis congue tortor. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nunc quis orci porttitor, dictum libero sit amet, feugiat ipsum.</p>

    <p>Nunc auctor lorem vitae neque sodales cursus. Sed scelerisque tempor tincidunt. Praesent eu pretium mi. Duis vitae venenatis nunc. Integer dolor sapien, vehicula ac dui id, fermentum malesuada justo. Donec ullamcorper enim sed nulla egestas condimentum.
      Etiam vitae dapibus sem, ut efficitur nulla. Donec laoreet, nunc quis aliquet blandit, erat nibh facilisis nibh, ut fermentum nisl dolor vel dui. Nunc pulvinar scelerisque urna, ut dictum purus placerat ac.</p>
  </div>
</div>

How to align canvas to center of button?

How would I center a canvas on a button?

const canvas = document.getElementById("myCanvas");
const ctx = canvas.getContext("2d");
ctx.fillStyle = "red";
ctx.fillRect(20, 20, 150, 100);
<button>
  <canvas id="myCanvas" width="100" height="100"></canvas>. 
</button>

Why does declaring a variable without a keyword result in a SyntaxError for var and const, but not for let in JavaScript? [duplicate]

Declaring variable in JS without keyword.

I get SyntaxError when I declare variable like var = 1 or const = 1. But I don’t get this error when i declare like let = 1. Why is this happening?

var = 1; // Uncaught SyntaxError: Unexpected token '=' (at index.js:2:5)
const = 1; // Uncaught SyntaxError: Unexpected token '=' (at index.js:2:5)
let = 1; // NO ERROR.

tag taller than it should be

example of issue

Hi! I’m making a chat app, but the <pre> tag is taking up too much space. There aren’t any issues with spacing between tags (I don’t think,) because I’ve trimmed the strings, and removed the whitespace between them entirely, but it didn’t work:

function cleanseMessage(message) {
  return badwords.filter(DOMPurify.sanitize(markdown.render(message.replace(/</g, "<").replace(/>/g, "&gt;"))));
}

function createMessage(username, message, bio, date) {
  let cleansedMessage = cleanseMessage(message).trim();
  let formattedUsername = `<a href='/profile/${encodeURIComponent(
    username[0] + "@" + username[1]
  )}'>${username[0]}@${username[1]}</a>`;
  let formattedDate = `<time datetime="${date.toISOString()}">${date.toLocaleString()}</time>`;
  let formattedMessage = `<div id='message'><pre style="display: inline;">${cleansedMessage}</pre></div>`;
  let formattedDiv = `<div style='margin: 10px 0;'><div class="userDisplay">${jdenticon.toSvg(
    username[2],
    26
  )}<span>${formattedUsername} <span class="msgTime">[at ${formattedDate}]</span></span></div>${formattedMessage.trim()}</div>`;
  return formattedDiv;
}

or the CSS:

#message {
  background: var(--accent);
  color: whitesmoke;
  padding: 3.5px 5px;
  border-radius: 0.5em;
  width: max-content;
  max-width: calc(100% - 10px);
  word-wrap: break-word;
  overflow: hidden;
}

pre {
  font-family: "Inter Tight", sans-serif;
  white-space: pre-wrap;
  margin: 0;
  padding: 0;
}

.userDisplay {
  display: flex;
  justify-content: center;
  width: fit-content;
  margin-bottom: 4px;
}

.emoji {
  height: 1.2em;
}

.userDisplay > svg {
  margin-right: 4px;
  border-radius: 20px;
}

.msgTime {
  font-size: small;
}

so I don’t know. I’ve trimmed the strings before they’re applied and removed all the whitespace between tags, but to no avail. Any help would be nice, thanks!

Top Infinite scrolling

I’ve been working on implementing top infinite scrolling, but I’ve run into a bit of trouble. The issue I’m facing is that when new items are appended, the scroll bar doesn’t adjust as expected. Ideally, when new items are added, the scroll bar should move slightly to accommodate them, but that’s not happening.

Has anyone else faced a similar issue? Any suggestions on how to fix this?

Wrong colors on mobile when using Nextjs v14 with SVGR

I am experiencing a weird problem with my application where i have SVGs which are being rendered as inline SVGs using a custom next.config.js with SVGR and webpack. The problem is that some of the svgs look alright on desktop viewport but they lose colors when on less viewports like when we’re on mobile.

On Mobile
On Desktop

Here is my custom next.config.js file:

/** @type {import('next').NextConfig} */

const withBundleAnalyzer = require("@next/bundle-analyzer")({
  enabled: process.env.ANALYZE === "true",
});

const nextConfig = {
  webpack(config) {
    // Grab the existing rule that handles SVG imports
    const fileLoaderRule = config.module.rules.find((rule) =>
      rule.test?.test?.(".svg"),
    );

    config.module.rules.push(
      // Reapply the existing rule, but only for svg imports ending in ?url
      {
        ...fileLoaderRule,
        test: /.svg$/i,
        resourceQuery: /url/, // *.svg?url
      },
      // Convert all other *.svg imports to React components
      {
        test: /.svg$/i,
        issuer: fileLoaderRule.issuer,
        resourceQuery: { not: [...fileLoaderRule.resourceQuery.not, /url/] }, // exclude if *.svg?url
        use: ["@svgr/webpack"],
      },
    );

    // Modify the file loader rule to ignore *.svg, since we have it handled now.
    fileLoaderRule.exclude = /.svg$/i;

    return config;
  },
};

module.exports = withBundleAnalyzer(nextConfig);

I am using next.js v14 and @svgr/webpack v8.1.0.

I am stuck for so much time, any help will be highly appreciated, Thanks!

I have tried some solutions, even moving to babel-plugin-inline-react-svg but some of nextjs features are only supported on SWC, apart from that I did not find anything related to this online.

How to fix error on react Route component render using wrapper-component?

I have basic reactjs app and I want to implement kind of is authenticated check. So if user is authenticated, he can access pages, of not user must be redirected to /login.
here is rootes configuration

export const privateRoutes: Array<RouteType> = [
    {
        path: '/users',
        element: UsersPage,
        exact: true,
    }
];

export const publicRoutes: Array<RouteType> = [
    {
        path: '/login',
        element: LoginPage,
        exact: true,
    },
];

I created Route wrapper which checks authentication:

interface PrivateRouteProps {
    key: number,
    path: string;
    element: React.ReactNode;
}

const PrivateRoute: FC<PrivateRouteProps> = ({key, path, element}) => {
    const {userIsAuthenticated, hasPermission} = usePermission();

    return (
        <Route
            path={path}
            element={userIsAuthenticated() ? element : <Navigate to="/login" />}
        />
    );
};

and here is routing service:

export const RouterService: React.FC = () => {
    return (
        <Router>
            <SecurityProvider>
                <Routes>
                    {privateRoutes.map((route: RouteType, index: number) => (
                        <PrivateRoute
                            key={index}
                            path={route.path}
                            element={<Layout>
                                <route.element/>
                            </Layout>}
                        />
                    ))}
                    {publicRoutes.map((route: RouteType, index: number) => (
                        <PrivateRoute
                            key={index}
                            path={route.path}
                            element={<BaseLayout>
                                <route.element/>
                            </BaseLayout>}
                        />
                    ))}
                </Routes>
            </SecurityProvider>
        </Router>
    );

In browser console I get:

history.ts:494 Uncaught Error: [PrivateRoute] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>

What I’m doing wrong and how to implement this functionality properly?

Plotly change value of “reference:”

I want to change the value of the “reference” tag off a gauge in my ESP32 code.
The gauge:

var humidityData = [
  {
    domain: { x: [0, 1], y: [0, 1] },
    value: 0,
    title: { text: "Feuchtigkeit" },
    type: "indicator",
    mode: "gauge+number+delta",
    delta: { reference: 69 },
    gauge: {
      axis: { range: [40, 103] },
      steps: [
        { range: [10, 65], color: "red" },
        { range: [65, 68], color: "yellow" },
        { range: [68, 75], color: "lightgreen" },
        { range: [75, 78], color: "yellow" },
        { range: [78, 103], color: "red" },
      ],
    },
  },
];

The code that should update the reference:

function updateGauge(temperature, humidity, humidity_soll) {
  var temperature_update = {
    value: temperature,
  };
  var humidity_update = {
    value: humidity,
    reference: humidity_soll,
  };
  Plotly.update(temperatureGaugeDiv, temperature_update);
  Plotly.update(humidityGaugeDiv, humidity_update);
}

But the reference is still the initial one. It is not updated by the function with the new value from the json i handed over correctly.
Changing the simple “value” tag ist no problem. But the “reference” tag is not updated. Maybe I have to do this another way?
Any suggestions for me?
Its my first implementation of plotly.io so far.
So sorry for the noob question…

Kind regards
Frank

Writing comments spring boot

I’m building a Spring Boot app similar to YouTube, I can successfully upload videos but I can’t write comments or like and dislike reactions, and for some reason the thumbnail I uploaded with the video is not showing up

so this is my home controller


@Controller
public class HomeController {

    @Autowired
    private VideoRepository videoRepository;

    @Autowired
    private VideoService videoService;


    @GetMapping("/springtube")
    public String home(Model model) {
        model.addAttribute("videos", videoRepository.findAll());
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        boolean isAuthenticated = auth.isAuthenticated();
        model.addAttribute("isAuthenticated", isAuthenticated);
        return "home";
    }



    @GetMapping("/video_detail")
    public String videoDetailPage() {
        return "video_detail"; // Return the video_detail.html template
    }


    @GetMapping("/files/{file-name:.+}")
    public void getFile(@PathVariable("file-name") String fileName, HttpServletResponse response){
        Video video = videoService.findByStorageName(fileName);
        if (video == null) {
            // Handle file not found
            return;
        }
        if (fileName.endsWith("_thumbnail")) {
            videoService.writeThumbnailToResponse(video.getThumbnailUrl(), response);
        } else {
            videoService.writeFileToResponse(fileName, response);
        }
    }
}

Video model



@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Data
public class Video {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String originalName;
    private String storageFileName;
    private String url;
    private Long size;
    private String type;
    private String thumbnailUrl;


    @ManyToOne
    @JoinColumn(name = "channel_id")
    private Channel channel;


    @OneToMany(mappedBy = "video")
    private Set<Comment> comments = new HashSet<>();
}


@Controller
public class VideoController {

    @Autowired
    private UserRepository userRepository;
    @Autowired
    private VideoService videoService;

    @GetMapping("/channel")
    public String showUploadForm(Model model, Principal principal) {
        // Fetch the authenticated user's channel
        String email = principal.getName();
        Optional<User> optionalUser = userRepository.findByEmail(email);
        if (optionalUser.isPresent()) {
            User user = optionalUser.get();
            List<Video> userVideos = videoService.getUploadedVideos(user.getId());
            model.addAttribute("videos", userVideos);// Add a new Video object to the model);
            model.addAttribute("channelName", user.getChannel().getName()); // Add channel name
            return "upload"; // Returns the upload form HTML page
        }
        return "redirect:/error";
    }

    @PostMapping("/channel")
    public String handleFileUpload(@RequestParam("file") MultipartFile file,
                                   @RequestParam("thumbnail") MultipartFile thumbnail,
                                   Principal principal) {
        // Validate the uploaded files
        if (file.isEmpty() || thumbnail.isEmpty()) {
            return String.valueOf(ResponseEntity.badRequest().body("Please select both video and thumbnail files."));
        }

        videoService.saveFile(file, thumbnail, principal);

        return "redirect:/channel";
    }
}

@Repository
public interface VideoRepository extends JpaRepository<Video, Long> {
    Video findByStorageFileName (String fileName);
}

public interface VideoService {

    Video findById(Long id);

    String saveFile(MultipartFile uploadFile, MultipartFile thumbnailFile, Principal principal);
    void writeFileToResponse(String fileName, HttpServletResponse response);
    Video findByStorageName(String storageName);
    List<Video> getUploadedVideos(Long userId);
    void writeThumbnailToResponse(String fileName, HttpServletResponse response);
}


@Component
public class VideoServiceImpl implements VideoService {

    @Autowired
    private VideoRepository videoRepository;
    @Autowired
    private UserRepository userRepository;

    @Value("${storage.path}")
    private String storagePath;

    @Override
    public Video findById(Long id) {
        return videoRepository.findById(id).get();
    }




    @Override
    public String saveFile(MultipartFile uploadFile, MultipartFile thumbnailFile, Principal principal) {
        String email = principal.getName();
        Optional<User> optionalUser = userRepository.findByEmail(email);
        if (optionalUser.isPresent()) {
            User user = optionalUser.get();
            Channel channel = user.getChannel();
            if (channel != null) {
                String videoExtension = FilenameUtils.getExtension(uploadFile.getOriginalFilename());
                String thumbnailExtension = FilenameUtils.getExtension(thumbnailFile.getOriginalFilename());

                String videoStorageName = UUID.randomUUID().toString() + "." + videoExtension;
                String thumbnailStorageName = UUID.randomUUID().toString() + "_thumbnail." + thumbnailExtension;

                try {
                    String videoFullPath = Paths.get("src/main/resources", storagePath, videoStorageName).toString();
                    String thumbnailFullPath = Paths.get("src/main/resources", storagePath, thumbnailStorageName).toString();

                    Files.createDirectories(Paths.get(videoFullPath).getParent()); // Create directories if they don't exist
                    Files.createDirectories(Paths.get(thumbnailFullPath).getParent()); // Create directories if they don't exist

                    Files.copy(uploadFile.getInputStream(), Paths.get(videoFullPath));
                    Files.copy(thumbnailFile.getInputStream(), Paths.get(thumbnailFullPath));
                } catch (IOException e) {
                    throw new IllegalStateException("Failed to save files", e);
                }

                Video video = Video.builder()
                        .type(uploadFile.getContentType())
                        .originalName(uploadFile.getOriginalFilename())
                        .size(uploadFile.getSize())
                        .storageFileName(videoStorageName)
                        .url(storagePath + "/" + videoStorageName)
                        .thumbnailUrl(storagePath + "/" + thumbnailStorageName) // Set the thumbnail URL
                        .channel(channel)
                        .build();

                videoRepository.save(video);

                return video.getStorageFileName();
            }
        }
        throw new IllegalStateException("Failed to save files: User's channel not found");
    }


    @Override
    public void writeFileToResponse(String fileName, HttpServletResponse response) {
        Video fileInfo = videoRepository.findByStorageFileName(fileName);
        if (fileInfo == null) {
            throw new IllegalArgumentException("File not found with name: " + fileName);
        }
        response.setContentType(fileInfo.getType());
        try {
            IOUtils.copy(new FileInputStream("src/main/resources"+"/"+fileInfo.getUrl()), response.getOutputStream());
            response.flushBuffer();
        } catch (IOException e) {
            throw new IllegalArgumentException(e);
        }
    }
    @Override
    public Video findByStorageName(String storageName) {
        return videoRepository.findByStorageFileName(storageName);
    }

    @Override
    public List<Video> getUploadedVideos(Long userId) {
        return null;
    }



    @Override
    public void writeThumbnailToResponse(String fileName, HttpServletResponse response) {
        Video thumbnailVideo = videoRepository.findByStorageFileName(fileName);
        if (thumbnailVideo == null) {
            throw new IllegalArgumentException("Thumbnail file not found with name: " + fileName);
        }
        response.setContentType("image/png"); // Assuming thumbnails are JPEG images
        try {
            // Read the thumbnail image from file and write it to the response output stream
            IOUtils.copy(new FileInputStream("src/main/resources/" + thumbnailVideo.getThumbnailUrl()), response.getOutputStream());
            response.flushBuffer();
        } catch (IOException e) {
            throw new IllegalArgumentException("Error writing thumbnail to response", e);
        }
    }

}

home.js


document.addEventListener('DOMContentLoaded', function() {
    // Get all video items
    const videoItems = document.querySelectorAll('.video-item');

    // Add click event listener to each video item
    videoItems.forEach(videoItem => {
        videoItem.addEventListener('click', function() {
            // Extract video ID or storage file name from data attribute
            const videoId = this.getAttribute('data-video-id');

            // Construct URL for video detail page with parameters
            const videoDetailURL = `/video_detail.ftlh?videoId=${videoId}`;

            // Redirect user to video detail page
            window.location.href = videoDetailURL;
        });
    });
});

video_detail

<main>
    <div class="video-container">
    </div>
    <div class="video-actions">
        <!-- Like, dislike, and subscribe buttons -->
        <button class="like-btn"><i class="fas fa-thumbs-up"></i> Like</button>
        <button class="dislike-btn"><i class="fas fa-thumbs-down"></i> Dislike</button>
        <button class="subscribe-btn"><i class="fas fa-heart"></i> Subscribe</button>
    </div>
    <div class="comment-section">

    </div>
</main>

knowing that the thumbnail is being saved successfully but

I want to get the cost according to room-id which is define in form and i want to get using $(‘cost’).keyup this how can i achieve

I am unable to calculate using class? I am trying to access dynamic id using class

@foreach($room_types as $room_type)

 {!! Form::text('cost', null, ['class' => 'form-control cost-'.$room_type->id, 'placeholder' => 'Enter Cost']) !!}
 {!! $errors->first('cost','<span class="help-block text-danger">:message</span>') !!}   
@endforeach

and this is the script

$('.cost{{ $room_type->id }}').keyup(function() {

      var roomTypeId = $(this).data('room-type-id');
                    
      var cost           = parseFloat($('.cost').val());
      var profit         = parseFloat($('.profit').val());
      var tax_percentage = parseFloat($('.tax-percentage').val());

      checkNum('.cost'); 
      total_cost    = calculate_total_cost(cost, profit, tax_percentage);
      $('.total-cost').val(total_cost);

});

Why can I not access $_SESSION in this code please?

I’m trying to set and pass averrable to this script:

<?php

// Include Classes
global $db, $order, $currencies;
// Include the Stripe PHP SDK library 
require_once 'vendor/autoload.php';
// Set API key
StripeStripe::setApiKey($_SESSION["STRIPE_SECRET_API_KEY"]);

// Set content type to JSON 
header('Content-Type: application/json');

// Retrieve JSON from POST body 
$jsonStr = file_get_contents('php://input');
$jsonObj = json_decode($jsonStr);


$zc_ordertotal                      = '10.59';
$zc_currency                        = 'GBP';
$zc_description                     = 'Laptop Bag';

$sa_roduct_price                    = round($zc_ordertotal * 100);
$sa_currency                        = $zc_currency;
$sa_description                     = $zc_description;

try {
    $ap_PaymentIntent                  = StripePaymentIntent::create([
        'amount'                    => $sa_roduct_price,
        'currency'                  => $sa_currency,
        'description'               => $sa_description ? $sa_description : null,
        'automatic_payment_methods' => ['enabled' => true],
    ]);
    $output = [
        'paymentIntentId'           => $ap_PaymentIntent->id,
        'clientSecret'              => $ap_PaymentIntent->client_secret
    ];
    echo json_encode($output);
} catch (Error $e) {
    http_response_code(500);
    echo json_encode(['this error'       => $e->getMessage()]);
}

and the bit of code that fec this is:

// Fetch a payment intent and capture the client secret
  let payment_intent_id;
  async function initialize() {
    const { paymentIntentId, clientSecret } = await fetch(
      '/includes/modules/payment/stripe-payment-gateway/create_payment_intent.php',
      {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
      }
    ).then((r) => r.json());

    const appearance = {
      theme: 'stripe',
    };

    elements = stripe.elements({
      clientSecret,
      appearance,
    });

if I replace “$_SESSION[“STRIPE_SECRET_API_KEY”]” with the actual key it works and if I do a if statement to compare “$_SESSION[“STRIPE_SECRET_API_KEY”]” with the actual key it is the same. so defining the key globally is not working.

Vuejs 2 Multilevel Dropdown

I am trying to create a multilevel dropdown, but it does not work for me, idk why. There is no error on my console. I am using Vuejs 2.version.

Here is my dropdown;

  <b-dropdown id="benutzer-dropdown" text="Benutzer" class="navbar-item">
    <b-dropdown-item href="/main/de/verwaltung/users/">Benutzer verwalten</b-dropdown-item>
    <b-dropdown-item href="/main/de/verwaltung/roles/">Rollen verwalten</b-dropdown-item>
    <b-dropdown-item href="/main/de/verwaltung/permissions/">Berechtigungen verwalten</b-dropdown-item>
    <b-dropdown id="submenu" right>
      <b-dropdown-item @click="handleSubMenuClick">1</b-dropdown-item>
      <b-dropdown-item @click="handleSubMenuClick">2</b-dropdown-item>
      <b-dropdown-item @click="handleSubMenuClick">3</b-dropdown-item>
    </b-dropdown>
  </b-dropdown>

and js function (I just wanted to test it, but there is nothing in my console)

  handleSubMenuClick(){
  console.log("clicked!!");
},

How to add declarativeNetRequest rule dynamically for certain (controlled)tabs opened from a particular site

I have a product that opens 3rd party customer sites using window.open in an additional window.(For doing some WSIWYG type editing on the site). I need to remove a few headers (eg Cross-Origin-Opener-Policy) for tabs opened with our site in order for site to open and work like I need it to.

In MV2 it was easy as we would maintain an array of myProductTabs, when I open a new tab append tabId in myProductTabs. and in webRequest.onHeadersReceived I would check if current request is coming from one of the tabs in myProductTabs using details.tabId and then remove header right there.

But in MV3 the issues is the first time new tab is opened using window.open I have to now add a new declarative netrequest rule where tabs property will be myProductTabs as new tab is added to array. (Remove old rule ofc).
Now this doesn’t work . Probably because registering a new rule doesn’t immediately add the rule and by the time its in effect main document has loaded.
If I refresh the tab , then it would work as rule has already been set.

Now I can set the rule to all tabs by default but that would be a security risk for the user. So is there any other way to do it?

Note: Im using updateSessionRules(Dont think using updateDynamicRules would help.Correct me if I’m wrong).