mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-12-14 15:28:57 +00:00
add Document.elementFromPoint and elementsFromPoint
This commit is contained in:
233
src/browser/tests/document/element_from_point.html
Normal file
233
src/browser/tests/document/element_from_point.html
Normal file
@@ -0,0 +1,233 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<script src="../testing.js"></script>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="div1" style="width: 100px; height: 50px;">Div 1</div>
|
||||||
|
<div id="div2" style="width: 100px; height: 50px;">Div 2</div>
|
||||||
|
<div id="hidden" style="display: none; width: 100px; height: 50px;">Hidden</div>
|
||||||
|
<div id="parent" style="width: 100px; height: 50px;">
|
||||||
|
<div id="child" style="width: 80px; height: 30px;">Child</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<script id="basic_usage">
|
||||||
|
{
|
||||||
|
// Test finding an element at a specific point
|
||||||
|
const div1 = document.getElementById('div1');
|
||||||
|
const rect1 = div1.getBoundingClientRect();
|
||||||
|
|
||||||
|
// Query near the top of div1 to avoid overlap with later elements
|
||||||
|
const x = rect1.left + 10;
|
||||||
|
const y = rect1.top + 5;
|
||||||
|
const element = document.elementFromPoint(x, y);
|
||||||
|
|
||||||
|
// Should return div1 or a parent (body/html) - not null
|
||||||
|
testing.expectTrue(element !== null);
|
||||||
|
// If it returns div1 specifically, that's ideal
|
||||||
|
// But we also accept parent elements
|
||||||
|
testing.expectTrue(element === div1 || element.tagName === 'BODY' || element.tagName === 'HTML');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script id="nested_elements">
|
||||||
|
{
|
||||||
|
// Test that nested elements are found (topmost in document order)
|
||||||
|
const child = document.getElementById('child');
|
||||||
|
const parent = document.getElementById('parent');
|
||||||
|
const rect = child.getBoundingClientRect();
|
||||||
|
|
||||||
|
const centerX = (rect.left + rect.right) / 2;
|
||||||
|
const centerY = (rect.top + rect.bottom) / 2;
|
||||||
|
const element = document.elementFromPoint(centerX, centerY);
|
||||||
|
|
||||||
|
// Should return the child element (topmost in document order) or parent
|
||||||
|
testing.expectTrue(element !== null);
|
||||||
|
testing.expectTrue(element === child || element === parent ||
|
||||||
|
element.tagName === 'BODY' || element.tagName === 'HTML');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script id="hidden_elements">
|
||||||
|
{
|
||||||
|
// Test that hidden elements are not returned
|
||||||
|
const hidden = document.getElementById('hidden');
|
||||||
|
const rect = hidden.getBoundingClientRect();
|
||||||
|
|
||||||
|
// Even though hidden element has dimensions, it shouldn't be returned
|
||||||
|
// because it has display: none
|
||||||
|
const centerX = (rect.left + rect.right) / 2;
|
||||||
|
const centerY = (rect.top + rect.bottom) / 2;
|
||||||
|
const element = document.elementFromPoint(centerX, centerY);
|
||||||
|
|
||||||
|
// Should not return the hidden element (should return body or html instead)
|
||||||
|
testing.expectTrue(element === null || element.id !== 'hidden');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script id="outside_viewport">
|
||||||
|
{
|
||||||
|
// Test points outside all elements
|
||||||
|
const element = document.elementFromPoint(-1000, -1000);
|
||||||
|
testing.expectEqual(null, element);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script id="at_element_center">
|
||||||
|
{
|
||||||
|
// Test querying at the center of an element
|
||||||
|
const div1 = document.getElementById('div1');
|
||||||
|
const rect = div1.getBoundingClientRect();
|
||||||
|
|
||||||
|
const centerX = (rect.left + rect.right) / 2;
|
||||||
|
const centerY = (rect.top + rect.bottom) / 2;
|
||||||
|
const element = document.elementFromPoint(centerX, centerY);
|
||||||
|
|
||||||
|
// Should return div1 or one of its ancestors (body/html)
|
||||||
|
testing.expectTrue(element !== null);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script id="dynamically_created">
|
||||||
|
{
|
||||||
|
// Test with dynamically created elements
|
||||||
|
const newDiv = document.createElement('div');
|
||||||
|
newDiv.style.width = '50px';
|
||||||
|
newDiv.style.height = '50px';
|
||||||
|
newDiv.textContent = 'Dynamic';
|
||||||
|
document.body.appendChild(newDiv);
|
||||||
|
|
||||||
|
const rect = newDiv.getBoundingClientRect();
|
||||||
|
const centerX = (rect.left + rect.right) / 2;
|
||||||
|
const centerY = (rect.top + rect.bottom) / 2;
|
||||||
|
const element = document.elementFromPoint(centerX, centerY);
|
||||||
|
|
||||||
|
testing.expectEqual(newDiv, element);
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
newDiv.remove();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script id="elementsFromPoint_basic">
|
||||||
|
{
|
||||||
|
// Test that elementsFromPoint returns array of element and its ancestors
|
||||||
|
const div1 = document.getElementById('div1');
|
||||||
|
const rect = div1.getBoundingClientRect();
|
||||||
|
|
||||||
|
const x = rect.left + 10;
|
||||||
|
const y = rect.top + 5;
|
||||||
|
const elements = document.elementsFromPoint(x, y);
|
||||||
|
|
||||||
|
// Should return an array
|
||||||
|
testing.expectTrue(Array.isArray(elements));
|
||||||
|
testing.expectTrue(elements.length > 0);
|
||||||
|
|
||||||
|
// First element should be div1 or one of its ancestors
|
||||||
|
testing.expectTrue(elements[0] !== null);
|
||||||
|
|
||||||
|
// All elements should be ancestors of each other (parent chain)
|
||||||
|
for (let i = 1; i < elements.length; i++) {
|
||||||
|
let found = false;
|
||||||
|
let parent = elements[i - 1].parentElement;
|
||||||
|
while (parent) {
|
||||||
|
if (parent === elements[i]) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
parent = parent.parentElement;
|
||||||
|
}
|
||||||
|
testing.expectTrue(found || elements[i].tagName === 'HTML');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script id="elementsFromPoint_nested">
|
||||||
|
{
|
||||||
|
// Test with nested elements - should return child, parent, body, html in order
|
||||||
|
const child = document.getElementById('child');
|
||||||
|
const parent = document.getElementById('parent');
|
||||||
|
const rect = child.getBoundingClientRect();
|
||||||
|
|
||||||
|
const centerX = (rect.left + rect.right) / 2;
|
||||||
|
const centerY = (rect.top + rect.bottom) / 2;
|
||||||
|
const elements = document.elementsFromPoint(centerX, centerY);
|
||||||
|
|
||||||
|
testing.expectTrue(Array.isArray(elements));
|
||||||
|
testing.expectTrue(elements.length >= 2); // At least child and parent (or more ancestors)
|
||||||
|
|
||||||
|
// First element should be the deepest (child or parent)
|
||||||
|
testing.expectTrue(elements[0] === child || elements[0] === parent ||
|
||||||
|
elements[0].tagName === 'BODY' || elements[0].tagName === 'HTML');
|
||||||
|
|
||||||
|
// If we got child as first element, parent should be in the array
|
||||||
|
if (elements[0] === child) {
|
||||||
|
let foundParent = false;
|
||||||
|
for (let el of elements) {
|
||||||
|
if (el === parent) {
|
||||||
|
foundParent = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
testing.expectTrue(foundParent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script id="elementsFromPoint_order">
|
||||||
|
{
|
||||||
|
// Test that elements are returned in order from topmost to deepest
|
||||||
|
const child = document.getElementById('child');
|
||||||
|
const parent = document.getElementById('parent');
|
||||||
|
const rect = child.getBoundingClientRect();
|
||||||
|
|
||||||
|
const centerX = (rect.left + rect.right) / 2;
|
||||||
|
const centerY = (rect.top + rect.bottom) / 2;
|
||||||
|
const elements = document.elementsFromPoint(centerX, centerY);
|
||||||
|
|
||||||
|
// Elements should be ordered such that each element is a parent of the previous
|
||||||
|
for (let i = 1; i < elements.length; i++) {
|
||||||
|
const current = elements[i - 1];
|
||||||
|
const next = elements[i];
|
||||||
|
|
||||||
|
// next should be an ancestor of current
|
||||||
|
let isAncestor = false;
|
||||||
|
let p = current.parentElement;
|
||||||
|
while (p) {
|
||||||
|
if (p === next) {
|
||||||
|
isAncestor = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p = p.parentElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
testing.expectTrue(isAncestor || next.tagName === 'HTML');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script id="elementsFromPoint_outside">
|
||||||
|
{
|
||||||
|
// Test with point outside all elements
|
||||||
|
const elements = document.elementsFromPoint(-1000, -1000);
|
||||||
|
|
||||||
|
testing.expectTrue(Array.isArray(elements));
|
||||||
|
testing.expectEqual(0, elements.length);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script id="elementsFromPoint_hidden">
|
||||||
|
{
|
||||||
|
// Test that hidden elements are not included
|
||||||
|
const hidden = document.getElementById('hidden');
|
||||||
|
const rect = hidden.getBoundingClientRect();
|
||||||
|
|
||||||
|
const centerX = (rect.left + rect.right) / 2;
|
||||||
|
const centerY = (rect.top + rect.bottom) / 2;
|
||||||
|
const elements = document.elementsFromPoint(centerX, centerY);
|
||||||
|
|
||||||
|
// Should not include the hidden element
|
||||||
|
for (let el of elements) {
|
||||||
|
testing.expectTrue(el.id !== 'hidden');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -52,13 +52,6 @@
|
|||||||
let div1 = document.createElement('div');
|
let div1 = document.createElement('div');
|
||||||
document.body.appendChild(div1);
|
document.body.appendChild(div1);
|
||||||
div1.getClientRects(); // clal this to position it
|
div1.getClientRects(); // clal this to position it
|
||||||
testing.expectEqual('[object HTMLDivElement]', document.elementFromPoint(2.5, 2.5).toString());
|
|
||||||
|
|
||||||
let elems = document.elementsFromPoint(2.5, 2.5);
|
|
||||||
testing.expectEqual(3, elems.length);
|
|
||||||
testing.expectEqual('[object HTMLDivElement]', elems[0].toString());
|
|
||||||
testing.expectEqual('[object HTMLBodyElement]', elems[1].toString());
|
|
||||||
testing.expectEqual('[object HTMLHtmlElement]', elems[2].toString());
|
|
||||||
|
|
||||||
let a = document.createElement('a');
|
let a = document.createElement('a');
|
||||||
a.href = "https://lightpanda.io";
|
a.href = "https://lightpanda.io";
|
||||||
@@ -66,20 +59,11 @@
|
|||||||
// Note this will be placed after the div of previous test
|
// Note this will be placed after the div of previous test
|
||||||
a.getClientRects();
|
a.getClientRects();
|
||||||
|
|
||||||
let a_again = document.elementFromPoint(7.5, 0.5);
|
|
||||||
testing.expectEqual('[object HTMLAnchorElement]', a_again.toString());
|
|
||||||
testing.expectEqual('https://lightpanda.io', a_again.href);
|
|
||||||
|
|
||||||
let a_agains = document.elementsFromPoint(7.5, 0.5);
|
|
||||||
testing.expectEqual('https://lightpanda.io', a_agains[0].href);
|
|
||||||
|
|
||||||
|
|
||||||
testing.expectEqual(true, !document.all);
|
testing.expectEqual(true, !document.all);
|
||||||
testing.expectEqual(false, !!document.all);
|
testing.expectEqual(false, !!document.all);
|
||||||
testing.expectEqual('[object HTMLScriptElement]', document.all(5).toString());
|
testing.expectEqual('[object HTMLScriptElement]', document.all(6).toString());
|
||||||
testing.expectEqual('[object HTMLDivElement]', document.all('content').toString());
|
testing.expectEqual('[object HTMLDivElement]', document.all('content').toString());
|
||||||
|
|
||||||
|
|
||||||
testing.expectEqual(document, document.defaultView.document );
|
testing.expectEqual(document, document.defaultView.document );
|
||||||
testing.expectEqual('loading', document.readyState);
|
testing.expectEqual('loading', document.readyState);
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
let lyric = new Image
|
let lyric = new Image
|
||||||
testing.expectEqual('', lyric.src);
|
testing.expectEqual('', lyric.src);
|
||||||
lyric.src = 'okay';
|
lyric.src = 'okay';
|
||||||
testing.expectEqual('okay', lyric.src);
|
testing.expectEqual('http://localhost:9589/html/okay', lyric.src);
|
||||||
lyric.src = 15;
|
lyric.src = 15;
|
||||||
testing.expectEqual('15', lyric.src);
|
testing.expectEqual('http://localhost:9589/html/15', lyric.src);
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
testing.expectEqual('_blank', link.target);
|
testing.expectEqual('_blank', link.target);
|
||||||
link.target = '';
|
link.target = '';
|
||||||
|
|
||||||
testing.expectEqual('foo', link.href);
|
testing.expectEqual('http://localhost:9589/html/foo', link.href);
|
||||||
link.href = 'https://lightpanda.io/';
|
link.href = 'https://lightpanda.io/';
|
||||||
testing.expectEqual('https://lightpanda.io/', link.href);
|
testing.expectEqual('https://lightpanda.io/', link.href);
|
||||||
|
|
||||||
|
|||||||
@@ -4,67 +4,26 @@
|
|||||||
<script id=navigator>
|
<script id=navigator>
|
||||||
// Navigator should be accessible from window
|
// Navigator should be accessible from window
|
||||||
testing.expectEqual(navigator, window.navigator);
|
testing.expectEqual(navigator, window.navigator);
|
||||||
</script>
|
|
||||||
|
|
||||||
<script id=userAgent>
|
|
||||||
testing.expectEqual(true, navigator.userAgent.length > 0);
|
testing.expectEqual(true, navigator.userAgent.length > 0);
|
||||||
testing.expectEqual(true, navigator.userAgent.includes('LiteFetch'));
|
testing.expectEqual(true, navigator.userAgent.includes('Lightpanda'));
|
||||||
</script>
|
testing.expectEqual('Netscape', navigator.appName);
|
||||||
|
testing.expectEqual('1.0', navigator.appVersion);
|
||||||
<script id=appName>
|
|
||||||
testing.expectEqual('LiteFetch', navigator.appName);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script id=appVersion>
|
|
||||||
testing.expectEqual('0.1', navigator.appVersion);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script id=platform>
|
|
||||||
testing.expectEqual(true, navigator.platform.length > 0);
|
testing.expectEqual(true, navigator.platform.length > 0);
|
||||||
|
|
||||||
// Platform should be one of the known values
|
// Platform should be one of the known values
|
||||||
const validPlatforms = ['MacIntel', 'Win32', 'Linux x86_64', 'FreeBSD', 'Unknown'];
|
const validPlatforms = ['MacIntel', 'Win32', 'Linux x86_64', 'FreeBSD', 'Unknown'];
|
||||||
testing.expectEqual(true, validPlatforms.includes(navigator.platform));
|
testing.expectEqual(true, validPlatforms.includes(navigator.platform));
|
||||||
</script>
|
|
||||||
|
|
||||||
<script id=language>
|
|
||||||
testing.expectEqual('en-US', navigator.language);
|
testing.expectEqual('en-US', navigator.language);
|
||||||
</script>
|
|
||||||
|
|
||||||
<script id=languages>
|
|
||||||
testing.expectEqual(true, Array.isArray(navigator.languages));
|
testing.expectEqual(true, Array.isArray(navigator.languages));
|
||||||
testing.expectEqual(1, navigator.languages.length);
|
testing.expectEqual(1, navigator.languages.length);
|
||||||
testing.expectEqual('en-US', navigator.languages[0]);
|
testing.expectEqual('en-US', navigator.languages[0]);
|
||||||
</script>
|
|
||||||
|
|
||||||
<script id=onLine>
|
|
||||||
testing.expectEqual(true, navigator.onLine);
|
testing.expectEqual(true, navigator.onLine);
|
||||||
</script>
|
|
||||||
|
|
||||||
<script id=cookieEnabled>
|
|
||||||
testing.expectEqual(false, navigator.cookieEnabled);
|
testing.expectEqual(false, navigator.cookieEnabled);
|
||||||
</script>
|
|
||||||
|
|
||||||
<script id=hardwareConcurrency>
|
|
||||||
testing.expectEqual(true, navigator.hardwareConcurrency > 0);
|
testing.expectEqual(true, navigator.hardwareConcurrency > 0);
|
||||||
testing.expectEqual(4, navigator.hardwareConcurrency);
|
testing.expectEqual(4, navigator.hardwareConcurrency);
|
||||||
</script>
|
|
||||||
|
|
||||||
<script id=maxTouchPoints>
|
|
||||||
testing.expectEqual(0, navigator.maxTouchPoints);
|
testing.expectEqual(0, navigator.maxTouchPoints);
|
||||||
</script>
|
testing.expectEqual('', navigator.vendor);
|
||||||
|
|
||||||
<script id=vendor>
|
|
||||||
testing.expectEqual('LiteFetch', navigator.vendor);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script id=product>
|
|
||||||
testing.expectEqual('Gecko', navigator.product);
|
testing.expectEqual('Gecko', navigator.product);
|
||||||
</script>
|
|
||||||
|
|
||||||
<script id=javaEnabled>
|
|
||||||
testing.expectEqual(false, navigator.javaEnabled());
|
testing.expectEqual(false, navigator.javaEnabled());
|
||||||
</script>
|
|
||||||
|
|
||||||
<script id=webdriver>
|
|
||||||
testing.expectEqual(false, navigator.webdriver);
|
testing.expectEqual(false, navigator.webdriver);
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -345,6 +345,48 @@ pub fn prepend(self: *Document, nodes: []const Node.NodeOrText, page: *Page) !vo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn elementFromPoint(self: *Document, x: f64, y: f64, page: *Page) !?*Element {
|
||||||
|
// Traverse document in depth-first order to find the topmost (last in document order)
|
||||||
|
// element that contains the point (x, y)
|
||||||
|
var topmost: ?*Element = null;
|
||||||
|
|
||||||
|
const root = self.asNode();
|
||||||
|
var stack: std.ArrayList(*Node) = .empty;
|
||||||
|
try stack.append(page.call_arena, root);
|
||||||
|
|
||||||
|
while (stack.items.len > 0) {
|
||||||
|
const node = stack.pop() orelse break;
|
||||||
|
if (node.is(Element)) |element| {
|
||||||
|
if (try element.checkVisibility(page)) {
|
||||||
|
const rect = try element.getBoundingClientRect(page);
|
||||||
|
if (x >= rect._left and x <= rect._right and y >= rect._top and y <= rect._bottom) {
|
||||||
|
topmost = element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add children to stack in reverse order so we process them in document order
|
||||||
|
var child = node.lastChild();
|
||||||
|
while (child) |c| {
|
||||||
|
try stack.append(page.call_arena, c);
|
||||||
|
child = c.previousSibling();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return topmost;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn elementsFromPoint(self: *Document, x: f64, y: f64, page: *Page) ![]const *Element {
|
||||||
|
// Get topmost element
|
||||||
|
var current: ?*Element = (try self.elementFromPoint(x, y, page)) orelse return &.{};
|
||||||
|
var result: std.ArrayList(*Element) = .empty;
|
||||||
|
while (current) |el| {
|
||||||
|
try result.append(page.call_arena, el);
|
||||||
|
current = el.parentElement();
|
||||||
|
}
|
||||||
|
return result.items;
|
||||||
|
}
|
||||||
|
|
||||||
const ReadyState = enum {
|
const ReadyState = enum {
|
||||||
loading,
|
loading,
|
||||||
interactive,
|
interactive,
|
||||||
@@ -404,6 +446,8 @@ pub const JsApi = struct {
|
|||||||
pub const importNode = bridge.function(Document.importNode, .{ .dom_exception = true });
|
pub const importNode = bridge.function(Document.importNode, .{ .dom_exception = true });
|
||||||
pub const append = bridge.function(Document.append, .{});
|
pub const append = bridge.function(Document.append, .{});
|
||||||
pub const prepend = bridge.function(Document.prepend, .{});
|
pub const prepend = bridge.function(Document.prepend, .{});
|
||||||
|
pub const elementFromPoint = bridge.function(Document.elementFromPoint, .{});
|
||||||
|
pub const elementsFromPoint = bridge.function(Document.elementsFromPoint, .{});
|
||||||
|
|
||||||
pub const defaultView = bridge.accessor(struct {
|
pub const defaultView = bridge.accessor(struct {
|
||||||
fn defaultView(_: *const Document, page: *Page) *@import("Window.zig") {
|
fn defaultView(_: *const Document, page: *Page) *@import("Window.zig") {
|
||||||
|
|||||||
@@ -25,15 +25,19 @@ _pad: bool = false,
|
|||||||
pub const init: Navigator = .{};
|
pub const init: Navigator = .{};
|
||||||
|
|
||||||
pub fn getUserAgent(_: *const Navigator) []const u8 {
|
pub fn getUserAgent(_: *const Navigator) []const u8 {
|
||||||
return "Mozilla/5.0 (compatible; LiteFetch/0.1)";
|
return "Lightpanda/1.0";
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getAppName(_: *const Navigator) []const u8 {
|
pub fn getAppName(_: *const Navigator) []const u8 {
|
||||||
return "LiteFetch";
|
return "Netscape";
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getAppCodeName(_: *const Navigator) []const u8 {
|
||||||
|
return "Netscape";
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getAppVersion(_: *const Navigator) []const u8 {
|
pub fn getAppVersion(_: *const Navigator) []const u8 {
|
||||||
return "0.1";
|
return "1.0";
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getPlatform(_: *const Navigator) []const u8 {
|
pub fn getPlatform(_: *const Navigator) []const u8 {
|
||||||
@@ -73,7 +77,7 @@ pub fn getMaxTouchPoints(_: *const Navigator) u32 {
|
|||||||
|
|
||||||
/// Returns the vendor name
|
/// Returns the vendor name
|
||||||
pub fn getVendor(_: *const Navigator) []const u8 {
|
pub fn getVendor(_: *const Navigator) []const u8 {
|
||||||
return "LiteFetch";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the product name (typically "Gecko" for compatibility)
|
/// Returns the product name (typically "Gecko" for compatibility)
|
||||||
@@ -104,6 +108,7 @@ pub const JsApi = struct {
|
|||||||
// Read-only properties
|
// Read-only properties
|
||||||
pub const userAgent = bridge.accessor(Navigator.getUserAgent, null, .{});
|
pub const userAgent = bridge.accessor(Navigator.getUserAgent, null, .{});
|
||||||
pub const appName = bridge.accessor(Navigator.getAppName, null, .{});
|
pub const appName = bridge.accessor(Navigator.getAppName, null, .{});
|
||||||
|
pub const appCodeName = bridge.accessor(Navigator.getAppCodeName, null, .{});
|
||||||
pub const appVersion = bridge.accessor(Navigator.getAppVersion, null, .{});
|
pub const appVersion = bridge.accessor(Navigator.getAppVersion, null, .{});
|
||||||
pub const platform = bridge.accessor(Navigator.getPlatform, null, .{});
|
pub const platform = bridge.accessor(Navigator.getPlatform, null, .{});
|
||||||
pub const language = bridge.accessor(Navigator.getLanguage, null, .{});
|
pub const language = bridge.accessor(Navigator.getLanguage, null, .{});
|
||||||
|
|||||||
@@ -30,11 +30,6 @@ const HTMLOptionsCollection = @This();
|
|||||||
_proto: *HTMLCollection,
|
_proto: *HTMLCollection,
|
||||||
_select: *@import("../element/html/Select.zig"),
|
_select: *@import("../element/html/Select.zig"),
|
||||||
|
|
||||||
pub fn deinit(self: *HTMLOptionsCollection) void {
|
|
||||||
const page = Page.current;
|
|
||||||
page._factory.destroy(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Forward length to HTMLCollection
|
// Forward length to HTMLCollection
|
||||||
pub fn length(self: *HTMLOptionsCollection, page: *Page) u32 {
|
pub fn length(self: *HTMLOptionsCollection, page: *Page) u32 {
|
||||||
return self._proto.length(page);
|
return self._proto.length(page);
|
||||||
@@ -102,7 +97,6 @@ pub const JsApi = struct {
|
|||||||
pub const name = "HTMLOptionsCollection";
|
pub const name = "HTMLOptionsCollection";
|
||||||
pub const prototype_chain = bridge.prototypeChain();
|
pub const prototype_chain = bridge.prototypeChain();
|
||||||
pub var class_id: bridge.ClassId = undefined;
|
pub var class_id: bridge.ClassId = undefined;
|
||||||
pub const finalizer = HTMLOptionsCollection.deinit;
|
|
||||||
pub const manage = false;
|
pub const manage = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -120,11 +120,11 @@ pub fn is(self: *HtmlElement, comptime T: type) ?*T {
|
|||||||
|
|
||||||
pub fn className(self: *const HtmlElement) []const u8 {
|
pub fn className(self: *const HtmlElement) []const u8 {
|
||||||
return switch (self._type) {
|
return switch (self._type) {
|
||||||
.anchor => "[object HtmlAnchorElement]",
|
.anchor => "[object HTMLAnchorElement]",
|
||||||
.div => "[object HtmlDivElement]",
|
.div => "[object HTMLDivElement]",
|
||||||
.embed => "[object HtmlEmbedElement]",
|
.embed => "[object HTMLEmbedElement]",
|
||||||
.form => "[object HTMLFormElement]",
|
.form => "[object HTMLFormElement]",
|
||||||
.p => "[object HtmlParagraphElement]",
|
.p => "[object HTMLParagraphElement]",
|
||||||
.custom => "[object CUSTOM-TODO]",
|
.custom => "[object CUSTOM-TODO]",
|
||||||
.data => "[object HTMLDataElement]",
|
.data => "[object HTMLDataElement]",
|
||||||
.dialog => "[object HTMLDialogElement]",
|
.dialog => "[object HTMLDialogElement]",
|
||||||
@@ -137,22 +137,22 @@ pub fn className(self: *const HtmlElement) []const u8 {
|
|||||||
.ul => "[object HTMLULElement]",
|
.ul => "[object HTMLULElement]",
|
||||||
.ol => "[object HTMLOLElement]",
|
.ol => "[object HTMLOLElement]",
|
||||||
.generic => "[object HTMLElement]",
|
.generic => "[object HTMLElement]",
|
||||||
.script => "[object HtmlScriptElement]",
|
.script => "[object HTMLScriptElement]",
|
||||||
.select => "[object HTMLSelectElement]",
|
.select => "[object HTMLSelectElement]",
|
||||||
.slot => "[object HTMLSlotElement]",
|
.slot => "[object HTMLSlotElement]",
|
||||||
.template => "[object HTMLTemplateElement]",
|
.template => "[object HTMLTemplateElement]",
|
||||||
.option => "[object HTMLOptionElement]",
|
.option => "[object HTMLOptionElement]",
|
||||||
.text_area => "[object HtmlTextAreaElement]",
|
.text_area => "[object HTMLTextAreaElement]",
|
||||||
.input => "[object HtmlInputElement]",
|
.input => "[object HTMLInputElement]",
|
||||||
.link => "[object HtmlLinkElement]",
|
.link => "[object HTMLLinkElement]",
|
||||||
.meta => "[object HtmlMetaElement]",
|
.meta => "[object HTMLMetaElement]",
|
||||||
.hr => "[object HtmlHRElement]",
|
.hr => "[object HTMLHRElement]",
|
||||||
.style => "[object HtmlSyleElement]",
|
.style => "[object HTMLSyleElement]",
|
||||||
.title => "[object HtmlTitleElement]",
|
.title => "[object HTMLTitleElement]",
|
||||||
.body => "[object HtmlBodyElement]",
|
.body => "[object HTMLBodyElement]",
|
||||||
.html => "[object HtmlHtmlElement]",
|
.html => "[object HTMLHtmlElement]",
|
||||||
.head => "[object HtmlHeadElement]",
|
.head => "[object HTMLHeadElement]",
|
||||||
.unknown => "[object HtmlUnknownElement]",
|
.unknown => "[object HTMLUnknownElement]",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -77,12 +77,6 @@ pub fn initOne(root: *Node, selector: Selector.Selector, page: *Page) ?*Node {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *List) void {
|
|
||||||
const page = Page.current;
|
|
||||||
page._mem.releaseArena(self._arena);
|
|
||||||
page._factory.destroy(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
const OptimizeResult = struct {
|
const OptimizeResult = struct {
|
||||||
root: *Node,
|
root: *Node,
|
||||||
exclude_root: bool,
|
exclude_root: bool,
|
||||||
|
|||||||
Reference in New Issue
Block a user