diff --git a/src/browser/webapi/Element.zig b/src/browser/webapi/Element.zig index 2b5db1f7..9ce7b0bc 100644 --- a/src/browser/webapi/Element.zig +++ b/src/browser/webapi/Element.zig @@ -1041,6 +1041,8 @@ pub fn parentElement(self: *Element) ?*Element { return self._proto.parentElement(); } +const CSSStyleRule = @import("css/CSSStyleRule.zig"); + pub fn checkVisibility(self: *Element, page: *Page) bool { var current: ?*Element = self; @@ -1051,9 +1053,40 @@ pub fn checkVisibility(self: *Element, page: *Page) bool { return false; } } + + // Also check if any global stylesheet hides this element + const doc_sheets = page.document.getStyleSheets(page) catch null; + if (doc_sheets) |sheets| { + var i: usize = 0; + if (sheets.length() > 0) log.info(.dom, "css.visibility.check", .{}); + while (i < sheets.length()) : (i += 1) { + const sheet = sheets.item(i) orelse continue; + const rules = sheet.getCssRules(page) catch continue; + var j: usize = 0; + while (j < rules.length()) : (j += 1) { + const rule = rules.item(j) orelse continue; + if (rule.is(CSSStyleRule)) |style_rule| { + const selector = style_rule.getSelectorText(); + // log.info(.dom, "check_visibility.eval {s}", .{selector}); + const does_match = el.matches(selector, page) catch |err| blk: { + log.info(.dom, "check_visibility.err", .{ .err = err }); + break :blk false; + }; + if (does_match) { + const style = (style_rule.getStyle(page) catch continue).asCSSStyleDeclaration(); + const display = style.getPropertyValue("display", page); + log.info(.dom, "check_visibility.hit", .{}); + if (std.mem.eql(u8, display, "none")) { + return false; + } + } + } + } + } + } + current = el.parentElement(); } - return true; } diff --git a/src/browser/webapi/css/CSSStyleSheet.zig b/src/browser/webapi/css/CSSStyleSheet.zig index 7474ea50..893c62df 100644 --- a/src/browser/webapi/css/CSSStyleSheet.zig +++ b/src/browser/webapi/css/CSSStyleSheet.zig @@ -61,6 +61,7 @@ pub fn insertRule(self: *CSSStyleSheet, rule: []const u8, index: u32, page: *Pag const style_rule = try CSSStyleRule.init(page); try style_rule.setSelectorText(parsed_rule.selector, page); + @import("../../../log.zig").info(.dom, "css.rule.add {s}", .{parsed_rule.selector}); const style_props = try style_rule.getStyle(page); const style = style_props.asCSSStyleDeclaration(); @@ -90,6 +91,7 @@ pub fn replaceSync(self: *CSSStyleSheet, text: []const u8, page: *Page) !void { while (it.next()) |parsed_rule| { const style_rule = try CSSStyleRule.init(page); try style_rule.setSelectorText(parsed_rule.selector, page); + @import("../../../log.zig").info(.dom, "css.rule.add {s}", .{parsed_rule.selector}); const style_props = try style_rule.getStyle(page); const style = style_props.asCSSStyleDeclaration(); diff --git a/src/browser/webapi/css/StyleSheetList.zig b/src/browser/webapi/css/StyleSheetList.zig index c44dc601..07aa0f4e 100644 --- a/src/browser/webapi/css/StyleSheetList.zig +++ b/src/browser/webapi/css/StyleSheetList.zig @@ -5,19 +5,24 @@ const CSSStyleSheet = @import("CSSStyleSheet.zig"); const StyleSheetList = @This(); -_sheets: []*CSSStyleSheet = &.{}, +_sheets: std.ArrayListUnmanaged(*CSSStyleSheet) = .{}, pub fn init(page: *Page) !*StyleSheetList { return page._factory.create(StyleSheetList{}); } pub fn length(self: *const StyleSheetList) u32 { - return @intCast(self._sheets.len); + return @intCast(self._sheets.items.len); } pub fn item(self: *const StyleSheetList, index: usize) ?*CSSStyleSheet { - if (index >= self._sheets.len) return null; - return self._sheets[index]; + if (index >= self._sheets.items.len) return null; + return self._sheets.items[index]; +} + +pub fn add(self: *StyleSheetList, sheet: *CSSStyleSheet, page: *Page) !void { + @import("../../../log.zig").info(.dom, "css.sheet.add", .{}); + try self._sheets.append(page.arena, sheet); } pub const JsApi = struct { diff --git a/src/browser/webapi/element/html/Style.zig b/src/browser/webapi/element/html/Style.zig index 3a5f4bc5..9c30da1a 100644 --- a/src/browser/webapi/element/html/Style.zig +++ b/src/browser/webapi/element/html/Style.zig @@ -78,6 +78,7 @@ pub fn setDisabled(self: *Style, disabled: bool, page: *Page) !void { const CSSStyleSheet = @import("../../css/CSSStyleSheet.zig"); pub fn getSheet(self: *Style, page: *Page) !?*CSSStyleSheet { + @import("../../../../log.zig").info(.dom, "css.style.get_sheet", .{}); // Per spec, sheet is null for disconnected elements or non-CSS types. // Valid types: absent (defaults to "text/css"), empty string, or // case-insensitive match for "text/css". @@ -98,10 +99,16 @@ pub fn getSheet(self: *Style, page: *Page) !?*CSSStyleSheet { const text = try self.asNode().getTextContentAlloc(page.call_arena); try sheet.replaceSync(text, page); + const sheets = try page.document.getStyleSheets(page); + try sheets.add(sheet, page); + return sheet; } pub fn styleAddedCallback(self: *Style, page: *Page) !void { + // Force stylesheet initialization so rules are parsed immediately + _ = self.getSheet(page) catch null; + // if we're planning on navigating to another page, don't trigger load event. if (page.isGoingAway()) { return;