public static final class HtmlBuilder.ContextParent extends Object
The context parent is an HtmlParent
which builder methods
add pieces to. In the following example
_form( ()->{ _input(); // add an <input> to the context parent });
when the _input() methods is invoked, the context parent is the <form> element. The _input() method creates an <input> element and adds it to the <form> context parent.
The context parent is a thread local value, initially null. For conciseness, we consider null a valid context parent; operations on a null context parent has no effect. For example, adding children to a null context parent is a no-op.
This class contains only static methods that builder methods use to operate with context parents.
Static Methods | |
---|---|
HtmlParent |
get()
Get the context parent; may return null.
|
void |
with(HtmlParent parent,
Runnable code)
Run `code` with `parent` as the context parent.
|
<P extends HtmlPiece> P |
add(P piece)
Add `piece` to the context parent.
|
void |
detach(Object... args)
Detach child pieces from the context parent.
|
<P extends HtmlParent> P |
add(P piece,
Object... children)
Add `piece` to the context parent, and add `children` to `piece`.
|
<P extends HtmlParent> P |
add(P piece,
Runnable code)
Add `piece` to the context parent, and run `code` with `piece` as the context parent.
|
void |
detachThenAddTo(Object[] children,
HtmlParent piece)
Detach `children` from the context parent, then add `children` to `piece`.
|
public static HtmlParent get()
public static void with(HtmlParent parent, Runnable code)
When `code` is executed, it'll see `ContextParent.get()==parent`, for example
DIV div = new DIV(); ContextParent.with(div, ()-> { assert ContextParent.get()==div; });
`parent` can be null, which might be useful in some cases.
Example Usage:
class Foo implements HtmlParent { public Foo add(Runnable code) { ContextParent.with(this, code); return this; } ...
public static <P extends HtmlPiece> P add(P piece)
Example Usage:
DIV _div() { return ContextParent.add(new DIV()); }
`piece` cannot be null.
public static void detach(Object... args)
Purpose of this method: In the following example
_p( "abc", _img() );
per Java's evaluation order, the code is executed as
IMG img = _img(); _p( "abc", img );
But _img() adds a <img> to the context parent, so wouldn't the above code build a tree like
<img> <p> abc<img> </p>
which is clearly not intended by the original code?
Our solution: when adding children to a piece, if they are at the tail of the context parent's child list, they are detached from the context parent first, because it is most likely that they were intended for the piece, not for the context parent.
The specification of `detach(args)` in pseudo code:
List children = children of the context parent while children is not empty find the max i that args[i]==children.getLast() if not found, break children.removeLast() args = {args[0], ..., args[i-1]} // drop args[i] and the rest
It is a little complicated since `args` may contain non-HtmlPiece objects.
This method simply invokes HtmlParent.detachChildren(Object...)
which actually implements the specification.
public static <P extends HtmlParent> P add(P piece, Object... children)
The `children` are first detached
from the context parent.
This method is equivalent to
ContextParent.detach(children); piece.addChildren(children); ContextParent.add(piece);
Example Usage:
DIV _div(Object... children) { return ContextParent.add(new DIV(), children); }
public static <P extends HtmlParent> P add(P piece, Runnable code)
This method is equivalent to
ContextParent.add(piece); ContextParent.with(piece, code);
Example Usage:
DIV _div(Runnable code) { return ContextParent.add(new DIV(), code); }
public static void detachThenAddTo(Object[] children, HtmlParent piece)
This method is equivalent to
ContextParent.detach(children); piece.addChildren(children);
Note that this method does not add `piece` to the context parent - presumably it was already added.
Example Usage:
class Foo implements HtmlParent { public Foo add(Object... children) { ContextParent.detachThenAddTo(children, this); return this; } ...