You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2018/07/13 00:58:34 UTC
[juneau] branch master updated: pre/post javascript hooks on
MenuItemWidget
This is an automated email from the ASF dual-hosted git repository.
jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/master by this push:
new b0a591c pre/post javascript hooks on MenuItemWidget
b0a591c is described below
commit b0a591c5efbe1d52ab700910659589ce4e0cb89b
Author: JamesBognar <ja...@apache.org>
AuthorDate: Thu Jul 12 20:58:15 2018 -0400
pre/post javascript hooks on MenuItemWidget
---
juneau-doc/src/main/javadoc/overview.html | 7 ++
.../examples/rest/petstore/AddOrderMenuItem.java | 21 ++---
.../rest/petstore/AddOrderMenuItem_beforeShow.js | 32 +++++++
.../juneau/examples/rest/RootContentTest.java | 4 +-
.../apache/juneau/rest/widget/MenuItemWidget.java | 105 ++++++++++++++++++++-
5 files changed, 149 insertions(+), 20 deletions(-)
diff --git a/juneau-doc/src/main/javadoc/overview.html b/juneau-doc/src/main/javadoc/overview.html
index 6b7459b..f0975fb 100644
--- a/juneau-doc/src/main/javadoc/overview.html
+++ b/juneau-doc/src/main/javadoc/overview.html
@@ -21822,6 +21822,13 @@
<ul>
<li class='jf'>{@link org.apache.juneau.rest.client.RestClientBuilder#mockHttpConnection(MockHttpConnection) mockHttpConnection(MockHttpConnection)}
</ul>
+ <li>
+ New methods added to {@link org.apache.juneau.rest.widget.MenuItemWidget} to allow population of menu item content using Javascript and Ajax calls:
+ <li class='jc'>{@link org.apache.juneau.rest.widget.MenuItemWidget}
+ <ul>
+ <li class='jm'>{@link org.apache.juneau.rest.widget.MenuItemWidget#getBeforShowScript(RestRequest) getBeforShowScript(RestRequest)}
+ <li class='jm'>{@link org.apache.juneau.rest.widget.MenuItemWidget#getAfterShowScript(RestRequest) getAfterShowScript(RestRequest)}
+ </ul>
</ul>
<h5 class='topic w800'>juneau-rest-microservice</h5>
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/AddOrderMenuItem.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/AddOrderMenuItem.java
index 6832512..b1df268 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/AddOrderMenuItem.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/AddOrderMenuItem.java
@@ -15,10 +15,6 @@ package org.apache.juneau.examples.rest.petstore;
import static org.apache.juneau.dto.html5.HtmlBuilder.*;
import static org.apache.juneau.http.HttpMethodName.*;
-import java.util.*;
-import java.util.Map;
-
-import org.apache.juneau.dto.html5.*;
import org.apache.juneau.rest.*;
import org.apache.juneau.rest.widget.*;
@@ -32,15 +28,13 @@ public class AddOrderMenuItem extends MenuItemWidget {
return "add";
}
- @SuppressWarnings("unchecked")
+ @Override /* MenuItemWidget */
+ public String getBeforeShowScript(RestRequest req) throws Exception {
+ return loadScript("AddOrderMenuItem_beforeShow.js");
+ }
+
@Override /* Widget */
public Object getContent(RestRequest req) throws Exception {
- Map<Long,String> petNames = (Map<Long,String>)req.getAttribute("availablePets");
-
- List<Option> options = new ArrayList<>();
- for (Map.Entry<Long,String> e : petNames.entrySet())
- options.add(option(e.getKey(), e.getValue()));
-
return div(
form().id("form").action("servlet:/store/order").method(POST).children(
@@ -48,9 +42,7 @@ public class AddOrderMenuItem extends MenuItemWidget {
tr(
th("Pet:"),
td(
- select().name("petId").children(
- options.toArray()
- )
+ select().id("addPet_names").name("petId")
),
td(new Tooltip("(?)", "The pet to purchase."))
),
@@ -62,7 +54,6 @@ public class AddOrderMenuItem extends MenuItemWidget {
tr(
td().colspan(2).style("text-align:right").children(
button("reset", "Reset"),
- button("button","Cancel").onclick("window.location.href='/'"),
button("submit", "Submit")
)
)
diff --git a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/AddOrderMenuItem_beforeShow.js b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/AddOrderMenuItem_beforeShow.js
new file mode 100644
index 0000000..71d1ce1
--- /dev/null
+++ b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/AddOrderMenuItem_beforeShow.js
@@ -0,0 +1,32 @@
+/*
+ ***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+ * to you 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. *
+ ***************************************************************************************************************************
+*/
+
+/* Populates the list of pets on the add-order menu item. */
+var xhr = new XMLHttpRequest();
+xhr.open('GET', '/petstore/pet?s=status=AVAILABLE&v=id,name', true);
+xhr.setRequestHeader('Accept', 'application/json');
+xhr.onload = function() {
+ var pets = JSON.parse(xhr.responseText);
+ var select = document.getElementById('addPet_names');
+ select.innerHTML = '';
+ for (var i in pets) {
+ var pet = pets[i];
+ var opt = document.createElement('option');
+ opt.value = pet.id;
+ opt.innerHTML = pet.name;
+ select.appendChild(opt);
+ }
+}
+xhr.send();
\ No newline at end of file
diff --git a/juneau-examples/juneau-examples-rest/src/test/java/org/apache/juneau/examples/rest/RootContentTest.java b/juneau-examples/juneau-examples-rest/src/test/java/org/apache/juneau/examples/rest/RootContentTest.java
index 0125f47..9ba69f6 100644
--- a/juneau-examples/juneau-examples-rest/src/test/java/org/apache/juneau/examples/rest/RootContentTest.java
+++ b/juneau-examples/juneau-examples-rest/src/test/java/org/apache/juneau/examples/rest/RootContentTest.java
@@ -47,8 +47,8 @@ public class RootContentTest extends ContentComboTestBase {
new ComboInput("HTML-nav", "/", MediaType.HTML,
"<nav>",
"<a href='/?method=OPTIONS'>options</a>",
- "<a onclick='menuClick(this)'>content-type</a>",
- "<a onclick='menuClick(this)'>themes</a>",
+ "<a onclick='menuClick(this);'>content-type</a>",
+ "<a onclick='menuClick(this);'>themes</a>",
"<a href='https://github.com/apache/juneau/blob/master/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java'>source</a>"
)
},
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/widget/MenuItemWidget.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/widget/MenuItemWidget.java
index 45a0f06..bfa4a81 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/widget/MenuItemWidget.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/widget/MenuItemWidget.java
@@ -12,6 +12,8 @@
// ***************************************************************************************************************************
package org.apache.juneau.rest.widget;
+import static org.apache.juneau.internal.StringUtils.*;
+
import java.io.*;
import org.apache.juneau.html.*;
@@ -71,6 +73,70 @@ public abstract class MenuItemWidget extends Widget {
}
/**
+ * Optional Javascript to execute immediately before a menu item is shown.
+ *
+ * <p>
+ * For example, the following shows how the method could be used to make an AJAX call back to the REST
+ * interface to populate a SELECT element in the contents of the popup dialog:
+ *
+ * <p class='bcode'>
+ * <ja>@Override</ja>
+ * <jk>public</jk> String getBeforeShowScript(RestRequest req) {
+ * <jk>return</jk> <js>""</js>
+ * + <js>"\n var xhr = new XMLHttpRequest();"</js>
+ * + <js>"\n xhr.open('GET', '/petstore/pet?s=status=AVAILABLE&v=id,name', true);"</js>
+ * + <js>"\n xhr.setRequestHeader('Accept', 'application/json');"</js>
+ * + <js>"\n xhr.onload = function() {"</js>
+ * + <js>"\n var pets = JSON.parse(xhr.responseText);"</js>
+ * + <js>"\n var select = document.getElementById('addPet_names');"</js>
+ * + <js>"\n select.innerHTML = '';"</js>
+ * + <js>"\n for (var i in pets) {"</js>
+ * + <js>"\n var pet = pets[i];"</js>
+ * + <js>"\n var opt = document.createElement('option');"</js>
+ * + <js>"\n opt.value = pet.id;"</js>
+ * + <js>"\n opt.innerHTML = pet.name;"</js>
+ * + <js>"\n select.appendChild(opt);"</js>
+ * + <js>"\n }"</js>
+ * + <js>"\n }"</js>
+ * + <js>"\n xhr.send();"</js>
+ * ;
+ * }
+ * </p>
+ *
+ * <p>
+ * Note that it's often easier (and cleaner) to use the {@link #loadScript(String)} method and read the Javascript from
+ * your classpath:
+ *
+ * <p class='bcode'>
+ * <ja>@Override</ja>
+ * <jk>public</jk> String getBeforeShowScript(RestRequest req) <jk>throws</jk> Exception {
+ * <jk>return</jk> loadScript(<js>"AddOrderMenuItem_beforeShow.js"</js>);
+ * }
+ * </p>
+ *
+ * @param req The current request.
+ * @return Javascript code to execute, or <jk>null</jk> if there isn't any.
+ * @throws Exception
+ */
+ public String getBeforeShowScript(RestRequest req) throws Exception {
+ return null;
+ }
+
+ /**
+ * Optional Javascript to execute immediately after a menu item is shown.
+ *
+ * <p>
+ * Same as {@link #getBeforeShowScript(RestRequest)} except this Javascript gets executed after the popup dialog has become visible.
+ *
+ * @param req The current request.
+ * @return Javascript code to execute, or <jk>null</jk> if there isn't any.
+ * @throws Exception
+ */
+ public String getAfterShowScript(RestRequest req) throws Exception {
+ return null;
+ }
+
+ /**
* Defines a <js>"menu-item"</js> class that needs to be used on the outer element of the HTML returned by the
* {@link #getHtml(RestRequest)} method.
*/
@@ -82,10 +148,33 @@ public abstract class MenuItemWidget extends Widget {
@Override /* Widget */
public String getHtml(RestRequest req) throws Exception {
StringBuilder sb = new StringBuilder();
+
+ // Need a unique number to define unique function names.
+ Integer id = null;
+
+ String pre = nullIfEmpty(getBeforeShowScript(req)), post = nullIfEmpty(getAfterShowScript(req));
+
+ sb.append("\n<div class='menu-item'>");
+ if (pre != null || post != null) {
+ id = getId(req);
+
+ sb.append("\n\t<script>");
+ if (pre != null) {
+ sb.append("\n\t\tfunction onPreShow" + id + "() {");
+ sb.append("\n").append(pre);
+ sb.append("\n\t\t}");
+ }
+ if (post != null) {
+ sb.append("\n\t\tfunction onPostShow" + id + "() {");
+ sb.append("\n").append(pre);
+ sb.append("\n\t\t}");
+ }
+ sb.append("\n\t</script>");
+ }
+ String onclick = (pre == null ? "" : "onPreShow"+id+"();") + "menuClick(this);" + (post == null ? "" : "onPostShow"+id+"();");
sb.append(""
- + "<div class='menu-item'>"
- + "\n\t<a onclick='menuClick(this)'>"+getLabel(req)+"</a>"
- + "\n\t<div class='popup-content'>\n"
+ + "\n\t<a onclick='"+onclick+"'>"+getLabel(req)+"</a>"
+ + "\n<div class='popup-content'>"
);
Object o = getContent(req);
if (o instanceof Reader) {
@@ -107,6 +196,16 @@ public abstract class MenuItemWidget extends Widget {
return sb.toString();
}
+ private Integer getId(RestRequest req) {
+ Integer id = (Integer)req.getAttribute("LastMenuItemId");
+ if (id == null)
+ id = 1;
+ else
+ id = id + 1;
+ req.setAttribute("LastMenuItemId", id);
+ return id;
+ }
+
/**
* The label for the menu item as it's rendered in the menu bar.
*