apolloClient.query() error shows up as promise rejection instead of in result.errors

My apollo client config looks something like this:

const client = new ApolloClient({
    cache: ...,
    link: from([
        onError(...) // my custom error handler
        new HttpLink(...)
    ])
});

Now if I do const result = client.query(...) and there is an error that routes through my custom error handler, that error shows up as a promise rejection, instead of in result.errors.

Is that a bug? Is there a way to move the error?

Overlaying Text Boxes on Scroll using JavaScript?

I’m creating a website that shows a grid of black rectangles on HTML, and I want text boxes to appear when the user scrolls that appear above the rectangles and remain there for some time for the user to read, similar to here: https://mkorostoff.github.io/1-pixel-wealth/.

I’ve tried to do this with a combination of HTML and JS but have been unsuccessful so far, as the text boxes aren’t appearing on the screen.

document.addEventListener('DOMContentLoaded', (event) => {
  const gridContainer = document.getElementById('grid');
  const infoBoxes = [{
    title: 'Information Box 1',
    content: 'This is some information about the conflict.'
  }, {
    title: 'Information Box 2',
    content: 'More details and statistics.'
  }, {
    title: 'Information Box 3',
    content: 'Additional context and historical background.'
  }];

  const totalRectangles = 3000; // Total number of rectangles (example value)
  const scrollThreshold = 100; // Number of rectangles to scroll past before showing the next info box
  const stickyDuration = 400; // Number of pixels the info box should remain sticky
  let currentInfoBoxIndex = -1;
  let currentInfoBox = null;

  for (let i = 0; i < totalRectangles; i++) {
    const square = document.createElement('div');
    square.classList.add('grid-item');
    gridContainer.appendChild(square);
  }

  // Function to check if an element is in viewport
  function isElementInViewport(el) {
    const rect = el.getBoundingClientRect();
    return (
      rect.top >= 0 &&
      rect.left >= 0 &&
      rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
      rect.right <= (window.innerWidth || document.documentElement.clientWidth)
    );
  }

  // Function to handle scroll event
  function handleScroll() {
    const scrollPosition = window.scrollY || window.pageYOffset;
    const rectanglesScrolled = Math.floor(scrollPosition / 200); // Assuming each rectangle height is 200px
    console.log("rectangles", rectanglesScrolled)
    // Determine which info box to show based on scroll position
    const infoBoxIndex = Math.floor(rectanglesScrolled / scrollThreshold);

    if (infoBoxIndex !== currentInfoBoxIndex) {
      // Remove the current info box if it exists
      if (currentInfoBox) {
        currentInfoBox.classList.remove('visible', 'sticky');
      }

      // Add the new info box if it exists in the array
      if (infoBoxIndex < infoBoxes.length) {
        currentInfoBoxIndex = infoBoxIndex;
        currentInfoBox = document.querySelectorAll('.info-box')[infoBoxIndex];
        console.log(currentInfoBox)
        currentInfoBox.classList.add('visible', 'sticky');
      } else {
        currentInfoBoxIndex = -1;
        currentInfoBox = null;
      }
    }

    // Remove the sticky class after the sticky duration
    if (currentInfoBox) {
      const infoBoxRect = currentInfoBox.getBoundingClientRect();
      if (infoBoxRect.top < 20 || infoBoxRect.bottom > stickyDuration) {
        currentInfoBox.classList.remove('sticky');
      }
    }
  }

  // Listen for scroll events
  window.addEventListener('scroll', handleScroll);

  // Initial check in case some boxes are already in view
  handleScroll();
});
<div id="grid" class="grid-container"></div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

Instantiate a class name from a variable [duplicate]

I have two classes: Foo and Bar and I have a dictionary (coming from reading a JSON file) that specifies if an entry is of class Foo or class Bar

myDict = {
  "Alice": "Foo",
  "Bob": "Bar"
}

What I’m currently doing is to use a conditional to either create a Foo or a Bar instance.

let instances = [];

for (const [name, className] of Object.entries(myDict)) {
  if (className == "Foo") {
    instances.push(new Foo(name));
  } 
  else if (className == "Bar") {
    instances.push(new Bar(name));      
  }
}

However, I expect the number of class types to increase in a future, meaning that I will create new classes (eg: Baz) but I don’t want to have to modify the code of the conditional to add new else cases.

Is there a better way?

Sharing same variable reference in two components doesnt works in Angular >= 15

I´ve using this method to share data between components because is more agile than observables, services or whatever method… But, I´m using on an angular 15 project and it seems doesnt work.

I have a parent component with an object variable initialized as empty object.

Parent component

exhibitor: object = {};

I have a child component with an input variable which i share reference to exhibitor parent variable

@Input() exhibitorData: object = {};

Then, i share exhihibitor parent with child in template

<app-exhibitor-child [exhibitor-data]="exhibitor"></app-exhibitor-child>

But when I change exhibitorData it doesnt affect to exhibitor parent varible.

this.exhibitorData = { 'property': changed };

I´ve been using this method for years and it doesnt work, angular is creating isolated scopes for each component or what?

How to determine element overflowing in Firefox with box-sizing: border-box?

I want to determine if the element is overflowing, and the standard el.clientWidth < el.scrollWidth works pretty well in Chrome, but for some reason, it has some problems in Firefox.

My guess

My element has box-sizing: border-box + some 0.75rem padding. When the element has an overflow that falls exactly in this 0.75rem, Firefox visualizes the overflow, but the scrollWidth isn’t changing.

Why do I think so? Because clientWidth in Chrome is changing when I change the box-sizing property, and the opposite in Firefox.

Playground

So how could I check the overflow state of one element which will work in all browsers?

Issues with View Resolution in Spring Boot Application on WebLogic 12c

Title: Issues with View Resolution in Spring MVC Application on WebLogic 12c

Body:

I’m facing an issue with view resolution in my Spring MVC application when deployed on WebLogic 12c. The same application works fine on Tomcat, but on WebLogic, the view is not getting resolved correctly.

Spring Configuration:

  • Spring Version: 5.3
  • WebLogic Version: 12c

JSP Code:

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <%@include file="CommonInclude.jsp"%>
</head>
<body class="hold-transition skin-blue sidebar-mini">
<div class="wrapper">
    <%-- <%@include file="header.jsp"%> --%>
    <%@include file="homeHeader.jsp"%>
    <div class="content-wrapper" id="divWrapper">
    <br>
        <h2 class="animate-charcter" align="center">Welcome to Integra KYC Retrieval Application</h2>
    </div> 
    
    <footer class="main-footer">
        <div class="float-right d-none d-sm-block">
            <b>Version </b>1.0.0
        </div>
        <strong>Copyright &copy;  <a href="#">Integra Micro Systems</a>.</strong> All rights reserved.
    </footer>
</div>
</body>
</html>

HTML to append:

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@page contentType="text/html; charset=UTF-8"%>
<input type="hidden" id="ctxPath" name="ctxPath" value="<c:out value="${pageContext.request.contextPath}"/>" />
<input type="hidden" id="strMenuId" name="strMenuId" value="<c:out value="${strMenuId}"/>" />
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <script type="text/javascript" src="<c:url value="/js/kycInfo.js"/>"></script>
  <title>KYC Retrieval</title>
  <style>
      body {
          overflow-x: hidden;
      }
  </style>
</head>
<div class="wrapper">
    <div class="container-fluid">
        <div id="kycList">
            <div class="row">
                <div class="col-md-1"></div>
                <div class="col-md-10">
                    <br>
                    <div class="card card-primary card-outline">
                        <div class="card-header">
                            <label class="card-title">KYC Details</label>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

JavaScript Function:

function loadView(url) {
    url = $("#ctxPath").val() + url;
    var response = loadDetailsByAjax(url, "GET", null);
    $("#divWrapper").html(response.respBuffer);
    // Additional initialization if needed
}

Controller Method:

@RequestMapping(value = {"/reqForKycData"}, method = {RequestMethod.GET})
@ResponseBody
public BaseResponseDTO reqForkycData(HttpServletRequest request) {
    log.info("[EkycController][reqForkycData]");
    BaseResponseDTO baseResponseDTO = new BaseResponseDTO();
    try {
        baseResponseDTO.setRespBuffer(Common.resolveView(request, this.viewResolver, "KycInfo", null));
        baseResponseDTO.setStatus("00");
    } catch (Exception ex) {
        log.error("Error ", ex);
        baseResponseDTO = Common.getFailureResponse("INTERNAL_ERROR", "Internal Server Error");
    }
    return baseResponseDTO;
}

View Resolver Method:

public static String resolveView(HttpServletRequest request, ViewResolver viewResolver, String screenName, Map<String, Object> map) {
    try {
        MockHttpServletResponse mockResp = new MockHttpServletResponse();
        View resolvedView = viewResolver.resolveViewName(screenName, LocaleContextHolder.getLocale());
        resolvedView.render(map, request, (HttpServletResponse) mockResp);
        return mockResp.getContentAsString();
    } catch (Exception e) {
        log.error("Error while resolving view :: " + screenName + " :: ", e);
        return null;
    }
}

Issue:
The view is resolved correctly and rendered when the application is deployed on Tomcat. However, when deploying the same application on WebLogic 12c, the view does not render correctly, and I get an error or an empty response.

Steps Taken:

  1. Verified that the Spring and WebLogic configurations are correct.
  2. Ensured all dependencies are packaged correctly in the WAR file.
  3. Reviewed WebLogic server logs but didn’t find specific errors pointing to the cause.

Questions:

  1. What could be causing the view resolution to fail on WebLogic but work on Tomcat?
  2. Are there any specific configurations or settings needed for WebLogic to properly handle Spring view resolution?
  3. How can I debug this issue further to identify the root cause?

Any insights or suggestions would be greatly appreciated. Thank you!

problem with nextjs.org initial course, Unhandled Runtime Error

I’m learning nextjs by their website guide, but I’m on a problem that I cannot really find anywhere. Everything was good until this point:
https://nextjs.org/learn/dashboard-app/navigating-between-pages#pattern-showing-active-links – my localhost:3000/dashboard works charming, unless i add “use client”; directive on the top of my code. As soon as I do it this screen is thrown at me. Doing rest of the course doesnt work, all I can see is this error. Do you have any idea if it’s something wrong with guide (which I doubt) or I am just dumb and can’t see something? There’s my nav-links.tsx code just in case:

It works as charm unless I add ‘use client’;

'use client';

import {
  UserGroupIcon,
  HomeIcon,
  DocumentDuplicateIcon,
} from '@heroicons/react/24/outline';
import Link from 'next/link'

// Map of links to display in the side navigation.
// Depending on the size of the application, this would be stored in a database.
const links = [
  { name: 'Home', href: '/dashboard', icon: HomeIcon },
  {
    name: 'Invoices',
    href: '/dashboard/invoices',
    icon: DocumentDuplicateIcon,
  },
  { name: 'Customers', href: '/dashboard/customers', icon: UserGroupIcon },
];

export default function NavLinks() {
  return (
    <>
      {links.map((link) => {
        const LinkIcon = link.icon;
        return (
          <Link
            key={link.name}
            href={link.href}
            className="flex h-[48px] grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3"
          >
            <LinkIcon className="w-6" />
            <p className="hidden md:block">{link.name}</p>
          </Link>
        );
      })}
    </>
  );
}

For context – I’m following the guide since project installation, so I doubt I could’ve messed something up. Would be nice if someone knows whats up.

Searched through reddit, stack overflow but couldn’t find anything.

Font styling not captures with exporting html element to pngs

I am trying to export an html element (a div containing mostly an svg). There are no extra styles being applied (classes, etc) to the element.
The html element looks like this
enter image description here

But the saved png looks like enter image description here

Here are the different code snippets I have tried which all produce the same result

html2canvas:

const canvas = await html2canvas(el, { useCORS: true, copyStyles: true });
const image = canvas.toDataURL("image/png");
...

saveSvgAsPng

saveSvgAsPng.svgAsPngUri(
`filename.png`,{ scale: 1, encoderOptions: 1, excludeCss: true }).then(url => {
...
})

html-to-image

toPng(element).then((url) => {
...
}

Any advice or suggestions are greatly appreciated!

Flexmonster how to apply row/column freezing/pinning like excel

I would like to know whether is it possible to freeze/pin column

Is there option to do row pinning/freezing or column pinning/freezing and if so can freeze/pin particular column/row using flexmonster.
Please help needed

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Flexmonster Column Pinning Example</title>
    <link rel="stylesheet" href="https://cdn.flexmonster.com/2.8.16/flexmonster.css">
    <style>
        #pivot-container {
            height: 600px;
        }
    </style>
    <script src="https://cdn.flexmonster.com/2.8.16/flexmonster.js"></script>
</head>
<body>
    <div id="pivot-container"></div>

    <script>
        const pivot = new Flexmonster({
            container: "#pivot-container",
            toolbar: true,
            height: "100%",
            report: {
                dataSource: {
                    data: [
                        { "Product": "Apple", "Region": "North", "Sales": 1500 },
                        { "Product": "Orange", "Region": "South", "Sales": 1200 },
                        { "Product": "Banana", "Region": "East", "Sales": 1300 },
                        { "Product": "Grapes", "Region": "West", "Sales": 1700 }
                    ]
                },
                slices: {
                    rows: [{
                        uniqueName: "Product"
                    }],
                    columns: [{
                        uniqueName: "Region"
                    }],
                    measures: [{
                        uniqueName: "Sales",
                        aggregation: "sum"
                    }]
                }
            },
          
        });
    </script>
</body>
</html>

How do JavaScript instances access private methods without prototype inheritance?

My understanding is that private methods are not part of the prototype chain, and therefore, are not inherited by subclasses. However, I am confused about how instances of a class access private methods when those methods are invoked through public methods of the class.

class MyClass {
  #privateMethod() {
    return 'I am a private method';
  }

  publicMethod() {
    return this.#privateMethod(); // Access private method from within the class
  }
}

const instance = new MyClass();
console.log(instance.publicMethod()); // Logs: I am a private method

When instance.publicMethod() is called, this inside publicMethod refers to instance. Since private methods are not part of the instance itself or the prototype chain, how does this.#privateMethod() work? How does the private method get accessed even though the instance doesn’t directly contain the private method?

Why does my Flask website keep refreshing?

I am trying to make a social media website, (similar to TikTok) but the watch page keeps refreshing.

My JS sends JSON like this to the backend, which keeps track of likes, dislikes, views, etc. in a SQLite database:

{
  "action": {action e.g. like, dislike, view}
  "id": {video_id e.g. 1)
}

Then, the backend processes it with this function:

@app.route('/trackStatistics', methods=['POST'])
def track_statistics():
    try:
        # Get the JSON data from the request
        data = request.get_json()

        # Validate the action and id
        if 'action' not in data or 'id' not in data:
            return jsonify({'error': 'Invalid request'}), 400

        action = data['action']
        video_id = data['id']

        data = get_video(video_id)

        print(data)

        if action == "like":
            data["likes"] = int(data["likes"]) + 1
        elif action == "dislike":
            data["dislikes"] = int(data["dislikes"]) + 1
        elif action == "unlike":
            data["likes"] = int(data["likes"]) - 1
        elif action == "undislike":
            data["dislikes"] = int(data["dislikes"]) - 1
        elif action == "view":
            data["views"] = int(data["views"]) + 1
        
        update_video(video_id, data["publisher"], data["title"], data["likes"], data["dislikes"], data["views"], data["comments"], False)

        print(data)

        # Return the updated data
        return jsonify(data), 200

    except Exception as e:
        print(str(e))
        return jsonify({'error': str(e)}), 500

Here’s the file with my update_video, get_video, and create_video functions defined:

import sqlite3
import json
from datetime import datetime

def get_video(video_id):
    conn = sqlite3.connect('../databases/videos.db')
    c = conn.cursor()
    c.execute("SELECT * FROM videos WHERE id = ?", (video_id,))
    video = c.fetchone()
    comments = json.loads(video[6]) if video[6] else []
    video = list(video)
    video[6] = comments
    conn.close()
    return {
        "id": video[0],
        "publisher": video[1],
        "title": video[2],
        "likes": video[3],
        "dislikes": video[4],
        "views": video[5],
        "comments": video[6],
        "created_at": video[7],
        "updated_at": video[8]
    }

def create_video(publisher, title, likes, dislikes, views, comments):
    conn = sqlite3.connect('../databases/videos.db')
    c = conn.cursor()
    now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    comments_json = json.dumps(comments)
    c.execute("INSERT INTO videos (publisher, title, likes, dislikes, views, comments, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", 
              (publisher, title, likes, dislikes, views, comments_json, now, now))
    conn.commit()
    conn.close()
    return c.lastrowid

def update_video(video_id, publisher, title, likes, dislikes, views, comments, update_time):
    conn = sqlite3.connect('../databases/videos.db')
    c = conn.cursor()

    # Get the current updated_at time
    c.execute("SELECT updated_at FROM videos WHERE id = ?", (video_id,))
    last_updated = c.fetchone()[0]

    if update_time:
        now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    else:
        now = last_updated

    comments_json = json.dumps(comments)
    c.execute("UPDATE videos SET publisher = ?, title = ?, likes = ?, dislikes = ?, views = ?, comments = ?, updated_at = ? WHERE id = ?",
              (publisher, title, likes, dislikes, views, comments_json, now, video_id))
    conn.commit()
    conn.close()

I tried to keep track of the video stats and the server seems to work, it prints the correct data! But, after giving code 200 success, it refreshes the page.

Here’s the JS I’m using to interact with the backend:

let liked = false;
let disliked = false;
let followed = false;
let commentsOpen = false;
const url = window.location.search;
const urlParams = new URLSearchParams(url);
const id = urlParams.get('c');
const trackStatisticsRoute = 'http://localhost:5005/trackStatistics';

$(document).ready(() => {
  if (id) {
    document.title = "ByteClips - " + id;
  }

  const vidFile = `../videos/${id}/video.mp4`;

  console.log(vidFile);
  $('#vidSrc').attr('src', vidFile);
  $('.video')[0].load();

    updateRating('view', id);

  $('.video-buttons div button').hover(
    () => {
      $(this).find('i').css('opacity', 0);
      $(this).find('.counter').css('opacity', 1);
    },
    () => {
      $(this).find('i').css('opacity', 1);
      $(this).find('.counter').css('opacity', 0);
    }
  );
});

function updateRating(action, id) {
  const requestData = {
    action,
    id
  };

  $.ajax({
    type: 'POST',
    url: trackStatisticsRoute,
    data: JSON.stringify(requestData),
    contentType: 'application/json',
    success: data => {
      updateUI(data);
    },
    error: (jqXHR, textStatus, errorThrown) => {
      console.log('AJAX request error:', textStatus, errorThrown);
      console.log('Response:', jqXHR.responseText);
    }
  });
}

function updateUI(data) {
  const newData = typeof data === 'string' ? JSON.parse(data) : data;
  $('#like .counter').text(newData.likes);
  $('#dislike .counter').text(newData.dislikes);
  $('#share .counter').text(newData.views);
  $('#comment .counter').text(newData.comments.length);
}

$('#like').css('background', liked ? '#fff' : '#26daa5');
$('#like').css('color', liked ? '#26daa5' : '#fff');
$('#dislike').css('background', disliked ? '#fff' : '#26daa5');
$('#dislike').css('color', disliked ? '#26daa5' : '#fff');
$('#follow').css('background', followed ? '#fff' : '#26daa5');
$('#follow').css('color', followed ? '#26daa5' : '#fff');
$('#follow i').attr('class', followed ? 'fa-solid fa-user-minus' : 'fa-solid fa-user-plus');

$('#like').on('click', () => {
  if (liked) {
    liked = false;
    updateRating('unlike', id);
  } else {
    if (disliked) {
      updateRating('undislike', id);
    }
    liked = true;
    disliked = false;
    updateRating('like', id);
  }
  updateLikeDislike();
});

$('#dislike').on('click', () => {
  if (disliked) {
    disliked = false;
    updateRating('undislike', id);
  } else {
    if (liked) {
      updateRating('unlike', id);
    }
    disliked = true;
    liked = false;
    updateRating('dislike', id);
  }
  updateLikeDislike();
});

$('#follow').on('click', () => {
  followed = !followed;
  $('#follow i').attr('class', followed ? 'fa-solid fa-user-minus' : 'fa-solid fa-user-plus');
  $('#follow').css('background', followed ? '#fff' : '#26daa5');
  $('#follow').css('color', followed ? '#26daa5' : '#fff');
});

$('#comment').on('click', () => {
  console.log('comments opened');
  commentsOpen = !commentsOpen;
  $('#comment').css('background', commentsOpen ? '#fff' : '#26daa5');
  $('#comment').css('color', commentsOpen ? '#26daa5' : '#fff');
});

function updateLikeDislike() {
  $('#like').css('background', liked ? '#fff' : '#26daa5');
  $('#like').css('color', liked ? '#26daa5' : '#fff');
  $('#dislike').css('background', disliked ? '#fff' : '#26daa5');
  $('#dislike').css('color', disliked ? '#26daa5' : '#fff');
}

How to free webgpu gpu mem in onnxruntime web

I use onnxruntime web with following code

/**
 *
 * @param model don't pass session but pass model path and create session in infer inner. In this way, after infer finish, it will auto free gpu mem to prevent mem overflow
 * @param inputTensor
 */
export async function infer2(model: string, inputTensor: Tensor) {
  const session = await newSession(model)
  const feeds: any = {};
  const inputNames = session.inputNames;
  feeds[inputNames[0]] = inputTensor;
  const results = await session.run(feeds);
  const tensor = results[session.outputNames[0]]
  // await session.release() // free gpu mem
  await session.release() // free gpu mem
  return tensor;
}

/**
 * Load the ONNX model and perform inference
 * @param model don't pass session but pass model path and create session in infer inner. In this way, after infer finish, it will auto free gpu mem to prevent mem overflow
 * @param {onnxruntime.Tensor} inputTensor - Input tensor
 * @param {number[]} inputShape - Input tensor shape
 * @returns {Promise<Float32Array>} - Output tensor data
 */
export const infer = async (model: string, input: Ndarray) => {
  let inputTensor = ndarrayToTensor(input)
  const outTensor = await infer2(model, inputTensor);
  let na = new Ndarray(Array.from(outTensor.data as Float32Array) as number[], outTensor.dims as number[])
  inputTensor.dispose()
  outTensor.dispose()
  return na
  // const {data: out, dims: outShape} = results[session.outputNames[0]]
  // return {out: out as Float32Array, outShape: outShape as number[]}
};

and following is my test code

  let input = await imgToNdarray(t);
  let out = await infer(model, input)
  let imgDataUrl = outToImgDataUrl(out)
  testReact(<img src={imgDataUrl}/>)

but fater infer, nvidia-smi show the gpu mem is still in use

Javascript slider add counter slide number

I have a slider built in Javascript, CSS and HTML with no dependencies. The slider works fine.

How could I display the counter slide number in Javascript inside the div element .gallery-counter?

For example if there is a total of 8 slides, the first slide would display: 1/8.

The HTML:

<section id="gallery">
    <div class="gallery-container">
        <figure class="gallery-item">
            <img src="img-1.jpg" />
        </figure>
        <figure class="gallery-item">
            <img src="img-2.jpg" />
        </figure>
        <figure class="gallery-item">
            <img src="img-3.jpg" />
        </figure>
    </div>
    <div class="gallery-counter"></div>
    <nav class="gallery-navigation">
        <button class="nav-button prev-button"><span>&#60;</span></button>
        <button class="nav-button next-button"><span>&#62;</span></button>
    </nav>
</section>

The JS:

let currentIndex = 0;

document.querySelector('.prev-button').addEventListener('click', () => {
    navigate(-1);
});

document.querySelector('.next-button').addEventListener('click', () => {
    navigate(1);
});

// Navigation
function navigate(direction) {
    const galleryContainer = document.querySelector('.gallery-container');
    const totalImages = document.querySelectorAll('.gallery-item').length;
    
    currentIndex = (currentIndex + direction + totalImages) % totalImages;
    const offset = -currentIndex * 100;
    
    galleryContainer.style.transform = `translateX(${offset}%)`;
}

// Autoplay
let autoplayInterval = null;

function startAutoplay(interval) {
    stopAutoplay();
    autoplayInterval = setInterval(() => {
        navigate(1);
    }, interval);
}

function stopAutoplay() {
    clearInterval(autoplayInterval);
}

startAutoplay(3000);

// Stop autoplay when user interacts
document.querySelectorAll('.nav-button').forEach(button => {
    button.addEventListener('click', stopAutoplay);
});

Thank you.