Google Tag Manager – Uncaught Error: [object Set] is not an iterable or ArrayLike

I am getting the following error when trying to use gtm.js:
Uncaught Error: [object Set] is not an iterable or ArrayLike

I have been using GTM for a long time and have never experienced any issues like this, but as of yesterday (June 5, 2025), I have been seeing thousands of errors being logged in all of our environments and it is preventing hundreds of customers from using the site. The error is being thrown when GTM is initialized as well as any time an event is pushed to the dataLayer. It seems to happen 19 out of 20 times on initialization, in which case pushing events will also cause the same error. On the 1 out of 20 times where it doesn’t happen on initialization, the events won’t throw the error either.

I noticed the Tag Assistant Companion Chrome extension was merged with the Tag Assistant extension the other day, and whether or not this is a coincidence, I found that if I use the Tag Assistant extension and debug GTM (both in our staging environment and in production), the error doesn’t occur. But, if I stop debugging (even if the extension is still installed/enabled), the next time I load the page it’ll stop working again.

Has anyone else been seeing this the past 2 days (or ever)? My guess is that Google made some kind of internal change that started causing this, but to my surprise I don’t see anyone else mentioning it.

Nuxt.js layout: false displays an empty page

I have a Nuxt site that has pages and layouts enabled. I have one layout called default.vue that contains:

    <div id="app">
        <AppSidebar />
        <main class="main-content">
            <NuxtPage />
        </main>
    </div>

I am using NuxtAuth for authentication. I would ideally like the authentication page to not contain a sidebar which results in this definePageMeta():

definePageMeta({
        layout: false,
        auth: { unauthenticatedOnly: true, navigateAuthenticatedTo: '/' },
})

When I set layout: to false, instead of becoming fullscreen and using the page as its own page, it instead displays pure black.

Screenshot of black webpage

Highcharter/Highmaps – how to use TiledWebMap?

I am trying to build a map with highcharter/highmaps which includes a topographical map via a tiled web map.

As a test, I would like to replicate the OpenStreetMap demo (JSFiddle) as provided by highcharts in their API documention. However, I am unsuccessful. All I get is a white page with the title, but no map.

I’ve tried two variants in R – using the highcharter functions and direct JS (within the highcharter functions).

Variant A)

library(highcharter)

highchart(type = "map") %>%
  hc_add_dependency("modules/map") %>%
  hc_add_dependency("modules/tiledwebmap") %>%
  hc_title(text = "Highcharts Maps basic TiledWebMap Series") %>%
  hc_mapNavigation(
    enabled       = TRUE,
    buttonOptions = list(alignTo = "spacingBox")
  ) %>%
  hc_legend(enabled = FALSE) %>%
  hc_chart(
    mapView = list(
      center     = c(10, 50),
      zoom       = 4
    )
  ) %>%
  hc_add_series(
    type     = "tiledwebmap",
    provider = list(type = "Esri", theme = "WorldTopoMap")
  )

Variant B)

library(highcharter)
library(htmlwidgets)
library(htmltools)

hc_lib       <- system.file("htmlwidgets/lib/highcharts", package = "highcharter")
map_js       <- paste(readLines(file.path(hc_lib, "modules/map.js"),       warn = FALSE), collapse = "n")
tiled_js     <- paste(readLines(file.path(hc_lib, "modules/tiledwebmap.js"), warn = FALSE), collapse = "n")

highchart() %>%
  hc_chart(
    type = "map",
    events = list(load = JS(
      "
      function () {
        this.mapView = new Highcharts.MapView(this, {
          center: [10, 50],
          zoom: 4
        });

        this.addSeries({
          type: 'tiledwebmap',
          provider: { type: 'Esri', theme: 'WorldTopoMap' }
        });
      }
      "
    ))
  ) %>%
  
  hc_title(text = "Highcharts Maps basic TiledWebMap Series") %>%
  hc_mapNavigation(
    enabled     = TRUE,
    buttonOptions = list(alignTo = "spacingBox")
  ) %>%
  hc_legend(enabled = FALSE) %>% 
  htmlwidgets::prependContent(tags$script(HTML(map_js_code))) %>%
  htmlwidgets::prependContent(tags$script(HTML(tile_js_code)))

I am using the most recent highcharter version 0.9.4.9000, installed from the highcharter GitHub repo, which uses HighchartsJS 12.2.0.

Has someone managed to get TiledWebMap to work with highcharter?

Thanks and best regards,
Martin

Blocks created in random places, without overlay on pure java script

Help, please! I’ve already seen how to make from 5 to 20 random blocks, but I can’t make them not touch each other. Please don’t explain in words how this should work, but show an example of code on java script!

let bufferZoneCnt = document.querySelector('.bufferZone-cnt');
let bufferZoneCntHeight = bufferZoneCnt.getBoundingClientRect().height;
let bufferZoneCntWidth = bufferZoneCnt.getBoundingClientRect().width;


function generateDiv() {
    var dfrag = document.createDocumentFragment();
    var count = generateRandom(5, 20);
    var i = 0;
    for (var i = 0; i < count; i++) {
        var div = document.createElement("div");
        dfrag.appendChild(div);
    }
    for (i = 0; i < dfrag.childNodes.length; i++) {
        div = dfrag.childNodes[i];
        alterDivStyle(div);
    }
    bufferZoneCnt.appendChild(dfrag);
}
function rndColor() {
    var r = ('0' + generateRandom(0, 255).toString(16)).substr(-2), // red
        g = ('0' + generateRandom(0, 255).toString(16)).substr(-2), // green
        b = ('0' + generateRandom(0, 255).toString(16)).substr(-2); // blue
    return '#' + r + g + b;
}

function generateRandom(min, max) {
    var number = Math.floor(Math.random() * (max - min)) + min;
    return number;
}
function alterDivStyle(div) {
    div.style.width = generateRandom(20, 100) + "px";
    div.style.height = generateRandom(20, 100) + "px";
    let divHeight = parseInt(div.style.height);
    let divWidth = parseInt(div.style.width);
    div.style.backgroundColor = rndColor();
    div.style.color = rndColor();
    div.style.position = "absolute";
    div.style.border = "solid";
    div.style.borderColor = rndColor();
    div.style.borderWidth = rndColor();
    div.style.borderRadius = generateRandom(0, 10) + "px";
    div.innerHTML = "<strong>div</strong>";
    div.style.top = generateRandom(0, bufferZoneCntHeight - divHeight) + "px";
    div.style.left = generateRandom(0, bufferZoneCntWidth - divWidth) + "px";

I tried to put all the coordinates into an array, and then run each section of the array through a loop, but something doesn’t work.

IS there an easy way to spread an object’s properties as event functions?

I have an interface called “DataSet”, which features an optional property, which is an object with various optional event functions on it:

export interface DataSet {
    colour: string;
    value: number;
    events?: {
        onAuxClick?(event: React.MouseEvent<SVGPathElement, MouseEvent>, data: DataSet): void;
        onBlur?(event: React.FocusEvent<SVGPathElement, Element>, data: DataSet): void;
        onClick?(event: React.MouseEvent<SVGPathElement, MouseEvent>, data: DataSet): void;
        onDoubleClick?(event: React.MouseEvent<SVGPathElement, MouseEvent>, data: DataSet): void;
        onFocus?(event: React.FocusEvent<SVGPathElement, Element>, data: DataSet): void;
        onKeyDown?(event: React.KeyboardEvent<SVGPathElement>, data: DataSet): void;
        onKeyPress?(event: React.KeyboardEvent<SVGPathElement>, data: DataSet): void;
        onKeyUp?(event: React.KeyboardEvent<SVGPathElement>, data: DataSet): void;
        onMouseDown?(event: React.MouseEvent<SVGPathElement, MouseEvent>, data: DataSet): void;
        onMouseEnter?(event: React.MouseEvent<SVGPathElement, MouseEvent>, data: DataSet): void;
        onMouseLeave?(event: React.MouseEvent<SVGPathElement, MouseEvent>, data: DataSet): void;
        onMouseMove?(event: React.MouseEvent<SVGPathElement, MouseEvent>, data: DataSet): void;
        onMouseOut?(event: React.MouseEvent<SVGPathElement, MouseEvent>, data: DataSet): void;
        onMouseUp?(event: React.MouseEvent<SVGPathElement, MouseEvent>, data: DataSet): void;
        onPointerCancel?(event: React.PointerEvent<SVGPathElement>, data: DataSet): void;
        onPointerDown?(event: React.PointerEvent<SVGPathElement>, data: DataSet): void;
        onPointerEnter?(event: React.PointerEvent<SVGPathElement>, data: DataSet): void;
        onPointerLeave?(event: React.PointerEvent<SVGPathElement>, data: DataSet): void;
        onPointerMove?(event: React.PointerEvent<SVGPathElement>, data: DataSet): void;
        onPointerOut?(event: React.PointerEvent<SVGPathElement>, data: DataSet): void;
        onPointerUp?(event: React.PointerEvent<SVGPathElement>, data: DataSet): void;
        onTouchCancel?(event: React.TouchEvent<SVGPathElement>, data: DataSet): void;
        onTouchEnd?(event: React.TouchEvent<SVGPathElement>, data: DataSet): void;
        onTouchMove?(event: React.TouchEvent<SVGPathElement>, data: DataSet): void;
        onTouchStart?(event: React.TouchEvent<SVGPathElement>, data: DataSet): void;
    }
}

In a component, I iterate over an array of these “DataSet” objects to create SVGPathElements and attach those events to the element (whilst passing the “DataSet” object into the function itself)

data.map((dataEntry, index) => {
            segments.push(<path 

                        onAuxClick={(event) => dataEntry.events?.onAuxClick ? dataEntry.events?.onAuxClick(event, dataEntry) : null}
                        onBlur={(event) => dataEntry.events?.onBlur ? dataEntry.events?.onBlur(event, dataEntry) : null}
                        onClick={(event) => dataEntry.events?.onClick ? dataEntry.events?.onClick(event, dataEntry) : null}
                        onDoubleClick={(event) => dataEntry.events?.onDoubleClick ? dataEntry.events?.onDoubleClick(event, dataEntry) : null}
                        onFocus={(event) => dataEntry.events?.onFocus ? dataEntry.events?.onFocus(event, dataEntry) : null}
                        onKeyDown={(event) => dataEntry.events?.onKeyDown ? dataEntry.events?.onKeyDown(event, dataEntry) : null}
                        onKeyPress={(event) => dataEntry.events?.onKeyPress ? dataEntry.events?.onKeyPress(event, dataEntry) : null}
                        onKeyUp={(event) => dataEntry.events?.onKeyUp ? dataEntry.events?.onKeyUp(event, dataEntry) : null}
                        onMouseDown={(event) => dataEntry.events?.onMouseDown ? dataEntry.events?.onMouseDown(event, dataEntry) : null}
                        onMouseEnter={(event) => dataEntry.events?.onMouseEnter ? dataEntry.events?.onMouseEnter(event, dataEntry) : null}
                        onMouseLeave={(event) => dataEntry.events?.onMouseLeave ? dataEntry.events?.onMouseLeave(event, dataEntry) : null}
                        onMouseMove={(event) => dataEntry.events?.onMouseMove ? dataEntry.events?.onMouseMove(event, dataEntry) : null}
                        onMouseOut={(event) => dataEntry.events?.onMouseOut ? dataEntry.events?.onMouseOut(event, dataEntry) : null}
                        onMouseUp={(event) => dataEntry.events?.onMouseUp ? dataEntry.events?.onMouseUp(event, dataEntry) : null}
                        onPointerCancel={(event) => dataEntry.events?.onPointerCancel ? dataEntry.events?.onPointerCancel(event, dataEntry) : null}
                        onPointerDown={(event) => dataEntry.events?.onPointerDown ? dataEntry.events?.onPointerDown(event, dataEntry) : null}
                        onPointerEnter={(event) => dataEntry.events?.onPointerEnter ? dataEntry.events?.onPointerEnter(event, dataEntry) : null}
                        onPointerLeave={(event) => dataEntry.events?.onPointerLeave ? dataEntry.events?.onPointerLeave(event, dataEntry) : null}
                        onPointerMove={(event) => dataEntry.events?.onPointerMove ? dataEntry.events?.onPointerMove(event, dataEntry) : null}
                        onPointerOut={(event) => dataEntry.events?.onPointerOut ? dataEntry.events?.onPointerOut(event, dataEntry) : null}
                        onPointerUp={(event) => dataEntry.events?.onPointerUp ? dataEntry.events?.onPointerUp(event, dataEntry) : null}
                        onTouchCancel={(event) => dataEntry.events?.onTouchCancel ? dataEntry.events?.onTouchCancel(event, dataEntry) : null}
                        onTouchEnd={(event) => dataEntry.events?.onTouchEnd ? dataEntry.events?.onTouchEnd(event, dataEntry) : null}
                        onTouchMove={(event) => dataEntry.events?.onTouchMove ? dataEntry.events?.onTouchMove(event, dataEntry) : null}
                        onTouchStart={(event) => dataEntry.events?.onTouchStart ? dataEntry.events?.onTouchStart(event, dataEntry) : null}
                />);      
    })

(I’ve removed irrelevant parts of the above code)

If I add a lot of other events to the interface, it’s going to be a bit time consuming to add them explicitly to the component.

Is there an elegant way to add all of those functions to the path element, so that I can only add to the interface without needing to edit the component too? Or has my approach of defining them on the DataSet made a rod for my own back? (Passing the DataSet object to the function probably complicates matters somewhat, too)

I did try {...dataEntry.events} but that didn’t work (I think the resulting code would just be the functions without binding them to the events on the element)

As a secondary question, is there any downside to adding the functions as I have (i.e. the path element will always have a click function, but it will do nothing if it wasn’t defined on the DataSet) or is React smart enough to strip them out when the function would just return null without any further processing?

Tailwind won’t show light mode and only shows dark mode styles

I made a toggle button to change to dark mode and light mode for the react project I’m working on. It does what it should, it correctly add and remove the “dark” class name from html tag and also local storage but the styles I see is just dark mode styles.
my dark mode button code:

export default function DarkModeSwitch() {
  const [isDarkMode, setIsDarkMode] = useState(false);

  useEffect(() => {
    // Check if theme is already saved in localStorage
    const savedTheme = localStorage.getItem('theme');

    // If no theme saved in localStorage, check system preference
    if (savedTheme === null) {
      const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
      setIsDarkMode(prefersDark);
      // Apply the correct class based on system preference
      if (prefersDark) {
        document.documentElement.classList.add('dark');
      } else {
        document.documentElement.classList.remove('dark');
      }
    } else {
      // Apply saved theme from localStorage
      setIsDarkMode(savedTheme === 'dark');
      if (savedTheme === 'dark') {
        document.documentElement.classList.add('dark');
      } else {
        document.documentElement.classList.remove('dark');
      }
    }
  }, []);

  // Toggle the theme and save it to localStorage
  const toggleDarkMode = () => {
    const newMode = !isDarkMode;
    setIsDarkMode(newMode);
    if (newMode) {
      document.documentElement.classList.add('dark');
      localStorage.setItem('theme', 'dark');
    } else {
      document.documentElement.classList.remove('dark');
      localStorage.setItem('theme', 'light');
    }
  };

  const spring = {
    type: 'spring',
    stiffness: 700,
    damping: 30,
  };

  return (
    <div
      onClick={toggleDarkMode}
      className={`flex-start flex h-[48px] w-[100px] rounded-[30px] bg-zinc-100 p-[5px] shadow-inner hover:cursor-pointer dark:bg-zinc-700 ${isDarkMode ? 'place-content-end' : ''}`}
    >
      <motion.div
        className="flex h-[40px] w-[40px] items-center justify-center rounded-full bg-black/90"
        layout
        transition={spring}
      >
        <motion.div whileTap={{ rotate: 360 }}>
          {isDarkMode ? (
            <RiSunFill className="h-6 w-6 text-yellow-300" />
          ) : (
            <RiMoonClearFill className="h-6 w-6 text-slate-200" />
          )}
        </motion.div>
      </motion.div>
    </div>
  );
}

and here is my tailwind config file:

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./index.html",
    "./src/**/*.{js,ts,jsx,tsx}",
  ],
  darkMode: "class",
  theme: {
    extend: {
      fontFamily: {
        iran: ["iran"],
      },
      colors: {
        background: {
          light: 'oklch(0.985 0.002 247.839)',
          dark: '#030712',
        },
        titles: {
          light: '#fafafa',
          dark: '#030712',
        },
        text: {
          light: '#fafafa',
          dark: '#030712',
          gray: '#374151',
        },
        icons: {
          light: '#44403c',
          dark: '#115e59',
        },
        nav: {
          light: '#99f6e4',
          dark: '#115e59',
        },
      },
      lineHeight: {
        relaxed: '1.25',
      },
    },
  },
  plugins: [
    require('tailwindcss-rtl'),
    require('daisyui'), 
  ],
};

It correctly changes the class name but when I use something like className="fixed w-full z-50 bg-white dark:bg-gray-800 backdrop-blur-sm border-b border-gray-100" it only shows the dark:bg-gray-800 and if I delete dark style it shows the light mode styles.

I tried ignoring system default from the JS but it didn’t work.

How to send a message from anonymous script executed with `browser.scripting.executeScript`?

I’m using browser.scripting.executeScript() and i need to send a message to webext background script/service worker script. Usually it means using browser.runtime.sendMessage(), but browser is reportedly undefined in anomymous script. I can pass browser as call script argument, but i believe it will be serialized and i’m not sure it survives the boundary passing.

Here is the code:

await browser.scripting.executeScript({
    target: details,
    world: "MAIN",
    injectImmediately: true,
    args: [tabId, frameId],
    func: (tabId, frameId) => {
      if (window.history.__pushState) {
        console.warn("Already injected");
        return;
      }
      window.history.__pushState = history.pushState;
      console.log("Injected pushState()");
      history.pushState = function(state, unused, url) {
        // eslint-disable-next-line no-console
        console.log("Intercepted pushState()", state, unused, url);
        window.history.__pushState(state, unused, url);

        console.log("debug", browser); // `browser` is undefined

        browser.runtime.sendMessage({
          type: "safari-onhistorystateupdated",
          state, unused, url
        });
      };
    }
  });

How can i access browser object in such anonymous script?

The regex does not identify all matching strings. It feels like a JS bug [closed]

const text = ":apple: fsd<@viktor>fsd text :apple :apple: banana 2332 <@maria> :apple: nice <@maria> :apple:"
console.log("ALL APPLES")
console.log(text.match(/:apple:/g))
console.log("-------------")

/**
 * 
 * @param {string} text 
 */
function countApples(text) {
    const matches = text.matchAll(/(?<name>(?<=<@)w+)>(?<text>[a-z0-9s:]+(?=<@|$))/g);
    for (const match of matches) {
        console.log(`Text group: ${match.groups.text}`)
        console.log(match.groups.text.match(/:apple:/g))
        console.log("-------------")
    }
}

countApples(text)

This is the output

ALL APPLES
[ ':apple:', ':apple:', ':apple:', ':apple:' ]
-------------
Text group: fsd text :apple :apple: banana 2332 
[ ':apple:' ]
-------------
Text group:  :apple: nice 
[ ':apple:' ]
-------------
Text group:  :apple:
[ ':apple:' ]
-------------

Does anyone have any idea why the output from the first text group is a single :apple: and not :apple: :apple:?

Drag event between browser tabs using fullcalendar

I want to use Fullcalendars External-DragNDrop-Functionality, but I can’t manage to drag the event from a seperate Browser-Tab.

Is there any possibilty to achieve this?

What I tried is to test with the Demo-Sites of FullCalendar(Duplicate the Tab and try to drag one of the events to the other Browser-Tab. I tested with my implementations before and this might sound stupid, but if it doesn’t work in their own demo, where else?
The demo can be found here.

Where are resolved values of promises stored?

I’ve been following a tutorial on full-stack development. On the client side, there is an api.js file, which contains the following code snippet:

var API = {

   api: axios.create({ baseURL: "http://localhost:5000/api" }),

   // a bunch of functions

   getAllAuthors: function() {
      return this.api.get(`/author`)
      .then(response => response.data)
   },

   // a bunch of functions
}

And there is also an actions.js file, which contains the following:

var actions = {

   // a bunch of functions
   
   refreshMessage: function(author) {
      if (!author) {
         API.getAllAuthors().then(response => {
         
            // some code
         
         })
      }
   }

   // a bunch of functions
}

I was initially confused about that second then() because I thought that a resolved promise (API.getAllAuthors() in this case) returns the resolved value (response.data in this case). It seemed like the second then() was called on what would be a string or a JavaScript object. But now I know (or think I know) that thens don’t just register a callback for the previous promise, they also create a new one which is going to be resolved with the value that the callback is going to spit out when it’s run.

I quickly created
a diagram to visualize my current understanding of this whole thing

Essentially, every then() creates a new promise and registers a callback that uses the resolved value associated with the previous promise, which is stored somewhere, hidden from the user (by that I mean that it’s not a property of the promise, though I’m not entirely sure where the resolved value “lives”). When the previous promise is fulfilled, its value gets passed on to the registered callback. And whatever THAT callback spits out is going to be stored somewhere and “associated” with the new promise. Is my current understanding correct? And where is this somewhere?

How to allow iframes or raw HTML inside Trix Editor in Rails (ActionText)?

I’m using Trix Editor via ActionText in a Ruby on Rails 7 application.

When I paste raw HTML like a YouTube or Vimeo into the Trix editor, it automatically escapes the tags. For example:

<iframe src="https://player.vimeo.com/video/123"></iframe>

Becomes:

&lt;iframe src="https://player.vimeo.com/video/123"&gt;&lt;/iframe&gt;

This ends up in the params[:text_page][:text_es] as escaped text, and renders as plain text in the view — not as an actual iframe.

Context:
Only trusted admins use this form, so XSS isn’t a concern in this case.

I just want to allow some safe tags (like iframes from Vimeo/YouTube) and render them correctly.

Question:
Is there a clean and safe way to allow specific raw HTML tags like in Trix (ActionText) in Rails?

Or is switching to another WYSIWYG like TinyMCE/CKEditor the only reliable path?

CS50W Project network, can’t figure how to implement the Paginator

I’ve been trying to implement the paginator function for about two months now. I’ve tried many different approaches, but they always lead to new bugs.

In views.py, I load the posts and send them to JavaScript. In loadPosts and loadProfile, I pass the fetch function as a parameter to the buttons. Everything else works fine. The buttons call the fetch function, and the posts are displayed.

The issue is: once I load the second page of profile posts, then switch to loadPosts and click “next” again, it loads the profile posts instead. I’ve already tried using removeEventListener and flags, but I couldn’t figure out how to properly reset the event listener when switching between the functions.

[06/Jun/2025 09:01:10] “GET /post?start=0&end=9 HTTP/1.1” 200 825
[06/Jun/2025 09:01:10] “GET /post/new?start=0&end=9 HTTP/1.1” 200 810


// Switch between the pages: 

document.querySelector("#profile-link").addEventListener('click', function(event) {
        // Top left username, to load the profile
        loadProfile(loggedInUsername)
    });

document.querySelector("#index").addEventListener('click', function(event) {
        event.preventDefault();
        loadPosts()
    });



@csrf_exempt
def post_view(request, username = None):
    if request.method == "GET":
        # Loading all posts
        if username == None:
            posts = Post.objects.all().order_by('-date')
            start = int(request.GET.get("start") or 0 )
            end = int(request.GET.get("end") or (start + 9))
            posts_in_range = posts[start:end+1].values("text","date","user__username")
            return JsonResponse({"posts": list(posts_in_range)})
        else:
            # Loading a profile
            user = User.objects.get(username=username)
            user_id = user.id
            posts = Post.objects.filter(user_id=user_id).order_by('-date')
            start = int(request.GET.get("start") or 0 )
            end = int(request.GET.get("end") or (start + 9))
            posts_in_range = posts[start:end+1].values("text","date","user__username")
            return JsonResponse({"posts": list(posts_in_range)})



// Loads all the posts on the All Posts page
    function loadPosts() {
        let counter = 1;
        let start = (page - 1) * 10;
        let end = start + 9;
        if (page < 1) {
            page = 1
        }
        // Fetch all posts
        fetch(`/post?start=${start}&end=${end}`,null)
            .then(response => response.json())
            .then(data => {
                buttons(counter, `/post?start=${start}&end=${end}`)
                // Hidding buttons and content
                document.getElementById("slider").style.display = "none";
                document.querySelector("#following").innerHTML = "";
                document.querySelector("#posts").innerHTML = "";
                document.getElementById("new-post-form").style.display = "block";
                // buttons next and previous
                data.posts.forEach(add_Post);
            })
    }

    // Loading a profile page
    function loadProfile(username, loggedInUsername) {
        let counter = 1;
        let start = (page - 1) * 10;
        let end = start + 9;
        if (page < 1) {
            page = 1
        }
        // Fetch profile 
        fetch(`/post/${username}?start=${start}&end=${end}`)
            .then(response => response.json())
            .then(data => {
                console.log(username)
                buttons(counter, `/post/${username}?start=${start}&end=${end}`, username)
                document.getElementById("slider").style.display = "none";
                document.querySelector("#following").innerHTML = "";
                document.getElementById("new-post-form").style.display = "none";
                document.querySelector("#posts").innerHTML = "";
                // Checks if a username is already followed
                checkFollow(username)
                // Check if the logged in user wants to see his own profile
                if (username === loggedInUsername) {
                    // Hide the follow function so user cannot follow himself
                    document.getElementById("slider").style.display = "none";
                    // Loads posts
                    if (data.posts.length > 0) {
                        data.posts.forEach(add_Post);
                    }
                } else {
                    // Load profile content
                    document.getElementById("slider").style.display = "block";
                    const checkbox = document.querySelector('.switch input[type="checkbox"]');
                    checkbox.addEventListener('change', function(event) {
                        handleCheckboxChange(username);
                    });
                    if (data.posts.length > 0) {
                        data.posts.forEach(add_Post);
                    }
                }
            })
    }



    function buttons(counter, url, username) {
        const previous = document.getElementById("previous");
        const next = document.getElementById("next");
        console.log(username)

        // If no username fetch all posts
    if (!username) {
            function handleNextClick() {
            counter++;
            start = (counter - 1) * 10;
            end = start + 9;
            const newUrl = `/post?start=${start}&end=${end}`
            load(counter, newUrl, start, end);
        }

    function handlePreviousClick() {
            counter--;
            start = (counter - 1) * 10;
            end = start + 9;
            const newUrl = `/post?start=${start}&end=${end}`
            load(counter, newUrl, start, end);
        }


        }

        // load profile
        else {
        function handleNextClick() {
            counter++;
            start = (counter - 1) * 10;
            end = start + 9;
            const newUrl = `/post/${username}?start=${start}&end=${end}`
            load(counter, newUrl, start, end);
        }

        function handlePreviousClick() {
            counter--;
            start = (counter - 1) * 10;
            end = start + 9;
            const newUrl = `/post/${username}?start=${start}&end=${end}`
            load(counter, newUrl, start, end);
        }
    }

         function handleClick(event) {
                    if (event.target.id === "next") {
                        handleNextClick();
                    }
                    else if (event.target.id === "previous") {
                        handlePreviousClick();
                    }
                }
        fetch(url)
            .then(response => response.json())
            .then(data => {
                pageContainer.removeEventListener("click", handleClick);
                pageContainer.addEventListener("click", handleClick);
            });
        }

   // Loads the post after being called by buttons
    function load(page, newUrl, start, end) {
        console.log(load)
        fetch(newUrl)
            .then(response => response.json())
            .then(data => {
                // Clear previous posts
                document.querySelector("#posts").innerHTML = "";
                if (data.posts.length > 0) {
                    data.posts.forEach(add_Post);
                }
            });
    }

One property missing when sending FormData object

I’m submitting data to the backend. The data includes patient_name, age, date, and medication_files, which are from the active record.

The problem is that I use formData in collecting the data and sending it to the API, however, all the other data is being sent except the medication_files from the active record. I shall share some code and a screenshot to help the more experienced guys help me.

enter image description here

As you can see from the screenshot, the formData object is empty hence can not process it for the API

import { Formik, Field, Form, FieldArray, ErrorMessage } from 'formik';
import './PrescriptionForm.scss';
import { prescriptionSchema } from '../../utils/schema';
import axios from 'axios';
import { getCookie } from '../../utils/helper/tokenHandler';


const PrescriptionForm = () => {
  console.log("Debugging!!!");
  const handleSubmit = async (
    values: {
      patientName: string;
      age: number;
      gender: string;
      date: string;
      medicationFiles: File[];
    },
    { setSubmitting, resetForm }: { setSubmitting: (isSubmitting: boolean) => void; resetForm: () => void }
  ) => {
    
    const token = getCookie();

    const formData = new FormData();

    formData.append('prescription[patient_name]', values.patientName);
    formData.append('prescription[age]', values.age.toString());
    formData.append('prescription[gender]', values.gender);
    formData.append('prescription[date]', values.date);

    console.log('Type:', typeof values.medicationFiles);

    if (values.medicationFiles && values.medicationFiles.length > 0) {
      values.medicationFiles.forEach((file) => {
        formData.append('prescription[medication_files][]', file);
      });
    }

    console.log('Files appended to FormData:');
    Array.from(formData.entries()).forEach(([key, value]) => {
      console.log(`${key}:`, value);
    });

    console.log('medicationFiles:', values.medicationFiles);

    try {
      console.log("Submitting prescription with values:", values);
      console.log("Form data:", formData);
      const res = await axios.post(
        'http://localhost:3000/api/v1/prescriptions',
        formData,
        {
          headers: {
            Authorization: `Bearer ${token}`,
          },
        }
      );
      console.log(res);
      alert('Prescription submitted successfully!');
      resetForm();
    } catch (error) {
      console.error('Submit error:', error);
      if (
        typeof error === 'object' &&
        error !== null &&
        'response' in error &&
        (error as any).response?.data?.errors
      ) {
        alert('Submission failed: ' + (error as any).response.data.errors.join(', '));
      } else {
        alert('An unexpected error occurred. Please try again.');
      }
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <Formik
      initialValues={{
        patientName: '',
        age: 0,
        gender: '',
        date: '',
        medicationFiles: [],
      }}
      validationSchema={prescriptionSchema}
      onSubmit={handleSubmit}
    >
      {({ values, isSubmitting, setFieldValue }) => (
        <Form className="prescription-form">
          <h2>Prescription Form</h2>

          <label>Patient Name</label>
          <Field name="patientName" />
          <ErrorMessage name="patientName" component="div" />

          <label>Age</label>
          <Field
            name="age"
            type="number"
            parse={(value: string) => (value === '' ? 0 : Number(value))}
          />
          <ErrorMessage name="age" component="div" />

          <label>Gender</label>
          <Field name="gender" as="select">
            <option value="">Select</option>
            <option value="male">Male</option>
            <option value="female">Female</option>
            <option value="other">Other</option>
          </Field>
          <ErrorMessage name="gender" component="div" />

          <label>Date</label>
          <Field name="date" type="date" />
          <ErrorMessage name="date" component="div" />

          <label>Medication File</label>
          <input
            name="medicationFiles"
            type="file"
            accept=".pdf,.doc,.docx"
            multiple
            onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
              const files = Array.from(e.currentTarget.files || []);
              setFieldValue("medicationFiles", files);
            }}
          />
          <ErrorMessage name="medicationFiles" component="div" />


          <button type="submit" disabled={isSubmitting}>Submit</button>
        </Form>
      )}
    </Formik>
  );
};

export default PrescriptionForm;

Pixi js – repeating texture for stroke

Hi I am having a hard time finding out how to set a texture of to repeat it self dynamically. Is there even a way to do that?

My use case is that I need to be able to create a 2d structure (top view), that has straight and curved walls around and inside it.

From what I was able to find using path for the walls (I want to be able to set different textures to different parts of the walls) is the best way.

const g = new PIXI.Graphics();
const path = new PIXI.GraphicsPath();

path.moveTo(100, 100);
path.lineTo(200, 100);
path.arcTo(250, 100, 250, 150, 30); // Rounded corner
path.lineTo(250, 200);

// Load texture
const baseTexture = await PIXI.Assets.load('https://pixijs.io/examples/examples/assets/bunny.png');

// ✅ Set wrap mode to REPEAT on baseTexture
baseTexture.wrapMode = PIXI.WRAP_MODES.REPEAT;
baseTexture.update(); // apply changes to GPU

// Create Texture from baseTexture (you can also reuse baseTexture directly)
const texture = new PIXI.Texture(baseTexture);

// Use the path and stroke with the texture
g.path(path);
g.stroke({ width: 12, texture: texture }); // adjust width for visibility

app.stage.addChild(g); 

Have someone encountered and handle how to this?