diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f502bb714..262fd2828 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,7 @@ jobs: id: setup-jdk uses: actions/setup-java@v3 with: - java-version: 17 + java-version: 11 distribution: temurin cache: maven - name: Package @@ -30,7 +30,7 @@ jobs: id: setup-maven-settings uses: actions/setup-java@v3 with: # running setup-java again overwrites the settings.xml - java-version: 17 + java-version: 11 distribution: temurin server-id: ossrh server-username: OSSRH_USERNAME @@ -72,7 +72,7 @@ jobs: id: setup-jdk uses: actions/setup-java@v3 with: - java-version: 17 + java-version: 11 distribution: temurin cache: maven - name: Package @@ -82,7 +82,7 @@ jobs: id: setup-maven-settings uses: actions/setup-java@v3 with: # running setup-java again overwrites the settings.xml - java-version: 17 + java-version: 11 distribution: temurin server-id: ossrh server-username: OSSRH_USERNAME @@ -111,12 +111,12 @@ jobs: id: setup-jdk uses: actions/setup-java@v3 with: - java-version: 17 + java-version: 19 distribution: temurin cache: maven - name: JavaDoc id: javadoc - run: $MVN javadoc:javadoc + run: $MVN javadoc:javadoc -P snippets - name: Publish id: publish uses: JamesIves/github-pages-deploy-action@v4.4.3 diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index f2917d5a7..69dc2b5a7 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -20,7 +20,7 @@ jobs: id: setup-jdk uses: actions/setup-java@v3 with: - java-version: 17 + java-version: 11 distribution: temurin cache: maven - name: Verify diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c5d91013..b72ef03d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] +### Added + +- Add methods to set `int` and `boolean` (aria) attributes: + - `ElementBuilder.attr(String, boolean)` + - `ElementBuilder.attr(String, int)` + - `ElementBuilder.aria(String, boolean)` + - `ElementBuilder.aria(String, int)` + +### Changed + +- Added [code snippets](https://openjdk.org/jeps/413) to the [API documentation](https://hal.github.io/elemento/). + ## [1.0.13] - 2023-08-03 ### Upgrades diff --git a/etc/eclipse-formatter-config.xml b/etc/eclipse-formatter-config.xml index 09d8e1a53..c26337e1f 100644 --- a/etc/eclipse-formatter-config.xml +++ b/etc/eclipse-formatter-config.xml @@ -183,7 +183,7 @@ - + @@ -258,7 +258,7 @@ - + @@ -312,7 +312,7 @@ - + diff --git a/pom.xml b/pom.xml index 0ea432887..f0e514e0f 100644 --- a/pom.xml +++ b/pom.xml @@ -106,13 +106,15 @@ 3.3.0 2.23.0 1.9.0 + 3.5.0 2.1.1 4.2 1.6.13 UTF-8 - 17 + 11 + ${java.version} ${java.version} 3.2.5 @@ -227,6 +229,7 @@ LICENSE sed/*.sed **/*license*.txt + src/demo/java/** @@ -284,11 +287,54 @@ + + org.apache.maven.plugins + maven-javadoc-plugin + ${version.javadoc.plugin} + + ${javadoc.options} + true + none + false + + https://www.gwtproject.org/javadoc/latest/ + https://javadoc.io/doc/org.gwtproject.event/gwt-event/${version.gwt.event} + https://javadoc.io/doc/org.gwtproject.safehtml/gwt-safehtml/${version.gwt.safehtml} + + https://javadoc.io/doc/com.google.elemental2/elemental2-core/${version.elemental2}/ + + https://javadoc.io/doc/com.google.elemental2/elemental2-dom/${version.elemental2}/ + + + https://javadoc.io/doc/com.google.elemental2/elemental2-webstorage/${version.elemental2}/ + + + public + + + + org.codehaus.mojo + build-helper-maven-plugin + + + add-demos + generate-test-sources + + add-test-source + + + + src/demo/java + + + + + net.revelc.code.formatter formatter-maven-plugin @@ -379,6 +425,16 @@ + + + snippets + + --snippet-path ${project.basedir}/src/demo/java + + release @@ -410,15 +466,6 @@ org.apache.maven.plugins maven-javadoc-plugin - - - -html5 - - true - none - false - public - attach-javadocs diff --git a/src/demo/java/ByDemo.java b/src/demo/java/ByDemo.java new file mode 100644 index 000000000..046eaa74d --- /dev/null +++ b/src/demo/java/ByDemo.java @@ -0,0 +1,29 @@ +import org.jboss.elemento.By; + +import static org.jboss.elemento.By.AttributeOperator.STARTS_WITH; + +@SuppressWarnings("unused") +public class ByDemo { + + public void groupDemo() { + // @start region = group + // #main [data-list-item=foo] a[href^="https://"] > .fas.fa-check, .external[hidden] + By.group( + By.id("main") + .desc(By.data("listItem", "foo") + .desc(By.element("a").and(By.attribute("href", STARTS_WITH, "https://")) + .child(By.classnames("fas", "fa-check")))), + By.classname("external").and(By.attribute("hidden"))); + // @end region = group + } + + public void andDemo() { + // @start region = and + // button.primary + By.element("button").and(By.classname("primary")); + + // input[type=checkbox] + By.element("input").and(By.attribute("type", "checkbox")); + // @end region = and + } +} diff --git a/src/demo/java/ElementsBagDemo.java b/src/demo/java/ElementsBagDemo.java new file mode 100644 index 000000000..1fa8606f5 --- /dev/null +++ b/src/demo/java/ElementsBagDemo.java @@ -0,0 +1,27 @@ +import java.util.HashMap; +import java.util.Map; + +import org.jboss.elemento.ElementsBag; + +import elemental2.dom.HTMLDListElement; + +import static org.jboss.elemento.Elements.bag; +import static org.jboss.elemento.Elements.dd; +import static org.jboss.elemento.Elements.dl; +import static org.jboss.elemento.Elements.dt; + +@SuppressWarnings({"MismatchedQueryAndUpdateOfCollection", "RedundantOperationOnEmptyContainer", "unused"}) +public class ElementsBagDemo { + + public void bagDemo() { + // @start region = bag + ElementsBag bag = bag(); + Map data = new HashMap<>(); // @replace substring='new HashMap<>()' replacement="..." + data.forEach((text, todo) -> { + bag.add(dt().textContent(text)); + bag.add(dd().add(new TodoElement(todo))); + }); + HTMLDListElement element = dl().addAll(bag.elements()).element(); + // @end region = bag + } +} diff --git a/src/demo/java/ElementsDemo.java b/src/demo/java/ElementsDemo.java new file mode 100644 index 000000000..aa1499d72 --- /dev/null +++ b/src/demo/java/ElementsDemo.java @@ -0,0 +1,112 @@ +import java.util.List; + +import org.jboss.elemento.By; + +import elemental2.dom.HTMLElement; +import elemental2.dom.HTMLLIElement; + +import static elemental2.dom.DomGlobal.document; +import static java.util.stream.Collectors.toList; +import static org.jboss.elemento.By.AttributeOperator.STARTS_WITH; +import static org.jboss.elemento.Elements.a; +import static org.jboss.elemento.Elements.asHtmlElement; +import static org.jboss.elemento.Elements.body; +import static org.jboss.elemento.Elements.button; +import static org.jboss.elemento.Elements.div; +import static org.jboss.elemento.Elements.find; +import static org.jboss.elemento.Elements.htmlElements; +import static org.jboss.elemento.Elements.input; +import static org.jboss.elemento.Elements.label; +import static org.jboss.elemento.Elements.li; +import static org.jboss.elemento.Elements.section; +import static org.jboss.elemento.Elements.stream; +import static org.jboss.elemento.Elements.ul; +import static org.jboss.elemento.EventType.blur; +import static org.jboss.elemento.EventType.change; +import static org.jboss.elemento.EventType.click; +import static org.jboss.elemento.EventType.dblclick; +import static org.jboss.elemento.EventType.keydown; +import static org.jboss.elemento.InputType.checkbox; +import static org.jboss.elemento.InputType.text; + +@SuppressWarnings("unused") +public class ElementsDemo { + + public void builderDemo() { + // @start region = builder + /* The code below, builds the following HTML snippet +
+ + +
    +
  • +
    + + + +
    + +
  • +
+
+ */ + HTMLElement section = section().css("main") + .add(input(checkbox).id("toggle-all").css("toggle-all")) + .add(label() + .apply(l -> l.htmlFor = "toggle-all") + .textContent("Mark all as complete")) + .add(ul().css("todo-list") + .add(li() + .add(div().css("view") + .add(input(checkbox) + .css("toggle") + .checked(true)) + .add(label().textContent("Taste Elemento")) + .add(button().css("destroy"))) + .add(input(text).css("edit")))) + .element(); + // @end region = builder + } + + public void findAllDemo() { + // @start region = findAll + By selector = By.element("a").and(By.attribute("href", STARTS_WITH, "https://")); + for (HTMLElement element : body().findAll(selector)) { + a(element).css("external"); + } + // @end region = findAll + } + + public void streamDemo() { + // @start region = stream + HTMLElement parent = find(document.body, By.data("foo", "bar")); + if (parent != null) { + List htmlElements = stream(parent) + .filter(htmlElements()) + .map(asHtmlElement()) + .collect(toList()); + } + // @end region = stream + } + + public void onDemo() { + // @start region = on + HTMLLIElement listItem = li() + .add(div().css("view") + .add(input(checkbox) + .css("toggle") + .on(change, event -> onDemo())) // @replace substring='onDemo()' replacement="..." + .add(label() + .textContent("Taste Elemento") + .on(dblclick, event -> onDemo())) // @replace substring='onDemo()' replacement="..." + .add(button() + .css("destroy") + .on(click, event -> onDemo()))) // @replace substring='onDemo()' replacement="..." + .add(input(text) + .css("edit") + .on(keydown, event -> onDemo()) // @replace substring='onDemo()' replacement="..." + .on(blur, event -> onDemo())) // @replace substring='onDemo()' replacement="..." + .element(); + // @end region = on + } +} diff --git a/src/demo/java/EventDemo.java b/src/demo/java/EventDemo.java new file mode 100644 index 000000000..d6400a062 --- /dev/null +++ b/src/demo/java/EventDemo.java @@ -0,0 +1,19 @@ +import org.gwtproject.event.shared.HandlerRegistration; + +import static elemental2.dom.DomGlobal.alert; +import static org.jboss.elemento.Elements.body; +import static org.jboss.elemento.EventType.bind; +import static org.jboss.elemento.EventType.click; + +@SuppressWarnings("unused") +public class EventDemo { + + public void bindDemo() { + // @start region = bind + HandlerRegistration handler = bind(body(), click, event -> alert("Clicked")); + // later... + handler.removeHandler(); + // @end region = bind + + } +} diff --git a/src/demo/java/Greeting.java b/src/demo/java/Greeting.java new file mode 100644 index 000000000..6d7438841 --- /dev/null +++ b/src/demo/java/Greeting.java @@ -0,0 +1,36 @@ +import org.jboss.elemento.Attachable; +import org.jboss.elemento.IsElement; + +import elemental2.dom.HTMLElement; +import elemental2.dom.MutationRecord; + +import static elemental2.dom.DomGlobal.console; +import static org.jboss.elemento.Elements.body; +import static org.jboss.elemento.Elements.div; + +@SuppressWarnings("unused") +// @start region = attach +public class Greeting implements IsElement, Attachable { + + private final HTMLElement root; + + Greeting(String name) { + root = div().textContent("Hello " + name).element(); + Attachable.register(root, this); + } + + @Override + public void attach(MutationRecord mutationRecord) { + console.log("Greeting has been attached to the DOM!"); + } + + @Override + public HTMLElement element() { + return root; + } + + public static void init() { + body().add(new Greeting("Smilla")); + } +} +// @end region = attach diff --git a/src/demo/java/HtmlContentDemo.java b/src/demo/java/HtmlContentDemo.java new file mode 100644 index 000000000..6d2ec8548 --- /dev/null +++ b/src/demo/java/HtmlContentDemo.java @@ -0,0 +1,19 @@ +import elemental2.dom.HTMLUListElement; + +import static org.jboss.elemento.Elements.ul; + +@SuppressWarnings("unused") +public class HtmlContentDemo { + + public void addAllDemo() { + // @start region = addAll + TodoRepository repository = new TodoRepository(); + TodoElement[] elements = repository.todos().stream() + .map(TodoElement::new) + .toArray(TodoElement[]::new); + HTMLUListElement ul = ul() + .addAll(elements) + .element(); + // @end region = addAll + } +} diff --git a/src/demo/java/KeyDemo.java b/src/demo/java/KeyDemo.java new file mode 100644 index 000000000..fb095c051 --- /dev/null +++ b/src/demo/java/KeyDemo.java @@ -0,0 +1,19 @@ +import static org.jboss.elemento.Elements.body; +import static org.jboss.elemento.EventType.keydown; +import static org.jboss.elemento.Key.Escape; + +@SuppressWarnings({"unused", "StatementWithEmptyBody"}) +public class KeyDemo { + + public void keyDemo() { + // @start region = key + body().on(keydown, e -> { + if (Escape.match(e)) { + // ... + } else { + // ... + } + }); + // @end region = key + } +} diff --git a/src/demo/java/Todo.java b/src/demo/java/Todo.java new file mode 100644 index 000000000..a46069ad1 --- /dev/null +++ b/src/demo/java/Todo.java @@ -0,0 +1,6 @@ +class Todo { + + String id; + String text; + boolean completed; +} diff --git a/src/demo/java/TodoElement.java b/src/demo/java/TodoElement.java new file mode 100644 index 000000000..fdf8abcf8 --- /dev/null +++ b/src/demo/java/TodoElement.java @@ -0,0 +1,72 @@ +import org.gwtproject.event.shared.HandlerRegistration; +import org.gwtproject.event.shared.HandlerRegistrations; +import org.jboss.elemento.Attachable; +import org.jboss.elemento.IsElement; + +import elemental2.dom.HTMLButtonElement; +import elemental2.dom.HTMLElement; +import elemental2.dom.HTMLInputElement; +import elemental2.dom.MutationRecord; + +import static org.jboss.elemento.Elements.button; +import static org.jboss.elemento.Elements.div; +import static org.jboss.elemento.Elements.input; +import static org.jboss.elemento.Elements.label; +import static org.jboss.elemento.Elements.li; +import static org.jboss.elemento.EventType.bind; +import static org.jboss.elemento.EventType.blur; +import static org.jboss.elemento.EventType.change; +import static org.jboss.elemento.EventType.click; +import static org.jboss.elemento.EventType.dblclick; +import static org.jboss.elemento.EventType.keydown; +import static org.jboss.elemento.InputType.checkbox; +import static org.jboss.elemento.InputType.text; + +// @start region = isElement +public class TodoElement implements IsElement, Attachable { + + private final HTMLElement root; + private final HTMLInputElement toggle; + private final HTMLElement label; + private final HTMLButtonElement destroy; + private final HTMLInputElement summary; + private HandlerRegistration handlerRegistration; + + TodoElement(Todo todo) { + this.root = li().data("item", todo.id) + .add(div().css("view") + .add(toggle = input(checkbox).css("toggle") + .checked(todo.completed) + .element()) + .add(label = label().textContent(todo.text).element()) + .add(destroy = button().css("destroy").element())) + .add(summary = input(text).css("edit").element()) + .element(); + this.root.classList.toggle("completed", todo.completed); + this.toggle.checked = todo.completed; + Attachable.register(this, this); + } + + @Override + public HTMLElement element() { + return root; + } + + @Override + public void attach(MutationRecord mutationRecord) { + handlerRegistration = HandlerRegistrations.compose( + bind(toggle, change, ev -> element()), // @replace substring='attach(null)' replacement="..." + bind(label, dblclick, ev -> element()), // @replace substring='element()' replacement="..." + bind(destroy, click, ev -> element()), // @replace substring='element()' replacement="..." + bind(summary, keydown, ev -> element()), // @replace substring='element()' replacement="..." + bind(summary, blur, ev -> element())); // @replace substring='element()' replacement="..." + } + + @Override + public void detach(MutationRecord mutationRecord) { + if (handlerRegistration != null) { + handlerRegistration.removeHandler(); + } + } +} +// @end region = isElement diff --git a/src/demo/java/TodoRepository.java b/src/demo/java/TodoRepository.java new file mode 100644 index 000000000..ea2a4bb1b --- /dev/null +++ b/src/demo/java/TodoRepository.java @@ -0,0 +1,10 @@ +import java.util.List; + +import static java.util.Collections.emptyList; + +class TodoRepository { + + List todos() { + return emptyList(); + } +} diff --git a/src/main/java/org/jboss/elemento/Attachable.java b/src/main/java/org/jboss/elemento/Attachable.java index 93c694cdc..7cc9ba1a7 100644 --- a/src/main/java/org/jboss/elemento/Attachable.java +++ b/src/main/java/org/jboss/elemento/Attachable.java @@ -21,7 +21,11 @@ import static org.jboss.elemento.Elements.onAttach; import static org.jboss.elemento.Elements.onDetach; -/** Interface to get notified when an element has been attached / detached from the DOM. */ +/** + * Interface to get notified when an element has been attached / detached from the DOM. + *

+ * {@snippet class = Greeting region = attach} + */ public interface Attachable { /** Registers the specified element for both attach and detach. */ diff --git a/src/main/java/org/jboss/elemento/By.java b/src/main/java/org/jboss/elemento/By.java index d6b14ff3f..58b9d624f 100644 --- a/src/main/java/org/jboss/elemento/By.java +++ b/src/main/java/org/jboss/elemento/By.java @@ -27,17 +27,7 @@ * Typesafe CSS selector API. *

* Use the static methods in this class to create arbitrary complex CSS selectors: - *

- * - *

- * // #main [data-list-item=foo] a[href^="http://"] > .fas.fa-check, .external[hidden]
- * By.group(
- *         By.id("main")
- *                 .desc(By.data("listItem", "foo")
- *                         .desc(By.element("a").and(By.attribute("href", STARTS_WITH, "http://"))
- *                                 .child(By.classnames("fas", "fa-check")))),
- *         By.classname("external").and(By.attribute("hidden")));
- * 
+ * {@snippet class = ByDemo region = group} * * @see https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors @@ -165,7 +155,11 @@ public static By data(String name, AttributeOperator operator, String value) { return new ByData(name, operator, value); } - /** Groups the specified selectors using {@code ,}. */ + /** + * Groups the specified selectors using {@code ,}. + *

+ * {@snippet class = ByDemo region = group} + */ public static By group(By first, By second, By... remaining) { int length = 2; if (remaining != null) { @@ -184,7 +178,11 @@ public static By group(By first, By second, By... remaining) { return new ByGroup(group); } - /** Groups the specified selectors using {@code ,}. */ + /** + * Groups the specified selectors using {@code ,}. + *

+ * {@snippet class = ByDemo region = group} + */ public static By group(By[] selectors) { return new ByGroup(selectors); } @@ -195,11 +193,7 @@ public static By group(By[] selectors) { * Combines this selector with the given selector. Use this method to express selectors like {@code button.primary} or * {@code input[type=checkbox]}: *

- * - *

-     * By.element("button").and(By.classname("primary"))
-     * By.element("input").and(By.attribute("type", "checkbox"));
-     * 
+ * {@snippet class = ByDemo region = and} */ public final By and(By selector) { return combinator(Combinator.AND, selector); diff --git a/src/main/java/org/jboss/elemento/ElementBuilder.java b/src/main/java/org/jboss/elemento/ElementBuilder.java index ec8b9e130..99ebc1918 100644 --- a/src/main/java/org/jboss/elemento/ElementBuilder.java +++ b/src/main/java/org/jboss/elemento/ElementBuilder.java @@ -106,6 +106,18 @@ public B style(String style) { return that(); } + /** Sets the specified attribute of the element. */ + public B attr(String name, boolean value) { + element().setAttribute(name, value); + return that(); + } + + /** Sets the specified attribute of the element. */ + public B attr(String name, int value) { + element().setAttribute(name, value); + return that(); + } + /** Sets the specified attribute of the element. */ public B attr(String name, String value) { element().setAttribute(name, value); @@ -123,6 +135,28 @@ public B data(String name, String value) { return that(); } + /** + * Adds an {@code aria-} attribute to the element. + * + * @param name The name of the aria attribute w/o the {@code aria-} prefix. However it won't be added if it's already + * present. + */ + public B aria(String name, boolean value) { + String safeName = name.startsWith("aria-") ? name : "aria-" + name; + return attr(safeName, value); + } + + /** + * Adds an {@code aria-} attribute to the element. + * + * @param name The name of the aria attribute w/o the {@code aria-} prefix. However it won't be added if it's already + * present. + */ + public B aria(String name, int value) { + String safeName = name.startsWith("aria-") ? name : "aria-" + name; + return attr(safeName, value); + } + /** * Adds an {@code aria-} attribute to the element. * @@ -148,7 +182,11 @@ public B hidden(boolean hidden) { // ------------------------------------------------------ event handler - /** Adds the given callback to the element. */ + /** + * Adds the given callback to the element. + *

+ * {@snippet class = ElementsDemo region = on} + */ public B on(EventType type, EventCallbackFn callback) { bind(element(), type, callback); return that(); @@ -156,7 +194,11 @@ public B on(EventType type, EventCallbackFn callback) // ------------------------------------------------------ finder methods - /** Finds all HTML elements for the given selector. */ + /** + * Finds all HTML elements for the given selector. + *

+ * {@snippet class = ElementsDemo region = findAll} + */ public Iterable findAll(By selector) { return Elements.findAll(element(), selector); } diff --git a/src/main/java/org/jboss/elemento/Elements.java b/src/main/java/org/jboss/elemento/Elements.java index 18a4b138f..c80f5bf3b 100644 --- a/src/main/java/org/jboss/elemento/Elements.java +++ b/src/main/java/org/jboss/elemento/Elements.java @@ -87,11 +87,14 @@ import static jsinterop.base.Js.cast; /** - * Helper methods for working with {@link elemental2.dom.HTMLElement}s and/or {@link IsElement}. + * Builder and helper methods for working with {@link elemental2.dom.HTMLElement}s and/or {@link IsElement}. + *

+ * {@snippet class = ElementsDemo region = builder} * * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element */ +@SuppressWarnings({ "unused", "ConfusingMainMethod" }) public final class Elements { static ElementCreator createElement = new ElementCreator() { @@ -926,7 +929,11 @@ public static TextContentBuilder textarea(Element element) // ------------------------------------------------------ builder factories - /** Returns a builder to collect {@link HTMLElement}s. */ + /** + * Returns a builder to collect {@link HTMLElement}s. + *

+ * {@snippet class = ElementsBagDemo region = bag} + */ public static ElementsBag bag() { return new ElementsBag(); } @@ -1006,12 +1013,22 @@ public static F find(IsElement return find(element.element(), selector); } - /** Finds the closest HTML elements for the given selector. */ + /** + * Finds the closest HTML elements for the given selector. + * + * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/closest + */ public static E closest(Element element, By selector) { return cast(element.closest(selector.selector())); } - /** Finds the closest HTML elements for the given selector. */ + /** + * Finds the closest HTML elements for the given selector. + * + * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/closest + */ public static F closest(IsElement element, By selector) { return cast(element.element().closest(selector.selector())); } @@ -1092,7 +1109,11 @@ public static Function asHtmlElement() { // ------------------------------------------------------ stream methods - /** Returns a stream for the elements in the given array-like. */ + /** + * Returns a stream for the elements in the given array-like. + *

+ * {@snippet class = ElementsDemo region = stream} + */ public static Stream stream(JsArrayLike nodes) { if (nodes == null) { return Stream.empty(); @@ -1101,7 +1122,11 @@ public static Stream stream(JsArrayLike nodes) { } } - /** Returns a stream for the child nodes of the given parent node. */ + /** + * Returns a stream for the child nodes of the given parent node. + *

+ * {@snippet class = ElementsDemo region = stream} + */ public static Stream stream(Node parent) { if (parent == null) { return Stream.empty(); @@ -1110,7 +1135,11 @@ public static Stream stream(Node parent) { } } - /** Returns a stream for the child elements of the given parent element. */ + /** + * Returns a stream for the child elements of the given parent element. + *

+ * {@snippet class = ElementsDemo region = stream} + */ public static Stream stream(HTMLElement parent) { if (parent == null) { return Stream.empty(); @@ -1119,7 +1148,11 @@ public static Stream stream(HTMLElement parent) { } } - /** Returns a stream for the child elements of the given parent element. */ + /** + * Returns a stream for the child elements of the given parent element. + *

+ * {@snippet class = ElementsDemo region = stream} + */ public static Stream stream(IsElement parent) { if (parent == null) { return Stream.empty(); @@ -1140,6 +1173,10 @@ public static void lazyAppend(Element parent, Element child) { } } + /** + * Appends element {@code child} to element {@code parent} if not already present. If parent already contains child, this + * method does nothing. + */ public static void lazyAppend(Element parent, IsElement child) { if (child != null) { lazyAppend(parent, child.element()); @@ -1151,6 +1188,7 @@ public static void insertAfter(Element newElement, Element after) { after.parentNode.insertBefore(newElement, after.nextSibling); } + /** Inserts element {@code newElement} into the parent after element {@code after}. */ public static void insertAfter(IsElement newElement, Element after) { if (newElement != null) { insertAfter(newElement.element(), after); @@ -1167,6 +1205,10 @@ public static void lazyInsertAfter(Element newElement, Element after) { } } + /** + * Inserts element {@code newElement} into the parent after element {@code after} if not already present. If parent already + * contains {@code newElement}, this method does nothing. + */ public static void lazyInsertAfter(IsElement newElement, Element after) { if (newElement != null) { lazyInsertAfter(newElement.element(), after); @@ -1183,6 +1225,10 @@ public static void lazyInsertAfter(Element parent, Element newElement, Element a } } + /** + * Inserts element {@code newElement} into the parent after element {@code after} if not already present. If parent already + * contains {@code newElement}, this method does nothing. + */ public static void lazyInsertAfter(Element parent, IsElement newElement, Element after) { if (newElement != null) { lazyInsertAfter(parent, newElement.element(), after); @@ -1194,6 +1240,7 @@ public static void insertBefore(Element newElement, Element before) { before.parentNode.insertBefore(newElement, before); } + /** Inserts element {@code newElement} into the parent before element {@code before}. */ public static void insertBefore(IsElement newElement, Element before) { if (newElement != null) { insertBefore(newElement.element(), before); @@ -1210,6 +1257,10 @@ public static void lazyInsertBefore(Element newElement, Element before) { } } + /** + * Inserts element {@code newElement} into the parent before element {@code before} if not already present. If parent + * already contains {@code newElement}, this method does nothing. + */ public static void lazyInsertBefore(IsElement newElement, Element before) { if (newElement != null) { lazyInsertBefore(newElement.element(), before); @@ -1226,6 +1277,10 @@ public static void lazyInsertBefore(Element parent, Element newElement, Element } } + /** + * Inserts element {@code newElement} into the parent before element {@code before} if not already present. If parent + * already contains {@code newElement}, this method does nothing. + */ public static void lazyInsertBefore(Element parent, IsElement newElement, Element before) { if (newElement != null) { lazyInsertBefore(parent, newElement.element(), before); @@ -1237,6 +1292,7 @@ public static void insertFirst(Element parent, Element newElement) { parent.insertBefore(newElement, parent.firstChild); } + /** Inserts element {@code newElement} as first element into {@code parent}. */ public static void insertFirst(Element parent, IsElement newElement) { if (newElement != null) { insertFirst(parent, newElement.element()); @@ -1252,6 +1308,7 @@ public static void removeChildrenFrom(Element element) { } } + /** Removes all child elements from {@code element} */ public static void removeChildrenFrom(IsElement element) { if (element != null) { removeChildrenFrom(element.element()); @@ -1261,12 +1318,17 @@ public static void removeChildrenFrom(IsElement eleme /** * Removes the element from its parent if the element is not null and has a parent. * - * @return {@code true} if the the element has been removed from its parent, {@code false} otherwise. + * @return {@code true} if the element has been removed from its parent, {@code false} otherwise. */ public static boolean failSafeRemoveFromParent(Element element) { return failSafeRemove(element != null ? element.parentNode : null, element); } + /** + * Removes the element from its parent if the element is not null and has a parent. + * + * @return {@code true} if the element has been removed from its parent, {@code false} otherwise. + */ public static boolean failSafeRemoveFromParent(IsElement element) { if (element != null) { return failSafeRemoveFromParent(element.element()); @@ -1286,6 +1348,11 @@ public static boolean failSafeRemove(Node parent, Element child) { return false; } + /** + * Removes the child from parent if both parent and child are not null and parent contains child. + * + * @return {@code true} if the element has been removed from its parent, {@code false} otherwise. + */ public static boolean failSafeRemove(Node parent, IsElement child) { if (child != null) { return failSafeRemove(parent, child.element()); @@ -1308,6 +1375,13 @@ public static void onAttach(HTMLElement element, ObserverCallback callback) { } } + /** + * Registers a callback when an element is appended to the document body. Note that the callback will be called only once, + * if the element is appended more than once a new callback should be registered. + * + * @param element the element which is going to be added to the body + * @param callback {@link ObserverCallback} + */ public static void onAttach(IsElement element, ObserverCallback callback) { if (element != null) { onAttach(element.element(), callback); @@ -1327,6 +1401,13 @@ public static void onDetach(HTMLElement element, ObserverCallback callback) { } } + /** + * Registers a callback when an element is removed from the document body. Note that the callback will be called only once, + * if the element is removed and re-appended a new callback should be registered. + * + * @param element the element which is going to be removed from the body + * @param callback {@link ObserverCallback} + */ public static void onDetach(IsElement element, ObserverCallback callback) { if (element != null) { onDetach(element.element(), callback); @@ -1340,6 +1421,7 @@ public static boolean isVisible(HTMLElement element) { return element != null && !"none".equals(element.style.display); } + /** Checks whether the given element is visible (i.e. {@code display} is not {@code none}) */ public static boolean isVisible(IsElement element) { return element != null && isVisible(element.element()); } @@ -1351,6 +1433,7 @@ public static void setVisible(HTMLElement element, boolean visible) { } } + /** Shows / hide the specified element by modifying the {@code display} property. */ public static void setVisible(IsElement element, boolean visible) { if (element != null) { setVisible(element.element(), visible); @@ -1366,6 +1449,7 @@ public static void toggle(HTMLElement element, String css, boolean condition) { } } + /** Adds the specified CSS class to the element if {@code condition} is {@code true}, removes it otherwise. */ public static void toggle(IsElement element, String css, boolean condition) { if (element != null) { toggle(element.element(), css, condition); @@ -1379,6 +1463,7 @@ public static void toggle(HTMLElement element, String css, Supplier con } } + /** Adds the specified CSS class to the element if {@code condition} is {@code true}, removes it otherwise. */ public static void toggle(IsElement element, String css, Supplier condition) { if (element != null) { element.element().classList.toggle(css, condition.get()); @@ -1394,6 +1479,7 @@ public static void innerHtml(HTMLElement element, SafeHtml html) { } } + /** Convenience method to set the inner HTML of the given element. */ public static void innerHtml(IsElement element, SafeHtml html) { if (element != null) { innerHtml(element.element(), html); @@ -1469,7 +1555,9 @@ public T next() { private static class JsArrayNodeIterator implements Iterator { - private Node parent, last, next; + private final Node parent; + private Node last; + private Node next; public JsArrayNodeIterator(Node parent) { this.parent = parent; @@ -1505,7 +1593,9 @@ public void remove() { // cast is forced, not sure about the implication bc not sure what elements can be Element and no HTMLElement private static class JsArrayElementIterator implements Iterator { - private HTMLElement parent, last, next; + private final HTMLElement parent; + private HTMLElement last; + private HTMLElement next; public JsArrayElementIterator(HTMLElement parent) { this.parent = parent; diff --git a/src/main/java/org/jboss/elemento/ElementsBag.java b/src/main/java/org/jboss/elemento/ElementsBag.java index c7959a55d..9c9823995 100644 --- a/src/main/java/org/jboss/elemento/ElementsBag.java +++ b/src/main/java/org/jboss/elemento/ElementsBag.java @@ -20,7 +20,11 @@ import elemental2.core.JsArray; import elemental2.dom.HTMLElement; -/** Class to collect {@link HTMLElement}s */ +/** + * Class to collect {@link HTMLElement}s + *

+ * {@snippet class = ElementsBagDemo region = bag} + */ public class ElementsBag implements TypedBuilder, ElementsBag> { private final IterableImpl iterable; diff --git a/src/main/java/org/jboss/elemento/EventType.java b/src/main/java/org/jboss/elemento/EventType.java index 5bfdb67dc..4317e8981 100644 --- a/src/main/java/org/jboss/elemento/EventType.java +++ b/src/main/java/org/jboss/elemento/EventType.java @@ -42,7 +42,8 @@ /** * Known event types used in {@link ElementBuilder#on(EventType, EventCallbackFn)}. * - * @see https://developer.mozilla.org/en-US/docs/Web/Events + * @see https://developer.mozilla.org/en-US/docs/Web/Events */ public class EventType { @@ -146,48 +147,85 @@ public static EventType of(String // ------------------------------------------------------ binding methods - /** Registers an event handler. */ + /** + * Registers an event handler. + *

+ * {@snippet class = EventDemo region = bind} + */ public static HandlerRegistration bind(EventTarget target, EventType type, EventCallbackFn listener) { return bind(target, type.name, e -> listener.onEvent(Js.cast(e))); } - /** Registers an event handler. */ + /** + * Registers an event handler. + *

+ * {@snippet class = EventDemo region = bind} + */ public static HandlerRegistration bind(EventTarget target, String type, EventListener listener) { target.addEventListener(type, listener); return () -> target.removeEventListener(type, listener); } - /** Registers an event handler. */ - public static HandlerRegistration bind(EventTarget target, EventType type, boolean useCapture, + /** + * Registers an event handler. + *

+ * {@snippet class = EventDemo region = bind} + */ + public static HandlerRegistration bind(EventTarget target, EventType type, + boolean useCapture, EventCallbackFn listener) { return bind(target, type.name, useCapture, e -> listener.onEvent(Js.cast(e))); } - /** Registers an event handler. */ - public static HandlerRegistration bind(EventTarget target, String type, boolean useCapture, EventListener listener) { + /** + * Registers an event handler. + *

+ * {@snippet class = EventDemo region = bind} + */ + public static HandlerRegistration bind(EventTarget target, String type, boolean useCapture, + EventListener listener) { target.addEventListener(type, listener, useCapture); return () -> target.removeEventListener(type, listener, useCapture); } - /** Registers an event handler. */ - public static HandlerRegistration bind(IsElement target, EventType type, + /** + * Registers an event handler. + *

+ * {@snippet class = EventDemo region = bind} + */ + public static HandlerRegistration bind(IsElement target, + EventType type, EventCallbackFn listener) { return bind(target.element(), type, listener); } - /** Registers an event handler. */ - public static HandlerRegistration bind(IsElement target, String type, EventListener listener) { + /** + * Registers an event handler. + *

+ * {@snippet class = EventDemo region = bind} + */ + public static HandlerRegistration bind(IsElement target, String type, + EventListener listener) { return bind(target.element(), type, listener); } - /** Registers an event handler. */ - public static HandlerRegistration bind(IsElement target, EventType type, + /** + * Registers an event handler. + *

+ * {@snippet class = EventDemo region = bind} + */ + public static HandlerRegistration bind(IsElement target, + EventType type, boolean useCapture, EventCallbackFn listener) { return bind(target.element(), type, useCapture, listener); } - /** Registers an event handler. */ + /** + * Registers an event handler. + *

+ * {@snippet class = EventDemo region = bind} + */ public static HandlerRegistration bind(IsElement target, String type, boolean useCapture, EventListener listener) { return bind(target.element(), type, useCapture, listener); diff --git a/src/main/java/org/jboss/elemento/HtmlContent.java b/src/main/java/org/jboss/elemento/HtmlContent.java index 062516c0e..1147ea31b 100644 --- a/src/main/java/org/jboss/elemento/HtmlContent.java +++ b/src/main/java/org/jboss/elemento/HtmlContent.java @@ -21,7 +21,11 @@ import elemental2.dom.HTMLElement; import elemental2.dom.Node; -/** Builder for container-like elements with inner HTML. */ +/** + * Builder for container-like elements with inner HTML. + *

+ * {@snippet class = HtmlContentDemo region = addAll} + */ public interface HtmlContent> extends TextContent { /** Modifies the inner HTML on the element using {@link HTMLElement#innerHTML}. */ diff --git a/src/main/java/org/jboss/elemento/IsElement.java b/src/main/java/org/jboss/elemento/IsElement.java index 25aa39226..48148e96c 100644 --- a/src/main/java/org/jboss/elemento/IsElement.java +++ b/src/main/java/org/jboss/elemento/IsElement.java @@ -17,7 +17,11 @@ import elemental2.dom.HTMLElement; -/** Interface for custom components returning a single element. */ +/** + * Interface for custom components returning a single element. + *

+ * {@snippet class = TodoElement region = isElement} + */ public interface IsElement { /** @return the element of the custom component */ diff --git a/src/main/java/org/jboss/elemento/Key.java b/src/main/java/org/jboss/elemento/Key.java index ab4cdae59..073a40a55 100644 --- a/src/main/java/org/jboss/elemento/Key.java +++ b/src/main/java/org/jboss/elemento/Key.java @@ -24,77 +24,101 @@ /** * Selected key values according to * https://www.w3.org/TR/DOM-Level-3-Events-key/. + *

+ * {@snippet class = KeyDemo region = key} * * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values */ public enum Key { - Accept("Accept"), Again("Again"), Alt("Alt"), AltGraph("AltGraph"), ArrowDown("ArrowDown", - new String[] { "Down" }), ArrowLeft("ArrowLeft", new String[] { "Left" }), ArrowRight("ArrowRight", new String[] { - "Right" }), ArrowUp("ArrowUp", new String[] { "Up" }), Attn("Attn"), Backspace("Backspace"), BrightnessDown( - "BrightnessDown"), BrightnessUp("BrightnessUp"), Cancel("Cancel"), CapsLock("CapsLock"), Clear( - "Clear"), ContextMenu("ContextMenu", new String[] { "Apps" }), Control("Control"), Copy( - "Copy"), CrSel("CrSel", new String[] { "Crsel" }), Cut("Cut"), Delete("Delete", - new String[] { "Del" }), Eject("Eject"), End("End"), Enter( - "Enter"), EraseEof("EraseEof"), Escape("Escape", - new String[] { "Esc" }), Execute("Execute"), ExSel("ExSel", - new String[] { "Exsel" }), F1("F1"), F10( - "F10"), F11("F11"), F13("F13"), F14( - "F14"), F15("F15"), F16("F16"), F17( - "F17"), F18("F18"), F19( - "F19"), F2( - "F2"), F20( - "F20"), F3( - "F3"), F4( - "F4"), F5( - "F5"), F6( - "F6"), F7( - "F7"), F8( - "F8"), F9( - "F9"), Find( - "Find"), Finish( - "Finish"), Fn( - "Fn"), FnLock( - "FnLock"), Help( - "Help"), Hibernate( - "Hibernate"), Home( - "Home"), Insert( - "Insert"), LogOff( - "LogOff"), Meta( - "Meta"), NumLock( - "NumLock"), PageDown( - "PageDown"), PageUp( - "PageUp"), Paste( - "Paste"), Pause( - "Pause"), Play( - "Play"), Power( - "Power"), PowerOff( - "PowerOff"), PrintScreen( - "PrintScreen"), Props( - "Props"), Redo( - "Redo"), ScrollLock( - "ScrollLock", - new String[] { - "Scroll" }), Select( - "Select"), Shift( - "Shift"), Soft1( - "Soft1"), Soft2( - "Soft2"), Soft3( - "Soft3"), Soft4( - "Soft4"), Spacebar( - " ", - new String[] { - "Spacebar" }), Standby( - "Standby"), Symbol( - "Symbol"), SymbolLock( - "SymbolLock"), Tab( - "Tab"), Undo( - "Undo"), Unidentified( - ""), WakeUp( - "WakeUp"), ZoomIn( - "ZoomIn"), ZoomOut( - "ZoomOut"); + // @formatter:off + Accept("Accept"), + Again("Again"), + Alt("Alt"), + AltGraph("AltGraph"), + ArrowDown("ArrowDown", new String[]{"Down"}), + ArrowLeft("ArrowLeft", new String[]{"Left"}), + ArrowRight("ArrowRight", new String[]{"Right"}), + ArrowUp("ArrowUp", new String[]{"Up"}), + Attn("Attn"), + Backspace("Backspace"), + BrightnessDown("BrightnessDown"), + BrightnessUp("BrightnessUp"), + Cancel("Cancel"), + CapsLock("CapsLock"), + Clear("Clear"), + ContextMenu("ContextMenu", new String[]{"Apps"}), + Control("Control"), + Copy("Copy"), + CrSel("CrSel", new String[]{"Crsel"}), + Cut("Cut"), + Delete("Delete", new String[]{"Del"}), + Eject("Eject"), + End("End"), + Enter("Enter"), + EraseEof("EraseEof"), + Escape("Escape", new String[]{"Esc"}), + Execute("Execute"), + ExSel("ExSel", new String[]{"Exsel"}), + F1("F1"), + F10("F10"), + F11("F11"), + F13("F13"), + F14("F14"), + F15("F15"), + F16("F16"), + F17("F17"), + F18("F18"), + F19("F19"), + F2("F2"), + F20("F20"), + F3("F3"), + F4("F4"), + F5("F5"), + F6("F6"), + F7("F7"), + F8("F8"), + F9("F9"), + Find("Find"), + Finish("Finish"), + Fn("Fn"), + FnLock("FnLock"), + Help("Help"), + Hibernate("Hibernate"), + Home("Home"), + Insert("Insert"), + LogOff("LogOff"), + Meta("Meta"), + NumLock("NumLock"), + PageDown("PageDown"), + PageUp("PageUp"), + Paste("Paste"), + Pause("Pause"), + Play("Play"), + Power("Power"), + PowerOff("PowerOff"), + PrintScreen("PrintScreen"), + Props("Props"), + Redo("Redo"), + ScrollLock("ScrollLock", new String[]{"Scroll"}), + Select("Select"), + Shift("Shift"), + Soft1("Soft1"), + Soft2("Soft2"), + Soft3("Soft3"), + Soft4("Soft4"), + Spacebar(" ", new String[]{"Spacebar"}), + Standby("Standby"), + Symbol("Symbol"), + SymbolLock("SymbolLock"), + Tab("Tab"), + Undo("Undo"), + Unidentified(""), + WakeUp("WakeUp"), + ZoomIn("ZoomIn"), + ZoomOut("ZoomOut"); + // @formatter:off private static Map keys = new HashMap<>();