From 5ec9f15d94ff727d8251d8f95249172176cc9ea2 Mon Sep 17 00:00:00 2001 From: "Adam D. Ruppe" Date: Tue, 7 Mar 2017 22:36:12 -0500 Subject: [PATCH] convenience methods for dealing with uncertain element presence --- dom.d | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/dom.d b/dom.d index 39c40ca..5bfaa56 100644 --- a/dom.d +++ b/dom.d @@ -1142,6 +1142,12 @@ class Document : FileResource { return root.requireSelector!(SomeElementType)(selector, file, line); } + final MaybeNullElement!SomeElementType optionSelector(SomeElementType = Element)(string selector, string file = __FILE__, size_t line = __LINE__) + if(is(SomeElementType : Element)) + { + return root.optionSelector!(SomeElementType)(selector, file, line); + } + /// ditto Element querySelector(string selector) { @@ -1376,6 +1382,16 @@ class Element { } + /++ + If a matching selector is found, it returns that Element. Otherwise, the returned object returns null for all methods. + +/ + final MaybeNullElement!SomeElementType optionSelector(SomeElementType = Element)(string selector, string file = __FILE__, size_t line = __LINE__) + if(is(SomeElementType : Element)) + { + auto e = cast(SomeElementType) querySelector(selector); + return MaybeNullElement!SomeElementType(e); + } + /// get all the classes on this element @@ -3268,6 +3284,37 @@ Element[] findComments(Element element, string txt) { return ret; } +/// An option type that propagates null. See: [Element.optionSelector] +struct MaybeNullElement(SomeElementType) { + this(SomeElementType ele) { + this.element = ele; + } + SomeElementType element; + + /// Forwards to the element, wit a null check inserted that propagates null. + auto opDispatch(string method, T...)(T args) { + alias type = typeof(__traits(getMember, element, method)(args)); + static if(is(type : Element)) { + if(element is null) + return MaybeNullElement!type(null); + return __traits(getMember, element, method)(args); + } else static if(is(type == string)) { + if(element is null) + return cast(string) null; + return __traits(getMember, element, method)(args); + } else static if(is(type == void)) { + if(element is null) + return; + __traits(getMember, element, method)(args); + } else { + static assert(0); + } + } + + /// Allows implicit casting to the wrapped element. + alias element this; +} + /++ A collection of elements which forwards methods to the children. +/ @@ -3324,6 +3371,17 @@ struct ElementCollection { return !elements.length; } + /// Collects strings from the collection, concatenating them together + /// Kinda like running reduce and ~= on it. + string collect(string method)(string separator = "") { + string text; + foreach(e; elements) { + text ~= mixin("e." ~ method); + text ~= separator; + } + return text; + } + /// Forward method calls to each individual element of the collection /// returns this so it can be chained. ElementCollection opDispatch(string name, T...)(T t) {