You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by ja...@apache.org on 2020/05/13 12:19:54 UTC
[ofbiz-framework] branch trunk updated: Improved:
widget tag (OFBIZ-11686)
This is an automated email from the ASF dual-hosted git repository.
jamesyong pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git
The following commit(s) were added to refs/heads/trunk by this push:
new 803f7fa Improved: <script-template> widget tag (OFBIZ-11686)
803f7fa is described below
commit 803f7fa06048baa5c4246c80ff249cba2edb9451
Author: James Yong <ja...@apache.org>
AuthorDate: Wed May 13 20:19:05 2020 +0800
Improved: <script-template> widget tag (OFBIZ-11686)
The new tag allows us to render a freemarker template containing javascript,
as external script in html instead of inline script.
This helps to reduce CSP errors.
---
applications/order/template/order/FindOrders.ftl | 74 -----------------
.../order/template/order/FindOrders.js.ftl | 86 ++++++++++++++++++++
.../order/widget/ordermgr/OrderViewScreens.xml | 5 +-
.../java/org/apache/ofbiz/common/CommonEvents.java | 25 ++++++
.../common/webcommon/WEB-INF/common-controller.xml | 11 +++
.../webapp/ftl/ScriptTemplateListTransform.java | 81 +++++++++++++++++++
.../ofbiz/webapp/freemarkerTransforms.properties | 1 +
framework/widget/dtd/widget-screen.xsd | 8 ++
.../widget/artifact/ArtifactInfoGatherer.java | 5 ++
.../org/apache/ofbiz/widget/model/HtmlWidget.java | 72 +++++++++++++++++
.../ofbiz/widget/model/ModelWidgetVisitor.java | 2 +
.../ofbiz/widget/model/ScriptTemplateUtil.java | 92 ++++++++++++++++++++++
.../ofbiz/widget/model/XmlWidgetVisitor.java | 9 +++
.../widget/renderer/html/HtmlWidgetRenderer.java | 4 +
themes/flatgrey/template/Footer.ftl | 1 +
themes/rainbowstone/template/includes/Footer.ftl | 1 +
themes/tomahawk/template/Footer.ftl | 1 +
17 files changed, 403 insertions(+), 75 deletions(-)
diff --git a/applications/order/template/order/FindOrders.ftl b/applications/order/template/order/FindOrders.ftl
index cb2c338..0d1923d 100644
--- a/applications/order/template/order/FindOrders.ftl
+++ b/applications/order/template/order/FindOrders.ftl
@@ -17,80 +17,6 @@ specific language governing permissions and limitations
under the License.
-->
-<script type="application/javascript">
-<!-- //
-function lookupOrders(click) {
- orderIdValue = document.lookuporder.orderId.value;
- if (orderIdValue.length > 1) {
- document.lookuporder.action = "<@o...@ofbizUrl>";
- document.lookuporder.method = "get";
- } else {
- document.lookuporder.action = "<@o...@ofbizUrl>";
- }
-
- if (click) {
- document.lookuporder.submit();
- }
- return true;
-}
-function toggleOrderId(master) {
- var form = document.massOrderChangeForm;
- var orders = form.elements.length;
- for (var i = 0; i < orders; i++) {
- var element = form.elements[i];
- if ("orderIdList" == element.name) {
- element.checked = master.checked;
- }
- }
- toggleOrderIdList();
-}
-function setServiceName(selection) {
- document.massOrderChangeForm.action = selection.value;
-}
-function runAction() {
- var form = document.massOrderChangeForm;
- form.submit();
-}
-
-function toggleOrderIdList() {
- var form = document.massOrderChangeForm;
- var orders = form.elements.length;
- var isAllSelected = true;
- var isSingle = true;
- for (var i = 0; i < orders; i++) {
- var element = form.elements[i];
- if ("orderIdList" == element.name) {
- if (element.checked) {
- isSingle = false;
- } else {
- isAllSelected = false;
- }
- }
- }
- if (isAllSelected) {
- jQuery('#checkAllOrders').attr('checked', true);
- } else {
- jQuery('#checkAllOrders').attr('checked', false);
- }
- jQuery('#checkAllOrders').attr("checked", isAllSelected);
- if (!isSingle && jQuery('#serviceName').val() != "") {
- jQuery('#submitButton').removeAttr("disabled");
- } else {
- jQuery('#submitButton').attr('disabled', true);
- }
-}
-
-// -->
-
- function paginateOrderList(viewSize, viewIndex, hideFields) {
- document.paginationForm.viewSize.value = viewSize;
- document.paginationForm.viewIndex.value = viewIndex;
- document.paginationForm.hideFields.value = hideFields;
- document.paginationForm.submit();
- }
-
-</script>
-
<#if security.hasEntityPermission("ORDERMGR", "_VIEW", session)>
<#if parameters.hideFields?has_content>
<form name='lookupandhidefields${requestParameters.hideFields?default("Y")}' method="post" action="<@o...@ofbizUrl>">
diff --git a/applications/order/template/order/FindOrders.js.ftl b/applications/order/template/order/FindOrders.js.ftl
new file mode 100644
index 0000000..0b98270
--- /dev/null
+++ b/applications/order/template/order/FindOrders.js.ftl
@@ -0,0 +1,86 @@
+/***********************************************
+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.
+***********************************************/
+
+function lookupOrders(click) {
+ orderIdValue = document.lookuporder.orderId.value;
+ if (orderIdValue.length > 1) {
+ document.lookuporder.action = "<@o...@ofbizUrl>";
+ document.lookuporder.method = "get";
+ } else {
+ document.lookuporder.action = "<@o...@ofbizUrl>";
+ }
+
+ if (click) {
+ document.lookuporder.submit();
+ }
+ return true;
+}
+function toggleOrderId(master) {
+ var form = document.massOrderChangeForm;
+ var orders = form.elements.length;
+ for (var i = 0; i < orders; i++) {
+ var element = form.elements[i];
+ if ("orderIdList" == element.name) {
+ element.checked = master.checked;
+ }
+ }
+ toggleOrderIdList();
+}
+function setServiceName(selection) {
+ document.massOrderChangeForm.action = selection.value;
+}
+function runAction() {
+ var form = document.massOrderChangeForm;
+ form.submit();
+}
+
+function toggleOrderIdList() {
+ var form = document.massOrderChangeForm;
+ var orders = form.elements.length;
+ var isAllSelected = true;
+ var isSingle = true;
+ for (var i = 0; i < orders; i++) {
+ var element = form.elements[i];
+ if ("orderIdList" == element.name) {
+ if (element.checked) {
+ isSingle = false;
+ } else {
+ isAllSelected = false;
+ }
+ }
+ }
+ if (isAllSelected) {
+ jQuery('#checkAllOrders').attr('checked', true);
+ } else {
+ jQuery('#checkAllOrders').attr('checked', false);
+ }
+ jQuery('#checkAllOrders').attr("checked", isAllSelected);
+ if (!isSingle && jQuery('#serviceName').val() != "") {
+ jQuery('#submitButton').removeAttr("disabled");
+ } else {
+ jQuery('#submitButton').attr('disabled', true);
+ }
+}
+
+function paginateOrderList(viewSize, viewIndex, hideFields) {
+ document.paginationForm.viewSize.value = viewSize;
+ document.paginationForm.viewIndex.value = viewIndex;
+ document.paginationForm.hideFields.value = hideFields;
+ document.paginationForm.submit();
+}
\ No newline at end of file
diff --git a/applications/order/widget/ordermgr/OrderViewScreens.xml b/applications/order/widget/ordermgr/OrderViewScreens.xml
index 80c99db..7d0667c 100644
--- a/applications/order/widget/ordermgr/OrderViewScreens.xml
+++ b/applications/order/widget/ordermgr/OrderViewScreens.xml
@@ -266,7 +266,10 @@ under the License.
<decorator-section name="body">
<platform-specific><html><html-template location="component://common-theme/template/includes/SetMultipleSelectJs.ftl"/></html></platform-specific>
<platform-specific>
- <html><html-template location="component://order/template/order/FindOrders.ftl"/></html>
+ <html>
+ <script-template location="component://order/template/order/FindOrders.js.ftl"/>
+ <html-template location="component://order/template/order/FindOrders.ftl"/>
+ </html>
</platform-specific>
</decorator-section>
</decorator-screen>
diff --git a/framework/common/src/main/java/org/apache/ofbiz/common/CommonEvents.java b/framework/common/src/main/java/org/apache/ofbiz/common/CommonEvents.java
index 76aa710..c97fa36 100644
--- a/framework/common/src/main/java/org/apache/ofbiz/common/CommonEvents.java
+++ b/framework/common/src/main/java/org/apache/ofbiz/common/CommonEvents.java
@@ -53,6 +53,7 @@ import org.apache.ofbiz.entity.GenericValue;
import org.apache.ofbiz.entity.util.EntityUtilProperties;
import org.apache.ofbiz.webapp.control.JWTManager;
import org.apache.ofbiz.webapp.control.LoginWorker;
+import org.apache.ofbiz.widget.model.ScriptTemplateUtil;
import org.apache.ofbiz.widget.model.ThemeFactory;
import org.apache.ofbiz.widget.renderer.VisualTheme;
@@ -176,6 +177,30 @@ public class CommonEvents {
return "success";
}
+ public static String jsResponseFromRequest(HttpServletRequest request, HttpServletResponse response) {
+
+ String fileName = request.getParameter("name");
+ String script = ScriptTemplateUtil.getScriptFromSession(request.getSession(), fileName);
+
+ // return the JS String
+ Writer out;
+ try {
+
+ // set the JS content type
+ response.setContentType("application/javascript");
+ // script.length is not reliable for unicode characters
+ response.setContentLength(script.getBytes("UTF8").length);
+
+ out = response.getWriter();
+ out.write(script);
+ out.flush();
+ } catch (IOException e) {
+ Debug.logError(e, MODULE);
+ return "error";
+ }
+ return "success";
+ }
+
public static String jsonResponseFromRequestAttributes(HttpServletRequest request, HttpServletResponse response) {
// pull out the service response from the request attribute
diff --git a/framework/common/webcommon/WEB-INF/common-controller.xml b/framework/common/webcommon/WEB-INF/common-controller.xml
index 46fa551..e6f9394 100644
--- a/framework/common/webcommon/WEB-INF/common-controller.xml
+++ b/framework/common/webcommon/WEB-INF/common-controller.xml
@@ -324,6 +324,17 @@ under the License.
<response name="error" type="request" value="json"/>
</request-map>
+ <request-map uri="getJs" method="get">
+ <security https="false" auth="false"/>
+ <response name="success" type="request" value="js"/>
+ <response name="error" type="request" value="js"/>
+ </request-map>
+ <request-map uri="js">
+ <security direct-request="false"/>
+ <event type="java" path="org.apache.ofbiz.common.CommonEvents" invoke="jsResponseFromRequest"/>
+ <response name="success" type="none"/>
+ </request-map>
+
<!--========================== AJAX events =====================-->
<!-- View Mappings -->
diff --git a/framework/webapp/src/main/java/org/apache/ofbiz/webapp/ftl/ScriptTemplateListTransform.java b/framework/webapp/src/main/java/org/apache/ofbiz/webapp/ftl/ScriptTemplateListTransform.java
new file mode 100644
index 0000000..c749c87
--- /dev/null
+++ b/framework/webapp/src/main/java/org/apache/ofbiz/webapp/ftl/ScriptTemplateListTransform.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * 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.
+ *******************************************************************************/
+package org.apache.ofbiz.webapp.ftl;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.ofbiz.widget.model.ScriptTemplateUtil;
+
+import freemarker.core.Environment;
+import freemarker.ext.beans.BeanModel;
+import freemarker.template.TemplateModelException;
+import freemarker.template.TemplateTransformModel;
+
+/**
+ * Render the script tags collected from the <script-template/>
+ */
+public class ScriptTemplateListTransform implements TemplateTransformModel {
+
+ public static final String MODULE = CsrfTokenAjaxTransform.class.getName();
+
+ @Override
+ public Writer getWriter(Writer out, @SuppressWarnings("rawtypes") Map args)
+ throws TemplateModelException, IOException {
+
+ return new Writer(out) {
+
+ @Override
+ public void close() throws IOException {
+ try {
+ Environment env = Environment.getCurrentEnvironment();
+ BeanModel req = (BeanModel) env.getVariable("request");
+ if (req != null) {
+ HttpServletRequest request = (HttpServletRequest) req.getWrappedObject();
+ Set<String> scriptSrcSet = ScriptTemplateUtil.getScriptSrcLinksFromRequest(request);
+ if (scriptSrcSet!=null) {
+ String srcList = "";
+ for (String scriptSrc : scriptSrcSet) {
+ srcList += ("<script src=\"" + scriptSrc + "\" type=\"application/javascript\"></script>\n");
+ }
+ out.write(srcList);
+ }
+ }
+ return;
+ } catch (Exception e) {
+ throw new IOException(e.getMessage());
+ }
+ }
+
+ @Override
+ public void flush() throws IOException {
+ out.flush();
+ }
+
+ @Override
+ public void write(char cbuf[], int off, int len) {
+ }
+ };
+
+ }
+}
diff --git a/framework/webapp/src/main/resources/org/apache/ofbiz/webapp/freemarkerTransforms.properties b/framework/webapp/src/main/resources/org/apache/ofbiz/webapp/freemarkerTransforms.properties
index 65cf04e..b4f4d8b 100644
--- a/framework/webapp/src/main/resources/org/apache/ofbiz/webapp/freemarkerTransforms.properties
+++ b/framework/webapp/src/main/resources/org/apache/ofbiz/webapp/freemarkerTransforms.properties
@@ -31,3 +31,4 @@ renderWrappedText=org.apache.ofbiz.webapp.ftl.RenderWrappedTextTransform
setContextField=org.apache.ofbiz.webapp.ftl.SetContextFieldTransform
csrfTokenAjax=org.apache.ofbiz.webapp.ftl.CsrfTokenAjaxTransform
csrfTokenPair=org.apache.ofbiz.webapp.ftl.CsrfTokenPairNonAjaxTransform
+scriptTemplateList=org.apache.ofbiz.webapp.ftl.ScriptTemplateListTransform
diff --git a/framework/widget/dtd/widget-screen.xsd b/framework/widget/dtd/widget-screen.xsd
index 7165f41..62ffc03 100644
--- a/framework/widget/dtd/widget-screen.xsd
+++ b/framework/widget/dtd/widget-screen.xsd
@@ -544,6 +544,14 @@ under the License.
<xs:attribute type="xs:string" name="name" use="required" />
</xs:complexType>
</xs:element>
+ <xs:element name="script-template" substitutionGroup="HtmlWidgets">
+ <xs:complexType>
+ <xs:attributeGroup ref="attlist.script-template" />
+ </xs:complexType>
+ </xs:element>
+ <xs:attributeGroup name="attlist.script-template">
+ <xs:attribute type="xs:string" name="location" use="required" />
+ </xs:attributeGroup>
<!-- ============== Swing Specific Elements =============== -->
<xs:element name="swing">
<xs:complexType />
diff --git a/framework/widget/src/main/java/org/apache/ofbiz/widget/artifact/ArtifactInfoGatherer.java b/framework/widget/src/main/java/org/apache/ofbiz/widget/artifact/ArtifactInfoGatherer.java
index 0ea3393..3c96f1e 100644
--- a/framework/widget/src/main/java/org/apache/ofbiz/widget/artifact/ArtifactInfoGatherer.java
+++ b/framework/widget/src/main/java/org/apache/ofbiz/widget/artifact/ArtifactInfoGatherer.java
@@ -38,6 +38,7 @@ import org.apache.ofbiz.widget.model.HtmlWidget;
import org.apache.ofbiz.widget.model.HtmlWidget.HtmlTemplate;
import org.apache.ofbiz.widget.model.HtmlWidget.HtmlTemplateDecorator;
import org.apache.ofbiz.widget.model.HtmlWidget.HtmlTemplateDecoratorSection;
+import org.apache.ofbiz.widget.model.HtmlWidget.ScriptTemplate;
import org.apache.ofbiz.widget.model.IterateSectionWidget;
import org.apache.ofbiz.widget.model.ModelAction;
import org.apache.ofbiz.widget.model.ModelActionVisitor;
@@ -356,6 +357,10 @@ public final class ArtifactInfoGatherer implements ModelWidgetVisitor, ModelActi
}
@Override
+ public void visit(ScriptTemplate scriptTemplate) throws Exception {
+ }
+
+ @Override
public void visit(Section section) throws Exception {
for (ModelAction action : section.getActions()) {
action.accept(this);
diff --git a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/HtmlWidget.java b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/HtmlWidget.java
index b39ec2d..b5afc68 100644
--- a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/HtmlWidget.java
+++ b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/HtmlWidget.java
@@ -19,6 +19,7 @@
package org.apache.ofbiz.widget.model;
import java.io.IOException;
+import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -120,6 +121,8 @@ public class HtmlWidget extends ModelScreenWidget {
subWidgets.add(new HtmlTemplate(modelScreen, childElement));
} else if ("html-template-decorator".equals(childElement.getNodeName())) {
subWidgets.add(new HtmlTemplateDecorator(modelScreen, childElement));
+ } else if ("script-template".equals(childElement.getNodeName())) {
+ subWidgets.add(new ScriptTemplate(modelScreen, childElement));
} else {
throw new IllegalArgumentException("Tag not supported under the platform-specific -> html tag with name: "
+ childElement.getNodeName());
@@ -175,6 +178,36 @@ public class HtmlWidget extends ModelScreenWidget {
}
}
+ public static void renderScriptTemplate(Appendable writer, FlexibleStringExpander locationExdr, Map<String, Object> context) {
+ String location = locationExdr.expandString(context);
+
+ if (UtilValidate.isEmpty(location)) {
+ throw new IllegalArgumentException("Template location is empty with search string location " + locationExdr.getOriginal());
+ }
+
+ if (location.endsWith(".ftl")) {
+ try {
+ boolean insertWidgetBoundaryComments = ModelWidget.widgetBoundaryCommentsEnabled(context);
+ if (insertWidgetBoundaryComments) {
+ writer.append(HtmlWidgetRenderer.formatBoundaryJsComment("Begin", "Template", location));
+ }
+
+ Template template = FreeMarkerWorker.getTemplate(location, specialTemplateCache, specialConfig);
+ FreeMarkerWorker.renderTemplate(template, context, writer);
+
+ if (insertWidgetBoundaryComments) {
+ writer.append(HtmlWidgetRenderer.formatBoundaryJsComment("End", "Template", location));
+ }
+ } catch (IllegalArgumentException | TemplateException | IOException e) {
+ String errMsg = "Error rendering included template at location [" + location + "]: " + e.toString();
+ Debug.logError(e, errMsg, MODULE);
+ writeError(writer, errMsg);
+ }
+ } else {
+ throw new IllegalArgumentException("Rendering not yet supported for the template at location: " + location);
+ }
+ }
+
// TODO: We can make this more fancy, but for now this is very functional
public static void writeError(Appendable writer, String message) {
try {
@@ -288,6 +321,45 @@ public class HtmlWidget extends ModelScreenWidget {
}
}
+ public static class ScriptTemplate extends ModelScreenWidget {
+ protected FlexibleStringExpander locationExdr;
+
+ public ScriptTemplate(ModelScreen modelScreen, Element htmlTemplateElement) {
+ super(modelScreen, htmlTemplateElement);
+ this.locationExdr = FlexibleStringExpander.getInstance(htmlTemplateElement.getAttribute("location"));
+ }
+
+ public String getLocation(Map<String, Object> context) {
+ return locationExdr.expandString(context);
+ }
+
+ @Override
+ public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws IOException {
+ StringWriter stringWriter = new StringWriter();
+ renderScriptTemplate(stringWriter, this.locationExdr, context);
+ String data = stringWriter.toString();
+ stringWriter.close();
+
+ String fileName = this.getLocation(context);
+ fileName = fileName.substring(fileName.lastIndexOf("/")+1);
+ // remove ".ftl"
+ fileName = fileName.substring(0, fileName.length()-4);
+ ScriptTemplateUtil.putScriptInSession(context, fileName, data);
+
+ String webappName = (String)context.get("webappName");
+ ScriptTemplateUtil.addScriptSrcToRequest(context, "/"+webappName+"/control/getJs?name="+fileName);
+ }
+
+ @Override
+ public void accept(ModelWidgetVisitor visitor) throws Exception {
+ visitor.visit(this);
+ }
+
+ public FlexibleStringExpander getLocationExdr() {
+ return locationExdr;
+ }
+ }
+
@Override
public void accept(ModelWidgetVisitor visitor) throws Exception {
visitor.visit(this);
diff --git a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelWidgetVisitor.java b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelWidgetVisitor.java
index f081f98..a1f89bb 100644
--- a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelWidgetVisitor.java
+++ b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelWidgetVisitor.java
@@ -32,6 +32,8 @@ public interface ModelWidgetVisitor {
void visit(HtmlWidget.HtmlTemplateDecoratorSection htmlTemplateDecoratorSection) throws Exception;
+ void visit(HtmlWidget.ScriptTemplate scriptTemplate) throws Exception;
+
void visit(IterateSectionWidget iterateSectionWidget) throws Exception;
void visit(ModelSingleForm modelForm) throws Exception;
diff --git a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ScriptTemplateUtil.java b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ScriptTemplateUtil.java
new file mode 100644
index 0000000..d6d16a2
--- /dev/null
+++ b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ScriptTemplateUtil.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * 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.
+ *******************************************************************************/
+package org.apache.ofbiz.widget.model;
+
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.apache.ofbiz.base.util.UtilGenerics;
+import org.apache.ofbiz.webapp.ftl.ScriptTemplateListTransform;
+
+public class ScriptTemplateUtil {
+
+ private static String sessionKey = "ScriptTemplateMap";
+ private static String requestKey = "ScriptTemplateList";
+ private static int maxNumOfScriptInCache = 10;
+
+ /**
+ * add script src link for use by @see {@link ScriptTemplateListTransform}
+ * @param context
+ * @param filePath
+ */
+ public static void addScriptSrcToRequest(Map<String, Object> context, String filePath){
+ HttpServletRequest request = (HttpServletRequest)context.get("request");
+ Set<String> scriptTemplates = UtilGenerics.cast(request.getAttribute(requestKey));
+ if (scriptTemplates==null){
+ // use of LinkedHashSet to maintain insertion order
+ scriptTemplates = new LinkedHashSet<String>();
+ request.setAttribute(requestKey, scriptTemplates);
+ }
+ scriptTemplates.add(filePath);
+ }
+
+ /**
+ * get the script src links collected from the <script-template/> tags
+ * @param request
+ * @return
+ */
+ public static Set<String> getScriptSrcLinksFromRequest(HttpServletRequest request){
+ Set<String> scriptTemplates = UtilGenerics.cast(request.getAttribute(requestKey));
+ return scriptTemplates;
+ }
+
+ public static void putScriptInSession(Map<String, Object> context, String fileName, String fileContent){
+ HttpSession session = (HttpSession)context.get("session");
+ Map<String,String> scriptTemplateMap = UtilGenerics.cast(session.getAttribute(sessionKey));
+ if (scriptTemplateMap==null){
+ synchronized (session) {
+ scriptTemplateMap = UtilGenerics.cast(session.getAttribute(sessionKey));
+ if (scriptTemplateMap==null){
+ // use of LinkedHashMap to limit size of the map
+ scriptTemplateMap = new LinkedHashMap<String, String>() {
+ private static final long serialVersionUID = 1L;
+ protected boolean removeEldestEntry(Map.Entry<String, String> eldest) {
+ return size() > maxNumOfScriptInCache;
+ }
+ };
+ session.setAttribute(sessionKey, scriptTemplateMap);
+ }
+ }
+ }
+ scriptTemplateMap.put(fileName, fileContent);
+ }
+
+ public static String getScriptFromSession(HttpSession session, String fileName){
+ Map<String,String> scriptTemplateMap = UtilGenerics.cast(session.getAttribute(sessionKey));
+ if (scriptTemplateMap!=null){
+ return scriptTemplateMap.get(fileName);
+ }
+ return null;
+ }
+}
diff --git a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/XmlWidgetVisitor.java b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/XmlWidgetVisitor.java
index 193a45a..737ced1 100644
--- a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/XmlWidgetVisitor.java
+++ b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/XmlWidgetVisitor.java
@@ -24,6 +24,7 @@ import java.util.Map;
import org.apache.ofbiz.widget.model.HtmlWidget.HtmlTemplate;
import org.apache.ofbiz.widget.model.HtmlWidget.HtmlTemplateDecorator;
import org.apache.ofbiz.widget.model.HtmlWidget.HtmlTemplateDecoratorSection;
+import org.apache.ofbiz.widget.model.HtmlWidget.ScriptTemplate;
import org.apache.ofbiz.widget.model.ModelScreenWidget.Column;
import org.apache.ofbiz.widget.model.ModelScreenWidget.ColumnContainer;
import org.apache.ofbiz.widget.model.ModelScreenWidget.Container;
@@ -405,6 +406,14 @@ public class XmlWidgetVisitor extends XmlAbstractWidgetVisitor implements ModelW
}
@Override
+ public void visit(ScriptTemplate scriptTemplate) throws Exception {
+ writer.append("<script-template");
+ visitModelWidget(scriptTemplate);
+ visitAttribute("location", scriptTemplate.getLocationExdr());
+ writer.append("/>");
+ }
+
+ @Override
public void visit(ModelScreen modelScreen) throws Exception {
writer.append("<screen");
visitModelWidget(modelScreen);
diff --git a/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/html/HtmlWidgetRenderer.java b/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/html/HtmlWidgetRenderer.java
index 62cb643..047037e 100644
--- a/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/html/HtmlWidgetRenderer.java
+++ b/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/html/HtmlWidgetRenderer.java
@@ -60,6 +60,10 @@ public class HtmlWidgetRenderer {
return "<!-- " + boundaryType + " " + widgetType + " " + widgetName + " -->" + whiteSpace;
}
+ public static String formatBoundaryJsComment(String boundaryType, String widgetType, String widgetName) {
+ return "// " + boundaryType + " " + widgetType + " " + widgetName + whiteSpace;
+ }
+
/**
* Renders the beginning boundary comment string.
* @param writer The writer to write to
diff --git a/themes/flatgrey/template/Footer.ftl b/themes/flatgrey/template/Footer.ftl
index 517c1b0..3a65a83 100644
--- a/themes/flatgrey/template/Footer.ftl
+++ b/themes/flatgrey/template/Footer.ftl
@@ -42,4 +42,5 @@ under the License.
</#list>
</#if>
</body>
+<@scriptTemplateList/>
</html>
diff --git a/themes/rainbowstone/template/includes/Footer.ftl b/themes/rainbowstone/template/includes/Footer.ftl
index 164b5aa..057ad23 100644
--- a/themes/rainbowstone/template/includes/Footer.ftl
+++ b/themes/rainbowstone/template/includes/Footer.ftl
@@ -34,4 +34,5 @@ under the License.
</#list>
</#if>
</body>
+<@scriptTemplateList/>
</html>
diff --git a/themes/tomahawk/template/Footer.ftl b/themes/tomahawk/template/Footer.ftl
index cc26dd7..baf94a8 100644
--- a/themes/tomahawk/template/Footer.ftl
+++ b/themes/tomahawk/template/Footer.ftl
@@ -42,4 +42,5 @@ under the License.
</div>
</body>
+<@scriptTemplateList/>
</html>