From 53cd861563ef5c77d0432776297cd54086517b3e Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Fri, 16 Oct 2015 15:55:24 +0300 Subject: [PATCH] Add JS API wrappers --- .../org/teavm/jso/ajax/XMLHttpRequest.java | 8 ++ .../java/org/teavm/jso/browser/History.java | 45 ++++++++ .../java/org/teavm/jso/browser/Location.java | 84 ++++++++++++++ .../Navigator.java} | 14 ++- .../java/org/teavm/jso/browser/Window.java | 97 +++++++++++++++- .../teavm/jso/browser/WindowEventTarget.java | 48 ++++++++ .../org/teavm/jso/browser/WindowFeatures.java | 75 ++++++++++++ .../main/java/org/teavm/jso/core/JSArray.java | 9 ++ .../jso/dom/events/FocusEventTarget.java | 38 ++++++ .../jso/dom/events/KeyboardEventTarget.java | 46 ++++++++ .../teavm/jso/dom/events/LoadEventTarget.java | 30 +++++ .../teavm/jso/dom/events/MessageEvent.java | 35 ++++++ .../jso/dom/events/MouseEventTarget.java | 86 ++++++++++++++ .../org/teavm/jso/dom/html/HTMLElement.java | 17 ++- .../teavm/jso/dom/html/HTMLIFrameElement.java | 61 ++++++++++ .../teavm/jso/dom/html/HTMLMediaElement.java | 12 ++ .../java/org/teavm/samples/hello/Client.java | 8 +- .../org/teavm/samples/scala/Client.scala | 2 +- .../teavm/samples/storage/Application.java | 18 +-- .../java/org/teavm/samples/video/Player.java | 108 +++++------------- 20 files changed, 730 insertions(+), 111 deletions(-) create mode 100644 jso/apis/src/main/java/org/teavm/jso/browser/History.java create mode 100644 jso/apis/src/main/java/org/teavm/jso/browser/Location.java rename jso/apis/src/main/java/org/teavm/jso/{dom/events/DocumentEvent.java => browser/Navigator.java} (69%) create mode 100644 jso/apis/src/main/java/org/teavm/jso/browser/WindowEventTarget.java create mode 100644 jso/apis/src/main/java/org/teavm/jso/browser/WindowFeatures.java create mode 100644 jso/apis/src/main/java/org/teavm/jso/dom/events/FocusEventTarget.java create mode 100644 jso/apis/src/main/java/org/teavm/jso/dom/events/KeyboardEventTarget.java create mode 100644 jso/apis/src/main/java/org/teavm/jso/dom/events/LoadEventTarget.java create mode 100644 jso/apis/src/main/java/org/teavm/jso/dom/events/MessageEvent.java create mode 100644 jso/apis/src/main/java/org/teavm/jso/dom/events/MouseEventTarget.java create mode 100644 jso/apis/src/main/java/org/teavm/jso/dom/html/HTMLIFrameElement.java diff --git a/jso/apis/src/main/java/org/teavm/jso/ajax/XMLHttpRequest.java b/jso/apis/src/main/java/org/teavm/jso/ajax/XMLHttpRequest.java index 5ed781fc6..b18b81caa 100644 --- a/jso/apis/src/main/java/org/teavm/jso/ajax/XMLHttpRequest.java +++ b/jso/apis/src/main/java/org/teavm/jso/ajax/XMLHttpRequest.java @@ -56,6 +56,14 @@ public abstract class XMLHttpRequest implements JSObject { @JSProperty("onreadystatechange") public abstract void setOnReadyStateChange(ReadyStateChangeHandler handler); + public final void onComplete(Runnable runnable) { + setOnReadyStateChange(() -> { + if (getReadyState() == DONE) { + runnable.run(); + } + }); + } + public abstract void overrideMimeType(String mimeType); @JSProperty diff --git a/jso/apis/src/main/java/org/teavm/jso/browser/History.java b/jso/apis/src/main/java/org/teavm/jso/browser/History.java new file mode 100644 index 000000000..db3c80994 --- /dev/null +++ b/jso/apis/src/main/java/org/teavm/jso/browser/History.java @@ -0,0 +1,45 @@ +/* + * Copyright 2015 Alexey Andreev. + * + * 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 + * + * http://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.teavm.jso.browser; + +import org.teavm.jso.JSObject; +import org.teavm.jso.JSProperty; + +/** + * + * @author Alexey Andreev + */ +public interface History extends JSObject { + @JSProperty + int getLength(); + + @JSProperty + JSObject getState(); + + void back(); + + void forward(); + + void go(int delta); + + void pushState(JSObject data, String title); + + void pushState(JSObject data, String title, String url); + + void replaceState(JSObject data, String title); + + void replaceState(JSObject data, String title, String url); +} diff --git a/jso/apis/src/main/java/org/teavm/jso/browser/Location.java b/jso/apis/src/main/java/org/teavm/jso/browser/Location.java new file mode 100644 index 000000000..0aa4e17f9 --- /dev/null +++ b/jso/apis/src/main/java/org/teavm/jso/browser/Location.java @@ -0,0 +1,84 @@ +/* + * Copyright 2015 Alexey Andreev. + * + * 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 + * + * http://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.teavm.jso.browser; + +import org.teavm.jso.JSObject; +import org.teavm.jso.JSProperty; + +/** + * + * @author Alexey Andreev + */ +public interface Location extends JSObject { + @JSProperty("href") + String getFullURL(); + + @JSProperty("href") + void setFullURL(String url); + + @JSProperty + String getProtocol(); + + @JSProperty + void setProtocol(String protocol); + + @JSProperty + String getHost(); + + @JSProperty + void setHost(String host); + + @JSProperty("hostname") + String getHostName(); + + @JSProperty("hostname") + void setHostName(String hostName); + + @JSProperty + String getPort(); + + @JSProperty + void setPort(String port); + + @JSProperty("pathname") + String getPathName(); + + @JSProperty("pathname") + void setPathName(String pathName); + + @JSProperty + String getSearch(); + + @JSProperty + void setSearch(String search); + + @JSProperty + String getHash(); + + void setHash(String hash); + + void assign(String url); + + void reload(); + + void reload(boolean force); + + void replace(String url); + + static Location current() { + return Window.current().getLocation(); + } +} diff --git a/jso/apis/src/main/java/org/teavm/jso/dom/events/DocumentEvent.java b/jso/apis/src/main/java/org/teavm/jso/browser/Navigator.java similarity index 69% rename from jso/apis/src/main/java/org/teavm/jso/dom/events/DocumentEvent.java rename to jso/apis/src/main/java/org/teavm/jso/browser/Navigator.java index 13ce2a771..5bc5eb91e 100644 --- a/jso/apis/src/main/java/org/teavm/jso/dom/events/DocumentEvent.java +++ b/jso/apis/src/main/java/org/teavm/jso/browser/Navigator.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 Alexey Andreev. + * Copyright 2015 Alexey Andreev. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,14 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.teavm.jso.dom.events; +package org.teavm.jso.browser; -import org.teavm.jso.JSObject; +import org.teavm.jso.JSBody; /** * * @author Alexey Andreev */ -public interface DocumentEvent extends JSObject { - Event createEvent(String eventType); +public final class Navigator { + private Navigator() { + } + + @JSBody(params = "", script = "return window.navigator.onLine;") + public static native boolean isOnline(); } diff --git a/jso/apis/src/main/java/org/teavm/jso/browser/Window.java b/jso/apis/src/main/java/org/teavm/jso/browser/Window.java index edffaeeeb..1309721f9 100644 --- a/jso/apis/src/main/java/org/teavm/jso/browser/Window.java +++ b/jso/apis/src/main/java/org/teavm/jso/browser/Window.java @@ -18,14 +18,17 @@ package org.teavm.jso.browser; import org.teavm.jso.JSBody; import org.teavm.jso.JSObject; import org.teavm.jso.JSProperty; -import org.teavm.jso.dom.events.EventTarget; +import org.teavm.jso.core.JSArray; +import org.teavm.jso.core.JSArrayReader; import org.teavm.jso.dom.html.HTMLDocument; +import org.teavm.jso.dom.html.HTMLElement; +import org.teavm.jso.dom.html.HTMLIFrameElement; /** * * @author Alexey Andreev */ -public abstract class Window implements JSObject, EventTarget, StorageProvider { +public abstract class Window implements JSObject, WindowEventTarget, StorageProvider, JSArrayReader { private Window() { } @@ -35,12 +38,64 @@ public abstract class Window implements JSObject, EventTarget, StorageProvider { @JSProperty public abstract Screen getScreen(); + @JSProperty + public abstract int getScreenX(); + + @JSProperty + public abstract int getScreenY(); + + @JSProperty + public abstract Location getLocation(); + + @JSProperty + public abstract HTMLElement getFrameElement(); + + @JSProperty + public abstract JSArrayReader getFrames(); + + @JSProperty + public abstract int getInnerWidth(); + + @JSProperty + public abstract int getInnerHeight(); + + @JSProperty + public abstract int getOuterWidth(); + + @JSProperty + public abstract int getOuterHeight(); + + @JSProperty + public abstract String getName(); + + @JSProperty + public abstract void setName(String name); + + @JSProperty + public abstract Window getParent(); + + @JSProperty + public abstract Window getTop(); + @JSBody(params = "message", script = "alert(message);") public static native void alert(JSObject message); @JSBody(params = "message", script = "alert(message);") public static native void alert(String message); + @JSBody(params = "message", script = "confirm(message);") + public static native boolean confirm(JSObject message); + + @JSBody(params = "message", script = "confirm(message);") + public static native boolean confirm(String message); + + public static String prompt(String message) { + return prompt(message, ""); + } + + @JSBody(params = { "message", "default" }, script = "prompt(message, default);") + public static native String prompt(String message, String defaultValue); + @JSBody(params = { "handler", "delay" }, script = "return setTimeout(handler, delay);") public static native int setTimeout(TimerHandler handler, int delay); @@ -59,6 +114,44 @@ public abstract class Window implements JSObject, EventTarget, StorageProvider { @JSBody(params = { "timeoutId" }, script = "clearInterval(timeoutId);") public static native void clearInterval(int timeoutId); + public abstract void blur(); + + public abstract void focus(); + + public abstract void close(); + + public abstract void moveBy(int deltaX, int deltaY); + + public abstract void moveTo(int x, int y); + + public abstract void resizeBy(int deltaX, int deltaY); + + public abstract void resizeTo(int x, int y); + + public abstract void scrollBy(int deltaX, int deltaY); + + public abstract void scrollTo(int x, int y); + + public abstract Window open(String url, String name); + + public final Window open(String url, String name, WindowFeatures features) { + return open(url, name, features.sb.toString()); + } + + public abstract Window open(String url, String name, String features); + + public abstract void print(); + + public abstract void stop(); + + public abstract void postMessage(JSObject message, String targetOrigin); + + public abstract void postMessage(JSObject message, String targetOrigin, JSArrayReader transfer); + + public final void postMessage(JSObject message, String targetOrigin, JSObject... transfer) { + postMessage(message, targetOrigin, JSArray.of(transfer)); + } + @JSBody(params = {}, script = "return window;") public static native Window current(); } diff --git a/jso/apis/src/main/java/org/teavm/jso/browser/WindowEventTarget.java b/jso/apis/src/main/java/org/teavm/jso/browser/WindowEventTarget.java new file mode 100644 index 000000000..4bde57aec --- /dev/null +++ b/jso/apis/src/main/java/org/teavm/jso/browser/WindowEventTarget.java @@ -0,0 +1,48 @@ +/* + * Copyright 2015 Alexey Andreev. + * + * 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 + * + * http://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.teavm.jso.browser; + +import org.teavm.jso.dom.events.Event; +import org.teavm.jso.dom.events.EventListener; +import org.teavm.jso.dom.events.EventTarget; +import org.teavm.jso.dom.events.FocusEventTarget; +import org.teavm.jso.dom.events.KeyboardEventTarget; +import org.teavm.jso.dom.events.LoadEventTarget; +import org.teavm.jso.dom.events.MessageEvent; +import org.teavm.jso.dom.events.MouseEventTarget; + +/** + * + * @author Alexey Andreev + */ +public interface WindowEventTarget extends EventTarget, FocusEventTarget, MouseEventTarget, KeyboardEventTarget, + LoadEventTarget { + default void listenBeforeOnload(EventListener listener) { + addEventListener("beforeunload", listener); + } + + default void neglectBeforeOnload(EventListener listener) { + removeEventListener("beforeunload", listener); + } + + default void listenMessage(EventListener listener) { + addEventListener("message", listener); + } + + default void neglectMessage(EventListener listener) { + removeEventListener("message", listener); + } +} diff --git a/jso/apis/src/main/java/org/teavm/jso/browser/WindowFeatures.java b/jso/apis/src/main/java/org/teavm/jso/browser/WindowFeatures.java new file mode 100644 index 000000000..730b2d04e --- /dev/null +++ b/jso/apis/src/main/java/org/teavm/jso/browser/WindowFeatures.java @@ -0,0 +1,75 @@ +/* + * Copyright 2015 Alexey Andreev. + * + * 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 + * + * http://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.teavm.jso.browser; + +/** + * + * @author Alexey Andreev + */ +public class WindowFeatures { + StringBuilder sb = new StringBuilder(); + + public WindowFeatures() { + } + + public WindowFeatures left(int left) { + return add("left=" + left); + } + + public WindowFeatures top(int top) { + return add("top=" + top); + } + + public WindowFeatures width(int width) { + return add("width=" + width); + } + + public WindowFeatures height(int height) { + return add("height=" + height); + } + + public WindowFeatures menubar() { + return add("menubar"); + } + + public WindowFeatures toolbar() { + return add("toolbar"); + } + + public WindowFeatures location() { + return add("location"); + } + + public WindowFeatures status() { + return add("status"); + } + + public WindowFeatures resizable() { + return add("resizable"); + } + + public WindowFeatures scrollbars() { + return add("resizable"); + } + + private WindowFeatures add(String feature) { + if (sb.length() > 0) { + sb.append(','); + } + sb.append(feature); + return this; + } +} diff --git a/jso/apis/src/main/java/org/teavm/jso/core/JSArray.java b/jso/apis/src/main/java/org/teavm/jso/core/JSArray.java index b711d4815..261105093 100644 --- a/jso/apis/src/main/java/org/teavm/jso/core/JSArray.java +++ b/jso/apis/src/main/java/org/teavm/jso/core/JSArray.java @@ -88,4 +88,13 @@ public abstract class JSArray implements JSArrayReader { @JSBody(params = "size", script = "return new Array(size);") public static native JSArray create(int size); + + @SafeVarargs + public static JSArray of(S... items) { + JSArray array = create(items.length); + for (int i = 0; i < items.length; ++i) { + array.set(i, items[i]); + } + return array; + } } diff --git a/jso/apis/src/main/java/org/teavm/jso/dom/events/FocusEventTarget.java b/jso/apis/src/main/java/org/teavm/jso/dom/events/FocusEventTarget.java new file mode 100644 index 000000000..93d2655a2 --- /dev/null +++ b/jso/apis/src/main/java/org/teavm/jso/dom/events/FocusEventTarget.java @@ -0,0 +1,38 @@ +/* + * Copyright 2015 Alexey Andreev. + * + * 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 + * + * http://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.teavm.jso.dom.events; + +/** + * + * @author Alexey Andreev + */ +public interface FocusEventTarget extends EventTarget { + default void listenFocus(EventListener listener) { + addEventListener("focus", listener); + } + + default void neglectFocus(EventListener listener) { + removeEventListener("focus", listener); + } + + default void listenBlur(EventListener listener) { + addEventListener("blur", listener); + } + + default void neglectBlur(EventListener listener) { + removeEventListener("blur", listener); + } +} diff --git a/jso/apis/src/main/java/org/teavm/jso/dom/events/KeyboardEventTarget.java b/jso/apis/src/main/java/org/teavm/jso/dom/events/KeyboardEventTarget.java new file mode 100644 index 000000000..94ea3e087 --- /dev/null +++ b/jso/apis/src/main/java/org/teavm/jso/dom/events/KeyboardEventTarget.java @@ -0,0 +1,46 @@ +/* + * Copyright 2015 Alexey Andreev. + * + * 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 + * + * http://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.teavm.jso.dom.events; + +/** + * + * @author Alexey Andreev + */ +public interface KeyboardEventTarget extends EventTarget { + default void listenKeyDown(EventListener listener) { + addEventListener("keydown", listener); + } + + default void neglectKeyDown(EventListener listener) { + removeEventListener("keydown", listener); + } + + default void listenKeyUp(EventListener listener) { + addEventListener("keyup", listener); + } + + default void neglectKeyUp(EventListener listener) { + removeEventListener("keyup", listener); + } + + default void listenKeyPress(EventListener listener) { + addEventListener("keypress", listener); + } + + default void neglectKeyPress(EventListener listener) { + removeEventListener("keypress", listener); + } +} diff --git a/jso/apis/src/main/java/org/teavm/jso/dom/events/LoadEventTarget.java b/jso/apis/src/main/java/org/teavm/jso/dom/events/LoadEventTarget.java new file mode 100644 index 000000000..9885b63f0 --- /dev/null +++ b/jso/apis/src/main/java/org/teavm/jso/dom/events/LoadEventTarget.java @@ -0,0 +1,30 @@ +/* + * Copyright 2015 Alexey Andreev. + * + * 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 + * + * http://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.teavm.jso.dom.events; + +/** + * + * @author Alexey Andreev + */ +public interface LoadEventTarget extends EventTarget { + default void listenLoad(EventListener listener) { + addEventListener("load", listener); + } + + default void neglectLoad(EventListener listener) { + addEventListener("load", listener); + } +} diff --git a/jso/apis/src/main/java/org/teavm/jso/dom/events/MessageEvent.java b/jso/apis/src/main/java/org/teavm/jso/dom/events/MessageEvent.java new file mode 100644 index 000000000..42a1b3d33 --- /dev/null +++ b/jso/apis/src/main/java/org/teavm/jso/dom/events/MessageEvent.java @@ -0,0 +1,35 @@ +/* + * Copyright 2015 Alexey Andreev. + * + * 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 + * + * http://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.teavm.jso.dom.events; + +import org.teavm.jso.JSObject; +import org.teavm.jso.JSProperty; +import org.teavm.jso.typedarrays.ArrayBuffer; + +/** + * + * @author Alexey Andreev + */ +public interface MessageEvent extends Event { + @JSProperty + JSObject getData(); + + @JSProperty("data") + String getDataAsString(); + + @JSProperty("data") + ArrayBuffer getDataAsArray(); +} diff --git a/jso/apis/src/main/java/org/teavm/jso/dom/events/MouseEventTarget.java b/jso/apis/src/main/java/org/teavm/jso/dom/events/MouseEventTarget.java new file mode 100644 index 000000000..2df745177 --- /dev/null +++ b/jso/apis/src/main/java/org/teavm/jso/dom/events/MouseEventTarget.java @@ -0,0 +1,86 @@ +/* + * Copyright 2015 Alexey Andreev. + * + * 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 + * + * http://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.teavm.jso.dom.events; + +/** + * + * @author Alexey Andreev + */ +public interface MouseEventTarget extends EventTarget { + default void listenClick(EventListener listener) { + addEventListener("click", listener); + } + + default void neglectClick(EventListener listener) { + removeEventListener("click", listener); + } + + default void listenDoubleClick(EventListener listener) { + addEventListener("dblclick", listener); + } + + default void neglectDoubleClick(EventListener listener) { + removeEventListener("dblclick", listener); + } + + default void listenMouseDown(EventListener listener) { + addEventListener("mousedown", listener); + } + + default void neglectMouseDown(EventListener listener) { + removeEventListener("mousedown", listener); + } + + default void listenMouseUp(EventListener listener) { + addEventListener("mouseup", listener); + } + + default void neglectMouseUp(EventListener listener) { + removeEventListener("mouseup", listener); + } + + default void listenMouseOver(EventListener listener) { + addEventListener("mouseover", listener); + } + + default void neglectMouseOver(EventListener listener) { + removeEventListener("mouseover", listener); + } + + default void listenMouseEnter(EventListener listener) { + addEventListener("mouseenter", listener); + } + + default void neglectMouseEnter(EventListener listener) { + removeEventListener("mouseenter", listener); + } + + default void listenMouseLeaeve(EventListener listener) { + addEventListener("mouseleave", listener); + } + + default void neglectMouseLeave(EventListener listener) { + removeEventListener("mouseleave", listener); + } + + default void listenMouseOut(EventListener listener) { + addEventListener("mouseout", listener); + } + + default void neglectMouseOut(EventListener listener) { + removeEventListener("mouseout", listener); + } +} diff --git a/jso/apis/src/main/java/org/teavm/jso/dom/html/HTMLElement.java b/jso/apis/src/main/java/org/teavm/jso/dom/html/HTMLElement.java index 812ceae93..1f4e13684 100644 --- a/jso/apis/src/main/java/org/teavm/jso/dom/html/HTMLElement.java +++ b/jso/apis/src/main/java/org/teavm/jso/dom/html/HTMLElement.java @@ -19,14 +19,20 @@ import java.util.function.Consumer; import org.teavm.jso.JSProperty; import org.teavm.jso.dom.css.ElementCSSInlineStyle; import org.teavm.jso.dom.events.EventTarget; +import org.teavm.jso.dom.events.FocusEventTarget; +import org.teavm.jso.dom.events.KeyboardEventTarget; +import org.teavm.jso.dom.events.LoadEventTarget; +import org.teavm.jso.dom.events.MouseEventTarget; import org.teavm.jso.dom.xml.Element; +import org.teavm.jso.dom.xml.Node; import org.teavm.jso.dom.xml.NodeList; /** * * @author Alexey Andreev */ -public interface HTMLElement extends Element, ElementCSSInlineStyle, EventTarget { +public interface HTMLElement extends Element, ElementCSSInlineStyle, EventTarget, FocusEventTarget, MouseEventTarget, + KeyboardEventTarget, LoadEventTarget { @Override @JSProperty NodeList getElementsByTagName(String name); @@ -120,14 +126,19 @@ public interface HTMLElement extends Element, ElementCSSInlineStyle, EventTarget default HTMLElement withChild(String tagName) { HTMLElement result = getOwnerDocument().createElement(tagName); appendChild(result); - return result; + return this; + } + + default HTMLElement withChild(Node node) { + appendChild(node); + return this; } default HTMLElement withChild(String tagName, Consumer consumer) { HTMLElement result = getOwnerDocument().createElement(tagName); appendChild(result); consumer.accept(result); - return result; + return this; } default HTMLElement clear() { diff --git a/jso/apis/src/main/java/org/teavm/jso/dom/html/HTMLIFrameElement.java b/jso/apis/src/main/java/org/teavm/jso/dom/html/HTMLIFrameElement.java new file mode 100644 index 000000000..a5ce18272 --- /dev/null +++ b/jso/apis/src/main/java/org/teavm/jso/dom/html/HTMLIFrameElement.java @@ -0,0 +1,61 @@ +/* + * Copyright 2015 Alexey Andreev. + * + * 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 + * + * http://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.teavm.jso.dom.html; + +import org.teavm.jso.JSProperty; +import org.teavm.jso.browser.Window; + +/** + * + * @author Alexey Andreev + */ +public interface HTMLIFrameElement extends HTMLElement { + @JSProperty + HTMLDocument getContentDocument(); + + @JSProperty + Window getContentWindow(); + + @JSProperty + String getWidth(); + + @JSProperty + void setWidth(String width); + + @JSProperty + String getHeight(); + + @JSProperty + void setHeight(String height); + + @JSProperty + String getName(); + + @JSProperty + void setName(String name); + + @JSProperty("src") + String getSourceAddress(); + + @JSProperty("src") + void setSourceAddress(String src); + + @JSProperty("srcdoc") + String getSourceDocument(); + + @JSProperty("srcdoc") + void setSourceDocument(String srcdoc); +} diff --git a/jso/apis/src/main/java/org/teavm/jso/dom/html/HTMLMediaElement.java b/jso/apis/src/main/java/org/teavm/jso/dom/html/HTMLMediaElement.java index a1ba21be1..542d24651 100644 --- a/jso/apis/src/main/java/org/teavm/jso/dom/html/HTMLMediaElement.java +++ b/jso/apis/src/main/java/org/teavm/jso/dom/html/HTMLMediaElement.java @@ -83,6 +83,10 @@ public interface HTMLMediaElement extends HTMLElement { @JSProperty void setCurrentTime(double currentTime); + default void addCurrentTime(double delta) { + setCurrentTime(getCurrentTime() + delta); + } + @JSProperty double getDuration(); @@ -104,6 +108,10 @@ public interface HTMLMediaElement extends HTMLElement { @JSProperty void setPlaybackRate(double playbackRate); + default void addPlaybackRate(double delta) { + setPlaybackRate(getPlaybackRate() + delta); + } + @JSProperty TimeRanges getPlayed(); @@ -149,6 +157,10 @@ public interface HTMLMediaElement extends HTMLElement { @JSProperty void setVolume(float volume); + default void addVolume(float delta) { + setVolume(getVolume() + delta); + } + @JSProperty boolean isMuted(); diff --git a/samples/hello/src/main/java/org/teavm/samples/hello/Client.java b/samples/hello/src/main/java/org/teavm/samples/hello/Client.java index ff4deb1f6..0b5a0b263 100644 --- a/samples/hello/src/main/java/org/teavm/samples/hello/Client.java +++ b/samples/hello/src/main/java/org/teavm/samples/hello/Client.java @@ -31,18 +31,14 @@ public final class Client { } public static void main(String[] args) { - helloButton.addEventListener("click", evt -> sayHello()); + helloButton.listenClick(evt -> sayHello()); } private static void sayHello() { helloButton.setDisabled(true); thinkingPanel.getStyle().setProperty("display", ""); XMLHttpRequest xhr = XMLHttpRequest.create(); - xhr.setOnReadyStateChange(() -> { - if (xhr.getReadyState() == XMLHttpRequest.DONE) { - receiveResponse(xhr.getResponseText()); - } - }); + xhr.onComplete(() -> receiveResponse(xhr.getResponseText())); xhr.open("GET", "hello"); xhr.send(); } diff --git a/samples/scala/src/main/scala/org/teavm/samples/scala/Client.scala b/samples/scala/src/main/scala/org/teavm/samples/scala/Client.scala index 3c7bd63a1..66c0f6aef 100644 --- a/samples/scala/src/main/scala/org/teavm/samples/scala/Client.scala +++ b/samples/scala/src/main/scala/org/teavm/samples/scala/Client.scala @@ -14,7 +14,7 @@ object Client { var exprElem = doc.getElementById("expr").asInstanceOf[HTMLInputElement] var calcElem = doc.getElementById("calculate") var resultList = doc.getElementById("result-list"); - calcElem.addEventListener("click", (e : MouseEvent) => { + calcElem.listenClick((e : MouseEvent) => { parse(exprElem.getValue().toSeq) match { case (None, _) => Window.alert("Error parsing expression"); case (Some(x), Nil) => { diff --git a/samples/storage/src/main/java/org/teavm/samples/storage/Application.java b/samples/storage/src/main/java/org/teavm/samples/storage/Application.java index 6acfae5c4..20d993522 100644 --- a/samples/storage/src/main/java/org/teavm/samples/storage/Application.java +++ b/samples/storage/src/main/java/org/teavm/samples/storage/Application.java @@ -39,7 +39,7 @@ public final class Application { } HTMLButtonElement saveButton = document.getElementById("save-button").cast(); - saveButton.addEventListener("click", e -> { + saveButton.listenClick(e -> { String key = document.getElementById("key").cast().getValue(); String value = document.getElementById("value").cast().getValue(); @@ -49,7 +49,7 @@ public final class Application { } }); HTMLButtonElement deleteButton = document.getElementById("delete-button").cast(); - deleteButton.addEventListener("click", e -> { + deleteButton.listenClick(e -> { String key = document.getElementById("key").cast().getValue(); if (key != null && key.length() > 0) { storage.removeItem(key); @@ -57,7 +57,7 @@ public final class Application { } }); HTMLButtonElement deleteAllButton = document.getElementById("delete-all-button").cast(); - deleteAllButton.addEventListener("click", e -> { + deleteAllButton.listenClick(e -> { storage.clear(); draw(); }); @@ -75,15 +75,9 @@ public final class Application { String key = storage.key(i); String value = storage.getItem(key); - HTMLElement tdKey = document.createElement("td"); - tdKey.appendChild(document.createTextNode(key)); - - HTMLElement tdValue = document.createElement("td"); - tdValue.appendChild(document.createTextNode(value)); - - HTMLElement tr = document.createElement("tr"); - tr.appendChild(tdKey); - tr.appendChild(tdValue); + HTMLElement tdKey = document.createElement("td").withText(key); + HTMLElement tdValue = document.createElement("td").withText(value); + HTMLElement tr = document.createElement("tr").withChild(tdKey).withChild(tdValue); tbody.appendChild(tr); } diff --git a/samples/video/src/main/java/org/teavm/samples/video/Player.java b/samples/video/src/main/java/org/teavm/samples/video/Player.java index 983f66c9e..49f048740 100644 --- a/samples/video/src/main/java/org/teavm/samples/video/Player.java +++ b/samples/video/src/main/java/org/teavm/samples/video/Player.java @@ -17,7 +17,6 @@ package org.teavm.samples.video; import org.teavm.jso.browser.Window; import org.teavm.jso.dom.html.HTMLBodyElement; -import org.teavm.jso.dom.html.HTMLButtonElement; import org.teavm.jso.dom.html.HTMLDocument; import org.teavm.jso.dom.html.HTMLElement; import org.teavm.jso.dom.html.HTMLSourceElement; @@ -31,17 +30,14 @@ public final class Player { public static void main(String[] args) { HTMLSourceElement sourceMp4 = document.createElement("source").cast(); - sourceMp4.setAttribute("id", "mp4"); sourceMp4.setSrc("http://media.w3.org/2010/05/sintel/trailer.mp4"); sourceMp4.setAttribute("type", "video/mp4"); HTMLSourceElement sourceWebm = document.createElement("source").cast(); - sourceWebm.setAttribute("id", "webm"); sourceWebm.setSrc("http://media.w3.org/2010/05/sintel/trailer.webm"); sourceWebm.setAttribute("type", "video/webm"); HTMLSourceElement sourceOgv = document.createElement("source").cast(); - sourceOgv.setAttribute("id", "ogv"); sourceOgv.setSrc("http://media.w3.org/2010/05/sintel/trailer.ogv"); sourceOgv.setAttribute("type", "video/ogg"); @@ -49,7 +45,6 @@ public final class Player { p.appendChild(document.createTextNode("Your user agent does not support the HTML5 Video element.")); HTMLVideoElement video = document.createElement("video").cast(); - video.setAttribute("id", "video"); video.setControls(true); video.setPreload("none"); video.setMediaGroup("myVideoGroup"); @@ -62,83 +57,32 @@ public final class Player { HTMLElement divVideo = document.createElement("div"); divVideo.appendChild(video); - HTMLButtonElement loadButton = document.createElement("button").cast(); - loadButton.appendChild(document.createTextNode("load()")); - loadButton.addEventListener("click", evt -> video.load()); - - HTMLButtonElement playButton = document.createElement("button").cast(); - playButton.appendChild(document.createTextNode("play()")); - playButton.addEventListener("click", evt -> video.play()); - - HTMLButtonElement pauseButton = document.createElement("button").cast(); - pauseButton.appendChild(document.createTextNode("pause()")); - pauseButton.addEventListener("click", evt -> video.pause()); - - HTMLButtonElement currentTimePlusButton = document.createElement("button").cast(); - currentTimePlusButton.appendChild(document.createTextNode("currentTime+=10")); - currentTimePlusButton.addEventListener("click", evt -> video.setCurrentTime(video.getCurrentTime() + 10)); - - HTMLButtonElement currentTimeMinusButton = document.createElement("button").cast(); - currentTimeMinusButton.appendChild(document.createTextNode("currentTime-=10")); - currentTimeMinusButton.addEventListener("click", evt -> video.setCurrentTime(video.getCurrentTime() - 10)); - - HTMLButtonElement currentTime50Button = document.createElement("button").cast(); - currentTime50Button.appendChild(document.createTextNode("currentTime=50")); - currentTime50Button.addEventListener("click", evt -> video.setCurrentTime(50)); - - HTMLButtonElement playbackRateIncrementButton = document.createElement("button").cast(); - playbackRateIncrementButton.appendChild(document.createTextNode("playbackRate++")); - playbackRateIncrementButton.addEventListener("click", evt -> video.setPlaybackRate( - video.getPlaybackRate() + 1)); - - HTMLButtonElement playbackRateDecrementButton = document.createElement("button").cast(); - playbackRateDecrementButton.appendChild(document.createTextNode("playbackRate--")); - playbackRateDecrementButton.addEventListener("click", evt -> video.setPlaybackRate( - video.getPlaybackRate() - 1)); - - HTMLButtonElement playbackRatePlusButton = document.createElement("button").cast(); - playbackRatePlusButton.appendChild(document.createTextNode("playbackRate+=0.1")); - playbackRatePlusButton.addEventListener("click", evt -> video.setPlaybackRate(video.getPlaybackRate() + 0.1)); - - HTMLButtonElement playbackRateMinusButton = document.createElement("button").cast(); - playbackRateMinusButton.appendChild(document.createTextNode("playbackRate-=0.1")); - playbackRateMinusButton.addEventListener("click", evt -> video.setPlaybackRate(video.getPlaybackRate() - 0.1)); - - HTMLButtonElement volumePlusButton = document.createElement("button").cast(); - volumePlusButton.appendChild(document.createTextNode("volume+=0.1")); - volumePlusButton.addEventListener("click", evt -> video.setVolume(video.getVolume() + 0.1f)); - - HTMLButtonElement volumeMinusButton = document.createElement("button").cast(); - volumeMinusButton.appendChild(document.createTextNode("volume-=0.1")); - volumeMinusButton.addEventListener("click", evt -> video.setVolume(video.getVolume() - 0.1f)); - - HTMLButtonElement muteButton = document.createElement("button").cast(); - muteButton.appendChild(document.createTextNode("muted=true")); - muteButton.addEventListener("click", evt -> video.setMuted(true)); - - HTMLButtonElement unmuteButton = document.createElement("button").cast(); - unmuteButton.appendChild(document.createTextNode("muted=false")); - unmuteButton.addEventListener("click", evt -> video.setMuted(false)); - - HTMLElement divButtons = document.createElement("div"); - divButtons.setAttribute("id", "buttons"); - divButtons.appendChild(loadButton); - divButtons.appendChild(playButton); - divButtons.appendChild(pauseButton); - divButtons.appendChild(document.createElement("br")); - divButtons.appendChild(currentTimePlusButton); - divButtons.appendChild(currentTimeMinusButton); - divButtons.appendChild(currentTime50Button); - divButtons.appendChild(document.createElement("br")); - divButtons.appendChild(playbackRateIncrementButton); - divButtons.appendChild(playbackRateDecrementButton); - divButtons.appendChild(playbackRatePlusButton); - divButtons.appendChild(playbackRateMinusButton); - divButtons.appendChild(document.createElement("br")); - divButtons.appendChild(volumePlusButton); - divButtons.appendChild(volumeMinusButton); - divButtons.appendChild(muteButton); - divButtons.appendChild(unmuteButton); + HTMLElement divButtons = document.createElement("div") + .withAttr("id", "button") + .withChild("button", elem -> elem.withText("load()").listenClick(evt -> video.load())) + .withChild("button", elem -> elem.withText("play()").listenClick(evt -> video.play())) + .withChild("button", elem -> elem.withText("pause()").listenClick(evt -> video.pause())) + .withChild("br") + .withChild("button", elem -> elem.withText("currentTime+=10") + .listenClick(evt -> video.addCurrentTime(10))) + .withChild("button", elem -> elem.withText("currentTime-=10") + .listenClick(evt -> video.addCurrentTime(-10))) + .withChild("button", elem -> elem.withText("currentTime-=50") + .listenClick(evt -> video.setCurrentTime(50))) + .withChild("br") + .withChild("button", elem -> elem.withText("playbackRate++") + .listenClick(evt -> video.addPlaybackRate(1))) + .withChild("button", elem -> elem.withText("playbackRate--") + .listenClick(evt -> video.addPlaybackRate(-1))) + .withChild("button", elem -> elem.withText("playbackRate+=0.1") + .listenClick(evt -> video.addPlaybackRate(0.1))) + .withChild("button", elem -> elem.withText("playbackRate-=0.1") + .listenClick(evt -> video.addPlaybackRate(-0.1))) + .withChild("br") + .withChild("button", elem -> elem.withText("volume+=1").listenClick(evt -> video.addVolume(0.1F))) + .withChild("button", elem -> elem.withText("volume-=1").listenClick(evt -> video.addVolume(-0.1F))) + .withChild("button", elem -> elem.withText("mute").listenClick(evt -> video.setMuted(true))) + .withChild("button", elem -> elem.withText("unmute").listenClick(evt -> video.setMuted(false))); HTMLBodyElement body = document.getBody(); body.appendChild(divVideo);