Skip to content

Commit

Permalink
Documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
hpehl committed Nov 28, 2024
1 parent c6e294d commit b5d6fc5
Show file tree
Hide file tree
Showing 6 changed files with 205 additions and 114 deletions.
18 changes: 11 additions & 7 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,19 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
The refactoring should make the use case and scope of the builder-like classes, interfaces and methods more obvious. It
introduces a common naming pattern for interfaces and classes:

- Interface `[HTML|MathML|SVG]Element<Scope>Methods`: These interfaces contain default methods to work with a specific aspect
of an HTML, MathML or SVG element.
- Interface `[HTML|MathML|SVG]Element<Scope>Methods`: These interfaces contain default methods to work with a specific aspect of
an HTML, MathML or SVG element.

Examples are
Some examples are
- `ElementAttributeMethods`
- `HTMLElementDataMethods`
- `HTMLInputElementMethods`
- `SVGElementStyleMethods`

- Class `[HTML|MathML|SVG](Element|Container)Builder`: Concrete builders that encapsulate an HTML, MathML or SVG element. The builders implement the method interfaces to work with the element.
- Class `[HTML|MathML|SVG](Element|Container)Builder`: Concrete builders that encapsulate an HTML, MathML or SVG element. The
builders implement the method interfaces to work with the element.

Examples are
Some examples are
- `HTMLElementBuilder`
- `HTMLInputElementBuilder`
- `SVGContainerBuilder`
Expand Down Expand Up @@ -51,13 +53,15 @@ introduces a common naming pattern for interfaces and classes:
- `Container<E extends Element, B extends TypedBuilder<E, B>>` has been deprecated. It is replaced by
`ElementContainerMethods<E, B>`

- `ElementsBag` has been deprecated. It can be replaced by using the normal collection API.
- `ElementsBag` has been deprecated. It should be replaced by using the standard collection API.

- `Finder<E extends Element, B extends TypedBuilder<E, B>>` has been deprecated. It is replaced by `ElementQueryMethods<E, B>`

- `HasInputElement<E extends HTMLInputElement, B extends TypedBuilder<E, B>>` and
`InputElementBuilder<E extends HTMLInputElement, B extends TypedBuilder<E, B>>` have been deprecated. They are replaced by
`HTMLInputElementBuilder<E, B>`.
`HTMLInputElementMethods<E, B>` and `HTMLInputElementBuilder<E, B>`.

- `LazyElement` has been deprecated. It should be replaced by using late initialization in `IsElement.element()`.

#### MathML

Expand Down
2 changes: 1 addition & 1 deletion core/src/main/java/org/jboss/elemento/ElementsBag.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import elemental2.dom.HTMLElement;

/**
* @deprecated Should be replaced by using the collection API.
* @deprecated Should be replaced by using the standard collection API.
*/
@Deprecated
public class ElementsBag implements TypedBuilder<Iterable<Element>, ElementsBag> {
Expand Down
103 changes: 2 additions & 101 deletions core/src/main/java/org/jboss/elemento/HTMLInputElementBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ public class HTMLInputElementBuilder<E extends HTMLInputElement> implements
HTMLElementAttributeMethods<E, HTMLInputElementBuilder<E>>,
HTMLElementDataMethods<E, HTMLInputElementBuilder<E>>,
HTMLElementStyleMethods<E, HTMLInputElementBuilder<E>>,
HTMLElementVisibilityMethods<E, HTMLInputElementBuilder<E>> {
HTMLElementVisibilityMethods<E, HTMLInputElementBuilder<E>>,
HTMLInputElementMethods<E, HTMLInputElementBuilder<E>> {

private final E element;

Expand All @@ -48,104 +49,4 @@ public HTMLInputElementBuilder<E> that() {
public E element() {
return element;
}

/** Modifies the {@code accept} attribute. */
public HTMLInputElementBuilder<E> accept(String accept) {
element().accept = accept;
return this;
}

/** Modifies the {@code autofocus} flag. */
public HTMLInputElementBuilder<E> autofocus(boolean autofocus) {
element().autofocus = autofocus;
return this;
}

/** Modifies the {@code autocomplete} attribute. */
public HTMLInputElementBuilder<E> autocomplete(String autocomplete) {
element().autocomplete = autocomplete;
return this;
}

/** Modifies the {@code checked} flag. */
public HTMLInputElementBuilder<E> checked(boolean checked) {
element().checked = checked;
return this;
}

/** Modifies the {@code disabled} flag. */
public HTMLInputElementBuilder<E> disabled(boolean disabled) {
element().disabled = disabled;
return this;
}

/** Modifies the {@code indeterminate} flag. */
public HTMLInputElementBuilder<E> indeterminate(boolean indeterminate) {
element().indeterminate = indeterminate;
return this;
}

/** Modifies the {@code max} attribute. */
public HTMLInputElementBuilder<E> max(int max) {
return max(String.valueOf(max));
}

/** Modifies the {@code max} attribute. */
public HTMLInputElementBuilder<E> max(String max) {
element().max = max;
return this;
}

/** Modifies the {@code min} attribute. */
public HTMLInputElementBuilder<E> min(int min) {
return min(String.valueOf(min));
}

/** Modifies the {@code min} attribute. */
public HTMLInputElementBuilder<E> min(String min) {
element().min = min;
return this;
}

/** Modifies the {@code multiple} attribute. */
public HTMLInputElementBuilder<E> multiple(boolean multiple) {
element().multiple = multiple;
return this;
}

/** Modifies the {@code name} attribute. */
public HTMLInputElementBuilder<E> name(String name) {
element().name = name;
return this;
}

/** Modifies the {@code placeholder} text. */
public HTMLInputElementBuilder<E> placeholder(String placeholder) {
element().placeholder = placeholder;
return this;
}

/** Modifies the {@code readOnly} flag. */
public HTMLInputElementBuilder<E> readOnly(boolean readOnly) {
element().readOnly = readOnly;
return this;
}

/** Modifies the {@code required} flag. */
public HTMLInputElementBuilder<E> required(boolean required) {
element().required = required;
return this;
}

/** Modifies the {@code tabIndex} number. */
public HTMLInputElementBuilder<E> tabIndex(int tabIndex) {
element().tabIndex = tabIndex;
return this;
}

/** Modifies the {@code value}. */
public HTMLInputElementBuilder<E> value(String value) {
element().value = value;
return this;
}
}
125 changes: 125 additions & 0 deletions core/src/main/java/org/jboss/elemento/HTMLInputElementMethods.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
* Copyright 2023 Red Hat
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jboss.elemento;

import elemental2.dom.HTMLInputElement;

/**
* Provides methods and default implementations for modifying the attributes of an HTML input element.
*/
public interface HTMLInputElementMethods<E extends HTMLInputElement, B extends TypedBuilder<E, B>>
extends TypedBuilder<E, B>, IsElement<E> {

/** Modifies the {@code accept} attribute. */
default B accept(String accept) {
element().accept = accept;
return that();
}

/** Modifies the {@code autofocus} flag. */
default B autofocus(boolean autofocus) {
element().autofocus = autofocus;
return that();
}

/** Modifies the {@code autocomplete} attribute. */
default B autocomplete(String autocomplete) {
element().autocomplete = autocomplete;
return that();
}

/** Modifies the {@code checked} flag. */
default B checked(boolean checked) {
element().checked = checked;
return that();
}

/** Modifies the {@code disabled} flag. */
default B disabled(boolean disabled) {
element().disabled = disabled;
return that();
}

/** Modifies the {@code indeterminate} flag. */
default B indeterminate(boolean indeterminate) {
element().indeterminate = indeterminate;
return that();
}

/** Modifies the {@code max} attribute. */
default B max(int max) {
return max(String.valueOf(max));
}

/** Modifies the {@code max} attribute. */
default B max(String max) {
element().max = max;
return that();
}

/** Modifies the {@code min} attribute. */
default B min(int min) {
return min(String.valueOf(min));
}

/** Modifies the {@code min} attribute. */
default B min(String min) {
element().min = min;
return that();
}

/** Modifies the {@code multiple} attribute. */
default B multiple(boolean multiple) {
element().multiple = multiple;
return that();
}

/** Modifies the {@code name} attribute. */
default B name(String name) {
element().name = name;
return that();
}

/** Modifies the {@code placeholder} text. */
default B placeholder(String placeholder) {
element().placeholder = placeholder;
return that();
}

/** Modifies the {@code readOnly} flag. */
default B readOnly(boolean readOnly) {
element().readOnly = readOnly;
return that();
}

/** Modifies the {@code required} flag. */
default B required(boolean required) {
element().required = required;
return that();
}

/** Modifies the {@code tabIndex} number. */
default B tabIndex(int tabIndex) {
element().tabIndex = tabIndex;
return that();
}

/** Modifies the {@code value}. */
default B value(String value) {
element().value = value;
return that();
}
}
4 changes: 2 additions & 2 deletions core/src/main/java/org/jboss/elemento/LazyElement.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@
import elemental2.dom.HTMLElement;

/**
* Convenience class to support lazy element creation. The bulk of a LazyElement is not instantiated until {@link #element()} is
* called.
* @deprecated Should be replaced by using late initialization in {@link IsElement#element()}.
*/
@Deprecated
public abstract class LazyElement<E extends HTMLElement> implements IsElement<E> {

private E element;
Expand Down
67 changes: 64 additions & 3 deletions docs/builder-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
Creating a hierarchy of elements is often awkward and cumbersome when working with GWT Elemental. Even simple structures like

```html

<section class="main">
<input class="toggle-all" type="checkbox">
<label for="toggle-all">Mark all as complete</label>
Expand All @@ -19,7 +20,8 @@ Creating a hierarchy of elements is often awkward and cumbersome when working wi
</section>
```

lead to a vast amount of `Document.createElement()` and chained `Node.appendChild()` calls. With Elemento, creating the above structure is as easy as
lead to a vast amount of `Document.createElement()` and chained `Node.appendChild()` calls. With Elemento, creating the above
structure is as easy as

```java
import static org.jboss.elemento.Elements.*;
Expand All @@ -43,11 +45,14 @@ HTMLElement section = section().css("main")
.element();
```

The class `Elements` provides convenient methods to create the most common elements. It uses a fluent API to create and append elements on the fly. Take a look at the [API documentation](https://hal.github.io/elemento/apidocs/org/jboss/elemento/Elements.html) for more details.
The class `Elements` provides convenient methods to create the most common elements. It uses a fluent API to create and append
elements on the fly. Take a look at
the [API documentation](https://hal.github.io/elemento/apidocs/org/jboss/elemento/Elements.html) for more details.

## References

When creating large hierarchies of elements, you often need to assign an element somewhere in the tree. Use an inline assignment together with `element()` to create and assign the element in one go:
When creating large hierarchies of elements, you often need to assign an element somewhere in the tree. Use an inline assignment
together with `element()` to create and assign the element in one go:

```java
import static org.jboss.elemento.Elements.*;
Expand All @@ -57,3 +62,59 @@ final HTMLElement footer = footer()
.add(count = span().css("todo-count").element())
.element();
```

## Classes and Interfaces

The builders returned by the methods in `Elements` are of one of the following classes:

- `HTMLContainerBuilder<E extends HTMLElement>`
- `HTMLElementBuilder<E extends HTMLElement>`
- `HTMLInputElementBuilder<E extends HTMLInputElement>`

For [MathML](mathml.md) and [SVG](svg.md), the builders are

- `MathMLElementBuilder<E extends MathMLElement>` and
- `SVGElementBuilder<E extends SVGElement>`

All builders encapsulate a given element and implement `TypedBuilder<T, B extends TypedBuilder<T, B>>` to make builders work
with inheritance. Apart from that, all builders are kept very simple and don't define their own methods. For example, this is
the definition of the `HTMLElementBuilder`:

```java
public class HTMLElementBuilder<E extends HTMLElement> { // implements section omitted

private final E element;

public HTMLElementBuilder(E element) {
this.element = requireNonNull(element, "element required");
}

@Override
public HTMLElementBuilder<E> that() {
return this;
}

@Override
public E element() {
return element;
}
}
```

The builders get their features solely by implementing specific interfaces. These interfaces contain default methods to
manipulate the encapsulated element in a specific way.

The interface names follow the pattern `[HTML|MathML|SVG]Element<Scope>Methods`. Some examples are

- `ElementAttributeMethods`
- `HTMLElementDataMethods`
- `HTMLInputElementMethods`
- `SVGElementStyleMethods`

If you only use Elemento to create a DOM tree quickly and easily, you will most likely hardly come into touch with the 'method'
interfaces. However, if you want to create your own builders, these interfaces come in very handy. You can have very
fine-grained control over which methods your builder should provide. And since these methods are defined as default methods in
interfaces, you are free to mix and match the interfaces across different builders without worrying about multiple inheritance.

The components in [PatternFly Java](https://patternfly-java.github.io/api-design) are a good example of this. They build upon
Elemento's builders and implement specific 'method' interfaces to define their features.

0 comments on commit b5d6fc5

Please sign in to comment.