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.
 	 *