# JavaScript script to run on the page
js_script_template = f"""
(function() {{
    let labels = [];

    function markPage() {{
        var bodyRect = document.body.getBoundingClientRect();

        var items = Array.prototype.slice.call(
            document.querySelectorAll('*')
        ).map(function(element) {{
            var vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
            var vh = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0);

            // Extract browsergym_id from aria-roledescription if present
            var browsergym_id = null;
            if (element.hasAttribute('aria-roledescription')) {{
                var ariaDescription = element.getAttribute('aria-roledescription');
                var match = ariaDescription.match(/^([a-z0-9]+)_.*/);
                if (match) {{
                    browsergym_id = match[1];  // Extract browsergym_id
                }}
            }}

            var rects = [...element.getClientRects()].filter(bb => {{
                var center_x = bb.left + bb.width / 2;
                var center_y = bb.top + bb.height / 2;
                var elAtCenter = document.elementFromPoint(center_x, center_y);

                return elAtCenter === element || element.contains(elAtCenter);
            }}).map(bb => {{
                const scrollX = window.scrollX || window.pageXOffset;
                const scrollY = window.scrollY || window.pageYOffset;

                const rect = {{
                    left: Math.max(0, bb.left + scrollX),
                    top: Math.max(0, bb.top + scrollY),
                    right: Math.min(window.innerWidth, bb.right + scrollX),
                    bottom: Math.min(window.innerHeight, bb.bottom + scrollY),
                    width: bb.width,
                    height: bb.height
                }};
                return {{
                    ...rect,
                    width: rect.right - rect.left,
                    height: rect.bottom - rect.top
                }};
            }});

            var area = rects.reduce((acc, rect) => acc + rect.width * rect.height, 0);

            return {{
                element: element,
                tagName: element.tagName,
                id: browsergym_id || element.id,  // Use browsergym_id if available, otherwise fallback to element ID
                include: 
                    (element.tagName === 'INPUT' || element.tagName === 'TEXTAREA' || element.tagName === 'SELECT') ||
                    (element.tagName === 'BUTTON' || element.tagName === 'A' || (element.onclick != null) || window.getComputedStyle(element).cursor == 'pointer') ||
                    (element.tagName === 'IFRAME' || element.tagName === 'VIDEO' || element.tagName === 'LI' || element.tagName === 'TD' || element.tagName === 'OPTION'),
                area: area,
                rects: rects,
                text: element.textContent.trim().replace(/\\s{{2,}}/g, ' ')
            }};
        }}).filter(item => item.include && item.area >= {20});

        const buttons = Array.from(document.querySelectorAll('button, a, input[type="button"], div[role="button"]'));

        items = items.filter(x => !buttons.some(y => items.some(z => z.element === y) && y.contains(x.element) && !(x.element === y)));
        items = items.filter(x => !(x.element.parentNode && 
            x.element.parentNode.tagName === 'SPAN' && 
            x.element.parentNode.children.length === 1 && 
            x.element.parentNode.getAttribute('role') &&
            items.some(y => y.element === x.element.parentNode)));
        items = items.filter(x => !items.some(y => x.element.contains(y.element) && !(x === y)));

        return items;
    }}
    return markPage();
}})();
"""