dom: implement getElementsByClassName

This commit is contained in:
Pierre Tachoire
2023-11-17 17:36:28 +01:00
parent e9edb8bab4
commit dd28204797
3 changed files with 48 additions and 0 deletions

View File

@@ -54,6 +54,11 @@ pub const Document = struct {
const root = parser.documentGetDocumentElement(self);
return collection.HTMLCollectionByTagName(parser.elementToNode(root), tag_name);
}
pub fn _getElementsByClassName(self: *parser.Document, classNames: []const u8) !collection.HTMLCollection {
const root = parser.documentGetDocumentElement(self);
return collection.HTMLCollectionByClassName(parser.elementToNode(root), classNames);
}
};
// Tests

View File

@@ -13,6 +13,7 @@ const Union = @import("element.zig").Union;
const Match = union(enum) {
matchByTagName: MatchByTagName,
matchByClassName: MatchByClassName,
pub fn match(self: Match, node: *parser.Node) bool {
switch (self) {
@@ -55,6 +56,37 @@ pub fn HTMLCollectionByTagName(root: *parser.Node, tag_name: []const u8) !HTMLCo
};
}
pub const MatchByClassName = struct {
classNames: []const u8,
fn init(classNames: []const u8) !MatchByClassName {
return MatchByClassName{
.classNames = classNames,
};
}
pub fn match(self: MatchByClassName, node: *parser.Node) bool {
var it = std.mem.splitAny(u8, self.classNames, " ");
const e = parser.nodeToElement(node);
while (it.next()) |c| {
if (!parser.elementHasClass(e, c)) {
return false;
}
}
return true;
}
};
pub fn HTMLCollectionByClassName(root: *parser.Node, classNames: []const u8) !HTMLCollection {
return HTMLCollection{
.root = root,
.match = Match{
.matchByClassName = try MatchByClassName.init(classNames),
},
};
}
// WEB IDL https://dom.spec.whatwg.org/#htmlcollection
// HTMLCollection is re implemented in zig here because libdom
// dom_html_collection expects a comparison function callback as arguement.

View File

@@ -522,6 +522,11 @@ pub fn nodeReplaceChild(node: *Node, new_child: *Node, old_child: *Node) *Node {
return res.?;
}
// nodeToElement is an helper to convert a node to an element.
pub inline fn nodeToElement(node: *Node) *Element {
return @as(*Element, @ptrCast(node));
}
// CharacterData
pub const CharacterData = c.dom_characterdata;
@@ -621,6 +626,12 @@ pub fn elementGetAttribute(elem: *Element, name: []const u8) ?[]const u8 {
return stringToData(s.?);
}
pub fn elementHasClass(elem: *Element, class: []const u8) bool {
var res: bool = undefined;
_ = elementVtable(elem).dom_element_has_class.?(elem, stringFromData(class), &res);
return res;
}
// elementToNode is an helper to convert an element to a node.
pub inline fn elementToNode(e: *Element) *Node {
return @as(*Node, @ptrCast(e));