You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by th...@apache.org on 2025/08/09 11:39:00 UTC
(tapestry-5) branch master updated: TAP5-2810 Adding a Require.js-less mode (#54)
This is an automated email from the ASF dual-hosted git repository.
thiagohp pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tapestry-5.git
The following commit(s) were added to refs/heads/master by this push:
new 976caa7f6 TAP5-2810 Adding a Require.js-less mode (#54)
976caa7f6 is described below
commit 976caa7f6610920963a370083ea56676fb4a6612
Author: Thiago H. de Paula Figueiredo <th...@arsmachina.com.br>
AuthorDate: Sat Aug 9 08:38:56 2025 -0300
TAP5-2810 Adding a Require.js-less mode (#54)
TAP5-2810: Require.js-less mode
---
5_10_RELEASE_NOTES.md | 18 +-
build.gradle | 9 +-
.../beanvalidator/modules/BeanValidatorModule.java | 26 ++-
.../corelib/base/AbstractComponentEventLink.java | 8 +-
.../tapestry5/corelib/base/AbstractField.java | 6 +-
.../tapestry5/corelib/components/AjaxFormLoop.java | 10 +-
.../tapestry5/corelib/components/Alerts.java | 6 +-
.../tapestry5/corelib/components/DateField.java | 10 +-
.../tapestry5/corelib/components/DevTool.java | 14 +-
.../tapestry5/corelib/components/Errors.java | 5 +-
.../corelib/components/ExceptionDisplay.java | 8 +-
.../apache/tapestry5/corelib/components/Form.java | 6 +-
.../tapestry5/corelib/components/FormFragment.java | 20 +-
.../tapestry5/corelib/components/Graphviz.java | 6 +-
.../apache/tapestry5/corelib/components/Grid.java | 8 +-
.../apache/tapestry5/corelib/components/Label.java | 6 +-
.../tapestry5/corelib/components/LinkSubmit.java | 24 ++-
.../tapestry5/corelib/components/LocalDate.java | 13 +-
.../tapestry5/corelib/components/Palette.java | 24 ++-
.../corelib/components/ProgressiveDisplay.java | 12 +-
.../tapestry5/corelib/components/Select.java | 49 ++---
.../tapestry5/corelib/components/Submit.java | 22 ++-
.../tapestry5/corelib/components/TimeInterval.java | 13 +-
.../apache/tapestry5/corelib/components/Tree.java | 36 +++-
.../apache/tapestry5/corelib/components/Zone.java | 23 ++-
.../tapestry5/corelib/mixins/Autocomplete.java | 28 ++-
.../apache/tapestry5/corelib/mixins/Confirm.java | 8 +-
.../tapestry5/corelib/mixins/TriggerFragment.java | 10 +-
.../tapestry5/corelib/mixins/ZoneRefresh.java | 9 +-
.../internal/alerts/AlertManagerImpl.java | 20 +-
.../internal/services/DocumentLinkerImpl.java | 41 +++--
.../internal/services/EsModuleInitsManager.java | 93 +++++++++-
.../services/PartialMarkupDocumentLinker.java | 14 +-
.../internal/services/ajax/BaseInitialization.java | 10 +
.../services/ajax/EsModuleInitializationImpl.java | 33 +++-
.../internal/services/ajax/EsShimManagerImpl.java | 66 +++++++
.../services/ajax/JavaScriptSupportImpl.java | 48 ++++-
.../services/ajax/RequireJsModeHelper.java | 41 +++++
.../services/ajax/RequireJsModeHelperImpl.java | 49 +++++
.../services/javascript/EsModuleManagerImpl.java | 165 ++++++++++-------
.../services/javascript/EsShimDispatcher.java | 141 +++++++++++++++
.../translator/NumericTranslatorSupportImpl.java | 20 +-
.../apache/tapestry5/modules/JavaScriptModule.java | 201 +++++++++++++++++----
.../apache/tapestry5/modules/TapestryModule.java | 7 +-
.../services/javascript/EsModuleManager.java | 54 +++++-
.../tapestry5/services/javascript/EsShim.java | 189 +++++++++++++++++++
.../services/javascript/EsShimManager.java | 49 +++++
.../javascript/ExtensibleJavaScriptStack.java | 18 +-
.../services/javascript/JavaScriptStack.java | 8 +
.../services/javascript/JavaScriptSupport.java | 8 +
.../services/javascript/StackExtension.java | 10 +
.../services/javascript/StackExtensionType.java | 7 +
.../tapestry5/validator/CheckboxValidator.java | 10 +-
.../java/org/apache/tapestry5/validator/Email.java | 9 +-
.../java/org/apache/tapestry5/validator/Max.java | 9 +-
.../org/apache/tapestry5/validator/MaxLength.java | 9 +-
.../java/org/apache/tapestry5/validator/Min.java | 10 +-
.../org/apache/tapestry5/validator/MinLength.java | 9 +-
.../org/apache/tapestry5/validator/Regexp.java | 9 +-
.../org/apache/tapestry5/validator/Required.java | 9 +-
.../assets/es-modules/{t5 => }/underscore.js | 0
.../META-INF/assets/tapestry5/moment-2.15.1.js | 2 +-
.../META-INF/assets/tapestry5/underscore-esm.js | 5 -
.../resources/org/apache/tapestry5/core.properties | 2 +-
.../t5/beanvalidator/beanvalidator-validation.ts | 5 +-
.../main/typescript/src/t5/core/autocomplete.ts | 6 +-
.../src/main/typescript/src/t5/core/fields.ts | 2 +-
.../main/typescript/src/t5/core/form-fragment.ts | 11 +-
.../typescript/src/t5/core/messages-es-module.ts | 4 +
.../src/main/typescript/src/t5/core/pageinit.ts | 94 +++++++---
.../src/main/typescript/src/t5/core/select.ts | 4 +-
.../typescript/src/t5/core/t53-compatibility.ts | 56 ++++++
.../src/main/typescript/src/t5/core/typeahead.ts | 2 +-
.../src/main/typescript/src/t5/core/validation.ts | 6 +-
.../src/main/typescript/src/t5/core/zone.ts | 2 +-
.../app1/ModuleConfigurationCallbackTests.groovy | 13 +-
.../services/DocumentLinkerImplTest.groovy | 59 ++++--
.../ajax/JavaScriptSupportAutofocusTests.groovy | 2 +-
.../services/ajax/JavaScriptSupportImplTest.groovy | 34 ++--
.../tapestry5/integration/app1/App1TestCase.java | 8 +
.../tapestry5/integration/app1/AssetTests.java | 8 +-
.../tapestry5/integration/app1/EsModuleTests.java | 1 -
.../integration/app1/components/Border.java | 14 +-
.../integration/app1/pages/ClientConsoleDemo.java | 12 +-
.../integration/app1/pages/EsModuleDemo.java | 2 +-
.../pages/ModuleConfigurationCallbackDemo.java | 2 +
.../integration/app1/pages/ModuleInitDemo.java | 10 +-
.../app1/pages/MultiZoneUpdateDemo.java | 12 +-
.../integration/app1/pages/PaletteDemo.java | 9 +-
.../integration/app1/pages/PaletteGroupedDemo.java | 11 +-
.../integration/app1/pages/PublishEventDemo.java | 33 +++-
.../app1/pages/ValidateInErrorEvent.java | 12 +-
.../integration/app1/services/AppModule.java | 7 +-
.../javascript/EsModuleManagerImplTest.java | 39 ++--
.../META-INF/assets/ExpressionInJsFunction.js | 11 +-
.../assets/es-modules/app/multi-zone-update.js | 5 +
.../META-INF/assets/es-modules/app/test-support.js | 14 ++
.../assets/es-modules/client-console-demo.js | 6 +
.../META-INF/assets/es-modules/palette-demo.js | 14 ++
.../assets/es-modules/publish-event-demo.js | 23 +++
.../assets/es-modules/validate-in-error.js | 8 +
.../src/test/resources/META-INF/assets/zonedemo.js | 22 ++-
.../META-INF/modules/client-console-demo.js | 8 +-
.../resources/META-INF/modules/palette-demo.js | 5 -
.../integration/app1/pages/nested/AssetDemo.js | 16 +-
.../apache/tapestry5/upload/components/Upload.java | 18 +-
106 files changed, 2010 insertions(+), 432 deletions(-)
diff --git a/5_10_RELEASE_NOTES.md b/5_10_RELEASE_NOTES.md
index d62d92163..4a942b709 100644
--- a/5_10_RELEASE_NOTES.md
+++ b/5_10_RELEASE_NOTES.md
@@ -17,16 +17,24 @@ Scratch pad for changes destined for the 5.10.0 release notes page.
* `org.apache.tapestry5.services.javascript.ImportPlacement`
* `org.apache.tapestry5.services.javascript.EsModuleConfigurationCallback`
* `org.apache.tapestry5.services.javascript.EsModuleManager`
+* `org.apache.tapestry5.services.javascript.ESWrapper`
# Non-backward-compatible changes (but that probably won't cause problems)
# Non-backward-compatible changes
-When using Require.js and AMD modules, from Tapestry 5.10.0 on,
-the previously returned objects, functions or values are now
-the `default` property of the object received from `require()`.
-This is a consequence we couldn't avoid from the CoffeeScript
-to JavaScript to TypeScript conversion.
+* When using Require.js and AMD modules, from Tapestry 5.10.0 on,
+ the previously returned objects, functions or values are now
+ the `default` property of the object received from `require()`.
+ This is a consequence we couldn't avoid from the CoffeeScript
+ to JavaScript to TypeScript conversion.
+
+
+# Notes about Require.js disabled mode
+* Underscore.js, jQuery and Require.js are not included in the default stack
+ (i.e. the set of JavaScript files which are included in pages by default).
+ If you need to use Underscore.js or jQuery, they're automatically available for
+ import as `underscore` and `jquery`, respectively.
# Overall notes
diff --git a/build.gradle b/build.gradle
index a80b69637..bde9ee18d 100755
--- a/build.gradle
+++ b/build.gradle
@@ -538,12 +538,13 @@ task combinedJacocoReport(type:JacocoReport){
}
task continuousIntegration {
- // tapestry-javadoc doesn't work with Java 8 anymore. That's why it's only added if != 8.
- def dependants = [subprojects.build, // jQuery and Require.js enabled
-// 'tapestry-core:testWithJqueryAndRequireJsDisabled',
-// 'tapestry-core:testWithPrototypeAndRequireJsEnabled',
+ def dependants = [
'tapestry-core:testWithPrototypeAndRequireJsDisabled',
+ 'tapestry-core:testWithJqueryAndRequireJsDisabled',
+ subprojects.build, // jQuery and Require.js enabled
+ 'tapestry-core:testWithPrototypeAndRequireJsEnabled',
combinedJacocoReport]
+ // tapestry-javadoc doesn't work with Java 8 anymore. That's why it's only added if != 8.
if (JavaVersion.current() != JavaVersion.VERSION_1_8) {
dependants << aggregateJavadoc
}
diff --git a/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/modules/BeanValidatorModule.java b/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/modules/BeanValidatorModule.java
index 2f93c789b..e068bb514 100644
--- a/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/modules/BeanValidatorModule.java
+++ b/tapestry-beanvalidator/src/main/java/org/apache/tapestry5/beanvalidator/modules/BeanValidatorModule.java
@@ -14,6 +14,7 @@
package org.apache.tapestry5.beanvalidator.modules;
import org.apache.tapestry5.MarkupWriter;
+import org.apache.tapestry5.SymbolConstants;
import org.apache.tapestry5.beanvalidator.*;
import org.apache.tapestry5.commons.Configuration;
import org.apache.tapestry5.commons.MappedConfiguration;
@@ -21,6 +22,7 @@ import org.apache.tapestry5.commons.OrderedConfiguration;
import org.apache.tapestry5.internal.beanvalidator.*;
import org.apache.tapestry5.ioc.ServiceBinder;
import org.apache.tapestry5.ioc.annotations.Local;
+import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.ioc.services.PropertyShadowBuilder;
import org.apache.tapestry5.ioc.services.ThreadLocale;
import org.apache.tapestry5.services.FieldValidatorDefaultSource;
@@ -92,14 +94,20 @@ public class BeanValidatorModule
}
public static void contributeClientConstraintDescriptorSource(final JavaScriptSupport javaScriptSupport,
- final Configuration<ClientConstraintDescriptor> configuration)
+ final Configuration<ClientConstraintDescriptor> configuration,
+ final @Symbol(SymbolConstants.REQUIRE_JS_ENABLED) boolean requireJsEnabled)
{
+
+ final Runnable importJs = requireJsEnabled ?
+ () -> javaScriptSupport.require(MODULE_NAME) :
+ () -> javaScriptSupport.importEsModule(MODULE_NAME);
+
configuration.add(new BaseCCD(Max.class, "value")
{
@Override
public void applyClientValidation(MarkupWriter writer, String message, Map<String, Object> attributes)
{
- javaScriptSupport.require("t5/core/validation");
+ importJs.run();
writer.attributes(
"data-validate", true,
"data-validate-max", attributes.get("value"),
@@ -113,7 +121,7 @@ public class BeanValidatorModule
@Override
public void applyClientValidation(MarkupWriter writer, String message, Map<String, Object> attributes)
{
- javaScriptSupport.require("t5/core/validation");
+ importJs.run();
writer.attributes(
DataConstants.VALIDATION_ATTRIBUTE, true,
"data-validate-min", attributes.get("value"),
@@ -127,7 +135,7 @@ public class BeanValidatorModule
@Override
public void applyClientValidation(MarkupWriter writer, String message, Map<String, Object> attributes)
{
- javaScriptSupport.require("t5/core/validation");
+ importJs.run();
writer.attributes(
DataConstants.VALIDATION_ATTRIBUTE, true,
"data-optionality", "required",
@@ -140,7 +148,7 @@ public class BeanValidatorModule
@Override
public void applyClientValidation(MarkupWriter writer, String message, Map<String, Object> attributes)
{
- javaScriptSupport.require(MODULE_NAME);
+ importJs.run();
writer.attributes(
DataConstants.VALIDATION_ATTRIBUTE, true,
"data-optionality", "prohibited",
@@ -153,7 +161,7 @@ public class BeanValidatorModule
@Override
public void applyClientValidation(MarkupWriter writer, String message, Map<String, Object> attributes)
{
- javaScriptSupport.require(MODULE_NAME);
+ importJs.run();
writer.attributes(
DataConstants.VALIDATION_ATTRIBUTE, true,
"data-validate-regexp", attributes.get("regexp"),
@@ -166,7 +174,7 @@ public class BeanValidatorModule
@Override
public void applyClientValidation(MarkupWriter writer, String message, Map<String, Object> attributes)
{
- javaScriptSupport.require(MODULE_NAME);
+ importJs.run();
writer.attributes(
DataConstants.VALIDATION_ATTRIBUTE, true,
"data-range-message", message);
@@ -192,7 +200,7 @@ public class BeanValidatorModule
@Override
public void applyClientValidation(MarkupWriter writer, String message, Map<String, Object> attributes)
{
- javaScriptSupport.require("t5/core/validation");
+ importJs.run();
writer.attributes(
DataConstants.VALIDATION_ATTRIBUTE, true,
@@ -206,7 +214,7 @@ public class BeanValidatorModule
@Override
public void applyClientValidation(MarkupWriter writer, String message, Map<String, Object> attributes)
{
- javaScriptSupport.require("t5/core/validation");
+ importJs.run();
writer.attributes(
DataConstants.VALIDATION_ATTRIBUTE, true,
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractComponentEventLink.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractComponentEventLink.java
index 64ac711af..4e27a3f6b 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractComponentEventLink.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractComponentEventLink.java
@@ -20,8 +20,8 @@ import org.apache.tapestry5.annotations.Environmental;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.http.Link;
import org.apache.tapestry5.http.services.Request;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
import org.apache.tapestry5.ioc.annotations.Inject;
-import org.apache.tapestry5.services.javascript.JavaScriptSupport;
/**
* Base class for link-generating components that are based on a component event request. Such events have an event
@@ -57,8 +57,8 @@ public abstract class AbstractComponentEventLink extends AbstractLink
@Inject
private Request request;
- @Environmental
- private JavaScriptSupport javaScriptSupport;
+ @Inject
+ private RequireJsModeHelper requireJsModeHelper;
void beginRender(MarkupWriter writer)
{
@@ -72,7 +72,7 @@ public abstract class AbstractComponentEventLink extends AbstractLink
if (async)
{
- javaScriptSupport.require("t5/core/zone");
+ requireJsModeHelper.importModule("t5/core/zone");
writer.attributes("data-async-trigger", true);
}
}
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractField.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractField.java
index 654917abd..22e991cae 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractField.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractField.java
@@ -22,6 +22,7 @@ import org.apache.tapestry5.http.services.Request;
import org.apache.tapestry5.internal.BeanValidationContext;
import org.apache.tapestry5.internal.InternalComponentResources;
import org.apache.tapestry5.internal.services.FormControlNameManager;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.ioc.internal.util.InternalUtils;
@@ -154,6 +155,9 @@ public abstract class AbstractField implements Field
@Environmental
protected JavaScriptSupport javaScriptSupport;
+
+ @Inject
+ private RequireJsModeHelper requireJsModeHelper;
@Environmental
protected ValidationTracker validationTracker;
@@ -296,7 +300,7 @@ public abstract class AbstractField implements Field
if (error != null)
{
- javaScriptSupport.require("t5/core/fields").invoke("showValidationError").with(assignedClientId, error);
+ requireJsModeHelper.importModule("t5/core/fields").invoke("showValidationError").with(assignedClientId, error);
}
}
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/AjaxFormLoop.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/AjaxFormLoop.java
index 789ca01eb..72eaded6b 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/AjaxFormLoop.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/AjaxFormLoop.java
@@ -20,6 +20,7 @@ import org.apache.tapestry5.corelib.internal.AjaxFormLoopContext;
import org.apache.tapestry5.dom.Element;
import org.apache.tapestry5.http.Link;
import org.apache.tapestry5.internal.services.RequestConstants;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.json.JSONObject;
import org.apache.tapestry5.services.ComponentDefaultProvider;
@@ -62,7 +63,6 @@ import java.util.Iterator;
*/
@Events(
{EventConstants.ADD_ROW, EventConstants.REMOVE_ROW})
-@Import(module = "t5/core/ajaxformloop")
@SupportsInformalParameters
public class AjaxFormLoop
{
@@ -139,6 +139,9 @@ public class AjaxFormLoop
@Inject
private ComponentResources resources;
+
+ @Inject
+ private RequireJsModeHelper requireJsModeHelper;
@Environmental
private FormSupport formSupport;
@@ -167,7 +170,7 @@ public class AjaxFormLoop
@Inject
private DeprecationWarning deprecationWarning;
-
+
void pageLoaded()
{
deprecationWarning.ignoredComponentParameters(resources, "show");
@@ -325,6 +328,9 @@ public class AjaxFormLoop
void setupRender(MarkupWriter writer)
{
+
+ requireJsModeHelper.importModule("t5/core/ajaxformloop");
+
pushContext();
iterator = source == null ? Collections.EMPTY_LIST.iterator() : source.iterator();
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Alerts.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Alerts.java
index cf6e06400..6893fc912 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Alerts.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Alerts.java
@@ -20,6 +20,7 @@ import org.apache.tapestry5.annotations.*;
import org.apache.tapestry5.corelib.base.BaseClientElement;
import org.apache.tapestry5.http.Link;
import org.apache.tapestry5.http.services.Request;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.json.JSONObject;
import org.apache.tapestry5.services.compatibility.DeprecationWarning;
@@ -63,6 +64,9 @@ public class Alerts extends BaseClientElement
@Inject
private Request request;
+
+ @Inject
+ private RequireJsModeHelper requireJsModeHelper;
void onPageLoaded()
{
@@ -120,7 +124,7 @@ public class Alerts extends BaseClientElement
for (Alert alert : storage.getAlerts())
{
- javaScriptSupport.require("t5/core/alert").with(alert.toJSON());
+ requireJsModeHelper.importModule("t5/core/alert").with(alert.toJSON());
}
storage.dismissNonPersistent();
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/DateField.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/DateField.java
index c986beb19..569ebfdc3 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/DateField.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/DateField.java
@@ -20,6 +20,7 @@ import org.apache.tapestry5.annotations.RequestParameter;
import org.apache.tapestry5.commons.Messages;
import org.apache.tapestry5.corelib.base.AbstractField;
import org.apache.tapestry5.dom.Element;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.ioc.internal.util.InternalUtils;
@@ -49,8 +50,7 @@ import java.util.Locale;
* @see TextField
*/
// TODO: More testing; see https://issues.apache.org/jira/browse/TAPESTRY-1844
-@Import(stylesheet = "${tapestry.datepicker}/css/datepicker.css",
- module = "t5/core/datefield")
+@Import(stylesheet = "${tapestry.datepicker}/css/datepicker.css")
@Events(EventConstants.VALIDATE)
public class DateField extends AbstractField
{
@@ -127,6 +127,9 @@ public class DateField extends AbstractField
@Inject
private DeprecationWarning deprecationWarning;
+
+ @Inject
+ private RequireJsModeHelper requireJsModeHelper;
@Inject
@Symbol(SymbolConstants.LENIENT_DATE_FORMAT)
@@ -225,6 +228,9 @@ public class DateField extends AbstractField
void beginRender(MarkupWriter writer)
{
+
+ requireJsModeHelper.importModule("t5/core/datefield");
+
String value = validationTracker.getInput(this);
if (value == null)
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/DevTool.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/DevTool.java
index 3c6f9f614..9c0ad42cc 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/DevTool.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/DevTool.java
@@ -14,6 +14,7 @@ package org.apache.tapestry5.corelib.components;
import org.apache.tapestry5.BindingConstants;
import org.apache.tapestry5.ComponentResources;
+import org.apache.tapestry5.SymbolConstants;
import org.apache.tapestry5.alerts.AlertManager;
import org.apache.tapestry5.annotations.Component;
import org.apache.tapestry5.annotations.Environmental;
@@ -94,6 +95,10 @@ public class DevTool
@Inject
private ReloadHelper reloadHelper;
+
+ @Inject
+ @Symbol(SymbolConstants.REQUIRE_JS_ENABLED)
+ private boolean requireJsEnabled;
public String getZoneElement()
{
@@ -122,7 +127,14 @@ public class DevTool
{
if (enabled)
{
- javaScriptSupport.importStack("core").require("bootstrap/dropdown");
+ if (requireJsEnabled)
+ {
+ javaScriptSupport.importStack("core").require("bootstrap/dropdown");
+ }
+ else
+ {
+ javaScriptSupport.importEsModule("bootstrap/dropdown");
+ }
}
return enabled;
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Errors.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Errors.java
index 7438dfd76..71c2cb6f2 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Errors.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Errors.java
@@ -24,6 +24,7 @@ import org.apache.tapestry5.ValidationTracker;
import org.apache.tapestry5.annotations.Environmental;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.commons.util.CollectionFactory;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.services.ComponentOverride;
@@ -79,7 +80,7 @@ public class Errors
private String closeButtonCssClass;
@Inject
- private JavaScriptSupport javaScriptSupport;
+ private RequireJsModeHelper requireJsModeHelper;
boolean beginRender(MarkupWriter writer)
{
@@ -146,7 +147,7 @@ public class Errors
* @see ComponentOverride
*/
protected void setUpJavaScript() {
- javaScriptSupport.require("bootstrap/alert");
+ requireJsModeHelper.importModule("bootstrap/alert");
}
}
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/ExceptionDisplay.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/ExceptionDisplay.java
index c1afa247a..b510d4375 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/ExceptionDisplay.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/ExceptionDisplay.java
@@ -17,6 +17,7 @@ package org.apache.tapestry5.corelib.components;
import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.annotations.Property;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.annotations.Primary;
import org.apache.tapestry5.ioc.services.ExceptionAnalysis;
@@ -34,7 +35,7 @@ import java.util.List;
* @tapestrydoc
* @see org.apache.tapestry5.ioc.services.ExceptionAnalyzer
*/
-@Import(stylesheet = "ExceptionDisplay.css", module = "t5/core/exception-display")
+@Import(stylesheet = "ExceptionDisplay.css")
public class ExceptionDisplay
{
/**
@@ -63,12 +64,17 @@ public class ExceptionDisplay
@Inject
@Primary
private StackTraceElementAnalyzer frameAnalyzer;
+
+ @Inject
+ private RequireJsModeHelper requireJsModeHelper;
void setupRender()
{
ExceptionAnalysis analysis = analyzer.analyze(exception);
stack = analysis.getExceptionInfos();
+
+ requireJsModeHelper.importModule("t5/core/exception-display");
}
public Object getPropertyValue()
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
index 3d0fe289b..5d8b8222c 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Form.java
@@ -33,6 +33,7 @@ import org.apache.tapestry5.internal.FormsRequirePostException;
import org.apache.tapestry5.internal.InternalConstants;
import org.apache.tapestry5.internal.services.FormControlNameManager;
import org.apache.tapestry5.internal.services.HeartbeatImpl;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
import org.apache.tapestry5.internal.util.AutofocusValidationDecorator;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.annotations.Symbol;
@@ -238,6 +239,9 @@ public class Form implements ClientElement, FormValidationControl
@Environmental
private JavaScriptSupport javascriptSupport;
+ @Inject
+ private RequireJsModeHelper requireJsModeHelper;
+
@Inject
private Request request;
@@ -394,7 +398,7 @@ public class Form implements ClientElement, FormValidationControl
if (async)
{
- javascriptSupport.require("t5/core/zone");
+ requireJsModeHelper.importModule("t5/core/zone");
writer.attributes("data-async-trigger", true);
}
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/FormFragment.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/FormFragment.java
index 972fde06d..c4046648b 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/FormFragment.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/FormFragment.java
@@ -12,10 +12,13 @@
package org.apache.tapestry5.corelib.components;
-import org.apache.tapestry5.*;
+import org.apache.tapestry5.BindingConstants;
+import org.apache.tapestry5.ClientElement;
+import org.apache.tapestry5.ComponentAction;
+import org.apache.tapestry5.ComponentResources;
+import org.apache.tapestry5.MarkupWriter;
import org.apache.tapestry5.annotations.Environmental;
import org.apache.tapestry5.annotations.HeartbeatDeferred;
-import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.annotations.SupportsInformalParameters;
import org.apache.tapestry5.corelib.internal.ComponentActionSink;
@@ -23,6 +26,7 @@ import org.apache.tapestry5.corelib.internal.FormSupportAdapter;
import org.apache.tapestry5.corelib.internal.HiddenFieldPositioner;
import org.apache.tapestry5.corelib.mixins.TriggerFragment;
import org.apache.tapestry5.dom.Element;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.services.ClientDataEncoder;
import org.apache.tapestry5.services.Environment;
@@ -54,7 +58,6 @@ import org.slf4j.Logger;
* @see Form
*/
@SupportsInformalParameters
-@Import(module = "t5/core/form-fragment")
public class FormFragment implements ClientElement
{
/**
@@ -122,9 +125,12 @@ public class FormFragment implements ClientElement
@Inject
private Environment environment;
-
+
@Environmental
private JavaScriptSupport javascriptSupport;
+
+ @Inject
+ private RequireJsModeHelper requireJsModeHelper;
@Inject
private ComponentResources resources;
@@ -143,7 +149,7 @@ public class FormFragment implements ClientElement
@Inject
private ClientDataEncoder clientDataEncoder;
-
+
String defaultElement()
{
return resources.getElementName("div");
@@ -170,6 +176,8 @@ public class FormFragment implements ClientElement
}
resources.renderInformalParameters(writer);
+
+ requireJsModeHelper.importModule("t5/core/form-fragment");
if (!visible)
{
@@ -177,7 +185,7 @@ public class FormFragment implements ClientElement
if (!alwaysSubmit)
{
- javascriptSupport.require("t5/core/form-fragment").invoke("hide").with(clientId);
+ requireJsModeHelper.importModule("t5/core/form-fragment").invoke("hide").with(clientId);
}
}
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Graphviz.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Graphviz.java
index 0f34cd3ec..d735c60db 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Graphviz.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Graphviz.java
@@ -21,6 +21,7 @@ import org.apache.tapestry5.annotations.Environmental;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.commons.Messages;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.services.ajax.AjaxResponseRenderer;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;
@@ -58,6 +59,9 @@ public class Graphviz
@Environmental
private JavaScriptSupport javaScriptSupport;
+ @Inject
+ private RequireJsModeHelper requireJsModeHelper;
+
@Inject
private AjaxResponseRenderer ajaxResponseRenderer;
@@ -88,7 +92,7 @@ public class Graphviz
// TODO import https://cdn.jsdelivr.net/npm/@hpcc-js/wasm/dist/graphviz.js
// if Require.js is disabled @hpcc-js/wasm
- javaScriptSupport.require("t5/core/graphviz").with(cachedValue, id, showDownloadLink);
+ requireJsModeHelper.importModule("t5/core/graphviz").with(cachedValue, id, showDownloadLink);
if (showDownloadLink)
{
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Grid.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Grid.java
index 79e120b79..bb5e5c3ee 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Grid.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Grid.java
@@ -22,12 +22,12 @@ import org.apache.tapestry5.corelib.data.GridPagerPosition;
import org.apache.tapestry5.grid.*;
import org.apache.tapestry5.internal.TapestryInternalUtils;
import org.apache.tapestry5.internal.bindings.AbstractBinding;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.internal.util.InternalUtils;
import org.apache.tapestry5.services.ComponentDefaultProvider;
import org.apache.tapestry5.services.ComponentEventResultProcessor;
import org.apache.tapestry5.services.FormSupport;
-import org.apache.tapestry5.services.javascript.JavaScriptSupport;
import java.io.IOException;
import java.util.Collections;
@@ -234,8 +234,8 @@ public class Grid implements GridModel, ClientElement
@Inject
private BeanModelSource modelSource;
- @Environmental
- private JavaScriptSupport javaScriptSupport;
+ @Inject
+ private RequireJsModeHelper requireJsModeHelper;
@Component(parameters =
{"index=inherit:columnIndex", "lean=inherit:lean", "overrides=overrides", "zone=zone"})
@@ -591,7 +591,7 @@ public class Grid implements GridModel, ClientElement
if (inPlace && zone == null)
{
- javaScriptSupport.require("t5/core/zone");
+ requireJsModeHelper.importModule("t5/core/zone");
writer.element("div", "data-container-type", "zone");
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Label.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Label.java
index c64853a38..529b027c5 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Label.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Label.java
@@ -19,6 +19,7 @@ import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.annotations.SupportsInformalParameters;
import org.apache.tapestry5.dom.Element;
import org.apache.tapestry5.http.TapestryHttpSymbolConstants;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.ioc.internal.util.InternalUtils;
@@ -67,6 +68,9 @@ public class Label
@Inject
private JavaScriptSupport javaScriptSupport;
+
+ @Inject
+ private RequireJsModeHelper requireJsModeHelper;
@Inject
@Symbol(TapestryHttpSymbolConstants.PRODUCTION_MODE)
@@ -120,7 +124,7 @@ public class Label
// TAP5-2500
String warningText = "The Label component " + resources.getCompleteId()
+ " is linked to a Field that failed to return a clientId. The 'for' attibute will not be rendered.";
- javaScriptSupport.require("t5/core/console").invoke("warn").with(warningText);
+ requireJsModeHelper.importModule("t5/core/console").invoke("warn").with(warningText);
}
String id = clientId != null ? clientId : javaScriptSupport.allocateClientId(fieldId + "-label");
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LinkSubmit.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LinkSubmit.java
index 4ab44ed18..66141a074 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LinkSubmit.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LinkSubmit.java
@@ -14,10 +14,20 @@
package org.apache.tapestry5.corelib.components;
-import org.apache.tapestry5.*;
-import org.apache.tapestry5.annotations.*;
+import org.apache.tapestry5.BindingConstants;
+import org.apache.tapestry5.ClientElement;
+import org.apache.tapestry5.ComponentAction;
+import org.apache.tapestry5.ComponentResources;
+import org.apache.tapestry5.EventConstants;
+import org.apache.tapestry5.MarkupWriter;
+import org.apache.tapestry5.TrackableComponentEventCallback;
+import org.apache.tapestry5.annotations.Environmental;
+import org.apache.tapestry5.annotations.Events;
+import org.apache.tapestry5.annotations.Parameter;
+import org.apache.tapestry5.annotations.SupportsInformalParameters;
import org.apache.tapestry5.corelib.SubmitMode;
import org.apache.tapestry5.http.services.Request;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.internal.util.InternalUtils;
import org.apache.tapestry5.json.JSONArray;
@@ -34,7 +44,6 @@ import org.apache.tapestry5.services.javascript.JavaScriptSupport;
*/
@SupportsInformalParameters
@Events(EventConstants.SELECTED + " by default, may be overridden")
-@Import(module = "t5/core/forms")
public class LinkSubmit implements ClientElement
{
/**
@@ -94,13 +103,17 @@ public class LinkSubmit implements ClientElement
@Inject
private Request request;
+
+ @Inject
+ private RequireJsModeHelper requireJsModeHelper;
- @SuppressWarnings("unchecked")
+ @SuppressWarnings("rawtypes")
@Environmental
private TrackableComponentEventCallback eventCallback;
private String clientId;
+ @SuppressWarnings("serial")
private static class ProcessSubmission implements ComponentAction<LinkSubmit>
{
private final String clientId;
@@ -143,6 +156,9 @@ public class LinkSubmit implements ClientElement
{
if (!disabled)
{
+
+ requireJsModeHelper.importModule("t5/core/forms");
+
clientId = javascriptSupport.allocateClientId(resources);
formSupport.store(this, new ProcessSubmission(clientId));
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java
index 797bc5fab..f9f0f33b1 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java
@@ -12,17 +12,16 @@
package org.apache.tapestry5.corelib.components;
+import java.util.Date;
+
import org.apache.tapestry5.BindingConstants;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.MarkupWriter;
-import org.apache.tapestry5.annotations.Environmental;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.annotations.SupportsInformalParameters;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.services.DateUtilities;
-import org.apache.tapestry5.services.javascript.JavaScriptSupport;
-
-import java.util.Date;
/**
* Used to present a date, formatted in the time zone of the client browser.
@@ -62,8 +61,8 @@ public class LocalDate
@Inject
ComponentResources resources;
- @Environmental
- JavaScriptSupport javaScriptSupport;
+ @Inject
+ private RequireJsModeHelper requireJsModeHelper;
@Inject
DateUtilities dateUtilities;
@@ -81,7 +80,7 @@ public class LocalDate
writer.end();
- javaScriptSupport.require("t5/core/localdate");
+ requireJsModeHelper.importModule("t5/core/localdate");
}
// Skip the body regardless.
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Palette.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Palette.java
index 69313c37b..955a3840b 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Palette.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Palette.java
@@ -12,19 +12,31 @@
package org.apache.tapestry5.corelib.components;
-import org.apache.tapestry5.*;
+import java.util.Collection;
+
+import org.apache.tapestry5.Asset;
+import org.apache.tapestry5.Binding;
+import org.apache.tapestry5.BindingConstants;
+import org.apache.tapestry5.Block;
+import org.apache.tapestry5.ComponentParameterConstants;
+import org.apache.tapestry5.FieldValidator;
+import org.apache.tapestry5.MarkupWriter;
+import org.apache.tapestry5.Renderable;
+import org.apache.tapestry5.SelectModel;
+import org.apache.tapestry5.SymbolConstants;
+import org.apache.tapestry5.ValidationException;
+import org.apache.tapestry5.ValueEncoder;
import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.corelib.base.AbstractField;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
import org.apache.tapestry5.internal.util.SelectModelRenderer;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.json.JSONArray;
import org.apache.tapestry5.services.compatibility.DeprecationWarning;
-import java.util.Collection;
-
/**
* Multiple selection component. Generates a UI consisting of two <select> elements configured for multiple
* selection; the one on the left is the list of "available" elements, the one on the right is "selected". Elements can
@@ -160,7 +172,6 @@ public class Palette extends AbstractField
* @since 5.2.0
*/
@Parameter(defaultPrefix = BindingConstants.VALIDATE)
- @SuppressWarnings("unchecked")
private FieldValidator<Object> validate;
@Inject
@@ -169,6 +180,9 @@ public class Palette extends AbstractField
@Inject
private DeprecationWarning deprecationWarning;
+
+ @Inject
+ private RequireJsModeHelper requireJsModeHelper;
void pageLoaded() {
deprecationWarning.ignoredComponentParameters(resources, "select", "moveUp", "moveDown", "deselect");
@@ -247,7 +261,7 @@ public class Palette extends AbstractField
// The client side just need to know the id of the selected (right column) select;
// it can take it from there.
- javaScriptSupport.require("t5/core/palette").with(clientId);
+ requireJsModeHelper.importModule("t5/core/palette").with(clientId);
}
/**
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/ProgressiveDisplay.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/ProgressiveDisplay.java
index 69da03e0f..726f4cd6e 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/ProgressiveDisplay.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/ProgressiveDisplay.java
@@ -18,6 +18,7 @@ import org.apache.tapestry5.annotations.Events;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.annotations.SupportsInformalParameters;
import org.apache.tapestry5.http.Link;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.services.compatibility.DeprecationWarning;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;
@@ -63,9 +64,12 @@ public class ProgressiveDisplay
@Inject
private ComponentResources resources;
-
+
@Environmental
- private JavaScriptSupport jsSupport;
+ private JavaScriptSupport javaScriptSupport;
+
+ @Inject
+ private RequireJsModeHelper requireJsModeHelper;
@Environmental
private TrackableComponentEventCallback eventCallback;
@@ -91,7 +95,7 @@ public class ProgressiveDisplay
Block beginRender(MarkupWriter writer)
{
- String clientId = jsSupport.allocateClientId(resources);
+ String clientId = javaScriptSupport.allocateClientId(resources);
String elementName = resources.getElementName("div");
writer.element(elementName, "id", clientId, "data-container-type", "zone");
@@ -99,7 +103,7 @@ public class ProgressiveDisplay
Link link = resources.createEventLink(EventConstants.ACTION, context);
- jsSupport.require("t5/core/zone").invoke("deferredZoneUpdate").with(clientId, link.toURI());
+ requireJsModeHelper.importModule("t5/core/zone").invoke("deferredZoneUpdate").with(clientId, link.toURI());
// Return the placeholder for the full content. That will render instead of the main body
// of the component.
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Select.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Select.java
index 1c15c0438..76e61e874 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Select.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Select.java
@@ -12,9 +12,29 @@
package org.apache.tapestry5.corelib.components;
-import org.apache.tapestry5.*;
-import org.apache.tapestry5.annotations.*;
-import org.apache.tapestry5.beanmodel.services.*;
+import java.util.List;
+
+import org.apache.tapestry5.Binding;
+import org.apache.tapestry5.BindingConstants;
+import org.apache.tapestry5.ComponentParameterConstants;
+import org.apache.tapestry5.EventConstants;
+import org.apache.tapestry5.EventContext;
+import org.apache.tapestry5.FieldValidationSupport;
+import org.apache.tapestry5.FieldValidator;
+import org.apache.tapestry5.MarkupWriter;
+import org.apache.tapestry5.OptionGroupModel;
+import org.apache.tapestry5.OptionModel;
+import org.apache.tapestry5.SelectModel;
+import org.apache.tapestry5.SelectModelVisitor;
+import org.apache.tapestry5.ValidationException;
+import org.apache.tapestry5.ValidationTracker;
+import org.apache.tapestry5.ValueEncoder;
+import org.apache.tapestry5.annotations.BeforeRenderTemplate;
+import org.apache.tapestry5.annotations.Environmental;
+import org.apache.tapestry5.annotations.Events;
+import org.apache.tapestry5.annotations.Mixin;
+import org.apache.tapestry5.annotations.Parameter;
+import org.apache.tapestry5.annotations.RequestParameter;
import org.apache.tapestry5.commons.Messages;
import org.apache.tapestry5.commons.services.TypeCoercer;
import org.apache.tapestry5.corelib.base.AbstractField;
@@ -26,6 +46,7 @@ import org.apache.tapestry5.http.services.Request;
import org.apache.tapestry5.internal.AbstractEventContext;
import org.apache.tapestry5.internal.InternalComponentResources;
import org.apache.tapestry5.internal.TapestryInternalUtils;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
import org.apache.tapestry5.internal.util.CaptureResultCallback;
import org.apache.tapestry5.internal.util.SelectModelRenderer;
import org.apache.tapestry5.ioc.annotations.Inject;
@@ -34,12 +55,8 @@ import org.apache.tapestry5.services.FieldValidatorDefaultSource;
import org.apache.tapestry5.services.FormSupport;
import org.apache.tapestry5.services.ValueEncoderFactory;
import org.apache.tapestry5.services.ValueEncoderSource;
-import org.apache.tapestry5.services.javascript.JavaScriptSupport;
import org.apache.tapestry5.util.EnumSelectModel;
-import java.util.Collections;
-import java.util.List;
-
/**
* Select an item from a list of values, using an [X]HTML <select> element on the client side. Any validation
* decorations will go around the entire <select> element.
@@ -180,12 +197,11 @@ public class Select extends AbstractField
private FormSupport formSupport;
@Inject
- private JavaScriptSupport javascriptSupport;
+ private RequireJsModeHelper requireJsModeHelper;
@Inject
private TypeCoercer typeCoercer;
- @SuppressWarnings("unused")
@Mixin
private RenderDisabled renderDisabled;
@@ -196,8 +212,6 @@ public class Select extends AbstractField
return TapestryInternalUtils.isEqual(clientValue, selectedClientValue);
}
- @SuppressWarnings(
- {"unchecked"})
@Override
protected void processSubmission(String controlName)
{
@@ -260,7 +274,7 @@ public class Select extends AbstractField
if (this.zone != null)
{
- javaScriptSupport.require("t5/core/select");
+ requireJsModeHelper.importModule("t5/core/select");
Link link = resources.createEventLink(CHANGE_EVENT, context);
@@ -391,17 +405,6 @@ public class Select extends AbstractField
return false;
}
- private static <T> List<T> orEmpty(List<T> list)
- {
- if (list == null)
- {
- return Collections.emptyList();
- }
-
- return list;
- }
-
- @SuppressWarnings("unchecked")
ValueEncoder defaultEncoder()
{
return defaultProvider.defaultValueEncoder("value", resources);
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Submit.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Submit.java
index b96db2ca4..9df3c97d8 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Submit.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Submit.java
@@ -14,10 +14,21 @@
package org.apache.tapestry5.corelib.components;
-import org.apache.tapestry5.*;
-import org.apache.tapestry5.annotations.*;
+import org.apache.tapestry5.Asset;
+import org.apache.tapestry5.BindingConstants;
+import org.apache.tapestry5.ClientElement;
+import org.apache.tapestry5.ComponentAction;
+import org.apache.tapestry5.ComponentResources;
+import org.apache.tapestry5.EventConstants;
+import org.apache.tapestry5.MarkupWriter;
+import org.apache.tapestry5.TrackableComponentEventCallback;
+import org.apache.tapestry5.annotations.Environmental;
+import org.apache.tapestry5.annotations.Events;
+import org.apache.tapestry5.annotations.Parameter;
+import org.apache.tapestry5.annotations.SupportsInformalParameters;
import org.apache.tapestry5.corelib.SubmitMode;
import org.apache.tapestry5.http.services.Request;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
import org.apache.tapestry5.internal.util.Holder;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.internal.util.InternalUtils;
@@ -36,7 +47,6 @@ import org.apache.tapestry5.services.javascript.JavaScriptSupport;
*/
@SupportsInformalParameters
@Events(EventConstants.SELECTED + " by default, may be overridden")
-@Import(module="t5/core/forms")
public class Submit implements ClientElement
{
/**
@@ -120,6 +130,9 @@ public class Submit implements ClientElement
@SuppressWarnings("unchecked")
@Environmental
private TrackableComponentEventCallback eventCallback;
+
+ @Inject
+ private RequireJsModeHelper requireJsModeHelper;
private String clientId;
@@ -150,6 +163,9 @@ public class Submit implements ClientElement
void beginRender(MarkupWriter writer)
{
+
+ requireJsModeHelper.importModule("t5/core/forms");
+
clientId = javascriptSupport.allocateClientId(resources);
String name = formSupport.allocateControlName(resources.getId());
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/TimeInterval.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/TimeInterval.java
index 01d3482da..45fec9e13 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/TimeInterval.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/TimeInterval.java
@@ -12,16 +12,16 @@
package org.apache.tapestry5.corelib.components;
+import java.util.Date;
+
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.MarkupWriter;
-import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.annotations.SupportsInformalParameters;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.services.DateUtilities;
-import java.util.Date;
-
/**
* Used to present an interval value using Moment.js's from() or fromNow() functions. The interval
* is determined in terms of a start and end date; either (but not both) may be omitted, in which
@@ -40,7 +40,6 @@ import java.util.Date;
* @since 5.4
*/
@SupportsInformalParameters
-@Import(module = "t5/core/time-interval")
public class TimeInterval
{
/**
@@ -65,6 +64,9 @@ public class TimeInterval
@Inject
ComponentResources resources;
+
+ @Inject
+ private RequireJsModeHelper requireJsModeHelper;
@Inject
DateUtilities dateUtilities;
@@ -76,6 +78,9 @@ public class TimeInterval
boolean beginRender(MarkupWriter writer)
{
+
+ requireJsModeHelper.importModule("t5/core/time-interval");
+
writer.element(resources.getElementName("span"),
// Trigger the client-side logic:
"data-timeinterval", "true",
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Tree.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Tree.java
index 7167574a4..a7a670236 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Tree.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Tree.java
@@ -12,13 +12,25 @@
package org.apache.tapestry5.corelib.components;
-import org.apache.tapestry5.*;
-import org.apache.tapestry5.annotations.*;
+import java.util.List;
+
+import org.apache.tapestry5.BindingConstants;
+import org.apache.tapestry5.Block;
+import org.apache.tapestry5.ComponentResources;
+import org.apache.tapestry5.EventConstants;
+import org.apache.tapestry5.MarkupWriter;
+import org.apache.tapestry5.annotations.Environmental;
+import org.apache.tapestry5.annotations.Events;
+import org.apache.tapestry5.annotations.Parameter;
+import org.apache.tapestry5.annotations.Persist;
+import org.apache.tapestry5.annotations.Property;
+import org.apache.tapestry5.annotations.RequestParameter;
import org.apache.tapestry5.dom.Element;
import org.apache.tapestry5.func.F;
import org.apache.tapestry5.func.Flow;
import org.apache.tapestry5.func.Worker;
import org.apache.tapestry5.http.Link;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
import org.apache.tapestry5.internal.util.CaptureResultCallback;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.json.JSONObject;
@@ -26,9 +38,11 @@ import org.apache.tapestry5.runtime.RenderCommand;
import org.apache.tapestry5.runtime.RenderQueue;
import org.apache.tapestry5.services.Heartbeat;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;
-import org.apache.tapestry5.tree.*;
-
-import java.util.List;
+import org.apache.tapestry5.tree.DefaultTreeExpansionModel;
+import org.apache.tapestry5.tree.TreeExpansionModel;
+import org.apache.tapestry5.tree.TreeModel;
+import org.apache.tapestry5.tree.TreeNode;
+import org.apache.tapestry5.tree.TreeSelectionModel;
/**
* A component used to render a recursive tree structure, with expandable/collapsable/selectable nodes. The data that is displayed
@@ -45,9 +59,8 @@ import java.util.List;
* @since 5.3
*/
@SuppressWarnings(
- {"rawtypes", "unchecked", "unused"})
+ {"rawtypes", "unchecked"})
@Events({EventConstants.NODE_SELECTED, EventConstants.NODE_UNSELECTED})
-@Import(module = "t5/core/tree")
public class Tree
{
/**
@@ -143,6 +156,14 @@ public class Tree
@Environmental
private Heartbeat heartbeat;
+
+ @Inject
+ private RequireJsModeHelper requireJsModeHelper;
+
+ void beginRender()
+ {
+ requireJsModeHelper.importModule("t5/core/tree");
+ }
/**
* Renders a single node (which may be the last within its containing node).
@@ -160,6 +181,7 @@ public class Tree
{
return new RenderCommand()
{
+ @SuppressWarnings("deprecation")
public void render(MarkupWriter writer, RenderQueue queue)
{
// Inform the component's container about what value is being rendered
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Zone.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Zone.java
index b4e9b0282..276cf8d82 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Zone.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Zone.java
@@ -12,14 +12,24 @@
package org.apache.tapestry5.corelib.components;
-import org.apache.tapestry5.*;
-import org.apache.tapestry5.annotations.*;
-import org.apache.tapestry5.beanmodel.services.*;
+import org.apache.tapestry5.BindingConstants;
+import org.apache.tapestry5.Block;
+import org.apache.tapestry5.ClientBodyElement;
+import org.apache.tapestry5.ComponentAction;
+import org.apache.tapestry5.ComponentResources;
+import org.apache.tapestry5.MarkupWriter;
+import org.apache.tapestry5.QueryParameterConstants;
+import org.apache.tapestry5.SymbolConstants;
+import org.apache.tapestry5.annotations.BeginRender;
+import org.apache.tapestry5.annotations.Environmental;
+import org.apache.tapestry5.annotations.Parameter;
+import org.apache.tapestry5.annotations.SupportsInformalParameters;
import org.apache.tapestry5.corelib.internal.ComponentActionSink;
import org.apache.tapestry5.corelib.internal.FormSupportAdapter;
import org.apache.tapestry5.corelib.internal.HiddenFieldPositioner;
import org.apache.tapestry5.dom.Element;
import org.apache.tapestry5.internal.services.RequestConstants;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.json.JSONObject;
@@ -68,7 +78,6 @@ import org.slf4j.Logger;
* @see FormFragment
*/
@SupportsInformalParameters
-@Import(module = "t5/core/zone")
public class Zone implements ClientBodyElement
{
/**
@@ -144,6 +153,9 @@ public class Zone implements ClientBodyElement
@Inject
private HiddenFieldLocationRules rules;
+
+ @Inject
+ private RequireJsModeHelper requireJsModeHelper;
private String clientId;
@@ -175,6 +187,9 @@ public class Zone implements ClientBodyElement
void beginRender(MarkupWriter writer)
{
+
+ requireJsModeHelper.importModule("t5/core/zone");
+
clientId = resources.isBound("id") ? idParameter : javascriptSupport.allocateClientId(resources);
Element e = writer.element(elementName,
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/mixins/Autocomplete.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/mixins/Autocomplete.java
index 8d72839fd..097fe7951 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/mixins/Autocomplete.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/mixins/Autocomplete.java
@@ -12,11 +12,27 @@
package org.apache.tapestry5.corelib.mixins;
-import org.apache.tapestry5.*;
-import org.apache.tapestry5.annotations.*;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.tapestry5.BindingConstants;
+import org.apache.tapestry5.ComponentEventCallback;
+import org.apache.tapestry5.ComponentResources;
+import org.apache.tapestry5.EventConstants;
+import org.apache.tapestry5.EventContext;
+import org.apache.tapestry5.Field;
+import org.apache.tapestry5.MarkupWriter;
+import org.apache.tapestry5.annotations.Environmental;
+import org.apache.tapestry5.annotations.Events;
+import org.apache.tapestry5.annotations.Import;
+import org.apache.tapestry5.annotations.InjectContainer;
+import org.apache.tapestry5.annotations.MixinAfter;
+import org.apache.tapestry5.annotations.Parameter;
+import org.apache.tapestry5.annotations.RequestParameter;
import org.apache.tapestry5.commons.services.TypeCoercer;
import org.apache.tapestry5.http.Link;
import org.apache.tapestry5.internal.AbstractEventContext;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
import org.apache.tapestry5.internal.util.Holder;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.json.JSONArray;
@@ -24,9 +40,6 @@ import org.apache.tapestry5.json.JSONObject;
import org.apache.tapestry5.services.compatibility.DeprecationWarning;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;
-import java.util.Collections;
-import java.util.List;
-
/**
* A mixin for a text field that allows for autocompletion of text fields. This is based on
* Twttter <a href="http://twitter.github.io/typeahead.js/">typeahead.js</a> version 0.10.5.
@@ -61,6 +74,9 @@ public class Autocomplete
@Environmental
private JavaScriptSupport jsSupport;
+
+ @Inject
+ private RequireJsModeHelper requireJsModeHelper;
@Inject
private TypeCoercer coercer;
@@ -129,7 +145,7 @@ public class Autocomplete
JSONObject spec = new JSONObject("id", field.getClientId(),
"url", link.toString()).put("minChars", minChars).put("limit", maxSuggestions);
- jsSupport.require("t5/core/autocomplete").with(spec);
+ requireJsModeHelper.importModule("t5/core/autocomplete").with(spec);
}
Object onAutocomplete(final EventContext context, @RequestParameter("t:input")
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/mixins/Confirm.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/mixins/Confirm.java
index f67d203e8..f41245338 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/mixins/Confirm.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/mixins/Confirm.java
@@ -17,6 +17,8 @@ import org.apache.tapestry5.MarkupWriter;
import org.apache.tapestry5.annotations.Environmental;
import org.apache.tapestry5.annotations.MixinAfter;
import org.apache.tapestry5.annotations.Parameter;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
+import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;
/**
@@ -47,8 +49,8 @@ public class Confirm
@Parameter("false")
private boolean disabled;
- @Environmental
- private JavaScriptSupport javaScriptSupport;
+ @Inject
+ private RequireJsModeHelper requireJsModeHelper;
/*
* The CSS class for the ok button
@@ -72,7 +74,7 @@ public class Confirm
{
if (!disabled)
{
- javaScriptSupport.require("t5/core/confirm-click");
+ requireJsModeHelper.importModule("t5/core/confirm-click");
writer.attributes("data-confirm-title", title,
"data-confirm-message", message,
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/mixins/TriggerFragment.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/mixins/TriggerFragment.java
index 2d497b53e..6055316ee 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/mixins/TriggerFragment.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/mixins/TriggerFragment.java
@@ -17,13 +17,13 @@ package org.apache.tapestry5.corelib.mixins;
import org.apache.tapestry5.BindingConstants;
import org.apache.tapestry5.ClientElement;
import org.apache.tapestry5.Field;
-import org.apache.tapestry5.annotations.Environmental;
import org.apache.tapestry5.annotations.HeartbeatDeferred;
import org.apache.tapestry5.annotations.InjectContainer;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.corelib.components.FormFragment;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
+import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.json.JSONObject;
-import org.apache.tapestry5.services.javascript.JavaScriptSupport;
/**
* A mixin that can be applied to a {@link org.apache.tapestry5.corelib.components.Checkbox} or
@@ -53,8 +53,8 @@ public class TriggerFragment
@Parameter
private boolean invert;
- @Environmental
- private JavaScriptSupport javascriptSupport;
+ @Inject
+ private RequireJsModeHelper requireJsModeHelper;
@HeartbeatDeferred
void beginRender()
@@ -73,6 +73,6 @@ public class TriggerFragment
spec.put("invert", true);
}
- javascriptSupport.require("t5/core/form-fragment").invoke("linkTrigger").with(spec);
+ requireJsModeHelper.importModule("t5/core/form-fragment").invoke("linkTrigger").with(spec);
}
}
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/mixins/ZoneRefresh.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/mixins/ZoneRefresh.java
index 372618c5b..e2e02fb7f 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/mixins/ZoneRefresh.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/mixins/ZoneRefresh.java
@@ -19,6 +19,7 @@ import org.apache.tapestry5.annotations.InjectContainer;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.corelib.components.Zone;
import org.apache.tapestry5.http.Link;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
import org.apache.tapestry5.internal.util.CaptureResultCallback;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;
@@ -57,17 +58,17 @@ public class ZoneRefresh
private Zone zone;
@Inject
- private JavaScriptSupport javaScriptSupport;
+ private RequireJsModeHelper requireJsModeHelper;
@Inject
private ComponentResources resources;
//For testing purpose
- ZoneRefresh(Object[] context, ComponentResources resources, JavaScriptSupport javaScriptSupport, Zone zone)
+ ZoneRefresh(Object[] context, ComponentResources resources, RequireJsModeHelper requireJsModeHelper, Zone zone)
{
this.context = context;
this.resources = resources;
- this.javaScriptSupport = javaScriptSupport;
+ this.requireJsModeHelper = requireJsModeHelper;
this.zone = zone;
}
@@ -76,7 +77,7 @@ public class ZoneRefresh
{
Link link = resources.createEventLink("zoneRefresh", context);
- javaScriptSupport.require("t5/core/zone-refresh").with(zone.getClientId(), period, link.toString());
+ requireJsModeHelper.importModule("t5/core/zone-refresh").with(zone.getClientId(), period, link.toString());
}
Object onZoneRefresh(EventContext eventContext)
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/alerts/AlertManagerImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/alerts/AlertManagerImpl.java
index 63ace7cf5..29f43d597 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/alerts/AlertManagerImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/alerts/AlertManagerImpl.java
@@ -14,10 +14,13 @@
package org.apache.tapestry5.internal.alerts;
+import org.apache.tapestry5.SymbolConstants;
import org.apache.tapestry5.alerts.*;
import org.apache.tapestry5.http.services.Request;
+import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.ioc.services.PerThreadValue;
import org.apache.tapestry5.ioc.services.PerthreadManager;
+import org.apache.tapestry5.json.JSONObject;
import org.apache.tapestry5.services.ApplicationStateManager;
import org.apache.tapestry5.services.ajax.AjaxResponseRenderer;
import org.apache.tapestry5.services.ajax.JavaScriptCallback;
@@ -32,12 +35,17 @@ public class AlertManagerImpl implements AlertManager
private final AjaxResponseRenderer ajaxResponseRenderer;
private final PerThreadValue<Boolean> needAlertStorageCleanup;
+
+ private final boolean requireJsEnabled;
- public AlertManagerImpl(ApplicationStateManager asm, Request request, AjaxResponseRenderer ajaxResponseRenderer, PerthreadManager perThreadManager)
+ public AlertManagerImpl(ApplicationStateManager asm, Request request,
+ AjaxResponseRenderer ajaxResponseRenderer, PerthreadManager perThreadManager,
+ @Symbol(SymbolConstants.REQUIRE_JS_ENABLED) boolean requireJsEnabled)
{
this.asm = asm;
this.request = request;
this.ajaxResponseRenderer = ajaxResponseRenderer;
+ this.requireJsEnabled = requireJsEnabled;
needAlertStorageCleanup = perThreadManager.createValue();
}
@@ -89,7 +97,15 @@ public class AlertManagerImpl implements AlertManager
{
public void run(JavaScriptSupport javascriptSupport)
{
- javascriptSupport.require("t5/core/alert").with(alert.toJSON());
+ final JSONObject json = alert.toJSON();
+ if (requireJsEnabled)
+ {
+ javascriptSupport.require("t5/core/alert").with(json);
+ }
+ else
+ {
+ javascriptSupport.importEsModule("t5/core/alert").with(json);
+ }
}
});
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DocumentLinkerImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DocumentLinkerImpl.java
index 8814e7faf..8c17f5ca2 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DocumentLinkerImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DocumentLinkerImpl.java
@@ -24,6 +24,7 @@ import org.apache.tapestry5.services.javascript.ModuleConfigurationCallback;
import org.apache.tapestry5.services.javascript.ModuleManager;
import org.apache.tapestry5.services.javascript.StylesheetLink;
+import java.util.Collections;
import java.util.List;
import java.util.Set;
@@ -38,7 +39,7 @@ public class DocumentLinkerImpl implements DocumentLinker
private final ModuleInitsManager initsManager = new ModuleInitsManager();
- private final EsModuleInitsManager esModulesinitsManager = new EsModuleInitsManager();
+ private final EsModuleInitsManager esModulesInitsManager = new EsModuleInitsManager();
private final List<ModuleConfigurationCallback> moduleConfigurationCallbacks = CollectionFactory.newList();
@@ -53,6 +54,8 @@ public class DocumentLinkerImpl implements DocumentLinker
private final boolean omitGeneratorMetaTag, enablePageloadingMask;
private final String tapestryBanner;
+
+ private final boolean requireJsEnabled;
// Initially false; set to true when a scriptURL or any kind of initialization is added.
private boolean hasScriptsOrInitializations;
@@ -66,12 +69,14 @@ public class DocumentLinkerImpl implements DocumentLinker
* @param tapestryVersion
*/
public DocumentLinkerImpl(ModuleManager moduleManager, EsModuleManager esModuleManager,
- boolean omitGeneratorMetaTag, boolean enablePageloadingMask, String tapestryVersion)
+ boolean omitGeneratorMetaTag, boolean enablePageloadingMask, String tapestryVersion,
+ boolean requireJsEnabled)
{
this.moduleManager = moduleManager;
this.esModuleManager = esModuleManager;
this.omitGeneratorMetaTag = omitGeneratorMetaTag;
this.enablePageloadingMask = enablePageloadingMask;
+ this.requireJsEnabled = requireJsEnabled;
tapestryBanner = "Apache Tapestry Framework (version " + tapestryVersion + ')';
}
@@ -149,15 +154,15 @@ public class DocumentLinkerImpl implements DocumentLinker
addElementBefore(head, existingMeta, "meta", "name", "generator", "content", tapestryBanner);
}
-
- addScriptElements(root);
- final List<EsModuleInitialization> esModuleInits = esModulesinitsManager.getInits();
- if (isHtmlRoot && !esModuleInits.isEmpty())
+ final List<EsModuleInitialization> imports = esModulesInitsManager.getImports();
+ if (isHtmlRoot && !imports.isEmpty())
{
esModuleManager.writeImportMap(root.find("head"), esModuleConfigurationCallbacks);
- esModuleManager.writeImports(root, esModuleInits);
+ esModuleManager.writeImports(root, imports);
}
+
+ addScriptElements(root);
}
@@ -252,8 +257,11 @@ public class DocumentLinkerImpl implements DocumentLinker
script.moveToTop(body);
}
-
- moduleManager.writeConfiguration(body, moduleConfigurationCallbacks);
+
+ if (requireJsEnabled)
+ {
+ moduleManager.writeConfiguration(body, moduleConfigurationCallbacks);
+ }
// Write the core libraries, which includes RequireJS:
@@ -265,8 +273,17 @@ public class DocumentLinkerImpl implements DocumentLinker
}
// Write the initialization at this point.
-
- moduleManager.writeInitialization(body, libraryURLs, initsManager.getSortedInits());
+ if (requireJsEnabled)
+ {
+ moduleManager.writeInitialization(body, libraryURLs, initsManager.getSortedInits());
+
+ // Libraries were already added in the line above.
+ esModuleManager.writeInitialization(body, Collections.emptyList(), esModulesInitsManager.getInitsAsJsonArrayList());
+ }
+ else
+ {
+ esModuleManager.writeInitialization(body, libraryURLs, esModulesInitsManager.getInitsAsJsonArrayList());
+ }
}
private static Element createTemporaryContainer(Element headElement, String existingElementName, String newElementName)
@@ -337,7 +354,7 @@ public class DocumentLinkerImpl implements DocumentLinker
public void addEsModuleInitialization(EsModuleInitialization initialization)
{
assert initialization != null;
- esModulesinitsManager.add(initialization);
+ esModulesInitsManager.add(initialization);
hasScriptsOrInitializations = true;
}
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/EsModuleInitsManager.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/EsModuleInitsManager.java
index e3fc767fe..c03bd6be2 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/EsModuleInitsManager.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/EsModuleInitsManager.java
@@ -25,37 +25,116 @@
package org.apache.tapestry5.internal.services;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.apache.tapestry5.commons.util.CollectionFactory;
import org.apache.tapestry5.internal.services.ajax.EsModuleInitializationImpl;
+import org.apache.tapestry5.json.JSONArray;
import org.apache.tapestry5.services.javascript.EsModuleInitialization;
public class EsModuleInitsManager
{
private final Set<String> modules = CollectionFactory.newSet();
+ private final List<EsModuleInitialization> imports = CollectionFactory.newList();
+
private final List<EsModuleInitialization> initializations = CollectionFactory.newList();
-
+
public void add(EsModuleInitialization initialization)
{
assert initialization != null;
- // We ignore a module being added again.
- final String moduleName = ((EsModuleInitializationImpl) initialization).getModuleId();
- if (!modules.contains(moduleName))
+ // We avoid having the same module being imported more than twice.
+ // Also notice non-pure inits (i.e. ones having a function name or
+ // both) are added both to the imports, so they can have
+ // <script type="module"> added for them, and to initializations,
+ // the function call will be made by t5/core/pageinit.
+ final EsModuleInitializationImpl init = (EsModuleInitializationImpl) initialization;
+ final String moduleName = init.getModuleName();
+ final boolean alreadyPresent = modules.contains(moduleName);
+ if (!init.isPure())
{
initializations.add(initialization);
+ }
+ if (!alreadyPresent)
+ {
+ imports.add(initialization);
modules.add(moduleName);
}
}
/**
- * Returns all previously added inits.
+ * Returns all imports.
+ */
+ public List<EsModuleInitialization> getImports()
+ {
+ return imports;
+ }
+
+ /**
+ * Returns all inits (pure imports and initializations) as a JSONArray list.
*/
- public List<EsModuleInitialization> getInits()
+ public List<JSONArray> getAllInitsAsJsonArrayList()
{
- return initializations;
+ List<JSONArray> list;
+ if (!imports.isEmpty() || !initializations.isEmpty())
+ {
+ list = new ArrayList<>(imports.size() + initializations.size());
+ list.addAll(toJSONArray(imports));
+ list.addAll(toJSONArray(initializations));
+ }
+ else
+ {
+ list = Collections.emptyList();
+ }
+ return list;
}
+
+ /**
+ * Returns all previously added inits as a JSONArray list.
+ */
+ public List<JSONArray> getInitsAsJsonArrayList()
+ {
+ return toJSONArray(initializations);
+ }
+
+ private List<JSONArray> toJSONArray(final List<EsModuleInitialization> inits) {
+ List<JSONArray> list;
+ if (!inits.isEmpty())
+ {
+ list = new ArrayList<>(inits.size());
+ for (EsModuleInitialization init : inits)
+ {
+ final EsModuleInitializationImpl initImpl = (EsModuleInitializationImpl) init;
+ final JSONArray arguments = initImpl.getArguments();
+ final JSONArray initArray = new JSONArray();
+
+ String moduleName = initImpl.getModuleName();
+ if (initImpl.getFunctionName() != null)
+ {
+ moduleName = moduleName + ":" + initImpl.getFunctionName();
+ }
+
+ initArray.add(moduleName);
+
+ if (arguments != null)
+ {
+ initArray.addAll(arguments);
+ }
+
+ list.add(initArray);
+
+ }
+ }
+ else
+ {
+ list = Collections.emptyList();
+ }
+ return list;
+ }
+
}
+
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PartialMarkupDocumentLinker.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PartialMarkupDocumentLinker.java
index 9ccf81629..c8fda5397 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PartialMarkupDocumentLinker.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PartialMarkupDocumentLinker.java
@@ -24,6 +24,7 @@ import org.apache.tapestry5.services.javascript.InitializationPriority;
import org.apache.tapestry5.services.javascript.ModuleConfigurationCallback;
import org.apache.tapestry5.services.javascript.StylesheetLink;
+import java.util.ArrayList;
import java.util.List;
public class PartialMarkupDocumentLinker implements DocumentLinker
@@ -34,6 +35,8 @@ public class PartialMarkupDocumentLinker implements DocumentLinker
private final ModuleInitsManager initsManager = new ModuleInitsManager();
+ private final EsModuleInitsManager esModulesinitsManager = new EsModuleInitsManager();
+
public void addCoreLibrary(String libraryURL)
{
notImplemented("addCoreLibrary");
@@ -84,7 +87,7 @@ public class PartialMarkupDocumentLinker implements DocumentLinker
@Override
public void addEsModuleInitialization(EsModuleInitialization initialization)
{
- notImplemented("addEsModuleInitialization");
+ esModulesinitsManager.add(initialization);
}
/**
@@ -106,10 +109,15 @@ public class PartialMarkupDocumentLinker implements DocumentLinker
}
List<?> inits = initsManager.getSortedInits();
+ final List<?> esModuleInits = esModulesinitsManager.getAllInitsAsJsonArrayList();
- if (inits.size() > 0)
+ if (inits.size() > 0 || esModuleInits.size() > 0)
{
- reply.in(InternalConstants.PARTIAL_KEY).put("inits", JSONArray.from(inits));
+ List<Object> allInits = new ArrayList<>(inits.size() + esModuleInits.size());
+ allInits.addAll(inits);
+ allInits.addAll(esModuleInits);
+ reply.in(InternalConstants.PARTIAL_KEY).put("inits", JSONArray.from(allInits));
}
+
}
}
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/BaseInitialization.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/BaseInitialization.java
index 589a8850a..7714dc461 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/BaseInitialization.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/BaseInitialization.java
@@ -1,3 +1,13 @@
+// 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
package org.apache.tapestry5.internal.services.ajax;
import org.apache.tapestry5.ioc.internal.util.InternalUtils;
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/EsModuleInitializationImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/EsModuleInitializationImpl.java
index 3b3bfeb4a..663b422f2 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/EsModuleInitializationImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/EsModuleInitializationImpl.java
@@ -1,9 +1,20 @@
+// 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
package org.apache.tapestry5.internal.services.ajax;
import java.util.Collections;
import java.util.Map;
import org.apache.tapestry5.commons.util.CollectionFactory;
+import org.apache.tapestry5.json.JSONArray;
import org.apache.tapestry5.services.javascript.EsModuleInitialization;
import org.apache.tapestry5.services.javascript.ImportPlacement;
@@ -12,9 +23,9 @@ public class EsModuleInitializationImpl extends BaseInitialization<EsModuleIniti
private Map<String, String> attributes;
private ImportPlacement placement = ImportPlacement.BODY_BOTTOM;
- private Object[] arguments;
+ private JSONArray arguments;
- EsModuleInitializationImpl(String moduleName)
+ public EsModuleInitializationImpl(String moduleName)
{
super(moduleName);
}
@@ -35,7 +46,7 @@ public class EsModuleInitializationImpl extends BaseInitialization<EsModuleIniti
return null;
}
- public String getModuleId() {
+ public String getModuleName() {
return moduleName;
}
@@ -56,12 +67,24 @@ public class EsModuleInitializationImpl extends BaseInitialization<EsModuleIniti
@Override
public void with(Object... arguments)
{
- this.arguments = arguments;
+ assert arguments != null;
+ this.arguments = new JSONArray(arguments);
}
- public Object[] getArguments()
+ public JSONArray getArguments()
{
return arguments;
}
+ public boolean isPure()
+ {
+ return functionName == null && arguments == null;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "ESInit[moduleName=" + moduleName + ", functionName=" + functionName + ", arguments=" + arguments + "]";
+ }
+
}
\ No newline at end of file
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/EsShimManagerImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/EsShimManagerImpl.java
new file mode 100644
index 000000000..f8a8c0dd8
--- /dev/null
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/EsShimManagerImpl.java
@@ -0,0 +1,66 @@
+// 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.apache.tapestry5.internal.services.ajax;
+
+import java.util.Map;
+
+import org.apache.tapestry5.SymbolConstants;
+import org.apache.tapestry5.commons.Resource;
+import org.apache.tapestry5.ioc.annotations.Symbol;
+import org.apache.tapestry5.services.PathConstructor;
+import org.apache.tapestry5.services.javascript.EsShimManager;
+
+public class EsShimManagerImpl implements EsShimManager
+{
+
+ private static final String ES_SUBPATH = "es-shims";
+
+ private final Map<String, Resource> shims;
+
+ private final PathConstructor pathConstructor;
+
+ private final String assetPrefix;
+
+ public EsShimManagerImpl(Map<String, Resource> shims,
+ PathConstructor pathConstructor,
+ @Symbol(SymbolConstants.ASSET_PATH_PREFIX)
+ String assetPrefix)
+ {
+ super();
+ this.shims = shims;
+ this.assetPrefix = assetPrefix;
+ this.pathConstructor = pathConstructor;
+ }
+
+ /**
+ * Returns the shims as a (module name, module resource) map.
+ * @return a {@code Map<String, Resource>}
+ */
+ @Override
+ public Map<String, Resource> getShims()
+ {
+ return shims;
+ }
+
+ @Override
+ public String getRequestPrefix(boolean compress)
+ {
+ return pathConstructor.constructDispatchPath(assetPrefix + "/" + (compress ? ES_SUBPATH + ".gz" : ES_SUBPATH) + "/");
+ }
+
+ @Override
+ public String getUrl(String moduleName) {
+ return getRequestPrefix(true) + moduleName + ".js";
+ }
+
+}
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/JavaScriptSupportImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/JavaScriptSupportImpl.java
index 5cf4dbd3b..f9f5e2b23 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/JavaScriptSupportImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/JavaScriptSupportImpl.java
@@ -22,16 +22,19 @@ import org.apache.tapestry5.Asset;
import org.apache.tapestry5.BooleanHook;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.FieldFocusPriority;
+import org.apache.tapestry5.SymbolConstants;
import org.apache.tapestry5.commons.util.CollectionFactory;
import org.apache.tapestry5.func.F;
import org.apache.tapestry5.func.Worker;
import org.apache.tapestry5.internal.InternalConstants;
import org.apache.tapestry5.internal.services.DocumentLinker;
import org.apache.tapestry5.internal.services.javascript.JavaScriptStackPathConstructor;
+import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.ioc.internal.util.InternalUtils;
import org.apache.tapestry5.ioc.util.IdAllocator;
import org.apache.tapestry5.json.JSONArray;
import org.apache.tapestry5.json.JSONObject;
+import org.apache.tapestry5.services.javascript.AbstractInitialization;
import org.apache.tapestry5.services.javascript.EsModuleConfigurationCallback;
import org.apache.tapestry5.services.javascript.EsModuleInitialization;
import org.apache.tapestry5.services.javascript.Initialization;
@@ -44,6 +47,8 @@ import org.apache.tapestry5.services.javascript.StylesheetLink;
public class JavaScriptSupportImpl implements JavaScriptSupport
{
+ private static final String PAGEINIT_MODULE_NAME = "t5/core/pageinit";
+
private final IdAllocator idAllocator;
private final DocumentLinker linker;
@@ -77,11 +82,14 @@ public class JavaScriptSupportImpl implements JavaScriptSupport
private String focusFieldId;
private Map<String, String> libraryURLToStackName, moduleNameToStackName;
+
+ private final boolean requireJsEnabled;
public JavaScriptSupportImpl(DocumentLinker linker, JavaScriptStackSource javascriptStackSource,
- JavaScriptStackPathConstructor stackPathConstructor, BooleanHook suppressCoreStylesheetsHook)
+ JavaScriptStackPathConstructor stackPathConstructor, BooleanHook suppressCoreStylesheetsHook,
+ @Symbol(SymbolConstants.REQUIRE_JS_ENABLED) boolean requireJsEnabled)
{
- this(linker, javascriptStackSource, stackPathConstructor, new IdAllocator(), false, suppressCoreStylesheetsHook);
+ this(linker, javascriptStackSource, stackPathConstructor, new IdAllocator(), false, suppressCoreStylesheetsHook, requireJsEnabled);
}
/**
@@ -105,7 +113,8 @@ public class JavaScriptSupportImpl implements JavaScriptSupport
*/
public JavaScriptSupportImpl(DocumentLinker linker, JavaScriptStackSource javascriptStackSource,
JavaScriptStackPathConstructor stackPathConstructor, IdAllocator idAllocator, boolean partialMode,
- BooleanHook suppressCoreStylesheetsHook)
+ BooleanHook suppressCoreStylesheetsHook,
+ @Symbol(SymbolConstants.REQUIRE_JS_ENABLED) boolean requireJsEnabled)
{
this.linker = linker;
this.idAllocator = idAllocator;
@@ -113,6 +122,7 @@ public class JavaScriptSupportImpl implements JavaScriptSupport
this.stackPathConstructor = stackPathConstructor;
this.partialMode = partialMode;
this.suppressCoreStylesheetsHook = suppressCoreStylesheetsHook;
+ this.requireJsEnabled = requireJsEnabled;
// In partial mode, assume that the infrastructure stack is already present
// (from the original page render).
@@ -126,10 +136,21 @@ public class JavaScriptSupportImpl implements JavaScriptSupport
public void commit()
{
+ final String pageInitModuleName = PAGEINIT_MODULE_NAME;
// TODO make no Require.js version of this
if (focusFieldId != null)
{
- require("t5/core/pageinit").invoke("focus").with(focusFieldId);
+ final AbstractInitialization<?> initialization;
+
+ if (requireJsEnabled)
+ {
+ initialization = require(pageInitModuleName);
+ }
+ else
+ {
+ initialization = importEsModule(pageInitModuleName);
+ }
+ initialization.invoke("focus").with(focusFieldId);
}
F.flow(stylesheetLinks).each(new Worker<StylesheetLink>()
@@ -217,7 +238,16 @@ public class JavaScriptSupportImpl implements JavaScriptSupport
if (partialMode)
{
- require("t5/core/pageinit").invoke("evalJavaScript").with(newScript);
+ final AbstractInitialization<?> initialization;
+ if (requireJsEnabled)
+ {
+ initialization = require(PAGEINIT_MODULE_NAME);
+ }
+ else
+ {
+ initialization = importEsModule(PAGEINIT_MODULE_NAME);
+ }
+ initialization.invoke("evalJavaScript").with(newScript);
} else
{
linker.addScript(priority, newScript);
@@ -450,8 +480,6 @@ public class JavaScriptSupportImpl implements JavaScriptSupport
assert InternalUtils.isNonBlank(moduleName);
- // TODO import core libraries (jQuery, Prototype/Scriptaculous/Underscore)
-
EsModuleInitialization init = new EsModuleInitializationImpl(moduleName);
if (!esModulesImported.contains(moduleName))
{
@@ -467,4 +495,10 @@ public class JavaScriptSupportImpl implements JavaScriptSupport
linker.addEsModuleConfigurationCallback(callback);
}
+ @Override
+ public boolean isRequireJsEnabled()
+ {
+ return requireJsEnabled;
+ }
+
}
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/RequireJsModeHelper.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/RequireJsModeHelper.java
new file mode 100644
index 000000000..e752c8b20
--- /dev/null
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/RequireJsModeHelper.java
@@ -0,0 +1,41 @@
+// 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.apache.tapestry5.internal.services.ajax;
+
+import org.apache.tapestry5.SymbolConstants;
+import org.apache.tapestry5.services.javascript.AbstractInitialization;
+import org.apache.tapestry5.services.javascript.JavaScriptSupport;
+
+/**
+ * Internal service to encapsulate the logic of calling
+ * {@linkplain JavaScriptSupport#require(String)} or
+ * {@linkplain JavaScriptSupport#importEsModule(String)}
+ * depending on the value of {@linkplain SymbolConstants#REQUIRE_JS_ENABLED}.
+ * Should only be used inside Tapestry itself. In user projects,
+ * explicit calls to the {@linkplain JavaScriptSupport} method should be used
+ * instead, since they'll be using just one mode (i.e. Require.js enabled or not).
+ * @since 5.10.0
+ */
+public interface RequireJsModeHelper
+{
+
+ /**
+ * Returns either {@linkplain JavaScriptSupport#require(String)} or
+ * {@linkplain JavaScriptSupport#importEsModule(String)} depending on the
+ * value of the {@linkplain SymbolConstants#REQUIRE_JS_ENABLED} configuration
+ * symbol value.
+
+ * @param moduleName the module name or id.
+ * @return an {@linkplain AbstractInitialization} instance.
+ */
+ AbstractInitialization<?> importModule(String moduleName);
+}
\ No newline at end of file
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/RequireJsModeHelperImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/RequireJsModeHelperImpl.java
new file mode 100644
index 000000000..d3406b4b7
--- /dev/null
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/RequireJsModeHelperImpl.java
@@ -0,0 +1,49 @@
+// 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.apache.tapestry5.internal.services.ajax;
+
+import org.apache.tapestry5.SymbolConstants;
+import org.apache.tapestry5.ioc.annotations.Symbol;
+import org.apache.tapestry5.services.javascript.AbstractInitialization;
+import org.apache.tapestry5.services.javascript.JavaScriptSupport;
+
+public class RequireJsModeHelperImpl implements RequireJsModeHelper
+{
+
+ private final JavaScriptSupport javaScriptSupport;
+
+ private final boolean requireJsEnabled;
+
+ public RequireJsModeHelperImpl(
+ final JavaScriptSupport javaScriptSupport,
+ @Symbol(SymbolConstants.REQUIRE_JS_ENABLED) final boolean requireJsEnabled)
+ {
+ this.javaScriptSupport = javaScriptSupport;
+ this.requireJsEnabled = requireJsEnabled;
+ }
+
+ /**
+ * Returns either {@linkplain JavaScriptSupport#require(String)} or
+ * {@linkplain JavaScriptSupport#importEsModule(String)} depending on the
+ * value of the {@linkplain SymbolConstants#REQUIRE_JS_ENABLED} configuration
+ * symbol value.
+
+ * @param moduleName the module name or id.
+ * @return an {@linkplain AbstractInitialization} instance.
+ */
+ public AbstractInitialization<?> importModule(String moduleName)
+ {
+ return requireJsEnabled ?
+ javaScriptSupport.require(moduleName) :
+ javaScriptSupport.importEsModule(moduleName);
+ }
+}
\ No newline at end of file
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/EsModuleManagerImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/EsModuleManagerImpl.java
index f65cc7a49..6c5f17a47 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/EsModuleManagerImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/EsModuleManagerImpl.java
@@ -17,6 +17,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.stream.Collectors;
import org.apache.tapestry5.Asset;
import org.apache.tapestry5.SymbolConstants;
@@ -24,28 +25,28 @@ import org.apache.tapestry5.commons.util.AvailableValues;
import org.apache.tapestry5.commons.util.CollectionFactory;
import org.apache.tapestry5.commons.util.UnknownValueException;
import org.apache.tapestry5.dom.Element;
-import org.apache.tapestry5.http.TapestryHttpSymbolConstants;
import org.apache.tapestry5.internal.InternalConstants;
import org.apache.tapestry5.internal.services.ajax.EsModuleInitializationImpl;
import org.apache.tapestry5.internal.services.assets.ResourceChangeTracker;
import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.ioc.services.ClasspathMatcher;
import org.apache.tapestry5.ioc.services.ClasspathScanner;
+import org.apache.tapestry5.json.JSONArray;
import org.apache.tapestry5.json.JSONCollection;
import org.apache.tapestry5.json.JSONLiteral;
import org.apache.tapestry5.json.JSONObject;
import org.apache.tapestry5.services.AssetSource;
+import org.apache.tapestry5.services.Core;
import org.apache.tapestry5.services.assets.StreamableResourceSource;
import org.apache.tapestry5.services.javascript.EsModuleConfigurationCallback;
import org.apache.tapestry5.services.javascript.EsModuleInitialization;
import org.apache.tapestry5.services.javascript.EsModuleManager;
import org.apache.tapestry5.services.javascript.ImportPlacement;
+import org.apache.tapestry5.services.javascript.JavaScriptStack;
public class EsModuleManagerImpl implements EsModuleManager
{
- private static final String GENERIC_IMPORTED_VARIABLE = "m";
-
/**
* Name of the JSON object property containing the imports in an import map.
*/
@@ -54,12 +55,14 @@ public class EsModuleManagerImpl implements EsModuleManager
private static final String CLASSPATH_ROOT = "META-INF/assets/es-modules/";
private final boolean compactJSON;
-
- private final boolean productionMode;
+
+ private final boolean requireJsEnabled;
private final Set<String> extensions;
private final AssetSource assetSource;
+
+ private final List<EsModuleInitialization> coreStackInits;
// Note: ConcurrentHashMap does not support null as a value, alas. We use classpathRoot as a null.
private final Map<String, String> cache = CollectionFactory.newConcurrentMap();
@@ -73,23 +76,35 @@ public class EsModuleManagerImpl implements EsModuleManager
private final List<EsModuleConfigurationCallback> baseCallbacks;
private final List<EsModuleConfigurationCallback> globalPerRequestCallbacks;
-
+
+ private final String infraProvider;
+
public EsModuleManagerImpl(
List<EsModuleManagerContribution> contributions,
AssetSource assetSource,
StreamableResourceSource streamableResourceSource,
@Symbol(SymbolConstants.COMPACT_JSON)
boolean compactJSON,
- @Symbol(TapestryHttpSymbolConstants.PRODUCTION_MODE)
- boolean productionMode,
+ @Symbol(SymbolConstants.REQUIRE_JS_ENABLED)
+ boolean requireJsEnabled,
+ @Symbol(SymbolConstants.JAVASCRIPT_INFRASTRUCTURE_PROVIDER)
+ String infraProvider,
ClasspathScanner classpathScanner,
- ResourceChangeTracker resourceChangeTracker)
+ ResourceChangeTracker resourceChangeTracker,
+ @Core JavaScriptStack javaScriptStack)
{
this.compactJSON = compactJSON;
+ this.requireJsEnabled = requireJsEnabled;
this.assetSource = assetSource;
this.classpathScanner = classpathScanner;
- this.productionMode = productionMode;
this.resourceChangeTracker = resourceChangeTracker;
+ this.infraProvider = infraProvider;
+
+ final List<String> coreStackEsModules = javaScriptStack.getEsModules();
+
+ coreStackInits = coreStackEsModules.stream()
+ .map(i -> new EsModuleInitializationImpl(i))
+ .collect(Collectors.toList());
baseCallbacks = new ArrayList<>();
globalPerRequestCallbacks = new ArrayList<>();
@@ -151,12 +166,22 @@ public class EsModuleManagerImpl implements EsModuleManager
final Set<String> scan = classpathScanner.scan(CLASSPATH_ROOT, matcher);
for (String file : scan)
{
- String id = file.replace(CLASSPATH_ROOT, "");
- id = id.substring(0, id.lastIndexOf('.'));
+ String moduleName = file.replace(CLASSPATH_ROOT, "");
+ moduleName = moduleName.substring(0, moduleName.lastIndexOf('.'));
+
+ if (moduleName.startsWith("t5/core/t5-core-dom-"))
+ {
+ // They're treated specially.
+ continue;
+ }
+ else if (moduleName.equals("t5/core/dom"))
+ {
+ file = file.replace("t5/core/dom", "t5/core/t5-core-dom-" + infraProvider);
+ }
final Asset asset = assetSource.getClasspathAsset(file);
resourceChangeTracker.trackResource(asset.getResource());
- imports.put(id, asset.toClientURL());
+ imports.put(moduleName, asset.toClientURL());
}
} catch (IOException e)
{
@@ -189,15 +214,18 @@ public class EsModuleManagerImpl implements EsModuleManager
Element head = null;
ImportPlacement placement;
EsModuleInitializationImpl init;
- String functionName;
- Object[] arguments;
- for (EsModuleInitialization i : inits)
+ List<EsModuleInitialization> allInits = new ArrayList<>(coreStackInits.size() + inits.size());
+ allInits.addAll(coreStackInits);
+ allInits.addAll(inits);
+
+ for (EsModuleInitialization i : allInits)
{
init = (EsModuleInitializationImpl) i;
- final String moduleId = init.getModuleId();
- // Making sure the user doesn't shoot heir own foot
+ final String moduleId = init.getModuleName();
+
+ // Making sure the user doesn't shoot their own foot
final String url = cache.get(moduleId);
if (url == null)
{
@@ -211,6 +239,14 @@ public class EsModuleManagerImpl implements EsModuleManager
if (head == null)
{
head = root.find("head");
+ // I think it's quite ugly, but HTML doesn't require
+ // <head>, <body> nor even <html> itself. In this case,
+ // if <head> isn't found, we just add the element to
+ // the root element.
+ if (head == null)
+ {
+ head = root;
+ }
}
script = head.element("script");
}
@@ -218,6 +254,14 @@ public class EsModuleManagerImpl implements EsModuleManager
if (body == null)
{
body = root.find("body");
+ // I think it's quite ugly, but HTML doesn't require
+ // <head>, <body> nor even <html> itself. In this case,
+ // if <body> isn't found, we just add the element to
+ // the root element.
+ if (body == null)
+ {
+ body = root;
+ }
}
if (placement.equals(ImportPlacement.BODY_BOTTOM)) {
script = body.element("script");
@@ -234,73 +278,64 @@ public class EsModuleManagerImpl implements EsModuleManager
writeAttributes(script, init);
script.attribute("src", url);
+ script.attribute("data-module-id", moduleId);
- functionName = init.getFunctionName();
- arguments = init.getArguments();
-
- if (!productionMode)
- {
- script.attribute("data-module-id", moduleId);
- final Element log = script.element("script", "type", "text/javascript");
- log.text(String.format("console.debug('Imported ES module %s');", moduleId));
- log.moveBefore(script);
- }
-
- // If we have not only the import, but also an automatic function call
- if (arguments != null || functionName != null)
+ }
+
+ }
+
+ @Override
+ public void writeInitialization(Element body, List<String> libraryURLs, List<JSONArray> inits)
+ {
+
+ final boolean noInits = !requireJsEnabled && libraryURLs.isEmpty() && inits.isEmpty();
+
+ if (noInits)
+ {
+ body.forceAttributes("data-page-initialized", "true");
+ Element script = body.element("script", "type", "text/javascript");
+ script.raw("document.querySelector(\"body > div.pageloading-mask\").remove()");
+ }
+ else
+ {
+ if (!requireJsEnabled || !libraryURLs.isEmpty() || !inits.isEmpty())
{
- final Element moduleFunctionCall = script.element("script");
-
- moduleFunctionCall.moveAfter(script);
-
- final String moduleFunctionCallFormat =
- "import %s from '%s';\n"
- + "%s(%s);";
-
- final String importName = functionName != null ? functionName : GENERIC_IMPORTED_VARIABLE;
- final String importDeclaration = functionName != null ?
- "{ " + functionName + " }":
- GENERIC_IMPORTED_VARIABLE;
-
- moduleFunctionCall.text(String.format(moduleFunctionCallFormat,
- importDeclaration, moduleId, importName,
- convertToJsFunctionParameters(arguments, compactJSON)));
-
- writeAttributes(moduleFunctionCall, init);
-
- // Avoiding duplicated ids
- final String id = moduleFunctionCall.getAttribute("id");
- if (id != null)
- {
- moduleFunctionCall.forceAttributes("id", id + "-function-call");
- }
-
+ Element element = body.element("script", "type", "module", "id", "__tapestry-es-module-pageinit__");
+
+ element.raw(String.format("import pageinit from \"t5/core/pageinit\";\npageinit(%s, %s, false);",
+ convert(libraryURLs), convert(inits)));
}
}
}
- static String convertToJsFunctionParameters(Object[] arguments, boolean compactJSON)
+ private String convert(List<?> input)
+ {
+ return new JSONArray().putAll(input).toString(compactJSON);
+ }
+
+
+ static String convertToJsFunctionParameters(JSONArray arguments, boolean compactJSON)
{
String result;
- if (arguments == null || arguments.length == 0)
+ if (arguments == null || arguments.size() == 0)
{
result = "";
}
- else if (arguments.length == 1)
+ else if (arguments.size() == 1)
{
- result = convertToJsFunctionParameter(arguments[0], compactJSON);
+ result = convertToJsFunctionParameter(arguments.get(0), compactJSON);
}
else {
StringBuilder builder = new StringBuilder();
- for (int i = 0; i < arguments.length; i++)
+ for (int i = 0; i < arguments.size(); i++)
{
if (i > 0)
{
builder.append(", ");
}
- builder.append(convertToJsFunctionParameter(arguments[i], compactJSON));
+ builder.append(convertToJsFunctionParameter(arguments.get(i), compactJSON));
}
result = builder.toString();
}
@@ -311,9 +346,9 @@ public class EsModuleManagerImpl implements EsModuleManager
{
String result;
- if (object == null)
+ if (object == null || object == JSONObject.NULL)
{
- result = null;
+ result = "null";
}
else if (object instanceof String || object instanceof JSONLiteral)
{
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/EsShimDispatcher.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/EsShimDispatcher.java
new file mode 100644
index 000000000..03ec9874a
--- /dev/null
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/EsShimDispatcher.java
@@ -0,0 +1,141 @@
+// 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.apache.tapestry5.internal.services.javascript;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tapestry5.commons.Resource;
+import org.apache.tapestry5.http.services.Dispatcher;
+import org.apache.tapestry5.http.services.Request;
+import org.apache.tapestry5.http.services.Response;
+import org.apache.tapestry5.internal.services.AssetDispatcher;
+import org.apache.tapestry5.internal.services.ResourceStreamer;
+import org.apache.tapestry5.internal.services.assets.ResourceChangeTracker;
+import org.apache.tapestry5.ioc.IOOperation;
+import org.apache.tapestry5.ioc.OperationTracker;
+import org.apache.tapestry5.services.assets.StreamableResource;
+import org.apache.tapestry5.services.assets.StreamableResourceProcessing;
+import org.apache.tapestry5.services.assets.StreamableResourceSource;
+import org.apache.tapestry5.services.javascript.EsShim;
+import org.apache.tapestry5.services.javascript.EsShimManager;
+
+import jakarta.servlet.http.HttpServletResponse;
+
+/**
+ * Handler contributed to {@link AssetDispatcher} with key "es-shims".
+ * It interprets the extra path as a module name and serves the ES shim
+ * for it.
+ *
+ * @see EsShim
+ */
+public class EsShimDispatcher implements Dispatcher
+{
+
+ private final ResourceStreamer streamer;
+
+ private final OperationTracker tracker;
+
+ private final String requestPrefix;
+
+ private final boolean compress;
+
+ private Map<String, StreamableResource> shimMap;
+
+ public EsShimDispatcher(EsShimManager esShimManager,
+ StreamableResourceSource streamableResourceSource,
+ ResourceChangeTracker resourceChangeTracker,
+ ResourceStreamer streamer,
+ OperationTracker tracker,
+ boolean compress)
+ {
+ this.streamer = streamer;
+ this.tracker = tracker;
+ this.compress = compress;
+
+ final Map<String, Resource> shims = esShimManager.getShims();
+ this.shimMap = new HashMap<>(shims.size());
+
+ try
+ {
+ for (String moduleName : shims.keySet())
+ {
+ shimMap.put(moduleName, streamableResourceSource.getStreamableResource(
+ shims.get(moduleName), StreamableResourceProcessing.COMPRESSION_ENABLED, resourceChangeTracker));
+ }
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+
+ requestPrefix = esShimManager.getRequestPrefix(compress);
+ }
+
+ public boolean dispatch(Request request, Response response) throws IOException
+ {
+ String path = request.getPath();
+
+ if (path.startsWith(requestPrefix))
+ {
+ String extraPath = path.substring(requestPrefix.length());
+
+ if (!handleModuleRequest(extraPath, response))
+ {
+ response.sendError(HttpServletResponse.SC_NOT_FOUND, String.format("No ES module shim for path '%s'.", extraPath));
+ }
+
+ return true;
+ }
+
+ return false;
+
+ }
+
+ private boolean handleModuleRequest(String extraPath, Response response) throws IOException
+ {
+ int dotx = extraPath.lastIndexOf('.');
+
+ if (dotx < 0)
+ {
+ return false;
+ }
+
+ if (!extraPath.substring(dotx + 1).equals("js"))
+ {
+ return false;
+ }
+
+ final String moduleName = extraPath.substring(0, dotx);
+
+ return tracker.perform(String.format("Streaming %s %s",
+ compress ? "compressed module" : "module",
+ moduleName), new IOOperation<Boolean>()
+ {
+ public Boolean perform() throws IOException
+ {
+ StreamableResource resource = shimMap.get(moduleName);
+
+ if (resource != null)
+ {
+ final String checksum = resource.getChecksum();
+ return streamer.streamResource(resource, checksum, ResourceStreamer.DEFAULT_OPTIONS);
+ }
+
+ return false;
+ }
+ });
+ }
+
+}
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/translator/NumericTranslatorSupportImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/translator/NumericTranslatorSupportImpl.java
index 2ba6a1b3a..ab036a5a8 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/translator/NumericTranslatorSupportImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/translator/NumericTranslatorSupportImpl.java
@@ -14,12 +14,6 @@
package org.apache.tapestry5.internal.translator;
-import org.apache.tapestry5.commons.services.TypeCoercer;
-import org.apache.tapestry5.commons.util.CollectionFactory;
-import org.apache.tapestry5.dom.Element;
-import org.apache.tapestry5.ioc.services.ThreadLocale;
-import org.apache.tapestry5.services.javascript.JavaScriptSupport;
-
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DecimalFormat;
@@ -29,22 +23,28 @@ import java.text.ParseException;
import java.util.Locale;
import java.util.Set;
+import org.apache.tapestry5.commons.services.TypeCoercer;
+import org.apache.tapestry5.commons.util.CollectionFactory;
+import org.apache.tapestry5.dom.Element;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
+import org.apache.tapestry5.ioc.services.ThreadLocale;
+
public class NumericTranslatorSupportImpl implements NumericTranslatorSupport
{
private final TypeCoercer typeCoercer;
private final ThreadLocale threadLocale;
- private final JavaScriptSupport javascriptSupport;
+ private final RequireJsModeHelper requireJsModeHelper;
private final Set<Class> integerTypes = CollectionFactory.newSet();
public NumericTranslatorSupportImpl(TypeCoercer typeCoercer, ThreadLocale threadLocale,
- JavaScriptSupport javascriptSupport)
+ RequireJsModeHelper requireJsModeHelper)
{
this.typeCoercer = typeCoercer;
this.threadLocale = threadLocale;
- this.javascriptSupport = javascriptSupport;
+ this.requireJsModeHelper = requireJsModeHelper;
Class[] integerTypes =
{Byte.class, Short.class, Integer.class, Long.class, BigInteger.class};
@@ -60,7 +60,7 @@ public class NumericTranslatorSupportImpl implements NumericTranslatorSupport
{
String translation = isIntegerType(type) ? "integer" : "numeric";
- javascriptSupport.require("t5/core/validation");
+ requireJsModeHelper.importModule("t5/core/validation");
element.attributes("data-validation", "true",
"data-translation", translation,
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/modules/JavaScriptModule.java b/tapestry-core/src/main/java/org/apache/tapestry5/modules/JavaScriptModule.java
index acaa25334..f069ff639 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/modules/JavaScriptModule.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/modules/JavaScriptModule.java
@@ -28,11 +28,15 @@ import org.apache.tapestry5.http.services.Request;
import org.apache.tapestry5.internal.InternalConstants;
import org.apache.tapestry5.internal.services.DocumentLinker;
import org.apache.tapestry5.internal.services.ResourceStreamer;
+import org.apache.tapestry5.internal.services.ajax.EsShimManagerImpl;
import org.apache.tapestry5.internal.services.ajax.JavaScriptSupportImpl;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelperImpl;
import org.apache.tapestry5.internal.services.assets.ResourceChangeTracker;
import org.apache.tapestry5.internal.services.javascript.AddBrowserCompatibilityStyles;
import org.apache.tapestry5.internal.services.javascript.ConfigureHTMLElementFilter;
import org.apache.tapestry5.internal.services.javascript.EsModuleManagerImpl;
+import org.apache.tapestry5.internal.services.javascript.EsShimDispatcher;
import org.apache.tapestry5.internal.services.javascript.Internal;
import org.apache.tapestry5.internal.services.javascript.JavaScriptStackPathConstructor;
import org.apache.tapestry5.internal.services.javascript.JavaScriptStackSourceImpl;
@@ -48,6 +52,7 @@ import org.apache.tapestry5.ioc.services.FactoryDefaults;
import org.apache.tapestry5.ioc.services.SymbolProvider;
import org.apache.tapestry5.ioc.util.IdAllocator;
import org.apache.tapestry5.json.JSONObject;
+import org.apache.tapestry5.services.AssetSource;
import org.apache.tapestry5.services.ComponentOverride;
import org.apache.tapestry5.services.Core;
import org.apache.tapestry5.services.Environment;
@@ -58,12 +63,15 @@ import org.apache.tapestry5.services.MarkupRendererFilter;
import org.apache.tapestry5.services.PartialMarkupRenderer;
import org.apache.tapestry5.services.PartialMarkupRendererFilter;
import org.apache.tapestry5.services.PathConstructor;
+import org.apache.tapestry5.services.assets.StreamableResourceSource;
import org.apache.tapestry5.services.compatibility.Compatibility;
import org.apache.tapestry5.services.compatibility.Trait;
import org.apache.tapestry5.services.javascript.AMDWrapper;
import org.apache.tapestry5.services.javascript.EsModuleConfigurationCallback;
import org.apache.tapestry5.services.javascript.EsModuleManager;
import org.apache.tapestry5.services.javascript.EsModuleManager.EsModuleManagerContribution;
+import org.apache.tapestry5.services.javascript.EsShim;
+import org.apache.tapestry5.services.javascript.EsShimManager;
import org.apache.tapestry5.services.javascript.ExtensibleJavaScriptStack;
import org.apache.tapestry5.services.javascript.JavaScriptModuleConfiguration;
import org.apache.tapestry5.services.javascript.JavaScriptStack;
@@ -100,6 +108,8 @@ public class JavaScriptModule
binder.bind(JavaScriptStackSource.class, JavaScriptStackSourceImpl.class);
binder.bind(JavaScriptStack.class, ExtensibleJavaScriptStack.class).withMarker(Core.class).withId("CoreJavaScriptStack");
binder.bind(JavaScriptStack.class, ExtensibleJavaScriptStack.class).withMarker(Internal.class).withId("InternalJavaScriptStack");
+ binder.bind(RequireJsModeHelper.class, RequireJsModeHelperImpl.class);
+ binder.bind(EsShimManager.class, EsShimManagerImpl.class);
}
/**
@@ -126,15 +136,15 @@ public class JavaScriptModule
/**
* The core JavaScriptStack has a number of entries:
* <dl>
- * <dt>requirejs</dt> <dd>The RequireJS AMD JavaScript library</dd>
+ * <dt>requirejs</dt> <dd>The RequireJS AMD JavaScript library (if Require.js is enabled)</dd>
* <dt>scriptaculous.js, effects.js</dt> <dd>Optional JavaScript libraries in compatibility mode (see {@link Trait#SCRIPTACULOUS})</dd>
* <dt>t53-compatibility.js</dt> <dd>Optional JavaScript library (see {@link Trait#INITIALIZERS})</dd>
- * <dt>underscore-library, underscore-module</dt>
+ * <dt>underscore-library, underscore-module (if Require.js is enabled. An ES module version of it is provided by Tapestry)</dt>
* <dt>The Underscore JavaScript library, and the shim that allows underscore to be injected</dt>
* <dt>t5/core/init</dt> <dd>Optional module related to t53-compatibility.js</dd>
- * <dt>jquery-library</dt> <dd>The jQuery library</dd>
- * <dt>jquery-noconflict</dt> <dd>Switches jQuery to no-conflict mode (only present when the infrastructure is "prototype").</dd>
- * <dt>jquery</dt> <dd>A module shim that allows jQuery to be injected (and also switches jQuery to no-conflict mode)</dd>
+ * <dt>jquery-library</dt> <dd>The jQuery library (if Require.js is enabled. An ES module version of it is provided by Tapestry)</dd>
+ * <dt>jquery-noconflict</dt> <dd>Switches jQuery to no-conflict mode (only present when the infrastructure is "prototype" and Require.js is enabled).</dd>
+ * <dt>jquery</dt> <dd>A module shim that allows jQuery to be injected (and also switches jQuery to no-conflict mode) (if Require.js is enabled. An ES module version of it is provided by Tapestry)</dd>
* <dt>bootstrap.css, tapestry.css, exception-frame.css, tapestry-console.css, tree.css</dt>
* <dd>CSS files</dd>
* <dt>t5/core/[...]</dt>
@@ -150,10 +160,14 @@ public class JavaScriptModule
public static void setupCoreJavaScriptStack(OrderedConfiguration<StackExtension> configuration,
Compatibility compatibility,
@Symbol(SymbolConstants.JAVASCRIPT_INFRASTRUCTURE_PROVIDER)
- String provider)
+ String provider,
+ @Symbol(SymbolConstants.REQUIRE_JS_ENABLED) boolean requireJsEnabled)
{
- configuration.add("requirejs", StackExtension.library(ROOT + "/require.js"));
- configuration.add("underscore-library", StackExtension.library(ROOT + "/underscore-1.13.7.js"));
+ if (requireJsEnabled)
+ {
+ configuration.add("requirejs", StackExtension.library(ROOT + "/require.js"));
+ configuration.add("underscore-library", StackExtension.library(ROOT + "/underscore-1.13.7.js"));
+ }
if (provider.equals("prototype"))
{
@@ -171,18 +185,32 @@ public class JavaScriptModule
if (compatibility.enabled(Trait.INITIALIZERS))
{
- add(configuration, StackExtensionType.LIBRARY, ROOT + "/t53-compatibility.js");
- configuration.add("t5/core/init", new StackExtension(StackExtensionType.MODULE, "t5/core/init"));
+ if (requireJsEnabled)
+ {
+ add(configuration, StackExtensionType.LIBRARY, ROOT + "/t53-compatibility.js");
+ configuration.add("t5/core/init", new StackExtension(StackExtensionType.MODULE, "t5/core/init"));
+ }
+ else
+ {
+ add(configuration, StackExtensionType.ES_MODULE, "t5/core/t53-compatibility");
+ add(configuration, StackExtensionType.ES_MODULE, "t5/core/init");
+ }
}
- configuration.add("jquery-library", StackExtension.library(ROOT + "/jquery.js"));
+ if (requireJsEnabled)
+ {
+ configuration.add("jquery-library", StackExtension.library(ROOT + "/jquery.js"));
+ }
- if (provider.equals("prototype"))
+ if (provider.equals("prototype") && requireJsEnabled)
{
configuration.add("jquery-noconflict", StackExtension.library(ROOT + "/jquery-noconflict.js"));
}
- add(configuration, StackExtensionType.MODULE, "jquery");
+ if (requireJsEnabled)
+ {
+ add(configuration, StackExtensionType.MODULE, "jquery");
+ }
add(configuration, StackExtensionType.STYLESHEET, "${" + SymbolConstants.FONT_AWESOME_ROOT + "}/css/font-awesome.css");
@@ -280,6 +308,9 @@ public class JavaScriptModule
JavaScriptStackSource javaScriptStackSource,
JavaScriptStackPathConstructor javaScriptStackPathConstructor,
LocalizationSetter localizationSetter,
+ EsShimManager esShimManager,
+ StreamableResourceSource streamableResourceSource,
+ ResourceChangeTracker resourceChangeTracker,
@Symbol(SymbolConstants.MODULE_PATH_PREFIX)
String modulePathPrefix,
@Symbol(SymbolConstants.ASSET_PATH_PREFIX)
@@ -296,6 +327,15 @@ public class JavaScriptModule
javaScriptStackSource, javaScriptStackPathConstructor, localizationSetter, modulePathPrefix,
assetPathPrefix, true),
"after:Modules", "before:ComponentEvent");
+
+ configuration.add("EsShims", new EsShimDispatcher(esShimManager, streamableResourceSource, resourceChangeTracker,
+ resourceStreamer, tracker, false),
+ "before:Asset", "before:ComponentEvent");
+
+ configuration.add("CompressedEsShims", new EsShimDispatcher(esShimManager, streamableResourceSource, resourceChangeTracker,
+ resourceStreamer, tracker, true),
+ "after:EsShims", "before:Asset", "before:ComponentEvent");
+
}
/**
@@ -312,7 +352,8 @@ public class JavaScriptModule
public void exposeJavaScriptSupportForFullPageRenders(OrderedConfiguration<MarkupRendererFilter> configuration,
final JavaScriptStackSource javascriptStackSource,
final JavaScriptStackPathConstructor javascriptStackPathConstructor,
- final Request request)
+ final Request request,
+ @Symbol(SymbolConstants.REQUIRE_JS_ENABLED) final boolean requireJsEnabled)
{
final BooleanHook suppressCoreStylesheetsHook = createSuppressCoreStylesheetHook(request);
@@ -324,7 +365,7 @@ public class JavaScriptModule
DocumentLinker linker = environment.peekRequired(DocumentLinker.class);
JavaScriptSupportImpl support = new JavaScriptSupportImpl(linker, javascriptStackSource,
- javascriptStackPathConstructor, suppressCoreStylesheetsHook);
+ javascriptStackPathConstructor, suppressCoreStylesheetsHook, requireJsEnabled);
environment.push(JavaScriptSupport.class, support);
@@ -353,7 +394,9 @@ public class JavaScriptModule
final JavaScriptStackPathConstructor javascriptStackPathConstructor,
- final Request request)
+ final Request request,
+
+ @Symbol(SymbolConstants.REQUIRE_JS_ENABLED) final boolean requireJsEnabled)
{
final BooleanHook suppressCoreStylesheetsHook = createSuppressCoreStylesheetHook(request);
@@ -379,7 +422,7 @@ public class JavaScriptModule
DocumentLinker linker = environment.peekRequired(DocumentLinker.class);
JavaScriptSupportImpl support = new JavaScriptSupportImpl(linker, javascriptStackSource,
- javascriptStackPathConstructor, idAllocator, true, suppressCoreStylesheetsHook);
+ javascriptStackPathConstructor, idAllocator, true, suppressCoreStylesheetsHook, requireJsEnabled);
environment.push(JavaScriptSupport.class, support);
@@ -513,29 +556,123 @@ public class JavaScriptModule
}
}
- @Contribute(EsModuleManager.class)
- public static void setupApplicationCatalogEsModules(OrderedConfiguration<EsModuleManagerContribution> configuration,
- LocalizationSetter localizationSetter,
- ComponentMessagesSource messagesSource,
- ResourceChangeTracker resourceChangeTracker,
- @Symbol(SymbolConstants.COMPACT_JSON) boolean compactJSON)
+ @Contribute(EsShimManager.class)
+ public static void setupBaseEsShims(
+ MappedConfiguration<String, Resource> configuration,
+ @Path("${tapestry.asset.root}/bootstrap/js/transition.js")
+ Resource transition,
+ @Path("${tapestry.asset.root}/bootstrap4/js/bootstrap-util.js")
+ Resource bootstrapUtil,
+ Compatibility compatibility,
+ AssetSource assetSource,
+ LocalizationSetter localizationSetter,
+ ComponentMessagesSource messagesSource,
+ ResourceChangeTracker resourceChangeTracker,
+ @Symbol(SymbolConstants.COMPACT_JSON) boolean compactJSON)
{
- EsModuleConfigurationCallback callback = jsonObject -> {
+ final Resource jQuery = assetSource.getClasspathAsset("/META-INF/assets/tapestry5/jquery.js")
+ .getResource();
+ configuration.add("jquery", new EsShim(jQuery)
+ .defaultExport("jQuery.noConflict()")
+ .getResource());
+
+ final Resource moment = assetSource.getClasspathAsset("/META-INF/assets/tapestry5//moment-2.15.1.js")
+ .getResource();
+ configuration.add("t5/core/moment", new EsShim(moment)
+ .defaultExport("moment")
+ .getResource());
- for (Locale locale : localizationSetter.getSupportedLocales())
+ if (compatibility.enabled(Trait.BOOTSTRAP_3))
+ {
+ final String[] modules = new String[]{"affix", "alert", "button", "carousel", "collapse", "dropdown", "modal",
+ "scrollspy", "tab", "tooltip"};
+ addBootstrap3EsShims(configuration, modules, transition);
+
+ Resource popover = transition.forFile("popover.js");
+
+ final String popoverModuleName = "bootstrap/popover";
+ configuration.add(popoverModuleName,
+ new EsShim(popover)
+ .importModule("jquery")
+ .importModule("bootstrap/tooltip")
+ .getResource());
+ }
+
+ if (compatibility.enabled(Trait.BOOTSTRAP_4))
+ {
+ final String bootstrapUtilModuleName = "bootstrap/bootstrap-util";
+ configuration.add(bootstrapUtilModuleName,
+ new EsShim(bootstrapUtil)
+ .getResource());
+
+ final String popperModuleName = "bootstrap/popper";
+ final Resource popper = bootstrapUtil.forFile("popper.js");
+ configuration.add(popperModuleName,
+ new EsShim(popper).getResource());
+
+ for (String name : new String[]{"alert", "button", "carousel", "collapse", "dropdown", "modal",
+ "scrollspy", "tab", "tooltip"})
{
- MessageCatalogResource resource = new MessageCatalogResource(false, locale, messagesSource, resourceChangeTracker, compactJSON);
-
- jsonObject.put("t5/core/messages/" + locale.toString(), resource.toURL());
+ Resource lib = bootstrapUtil.forFile(name + ".js");
+ if (lib.exists())
+ {
+ final String moduleName = "bootstrap/" + name;
+ configuration.add(moduleName,
+ new EsShim(lib)
+ .importModule(bootstrapUtilModuleName)
+ .importModule(popperModuleName)
+ .getResource());
+ }
}
-
- };
+ }
+
+ // Just the minimum to have alerts and AJAX validation working when Bootstrap
+ // is completely disabled
+ if (!compatibility.enabled(Trait.BOOTSTRAP_3) && !compatibility.enabled(Trait.BOOTSTRAP_4))
+ {
+ final String[] modules = new String[]{"alert", "dropdown", "collapse"};
+ addBootstrap3EsShims(configuration, modules, transition);
+ }
- configuration.add("ApplicationCatalog", EsModuleManagerContribution.base(callback));
+ for (Locale locale : localizationSetter.getSupportedLocales())
+ {
+ MessageCatalogResource resource = new MessageCatalogResource(true, locale, messagesSource, resourceChangeTracker, compactJSON);
+ configuration.add("t5/core/messages/" + locale.toString(),
+ new EsShim(resource).getResource());
+ }
}
-
+
+ @Contribute(EsModuleManager.class)
+ public static void setupBaseEsModules(
+ OrderedConfiguration<EsModuleManagerContribution> configuration,
+ EsShimManager esShimManager)
+ {
+ for (String moduleName : esShimManager.getShims().keySet())
+ {
+ configuration.add(moduleName, EsModuleManagerContribution.base(
+ c -> EsModuleConfigurationCallback.setImport(c, moduleName, esShimManager.getUrl(moduleName))));
+ }
+ }
+
+ private static void addBootstrap3EsShims(
+ MappedConfiguration<String, Resource> configuration,
+ String[] modules,
+ Resource reference)
+ {
+ for (String module : modules)
+ {
+ final String moduleId = "bootstrap/" + module;
+ final Resource resource = reference.forFile(module + ".js");
+ if (resource.exists())
+ {
+ configuration.add(moduleId, new EsShim(resource)
+ .importModule("jquery")
+ .getResource());
+ }
+ }
+ }
/**
* Contributes 'ConfigureHTMLElement', which writes the attributes into the HTML tag to describe locale, etc.
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java b/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
index 73a69419e..0709fd572 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
@@ -1810,6 +1810,9 @@ public final class TapestryModule
@Symbol(SymbolConstants.ENABLE_PAGELOADING_MASK)
final boolean enablePageloadingMask,
+
+ @Symbol(SymbolConstants.REQUIRE_JS_ENABLED)
+ final boolean requireJsEnabled,
final ValidationDecoratorFactory validationDecoratorFactory)
{
@@ -1817,7 +1820,9 @@ public final class TapestryModule
{
public void renderMarkup(MarkupWriter writer, MarkupRenderer renderer)
{
- DocumentLinkerImpl linker = new DocumentLinkerImpl(moduleManager, esModuleManager, omitGeneratorMeta, enablePageloadingMask, tapestryVersion);
+ DocumentLinkerImpl linker = new DocumentLinkerImpl(moduleManager,
+ esModuleManager, omitGeneratorMeta, enablePageloadingMask,
+ tapestryVersion, requireJsEnabled);
environment.push(DocumentLinker.class, linker);
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsModuleManager.java b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsModuleManager.java
index 70a3b00b0..0d97c0024 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsModuleManager.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsModuleManager.java
@@ -16,6 +16,7 @@ import java.util.List;
import org.apache.tapestry5.dom.Element;
import org.apache.tapestry5.ioc.annotations.UsesOrderedConfiguration;
+import org.apache.tapestry5.json.JSONArray;
import org.apache.tapestry5.services.javascript.EsModuleManager.EsModuleManagerContribution;
/**
@@ -45,15 +46,29 @@ public interface EsModuleManager
/**
* Invoked by the internal {@link org.apache.tapestry5.internal.services.DocumentLinker} service to write the
* ES module imports (as per {@link JavaScriptSupport#importEsModule(String)} into the page.
- * this occurs after the ES module infrastructure
+ * This occurs after the ES module infrastructure
* has been written into the page, along with the core libraries.
*
* @param root
* {@code <root>} element of the page.
- * @param inits
- * specify initialization on the page, based on loading modules, extacting functions from modules, and invoking those functions
+ * @param imports
+ * imported modules as {@linkplain EsModuleInitialization} instances.
+ */
+ void writeImports(Element root, List<EsModuleInitialization> imports);
+
+
+ /**
+ * Invoked by the internal {@link org.apache.tapestry5.internal.services.DocumentLinker} service to write the
+ * calls to {@code t5/core/pageinit} module.
+ * this occurs after the ES module infrastructure
+ * has been written into the page, along with the core libraries.
+ *
+ * @param body {@code body} element of the page.
+ * @param libraryURLs URLs of the JS files to be included in the page.
+ * @param inits a list of {@linkplain} JSONArray} instances containing the
+ * module initializations.
*/
- void writeImports(Element root, List<EsModuleInitialization> inits);
+ void writeInitialization(Element body, List<String> libraryURLs, List<JSONArray> inits);
/**
* Encapsulates a contribution to {@linkplain EsModuleManager}.
@@ -67,12 +82,16 @@ public interface EsModuleManager
private final EsModuleConfigurationCallback callback;
private final boolean isBase;
+
+ // In case this is an ES shim contribution.
+ private final EsShim esWrapper;
- EsModuleManagerContribution(EsModuleConfigurationCallback callback, boolean isBase)
+ private EsModuleManagerContribution(EsModuleConfigurationCallback callback, boolean isBase, EsShim esWrapper)
{
super();
this.callback = callback;
this.isBase = isBase;
+ this.esWrapper = esWrapper;
}
/**
@@ -83,9 +102,26 @@ public interface EsModuleManager
*/
public static EsModuleManagerContribution base(EsModuleConfigurationCallback callback)
{
- return new EsModuleManagerContribution(callback, true);
+ return new EsModuleManagerContribution(callback, true, null);
}
+ /**
+ * Creates a base contribution (one that contributes a callback used
+ * when creating the base import map to be used for all requests)
+ * which is also an ES module shim.
+ * @param esWrapper an {@linkplain EsShim} instance. It cannot be null.
+ * @param callback an {@linkplain EsModuleConfigurationCallback} instance.
+ * @return a corresponding {@linkplain EsModuleManagerContribution}.
+ */
+ public static EsModuleManagerContribution base(EsShim esWrapper, EsModuleConfigurationCallback callback)
+ {
+ if (esWrapper == null)
+ {
+ throw new IllegalArgumentException("Parameter esWrapper cannot be null");
+ }
+ return new EsModuleManagerContribution(callback, true, esWrapper);
+ }
+
/**
* Creates a global per-request contribution (one that contributes a callback used
* in all requests after the callbacks added through
@@ -96,7 +132,7 @@ public interface EsModuleManager
*/
public static EsModuleManagerContribution globalPerRequest(EsModuleConfigurationCallback callback)
{
- return new EsModuleManagerContribution(callback, false);
+ return new EsModuleManagerContribution(callback, false, null);
}
public EsModuleConfigurationCallback getCallback() {
@@ -106,6 +142,10 @@ public interface EsModuleManager
public boolean isBase() {
return isBase;
}
+
+ public EsShim getEsWrapper() {
+ return esWrapper;
+ }
}
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsShim.java b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsShim.java
new file mode 100644
index 000000000..89a2cde2d
--- /dev/null
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsShim.java
@@ -0,0 +1,189 @@
+// 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.apache.tapestry5.services.javascript;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.SequenceInputStream;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Vector;
+
+import org.apache.tapestry5.commons.Resource;
+import org.apache.tapestry5.internal.util.VirtualResource;
+
+/**
+ * Used to wrap plain JavaScript libraries as ES modules. The underlying
+ * resource is transformed before it is sent to the client.
+ *
+ * @since 5.10.0
+ */
+public class EsShim
+{
+
+ /**
+ * The underlying resource, usually a JavaScript library
+ */
+ private final Resource resource;
+
+ /**
+ * The modules that this module requires, the keys being module names and
+ * the values being the respective parameter names for the module's factory
+ * function.
+ */
+ private final Map<String, String> importConfig = new HashMap<String, String>();
+
+ /**
+ * The default export.
+ */
+ private String defaultExport;
+
+ public EsShim(final Resource resource)
+ {
+ this.resource = resource;
+ }
+
+ /**
+ * Adds a dependency on another module.
+ *
+ * @param moduleName
+ * the name of the required module, e.g. <code>jQuery</code>
+ * @param variableName
+ * the module's corresponding variable name
+ * @return this EsShim for further configuration
+ */
+ public EsShim importModule(final String moduleName,
+ final String variableName)
+ {
+ importConfig.put(moduleName, variableName);
+ return this;
+ }
+
+ /**
+ * Adds a dependency on another module. The module will be loaded but not
+ * passed to a variable. This is useful for dependencies on other
+ * modules that do not actually return a value.
+ *
+ * @param moduleName
+ * the name of the required module, e.g.
+ * <code>bootstrap/transition</code>
+ * @return this EsShim for further configuration
+ */
+ public EsShim importModule(final String moduleName)
+ {
+ importConfig.put(moduleName, null);
+ return this;
+ }
+
+ /**
+ * Defines the default export of this module.
+ * @param defaultExport the variable or expression to be the
+ * default export of the module
+ * @return this EsShim for further configuration
+ */
+ public EsShim defaultExport(final String defaultExport)
+ {
+ this.defaultExport = defaultExport;
+ return this;
+ }
+
+ /**
+ * Returns a virtual resource representing this shim.
+ * @return a {@linkplain Resource}.
+ */
+ public Resource getResource()
+ {
+ return new ESModuleWrapperResource(resource, importConfig, defaultExport);
+ }
+
+ /**
+ * A virtual resource that wraps a plain JavaScript library as an ES
+ * module.
+ */
+ private final static class ESModuleWrapperResource extends VirtualResource
+ {
+ private final Resource resource;
+ private final Map<String, String> importConfig;
+ private final String defaultExport;
+
+ public ESModuleWrapperResource(final Resource resource,
+ final Map<String, String> importConfig,
+ final String defaultExport)
+ {
+ this.resource = resource;
+ this.importConfig = importConfig;
+ this.defaultExport = defaultExport;
+ }
+
+ @Override
+ public InputStream openStream() throws IOException
+ {
+ StringBuilder imports = new StringBuilder();
+
+ for (String module : importConfig.keySet())
+ {
+ final String variableName = importConfig.get(module);
+ imports.append("import ");
+ if (variableName != null)
+ {
+ imports.append(variableName);
+ imports.append(" from ");
+ }
+ imports.append("\"");
+ imports.append(module);
+ imports.append("\";\n");
+ }
+
+
+ // Vector since SequenceInputStream doesn't have a varargs constructor
+ // nor something better than an Enumeration when you have more than
+ // 2 InputStreams to join.
+ Vector<InputStream> v = new Vector<>();
+ v.add(toInputStream(imports));
+ v.add(resource.openStream());
+ if (defaultExport != null)
+ {
+ v.add(toInputStream(String.format("\n export default %s;\n",
+ defaultExport)));
+ }
+
+ return new SequenceInputStream(v.elements());
+ }
+
+ @Override
+ public String getFile()
+ {
+ return "generated-module-for-" + resource.getFile();
+ }
+
+ @Override
+ public URL toURL()
+ {
+ return null;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "ES module wrapper for " + resource.toString();
+ }
+
+ private static InputStream toInputStream(final StringBuilder sb)
+ {
+ return new ByteArrayInputStream(sb.toString().getBytes(UTF8));
+ }
+ }
+
+}
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsShimManager.java b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsShimManager.java
new file mode 100644
index 000000000..f9d5c5f13
--- /dev/null
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsShimManager.java
@@ -0,0 +1,49 @@
+// 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.apache.tapestry5.services.javascript;
+
+import java.util.Map;
+
+import org.apache.tapestry5.commons.Resource;
+import org.apache.tapestry5.ioc.annotations.UsesMappedConfiguration;
+
+/**
+ * Service managing the ES shims.
+ *
+ * @since 5.10.0
+ */
+@UsesMappedConfiguration(Resource.class)
+public interface EsShimManager
+{
+
+ /**
+ * Returns the shims as a (module name, module resource) map.
+ * @return a {@code Map<String, Resource>}
+ */
+ Map<String, Resource> getShims();
+
+ /**
+ * Returns the request prefix to be used for ES shim URLs.
+ * @param compress a {@code boolean} to inform whether it's the compressed asset URL or not.
+ * @return the request prefix.
+ */
+ String getRequestPrefix(boolean compress);
+
+ /**
+ * Returns the full URL of a module.
+ * @param moduleName a module name.
+ * @return its URL.
+ */
+ String getUrl(String moduleName);
+
+}
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/ExtensibleJavaScriptStack.java b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/ExtensibleJavaScriptStack.java
index 8fa030fe5..0845431dd 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/ExtensibleJavaScriptStack.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/ExtensibleJavaScriptStack.java
@@ -12,6 +12,8 @@
package org.apache.tapestry5.services.javascript;
+import java.util.List;
+
import org.apache.tapestry5.Asset;
import org.apache.tapestry5.func.F;
import org.apache.tapestry5.func.Flow;
@@ -23,8 +25,6 @@ import org.apache.tapestry5.ioc.annotations.UsesOrderedConfiguration;
import org.apache.tapestry5.ioc.internal.util.InternalUtils;
import org.apache.tapestry5.services.AssetSource;
-import java.util.List;
-
/**
* An extensible implementation of {@link JavaScriptStack} that can be used as the implementation of a service.
* The contributions to the service are used to supply the libraries, stylesheets, and initialization for a
@@ -50,6 +50,8 @@ public class ExtensibleJavaScriptStack implements JavaScriptStack
private final List<String> stacks;
private final List<String> modules;
+
+ private final List<String> esModules;
private final String initialization;
@@ -116,6 +118,8 @@ public class ExtensibleJavaScriptStack implements JavaScriptStack
stacks = extensions.filter(by(StackExtensionType.STACK)).map(extractValue).toList();
modules = extensions.filter(by(StackExtensionType.MODULE)).map(extractValue).toList();
+
+ esModules = extensions.filter(by(StackExtensionType.ES_MODULE)).map(extractValue).toList();
stylesheets = extensions.filter(by(StackExtensionType.STYLESHEET)).map(extractValue).map(stringToAsset)
.map(assetToStylesheetLink).toList();
@@ -147,31 +151,41 @@ public class ExtensibleJavaScriptStack implements JavaScriptStack
}
}
+ @Override
public List<String> getStacks()
{
return stacks;
}
+ @Override
public List<Asset> getJavaScriptLibraries()
{
return libraries;
}
+ @Override
public List<StylesheetLink> getStylesheets()
{
return stylesheets;
}
+ @Override
public String getInitialization()
{
return initialization;
}
+ @Override
public List<String> getModules()
{
return modules;
}
+ @Override
+ public List<String> getEsModules() {
+ return esModules;
+ }
+
@Override
public JavaScriptAggregationStrategy getJavaScriptAggregationStrategy()
{
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/JavaScriptStack.java b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/JavaScriptStack.java
index 777c7a118..25555e396 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/JavaScriptStack.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/JavaScriptStack.java
@@ -72,6 +72,14 @@ public interface JavaScriptStack
* @since 5.4
*/
List<String> getModules();
+
+ /**
+ * Returns a list of ES modules to be automatically included in all pages.
+ *
+ * @see EsModuleManager
+ * @since 5.10.0
+ */
+ List<String> getEsModules();
/**
* Identifies how to aggregate JavaScript within the stack.
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/JavaScriptSupport.java b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/JavaScriptSupport.java
index 7624497b0..18fcedc4c 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/JavaScriptSupport.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/JavaScriptSupport.java
@@ -291,5 +291,13 @@ public interface JavaScriptSupport
* @since 5.10.0
*/
void addEsModuleConfigurationCallback(EsModuleConfigurationCallback callback);
+
+ /**
+ * Returns whether Require.js is enabled or not (i.e. the value of the
+ * {@linkplain SymbolConstants#REQUIRE_JS_ENABLED} configuration symbol.
+ *
+ * @since 5.10.0.
+ */
+ boolean isRequireJsEnabled();
}
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StackExtension.java b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StackExtension.java
index 67cc22d7b..42c463f38 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StackExtension.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StackExtension.java
@@ -62,6 +62,16 @@ public class StackExtension
return new StackExtension(StackExtensionType.MODULE, name);
}
+ /**
+ * Convenience for defining an ES_MODULE.
+ *
+ * @since 5.10.0
+ */
+ public static StackExtension esModule(String name)
+ {
+ return new StackExtension(StackExtensionType.ES_MODULE, name);
+ }
+
/**
* Convenience for defining a STYLESHEET.
*
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StackExtensionType.java b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StackExtensionType.java
index a4f0d7b48..0dccf2e44 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StackExtensionType.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StackExtensionType.java
@@ -69,6 +69,13 @@ public enum StackExtensionType
* @since 5.4
*/
MODULE,
+
+ /**
+ * An ES module to be automatically imported.
+ *
+ * @since 5.10.0
+ */
+ ES_MODULE,
/**
* Overrides the {@linkplain JavaScriptStack#getJavaScriptAggregationStrategy() JavaScript aggregation strategy}
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/validator/CheckboxValidator.java b/tapestry-core/src/main/java/org/apache/tapestry5/validator/CheckboxValidator.java
index 4cdc1d521..79a8eb231 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/validator/CheckboxValidator.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/validator/CheckboxValidator.java
@@ -67,7 +67,15 @@ class CheckboxValidator extends AbstractValidator<Void, Object>
{
if (formSupport.isClientValidationEnabled())
{
- javaScriptSupport.require("t5/core/validation");
+ if (javaScriptSupport.isRequireJsEnabled())
+ {
+ javaScriptSupport.require("t5/core/validation");
+ }
+ else
+ {
+ javaScriptSupport.importEsModule("t5/core/validation");
+ }
+
writer.attributes(
DataConstants.VALIDATION_ATTRIBUTE, true,
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/validator/Email.java b/tapestry-core/src/main/java/org/apache/tapestry5/validator/Email.java
index 07d84631c..2943ff21c 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/validator/Email.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/validator/Email.java
@@ -50,7 +50,14 @@ public class Email extends AbstractValidator<Void, String>
{
if (formSupport.isClientValidationEnabled())
{
- javaScriptSupport.require("t5/core/validation");
+ if (javaScriptSupport.isRequireJsEnabled())
+ {
+ javaScriptSupport.require("t5/core/validation");
+ }
+ else
+ {
+ javaScriptSupport.importEsModule("t5/core/validation");
+ }
writer.attributes(
DataConstants.VALIDATION_ATTRIBUTE, true,
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/validator/Max.java b/tapestry-core/src/main/java/org/apache/tapestry5/validator/Max.java
index add90ce4f..28d88d161 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/validator/Max.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/validator/Max.java
@@ -54,7 +54,14 @@ public class Max extends AbstractValidator<Long, Number>
{
if (formSupport.isClientValidationEnabled())
{
- javaScriptSupport.require("t5/core/validation");
+ if (javaScriptSupport.isRequireJsEnabled())
+ {
+ javaScriptSupport.require("t5/core/validation");
+ }
+ else
+ {
+ javaScriptSupport.importEsModule("t5/core/validation");
+ }
writer.attributes(DataConstants.VALIDATION_ATTRIBUTE, true,
"data-validate-max", constraintValue.toString(),
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/validator/MaxLength.java b/tapestry-core/src/main/java/org/apache/tapestry5/validator/MaxLength.java
index e52add886..1e424228b 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/validator/MaxLength.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/validator/MaxLength.java
@@ -49,7 +49,14 @@ public final class MaxLength extends AbstractValidator<Integer, String>
{
if (formSupport.isClientValidationEnabled())
{
- javaScriptSupport.require("t5/core/validation");
+ if (javaScriptSupport.isRequireJsEnabled())
+ {
+ javaScriptSupport.require("t5/core/validation");
+ }
+ else
+ {
+ javaScriptSupport.importEsModule("t5/core/validation");
+ }
writer.attributes(DataConstants.VALIDATION_ATTRIBUTE, true,
"data-validate-max-length", constraintValue.toString(),
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/validator/Min.java b/tapestry-core/src/main/java/org/apache/tapestry5/validator/Min.java
index b100047c0..4d2d158d7 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/validator/Min.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/validator/Min.java
@@ -51,7 +51,15 @@ public class Min extends AbstractValidator<Long, Number>
{
if (formSupport.isClientValidationEnabled())
{
- javaScriptSupport.require("t5/core/validation");
+ if (javaScriptSupport.isRequireJsEnabled())
+ {
+ javaScriptSupport.require("t5/core/validation");
+ }
+ else
+ {
+ javaScriptSupport.importEsModule("t5/core/validation");
+ }
+
writer.attributes(DataConstants.VALIDATION_ATTRIBUTE, true,
"data-validate-min", constraintValue.toString(),
"data-min-message", buildMessage(formatter, field, constraintValue));
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/validator/MinLength.java b/tapestry-core/src/main/java/org/apache/tapestry5/validator/MinLength.java
index c82bcac96..27af8bc9d 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/validator/MinLength.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/validator/MinLength.java
@@ -49,7 +49,14 @@ public final class MinLength extends AbstractValidator<Integer, String>
{
if (formSupport.isClientValidationEnabled())
{
- javaScriptSupport.require("t5/core/validation");
+ if (javaScriptSupport.isRequireJsEnabled())
+ {
+ javaScriptSupport.require("t5/core/validation");
+ }
+ else
+ {
+ javaScriptSupport.importEsModule("t5/core/validation");
+ }
writer.attributes(DataConstants.VALIDATION_ATTRIBUTE, true,
"data-validate-min-length", constraintValue.toString(),
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/validator/Regexp.java b/tapestry-core/src/main/java/org/apache/tapestry5/validator/Regexp.java
index aa4c84657..3448df986 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/validator/Regexp.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/validator/Regexp.java
@@ -48,7 +48,14 @@ public class Regexp extends AbstractValidator<Pattern, String>
if (formSupport.isClientValidationEnabled())
{
- javaScriptSupport.require("t5/core/validation");
+ if (javaScriptSupport.isRequireJsEnabled())
+ {
+ javaScriptSupport.require("t5/core/validation");
+ }
+ else
+ {
+ javaScriptSupport.importEsModule("t5/core/validation");
+ }
writer.attributes(DataConstants.VALIDATION_ATTRIBUTE, true,
"data-validate-regexp", constraintValue.pattern(),
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/validator/Required.java b/tapestry-core/src/main/java/org/apache/tapestry5/validator/Required.java
index 5410a71ab..05e7c1dcd 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/validator/Required.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/validator/Required.java
@@ -65,7 +65,14 @@ public final class Required extends AbstractValidator<Void, Object>
if (formSupport.isClientValidationEnabled())
{
- javaScriptSupport.require("t5/core/validation");
+ if (javaScriptSupport.isRequireJsEnabled())
+ {
+ javaScriptSupport.require("t5/core/validation");
+ }
+ else
+ {
+ javaScriptSupport.importEsModule("t5/core/validation");
+ }
writer.attributes(
DataConstants.VALIDATION_ATTRIBUTE, true,
diff --git a/tapestry-core/src/main/resources/META-INF/assets/es-modules/t5/underscore.js b/tapestry-core/src/main/resources/META-INF/assets/es-modules/underscore.js
similarity index 100%
rename from tapestry-core/src/main/resources/META-INF/assets/es-modules/t5/underscore.js
rename to tapestry-core/src/main/resources/META-INF/assets/es-modules/underscore.js
diff --git a/tapestry-core/src/main/resources/META-INF/assets/tapestry5/moment-2.15.1.js b/tapestry-core/src/main/resources/META-INF/assets/tapestry5/moment-2.15.1.js
index 1388ae65e..e7c5ff5d7 100644
--- a/tapestry-core/src/main/resources/META-INF/assets/tapestry5/moment-2.15.1.js
+++ b/tapestry-core/src/main/resources/META-INF/assets/tapestry5/moment-2.15.1.js
@@ -8,7 +8,7 @@
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
global.moment = factory()
-}(this, function () { 'use strict';
+}(this || window, function () { 'use strict';
var hookCallback;
diff --git a/tapestry-core/src/main/resources/META-INF/assets/tapestry5/underscore-esm.js b/tapestry-core/src/main/resources/META-INF/assets/tapestry5/underscore-esm.js
deleted file mode 100644
index dd5899219..000000000
--- a/tapestry-core/src/main/resources/META-INF/assets/tapestry5/underscore-esm.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// Underscore.js 1.13.7
-// https://underscorejs.org
-// (c) 2009-2024 Jeremy Ashkenas, Julian Gonggrijp, and DocumentCloud and Investigative Reporters & Editors
-// Underscore may be freely distributed under the MIT license.
-var VERSION="1.13.7",root="object"==typeof self&&self.self===self&&self||"object"==typeof global&&global.global===global&&global||Function("return this")()||{},ArrayProto=Array.prototype,ObjProto=Object.prototype,SymbolProto="undefined"!=typeof Symbol?Symbol.prototype:null,push=ArrayProto.push,slice=ArrayProto.slice,toString=ObjProto.toString,hasOwnProperty=ObjProto.hasOwnProperty,supportsArrayBuffer="undefined"!=typeof ArrayBuffer,supportsDataView="undefined"!=typeof DataView,nativeIsAr [...]
\ No newline at end of file
diff --git a/tapestry-core/src/main/resources/org/apache/tapestry5/core.properties b/tapestry-core/src/main/resources/org/apache/tapestry5/core.properties
index b699ea072..33c1b7f6f 100644
--- a/tapestry-core/src/main/resources/org/apache/tapestry5/core.properties
+++ b/tapestry-core/src/main/resources/org/apache/tapestry5/core.properties
@@ -118,7 +118,7 @@ core-datefield-none=None
private-no-validation-for-field=placeholder message
private-core-page-initialization-template=\
-require(["t5/core/pageinit"], function(pi) { pi.default(%s, %s); });
+require(["t5/core/pageinit"], function(pi) { pi.default(%s, %s, true); });
# BeanEditForm default className parameter default:
private-core-components.beaneditform.class=well
diff --git a/tapestry-core/src/main/typescript/src/t5/beanvalidator/beanvalidator-validation.ts b/tapestry-core/src/main/typescript/src/t5/beanvalidator/beanvalidator-validation.ts
index eb407fca4..6ba83312d 100644
--- a/tapestry-core/src/main/typescript/src/t5/beanvalidator/beanvalidator-validation.ts
+++ b/tapestry-core/src/main/typescript/src/t5/beanvalidator/beanvalidator-validation.ts
@@ -24,14 +24,13 @@
import _ from "underscore";
import dom from "t5/core/dom"
import events from "t5/core/events"
-import fields from "t5/core/fields"
+import "t5/core/fields"
import utils from "t5/core/utils"
import validation from "t5/core/validation"
-// Both lines below are used to force the TypeScript compiler to actually import t5/core/fields
+// Lines below ise used to force the TypeScript compiler to actually import t5/core/fields
// and t5/core/validation even though they're not used directly here. This file uses events
// set up by the imported files.
-let workaround1 = fields;
let workaround2 = validation;
// @ts-ignore
diff --git a/tapestry-core/src/main/typescript/src/t5/core/autocomplete.ts b/tapestry-core/src/main/typescript/src/t5/core/autocomplete.ts
index 69238e9fa..520ea8c58 100644
--- a/tapestry-core/src/main/typescript/src/t5/core/autocomplete.ts
+++ b/tapestry-core/src/main/typescript/src/t5/core/autocomplete.ts
@@ -22,11 +22,13 @@ import dom from "t5/core/dom";
import _ from "underscore";
import $ from "jquery"
import utils from "t5/core/utils";
-import typeahead from "t5/core/typeahead";
+import "t5/core/typeahead";
// Line below is used to force the TypeScript compiler to actually import t5/core/typeahead
// as it's not used directly here.
-let workaround = typeahead;
+// let workaround = typeahead;
+
+let Bloodhound = window.Bloodhound;
export default function(spec) {
const $field = $(document.getElementById(spec.id));
diff --git a/tapestry-core/src/main/typescript/src/t5/core/fields.ts b/tapestry-core/src/main/typescript/src/t5/core/fields.ts
index ba4c24005..f548d3695 100644
--- a/tapestry-core/src/main/typescript/src/t5/core/fields.ts
+++ b/tapestry-core/src/main/typescript/src/t5/core/fields.ts
@@ -237,4 +237,4 @@ dom.onDocument(events.field.showValidationError, null, function(event: EventWrap
});
-export default {findHelpBlocks, createHelpBlock, showValidationError};
\ No newline at end of file
+export {findHelpBlocks, createHelpBlock, showValidationError};
\ No newline at end of file
diff --git a/tapestry-core/src/main/typescript/src/t5/core/form-fragment.ts b/tapestry-core/src/main/typescript/src/t5/core/form-fragment.ts
index efe6cff8c..ef4931516 100644
--- a/tapestry-core/src/main/typescript/src/t5/core/form-fragment.ts
+++ b/tapestry-core/src/main/typescript/src/t5/core/form-fragment.ts
@@ -19,7 +19,7 @@ import _ from "underscore";
import dom from "t5/core/dom";
import events from "t5/core/events";
import forms from "t5/core/forms";
-import { ElementWrapper, EventWrapper }from "t5/core/types";
+import { ElementWrapper, EventWrapper } from "t5/core/types";
// Line below is used to force the TypeScript compiler to actually import t5/core/forms
// as it's not used directly here. This file uses events set up by the imported files.
@@ -82,7 +82,7 @@ dom.onDocument(events.formfragment.changeVisibility, SELECTOR, function(event: E
// When a FormFragment is initially rendered as hidden, then we need to do some
// book-keeping on the client side.
-const hide = function(id: string) {
+export const hide = function(id: string) {
const field = dom(id);
return updateFields(field!, false);
@@ -93,7 +93,7 @@ const hide = function(id: string) {
// * spec.triggerId - id of checkbox or radio button
// * spec.fragmentId - id of FormFragment element
// * spec.invert - (optional) if true, then checked trigger hides (not shows) the fragment
-const linkTrigger = function(spec: { triggerId: string | HTMLElement | null; fragmentId: string | HTMLElement | null; invert: boolean; }) {
+export const linkTrigger = function(spec: { triggerId: string | HTMLElement | null; fragmentId: string | HTMLElement | null; invert: boolean; }) {
if (spec.triggerId == null) { throw new Error("Incomplete parameters, triggerId is null"); }
if (spec.fragmentId == null) { throw new Error("Incomplete parameters, fragmentId is null"); }
const trigger = dom(spec.triggerId);
@@ -118,7 +118,4 @@ const linkTrigger = function(spec: { triggerId: string | HTMLElement | null; fra
} else {
return trigger!.on("click", null, update);
}
-};
-
-// Module exports:
-export default { linkTrigger, hide };
+};
\ No newline at end of file
diff --git a/tapestry-core/src/main/typescript/src/t5/core/messages-es-module.ts b/tapestry-core/src/main/typescript/src/t5/core/messages-es-module.ts
index afd3d4d8a..8b77d441f 100644
--- a/tapestry-core/src/main/typescript/src/t5/core/messages-es-module.ts
+++ b/tapestry-core/src/main/typescript/src/t5/core/messages-es-module.ts
@@ -43,6 +43,10 @@ const locale = (document.documentElement.getAttribute("data-locale")) || "en";
// @ts-ignore
let messages: any = await import(`t5/core/messages/${locale}`);
+if (messages['default'] != null && typeof messages['default'] === 'object') {
+ messages = messages.default;
+}
+
// Returns the application message catalog message for the given key. Returns
// a placeholder if the key is not found.
const get = function(key: string) {
diff --git a/tapestry-core/src/main/typescript/src/t5/core/pageinit.ts b/tapestry-core/src/main/typescript/src/t5/core/pageinit.ts
index 5100e68bd..8256e6c73 100644
--- a/tapestry-core/src/main/typescript/src/t5/core/pageinit.ts
+++ b/tapestry-core/src/main/typescript/src/t5/core/pageinit.ts
@@ -21,10 +21,11 @@
* Any additional values in the initializer are passed to the function. The context of the function (this) is null.
*/
-import _ from "underscore";
+import _, { partial } from "underscore";
import console from "t5/core/console";
import dom from "t5/core/dom";
import events from "t5/core/events";
+import { data } from "jquery";
let exports_: any;
let pathPrefix: String | null = null;
@@ -35,6 +36,8 @@ const isOpera = Object.prototype.toString.call(window.opera) === '[object Opera]
// @ts-ignore
const isIE = !!window.attachEvent && !isOpera;
+const requireJsEnabled = "true" == document.querySelector("html")?.dataset['requireJsEnabled'];
+
const rebuildURL = function(path: string) {
if (path.match(/^https?:/)) { return path; }
@@ -106,18 +109,15 @@ const addStylesheets = function(newStylesheets: StylesheetLink) {
};
-const invokeInitializer = function(tracker: () => any, qualifiedName: string, initArguments: any[]) {
+const invokeInitializer = function(tracker: () => any, qualifiedName: string, initArguments: any[], requireJsModule: boolean) {
const [moduleName, functionName] = Array.from(qualifiedName.split(':'));
- // @ts-ignore
- return require([moduleName], function(moduleLib: any) {
+ function executeInitializer(moduleLib: any) {
- // If it's an AMD module generated by TypeScript and it has a default export,
- // it gets wrapped, so we try to unwrap it here.
- if (moduleLib != null && moduleLib.__esModule && moduleLib["default"] != null) {
- moduleLib = moduleLib["default"];
+ if (!requireJsModule && moduleLib['default'] != null && _.isFunction(moduleLib['default'])) {
+ moduleLib = moduleLib['default'];
}
-
+
try {
// Some modules export nothing but do some full-page initialization, such as adding
// event handlers to the body.
@@ -151,17 +151,46 @@ const invokeInitializer = function(tracker: () => any, qualifiedName: string, in
} finally {
tracker();
}
- });
+
+ }
+
+ if (requireJsModule) {
+
+ // @ts-ignore
+ return require([moduleName], function(moduleLib: any) {
+
+ // If it's an AMD module generated by TypeScript and it has a default export,
+ // it gets wrapped, so we try to unwrap it here.
+ if (moduleLib != null && moduleLib.__esModule && moduleLib["default"] != null) {
+ moduleLib = moduleLib["default"];
+ }
+
+ return executeInitializer(moduleLib);
+
+ });
+
+ } else {
+
+ return import(moduleName).then(function(moduleLib: any) {
+ return executeInitializer(moduleLib);
+ });
+
+ }
};
// Pre-loads a number of libraries in order. When the last library is loaded,
// invokes the callback (with no parameters).
-function loadLibraries(libraries: string[], callback: () => any) {
+function loadLibraries(libraries: string[], requireJsModules: boolean, callback: () => any) {
// @ts-ignore
const reducer = (callback, library) => (function() {
console.debug(`Loading library ${library}`);
- // @ts-ignore
- return require([library], callback);
+ if (requireJsModules) {
+ // @ts-ignore
+ return require([library], callback);
+ }
+ else {
+ return import(library).then(callback);
+ }
});
const finalCallback = _.reduceRight(libraries, reducer, callback);
@@ -172,9 +201,9 @@ function loadLibraries(libraries: string[], callback: () => any) {
// Passed a list of initializers, executes each initializer in order. Due to asynchronous loading
// of modules, the exact order in which initializer functions are invoked is not predictable.
// @ts-ignore
-function initialize(inits, callback) {
+function initialize(inits, requireJsModules, callback) {
if (inits == null) { inits = []; }
- console.debug(`Executing ${inits.length} inits`);
+ console.debug(`Executing ${inits.length} ${requireJsModules ? "AMD" : "ES module"} inits`);
let callbackCountdown = inits.length + 1;
// tracker gets invoked once after each require/callback, plus once extra
@@ -184,7 +213,7 @@ function initialize(inits, callback) {
callbackCountdown--;
if (callbackCountdown === 0) {
- console.debug("All inits executed");
+ console.debug(`All ${requireJsModules ? "AMD" : "ES"} inits executed`);
if (callback) { return callback(); }
}
};
@@ -195,12 +224,12 @@ function initialize(inits, callback) {
// takes no parameters.
for (var init of Array.from(inits)) {
if (_.isString(init)) {
- invokeInitializer(tracker, init, []);
+ invokeInitializer(tracker, init, [], requireJsModules);
} else {
// @ts-ignore
var [qualifiedName, ...initArguments] = Array.from(init);
// @ts-ignore
- invokeInitializer(tracker, qualifiedName, initArguments);
+ invokeInitializer(tracker, qualifiedName, initArguments, requireJsModules);
}
}
@@ -215,12 +244,17 @@ function initialize(inits, callback) {
//
// This is the main export of the module; other functions are attached as properties.
// @ts-ignore
-const loadLibrariesAndInitialize = function(libraries, inits) {
+const loadLibrariesAndInitialize = function(libraries, inits, requireJsModules) {
console.debug(`Loading ${(libraries != null ? libraries.length : undefined) || 0} libraries`);
+
+ const dataAttribute = "data-page-initialized";
+ const partialValue = "partial";
+ const hasEsModulePageInit = document.querySelector("script[id='__tapestry-es-module-pageinit__']") != null;
+
// @ts-ignore
- return loadLibraries(libraries,
+ return loadLibraries(libraries, requireJsModules,
// @ts-ignore
- () => initialize(inits,
+ () => initialize(inits, requireJsModules,
function() {
// At this point, all libraries have been loaded, and all inits should have executed. Unless some of
// the inits triggered Ajax updates (such as a core/ProgressiveDisplay component), then the page should
@@ -228,6 +262,18 @@ const loadLibrariesAndInitialize = function(libraries, inits) {
// Later Ajax requests will cause the data-ajax-active attribute to be incremented (from 0)
// and decremented (when the requests complete).
+ // If Require.js is enabled, this function may be called twice: once for the
+ // Require.js initializations, another for the ES module ones.
+ // That way, we need to only set the data-page-initialized attribute to
+ // true when this function is called by the second time.
+ if (requireJsEnabled && hasEsModulePageInit) {
+ var value = dom.body.attr(dataAttribute);
+ if (value !== partialValue) {
+ dom.body.attr(dataAttribute, "partial");
+ return;
+ }
+ }
+
dom.body.attr("data-page-initialized", "true");
return Array.from(dom.body.find(".pageloading-mask")).map((mask) =>
@@ -250,7 +296,7 @@ export default exports_ = _.extend(loadLibrariesAndInitialize, {
// second, which helps ensure that other initializions on the page are in place.
//
// * fieldId - element id of field to focus on
- focus(fieldId: string) {
+ focus: function(fieldId: string) {
const field = dom(fieldId);
if (field) {
@@ -292,7 +338,7 @@ export default exports_ = _.extend(loadLibrariesAndInitialize, {
addStylesheets(partial != null ? partial.stylesheets : undefined);
// Make sure all libraries are loaded
- exports_.loadLibraries(partial != null ? partial.libraries : undefined, function() {
+ exports_.loadLibraries(partial != null ? partial.libraries : undefined, requireJsEnabled, function() {
// After libraries are loaded, update each zone:
_(partial != null ? partial.content : undefined).each(function(...args) {
@@ -310,7 +356,7 @@ export default exports_ = _.extend(loadLibrariesAndInitialize, {
callback && callback(response);
// Lastly, perform initializations from the partial page render response.
- return exports_.initialize(partial != null ? partial.inits : undefined);
+ return exports_.initialize(partial != null ? partial.inits : undefined, requireJsEnabled);
});
}
diff --git a/tapestry-core/src/main/typescript/src/t5/core/select.ts b/tapestry-core/src/main/typescript/src/t5/core/select.ts
index c109caf8a..40e537867 100644
--- a/tapestry-core/src/main/typescript/src/t5/core/select.ts
+++ b/tapestry-core/src/main/typescript/src/t5/core/select.ts
@@ -19,12 +19,12 @@
import events from "t5/core/events";
import dom from "t5/core/dom";
-import zone from "t5/core/zone";
+import { findZone } from "t5/core/zone";
dom.onDocument("change", "select[data-update-zone]", function() {
// @ts-ignore
- const containingZone = zone.findZone(this);
+ const containingZone = findZone(this);
if (containingZone) {
containingZone.trigger(events.zone.refresh, {
diff --git a/tapestry-core/src/main/typescript/src/t5/core/t53-compatibility.ts b/tapestry-core/src/main/typescript/src/t5/core/t53-compatibility.ts
new file mode 100644
index 000000000..5edf150a1
--- /dev/null
+++ b/tapestry-core/src/main/typescript/src/t5/core/t53-compatibility.ts
@@ -0,0 +1,56 @@
+// Copyright 2012, 2015 The Apache Software Foundation
+//
+// 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.
+
+// Provides a small amount of backwards compatibility to the Tapestry 5.3 approach.
+// This provides placeholders for the following:
+//
+// * `T5` namespace, including `extend`, `define`, and `initializers`, `extendInitializers`, and `_` properties
+//
+// * `Tapestry` namespace: just the `Initializer` property, as an alias of `T5.initializers`
+
+import _ from "underscore";
+
+// @ts-ignore
+var T5, Tapestry;
+T5 = {
+ _: _,
+ // @ts-ignore
+ extend: function(destination, source) {
+ if (_.isFunction(source)) {
+ source = source();
+ }
+ return _.extend(destination, source);
+ },
+ // @ts-ignore
+ define: function(name, source) {
+ var namespace;
+ namespace = {};
+ T5[name] = namespace;
+ // @ts-ignore
+ return T5.extend(namespace, source);
+ },
+ initializers: {},
+ // @ts-ignore
+ extendInitializers: function(source) {
+ // @ts-ignore
+ return T5.extend(T5.initializers, source);
+ }
+};
+Tapestry = {
+ Initializer: T5.initializers
+};
+// @ts-ignore
+window.T5 = T5;
+// @ts-ignore
+window.Tapestry = Tapestry;
diff --git a/tapestry-core/src/main/typescript/src/t5/core/typeahead.ts b/tapestry-core/src/main/typescript/src/t5/core/typeahead.ts
index 932fb05fc..6e0aa22f6 100644
--- a/tapestry-core/src/main/typescript/src/t5/core/typeahead.ts
+++ b/tapestry-core/src/main/typescript/src/t5/core/typeahead.ts
@@ -723,7 +723,7 @@
function ignoreDuplicates() {
return false;
}
- })(this);
+ })(this || window);
var html = function() {
return {
wrapper: '<span class="twitter-typeahead"></span>',
diff --git a/tapestry-core/src/main/typescript/src/t5/core/validation.ts b/tapestry-core/src/main/typescript/src/t5/core/validation.ts
index 39d47c5ab..cb5a4d69b 100644
--- a/tapestry-core/src/main/typescript/src/t5/core/validation.ts
+++ b/tapestry-core/src/main/typescript/src/t5/core/validation.ts
@@ -22,13 +22,9 @@ import dom from "t5/core/dom";
import events from "t5/core/events";
import utils from "t5/core/utils";
import messages from "t5/core/messages";
-import fields from "t5/core/fields";
+import "t5/core/fields";
import { ElementWrapper } from "t5/core/types";
-// Line below is used to force the TypeScript compiler to actually import t5/core/fields
-// as it's not used directly here. This file uses events set up by the imported files.
-let workaround = fields;
-
const REGEXP_META = "t5:regular-expression";
const minus = messages("decimal-symbols.minus");
diff --git a/tapestry-core/src/main/typescript/src/t5/core/zone.ts b/tapestry-core/src/main/typescript/src/t5/core/zone.ts
index 822e6da72..f08479029 100644
--- a/tapestry-core/src/main/typescript/src/t5/core/zone.ts
+++ b/tapestry-core/src/main/typescript/src/t5/core/zone.ts
@@ -213,5 +213,5 @@ const deferredZoneUpdate = (id: string, url: string) => _.defer(function() {
});
// Most of this module is document-level event handlers, but there's also some exports:
-export default { deferredZoneUpdate, findZone };
+export { deferredZoneUpdate, findZone };
diff --git a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/ModuleConfigurationCallbackTests.groovy b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/ModuleConfigurationCallbackTests.groovy
index c305d71a3..74ebce902 100644
--- a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/ModuleConfigurationCallbackTests.groovy
+++ b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/ModuleConfigurationCallbackTests.groovy
@@ -23,9 +23,18 @@ class ModuleConfigurationCallbackTests extends App1TestCase {
@Test
void simple() {
- openLinks "ModuleConfigurationCallback Demo"
+ if (isRequireJsEnabled()) {
- assert getHtmlSource().contains("\"waitSeconds\" : \"13\"");
+ openLinks "ModuleConfigurationCallback Demo"
+
+ assert getHtmlSource().contains("\"waitSeconds\" : \"13\"");
+
+ // Just to test @Import(module), since it's not used
+ // by Tapestry itself, being replaced by
+ // RequireJsModeHelper.importModule()
+ assert isElementPresent("css=script[data-requiremodule=validate-in-error]");
+
+ }
}
diff --git a/tapestry-core/src/test/groovy/org/apache/tapestry5/internal/services/DocumentLinkerImplTest.groovy b/tapestry-core/src/test/groovy/org/apache/tapestry5/internal/services/DocumentLinkerImplTest.groovy
index a9eafe7a7..183597c75 100644
--- a/tapestry-core/src/test/groovy/org/apache/tapestry5/internal/services/DocumentLinkerImplTest.groovy
+++ b/tapestry-core/src/test/groovy/org/apache/tapestry5/internal/services/DocumentLinkerImplTest.groovy
@@ -5,6 +5,7 @@ import org.apache.tapestry5.dom.Element
import org.apache.tapestry5.dom.XMLMarkupModel
import org.apache.tapestry5.internal.test.InternalBaseTestCase
import org.apache.tapestry5.json.JSONArray
+import org.apache.tapestry5.services.javascript.EsModuleManager
import org.apache.tapestry5.services.javascript.InitializationPriority
import org.apache.tapestry5.services.javascript.ModuleManager
import org.apache.tapestry5.services.javascript.StylesheetLink
@@ -32,7 +33,7 @@ class DocumentLinkerImplTest extends InternalBaseTestCase {
document.newRootElement("not-html").text("not an HTML document")
- DocumentLinkerImpl linker = new DocumentLinkerImpl(null, null, true, false, "1.2.3")
+ DocumentLinkerImpl linker = new DocumentLinkerImpl(null, null, true, false, "1.2.3", true)
// Only checked if there's something to link.
@@ -55,7 +56,7 @@ class DocumentLinkerImplTest extends InternalBaseTestCase {
document.newRootElement("not-html").text("not an HTML document")
- DocumentLinkerImpl linker = new DocumentLinkerImpl(null, null, true, false, "1.2.3")
+ DocumentLinkerImpl linker = new DocumentLinkerImpl(null, null, true, false, "1.2.3", true)
// Only checked if there's something to link.
@@ -76,7 +77,7 @@ class DocumentLinkerImplTest extends InternalBaseTestCase {
void missing_root_element_is_a_noop() {
Document document = new Document()
- DocumentLinkerImpl linker = new DocumentLinkerImpl(null, null, true, false, "1.2.3")
+ DocumentLinkerImpl linker = new DocumentLinkerImpl(null, null, true, false, "1.2.3", true)
linker.addLibrary("foo.js")
linker.addScript(InitializationPriority.NORMAL, "doSomething();")
@@ -93,8 +94,9 @@ class DocumentLinkerImplTest extends InternalBaseTestCase {
document.newRootElement("html").element("body").element("p").text("Ready to be updated with scripts.")
def manager = mockModuleManager(["core.js", "foo.js", "bar/baz.js"], [new JSONArray("t5/core/pageinit:evalJavaScript", "pageINIT();")])
+ def esManager = mockEsModuleManager()
- DocumentLinkerImpl linker = new DocumentLinkerImpl(manager, null, true, false, "1.2.3")
+ DocumentLinkerImpl linker = new DocumentLinkerImpl(manager, esManager, true, false, "1.2.3", true)
replay()
@@ -122,7 +124,7 @@ class DocumentLinkerImplTest extends InternalBaseTestCase {
document.newRootElement("html").element("body").element("p").text("Ready to be marked with generator meta.")
- DocumentLinkerImpl linker = new DocumentLinkerImpl(null, null, false, false, "1.2.3")
+ DocumentLinkerImpl linker = new DocumentLinkerImpl(null, null, false, false, "1.2.3", true)
linker.updateDocument(document)
@@ -141,7 +143,7 @@ class DocumentLinkerImplTest extends InternalBaseTestCase {
document.newRootElement("no_html").text("Generator meta only added if root is html tag.")
- DocumentLinkerImpl linker = new DocumentLinkerImpl(null, null, false, false, "1.2.3")
+ DocumentLinkerImpl linker = new DocumentLinkerImpl(null, null, false, false, "1.2.3", true)
linker.updateDocument(document)
@@ -158,7 +160,7 @@ class DocumentLinkerImplTest extends InternalBaseTestCase {
document.newRootElement("html").element("body").element("p").text("Ready to be updated with styles.")
- DocumentLinkerImpl linker = new DocumentLinkerImpl(null, null, true, false, "1.2.3")
+ DocumentLinkerImpl linker = new DocumentLinkerImpl(null, null, true, false, "1.2.3", true)
linker.addStylesheetLink(new StylesheetLink("foo.css"))
linker.addStylesheetLink(new StylesheetLink("bar/baz.css", new StylesheetOptions("print")))
@@ -178,7 +180,7 @@ class DocumentLinkerImplTest extends InternalBaseTestCase {
document.newRootElement("html").element("head").comment(" existing head ").container.element("body").text(
"body content")
- DocumentLinkerImpl linker = new DocumentLinkerImpl(null, null, true, false, "1.2.3")
+ DocumentLinkerImpl linker = new DocumentLinkerImpl(null, null, true, false, "1.2.3", true)
linker.addStylesheetLink(new StylesheetLink("foo.css"))
@@ -197,8 +199,9 @@ class DocumentLinkerImplTest extends InternalBaseTestCase {
document.newRootElement("html").element("body").element("p").text("Ready to be updated with scripts.")
def manager = mockModuleManager([], [new JSONArray("t5/core/pageinit:evalJavaScript", "doSomething();")])
+ def esManager = mockEsModuleManager()
- DocumentLinkerImpl linker = new DocumentLinkerImpl(manager, null, true, true, "1.2.3")
+ DocumentLinkerImpl linker = new DocumentLinkerImpl(manager, esManager, true, true, "1.2.3", true)
replay()
@@ -223,8 +226,9 @@ class DocumentLinkerImplTest extends InternalBaseTestCase {
document.newRootElement("html").element("notbody").element("p").text("Ready to be updated with scripts.")
def manager = mockModuleManager(["foo.js"], [])
+ def esManager = mockEsModuleManager()
- DocumentLinkerImpl linker = new DocumentLinkerImpl(manager, null, true, false, "1.2.3")
+ DocumentLinkerImpl linker = new DocumentLinkerImpl(manager, esManager, true, false, "1.2.3", true)
replay()
@@ -250,8 +254,9 @@ class DocumentLinkerImplTest extends InternalBaseTestCase {
head.element("script")
def manager = mockModuleManager([], [new JSONArray("['immediate/module:myfunc', {'fred':'barney'}]")])
+ def esManager = mockEsModuleManager()
- DocumentLinkerImpl linker = new DocumentLinkerImpl(manager, null, true, false, "1.2.3")
+ DocumentLinkerImpl linker = new DocumentLinkerImpl(manager, esManager, true, false, "1.2.3", true)
replay()
@@ -273,7 +278,7 @@ class DocumentLinkerImplTest extends InternalBaseTestCase {
document.newRootElement("html")
- DocumentLinkerImpl linker = new DocumentLinkerImpl(null, null, true, false, "1.2.3")
+ DocumentLinkerImpl linker = new DocumentLinkerImpl(null, null, true, false, "1.2.3", true)
linker.addStylesheetLink(new StylesheetLink("everybody.css"))
linker.addStylesheetLink(new StylesheetLink("just_ie.css", new StylesheetOptions().withCondition("IE")))
@@ -295,7 +300,7 @@ class DocumentLinkerImplTest extends InternalBaseTestCase {
document.newRootElement("html")
- DocumentLinkerImpl linker = new DocumentLinkerImpl(null, null, true, false, "1.2.3")
+ DocumentLinkerImpl linker = new DocumentLinkerImpl(null, null, true, false, "1.2.3", true)
linker.addStylesheetLink(new StylesheetLink("whatever.css"))
linker.addStylesheetLink(new StylesheetLink("insertion-point.css", new StylesheetOptions().asAjaxInsertionPoint()))
@@ -318,8 +323,10 @@ class DocumentLinkerImplTest extends InternalBaseTestCase {
def manager = mockModuleManager([], ["my/module",
new JSONArray("my/other/module:normal", 111, 222),
new JSONArray("my/other/module:late", 333, 444)])
+
+ def esManager = mockEsModuleManager()
- DocumentLinkerImpl linker = new DocumentLinkerImpl(manager, null, true, false, "1.2.3")
+ DocumentLinkerImpl linker = new DocumentLinkerImpl(manager, esManager, true, false, "1.2.3", true)
replay()
@@ -346,8 +353,10 @@ class DocumentLinkerImplTest extends InternalBaseTestCase {
def manager = mockModuleManager([], ["my/module",
new JSONArray("my/other/module:normal", 111, 222)])
+
+ def esManager = mockEsModuleManager()
- DocumentLinkerImpl linker = new DocumentLinkerImpl(manager, null, true, false, "1.2.3")
+ DocumentLinkerImpl linker = new DocumentLinkerImpl(manager, esManager, true, false, "1.2.3", true)
replay()
@@ -386,4 +395,24 @@ class DocumentLinkerImplTest extends InternalBaseTestCase {
return mock;
}
+
+ private EsModuleManager mockEsModuleManager() {
+
+ EsModuleManager mock = newMock(EsModuleManager);
+
+ expect(mock.writeInitialization(isA(Element),
+ isA(java.util.List), isA(java.util.List))).once()
+
+ /*expect(mock.writeInitialization(isA(Element),
+ eq(libraryURLs),
+ eq(inits))).andAnswer({
+ def body = EasyMock.currentArguments[0];
+
+ body.comment("MM-INIT");
+ } as IAnswer).once()*/
+
+
+ return mock;
+ }
+
}
diff --git a/tapestry-core/src/test/groovy/org/apache/tapestry5/internal/services/ajax/JavaScriptSupportAutofocusTests.groovy b/tapestry-core/src/test/groovy/org/apache/tapestry5/internal/services/ajax/JavaScriptSupportAutofocusTests.groovy
index c631d4448..7caf1b90d 100644
--- a/tapestry-core/src/test/groovy/org/apache/tapestry5/internal/services/ajax/JavaScriptSupportAutofocusTests.groovy
+++ b/tapestry-core/src/test/groovy/org/apache/tapestry5/internal/services/ajax/JavaScriptSupportAutofocusTests.groovy
@@ -42,7 +42,7 @@ class JavaScriptSupportAutofocusTests extends InternalBaseTestCase {
replay()
// Test in partial mode, to bypass the logic about importing the "core' stack.
- def jss = new JavaScriptSupportImpl(linker, stackSource, stackPathConstructor, null, true, null)
+ def jss = new JavaScriptSupportImpl(linker, stackSource, stackPathConstructor, null, true, null, true)
cls jss
diff --git a/tapestry-core/src/test/groovy/org/apache/tapestry5/internal/services/ajax/JavaScriptSupportImplTest.groovy b/tapestry-core/src/test/groovy/org/apache/tapestry5/internal/services/ajax/JavaScriptSupportImplTest.groovy
index 969498904..127389631 100644
--- a/tapestry-core/src/test/groovy/org/apache/tapestry5/internal/services/ajax/JavaScriptSupportImplTest.groovy
+++ b/tapestry-core/src/test/groovy/org/apache/tapestry5/internal/services/ajax/JavaScriptSupportImplTest.groovy
@@ -34,7 +34,7 @@ class JavaScriptSupportImplTest extends InternalBaseTestCase {
replay()
- JavaScriptSupport jss = new JavaScriptSupportImpl(null, null, null, null)
+ JavaScriptSupport jss = new JavaScriptSupportImpl(null, null, null, null, true)
assertEquals(jss.allocateClientId(resources), "tracy")
assertEquals(jss.allocateClientId(resources), "tracy_0")
@@ -45,7 +45,7 @@ class JavaScriptSupportImplTest extends InternalBaseTestCase {
@Test
void commit_with_no_javascript() {
- JavaScriptSupportImpl jss = new JavaScriptSupportImpl(null, null, null, null)
+ JavaScriptSupportImpl jss = new JavaScriptSupportImpl(null, null, null, null, true)
jss.commit()
}
@@ -62,7 +62,7 @@ class JavaScriptSupportImplTest extends InternalBaseTestCase {
replay()
- JavaScriptSupportImpl jss = new JavaScriptSupportImpl(linker, stackSource, null, new IdAllocator(), true, null)
+ JavaScriptSupportImpl jss = new JavaScriptSupportImpl(linker, stackSource, null, new IdAllocator(), true, null, true)
jss.addScript("doSomething();")
@@ -108,7 +108,7 @@ class JavaScriptSupportImplTest extends InternalBaseTestCase {
replay()
- JavaScriptSupportImpl jss = new JavaScriptSupportImpl(linker, stackSource, pathConstructor, falseHook)
+ JavaScriptSupportImpl jss = new JavaScriptSupportImpl(linker, stackSource, pathConstructor, falseHook, true)
jss.addScript(InitializationPriority.IMMEDIATE, "doSomething();")
@@ -129,7 +129,7 @@ class JavaScriptSupportImplTest extends InternalBaseTestCase {
replay()
- JavaScriptSupportImpl jss = new JavaScriptSupportImpl(linker, stackSource, pathConstructor, null, true, null)
+ JavaScriptSupportImpl jss = new JavaScriptSupportImpl(linker, stackSource, pathConstructor, null, true, null, true)
jss.importJavaScriptLibrary(library)
@@ -165,7 +165,7 @@ class JavaScriptSupportImplTest extends InternalBaseTestCase {
replay()
- JavaScriptSupportImpl jss = new JavaScriptSupportImpl(linker, stackSource, pathConstructor, null, true, null)
+ JavaScriptSupportImpl jss = new JavaScriptSupportImpl(linker, stackSource, pathConstructor, null, true, null, true)
jss.importJavaScriptLibrary(library1)
@@ -196,7 +196,7 @@ class JavaScriptSupportImplTest extends InternalBaseTestCase {
replay()
- JavaScriptSupportImpl jss = new JavaScriptSupportImpl(linker, stackSource, pathConstructor, null, false, new StaticHook(true))
+ JavaScriptSupportImpl jss = new JavaScriptSupportImpl(linker, stackSource, pathConstructor, null, false, new StaticHook(true), true)
jss.importStack(InternalConstants.CORE_STACK_NAME)
@@ -233,7 +233,7 @@ class JavaScriptSupportImplTest extends InternalBaseTestCase {
replay()
- JavaScriptSupportImpl jss = new JavaScriptSupportImpl(linker, stackSource, pathConstructor, null, true, null)
+ JavaScriptSupportImpl jss = new JavaScriptSupportImpl(linker, stackSource, pathConstructor, null, true, null, true)
jss.require("foo/bar")
@@ -275,7 +275,7 @@ class JavaScriptSupportImplTest extends InternalBaseTestCase {
replay()
- JavaScriptSupportImpl jss = new JavaScriptSupportImpl(linker, stackSource, pathConstructor, falseHook)
+ JavaScriptSupportImpl jss = new JavaScriptSupportImpl(linker, stackSource, pathConstructor, falseHook, true)
jss.importStack("custom")
@@ -331,7 +331,7 @@ class JavaScriptSupportImplTest extends InternalBaseTestCase {
replay()
- JavaScriptSupportImpl jss = new JavaScriptSupportImpl(linker, stackSource, pathConstructor, falseHook)
+ JavaScriptSupportImpl jss = new JavaScriptSupportImpl(linker, stackSource, pathConstructor, falseHook, true)
jss.importStack("child")
@@ -356,7 +356,7 @@ class JavaScriptSupportImplTest extends InternalBaseTestCase {
replay()
- JavaScriptSupportImpl jss = new JavaScriptSupportImpl(linker, stackSource, pathConstructor, null, true, null)
+ JavaScriptSupportImpl jss = new JavaScriptSupportImpl(linker, stackSource, pathConstructor, null, true, null, true)
jss.importJavaScriptLibrary(library1)
jss.importJavaScriptLibrary(library2)
@@ -380,7 +380,7 @@ class JavaScriptSupportImplTest extends InternalBaseTestCase {
replay()
- JavaScriptSupportImpl jss = new JavaScriptSupportImpl(linker, stackSource, pathConstructor, null, true, null)
+ JavaScriptSupportImpl jss = new JavaScriptSupportImpl(linker, stackSource, pathConstructor, null, true, null, true)
jss.addInitializerCall(InitializationPriority.IMMEDIATE, "setup", "chuck")
jss.addInitializerCall(InitializationPriority.IMMEDIATE, "setup", "charley")
@@ -406,7 +406,7 @@ class JavaScriptSupportImplTest extends InternalBaseTestCase {
replay()
- JavaScriptSupportImpl jss = new JavaScriptSupportImpl(linker, stackSource, pathConstructor, null, true, null)
+ JavaScriptSupportImpl jss = new JavaScriptSupportImpl(linker, stackSource, pathConstructor, null, true, null, true)
jss.addInitializerCall(InitializationPriority.IMMEDIATE, "setup", chuck)
jss.addInitializerCall(InitializationPriority.IMMEDIATE, "setup", buzz)
@@ -436,7 +436,7 @@ class JavaScriptSupportImplTest extends InternalBaseTestCase {
replay()
- JavaScriptSupportImpl jss = new JavaScriptSupportImpl(linker, stackSource, pathConstructor, null, true, null)
+ JavaScriptSupportImpl jss = new JavaScriptSupportImpl(linker, stackSource, pathConstructor, null, true, null, true)
jss.addInitializerCall("setup", "chuck")
@@ -470,7 +470,7 @@ class JavaScriptSupportImplTest extends InternalBaseTestCase {
replay()
- JavaScriptSupportImpl jss = new JavaScriptSupportImpl(linker, stackSource, pathConstructor, null, true, falseHook)
+ JavaScriptSupportImpl jss = new JavaScriptSupportImpl(linker, stackSource, pathConstructor, null, true, falseHook, true)
jss.addInitializerCall("setup", chuck)
@@ -494,7 +494,7 @@ class JavaScriptSupportImplTest extends InternalBaseTestCase {
replay()
- JavaScriptSupportImpl jss = new JavaScriptSupportImpl(linker, stackSource, pathConstructor, falseHook)
+ JavaScriptSupportImpl jss = new JavaScriptSupportImpl(linker, stackSource, pathConstructor, falseHook, true)
jss.importStylesheet(stylesheet)
@@ -517,7 +517,7 @@ class JavaScriptSupportImplTest extends InternalBaseTestCase {
replay()
- JavaScriptSupportImpl jss = new JavaScriptSupportImpl(linker, stackSource, pathConstructor, falseHook)
+ JavaScriptSupportImpl jss = new JavaScriptSupportImpl(linker, stackSource, pathConstructor, falseHook, true)
jss.importStylesheet(new StylesheetLink("style.css", options))
jss.importStylesheet(new StylesheetLink("style.css", new StylesheetOptions("hologram")))
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/App1TestCase.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/App1TestCase.java
index 6ca5457bb..ce0640d51 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/App1TestCase.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/App1TestCase.java
@@ -10,4 +10,12 @@ import org.apache.tapestry5.test.TapestryTestConfiguration;
@TapestryTestConfiguration(webAppFolder = "src/test/app1")
public abstract class App1TestCase extends TapestryCoreTestCase
{
+ protected boolean isRequireJsEnabled()
+ {
+ if (!isElementPresent("require-js-enabled-value"))
+ {
+ openBaseURL();
+ }
+ return Boolean.valueOf(getText("require-js-enabled-value"));
+ }
}
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/AssetTests.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/AssetTests.java
index 06a92458a..7cb10e5e5 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/AssetTests.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/AssetTests.java
@@ -52,10 +52,10 @@ public class AssetTests extends App1TestCase
{
openLinks("AssetDemo");
- assertEquals("http://cdnjs.cloudflare.com/ajax/libs/d3/3.0.0/d3.js", getText("httpAsset"));
- assertEquals("https://cdnjs.cloudflare.com/ajax/libs/d3/3.0.0/d3.js", getText("httpsAsset"));
- assertEquals("http://cdnjs.cloudflare.com/ajax/libs/d3/3.0.0/d3.js", getText("protocolRelativeAsset"));
- assertEquals("ftp://cdnjs.cloudflare.com/ajax/libs/d3/3.0.0/d3.js", getText("ftpAsset"));
+ assertEquals("http://cdnjs.cloudflare.com/ajax/libs/d3/7.9.0/d3.js", getText("httpAsset"));
+ assertEquals("https://cdnjs.cloudflare.com/ajax/libs/d3/7.9.0/d3.js", getText("httpsAsset"));
+ assertEquals("http://cdnjs.cloudflare.com/ajax/libs/d3/7.9.0/d3.js", getText("protocolRelativeAsset"));
+ assertEquals("ftp://cdnjs.cloudflare.com/ajax/libs/d3/7.9.0/d3.js", getText("ftpAsset"));
// check whether externaly @Import'ed d3 works
assertTrue(isElementPresent("css=svg"));
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/EsModuleTests.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/EsModuleTests.java
index d2ba735ee..26e85f508 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/EsModuleTests.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/EsModuleTests.java
@@ -30,7 +30,6 @@ import org.apache.tapestry5.services.javascript.EsModuleConfigurationCallback;
import org.apache.tapestry5.services.javascript.EsModuleInitialization;
import org.apache.tapestry5.services.javascript.EsModuleManager;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;
-import org.openqa.selenium.support.ui.ExpectedCondition;
import org.testng.annotations.Test;
/**
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/Border.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/Border.java
index b5a6d8e13..5ffe581ea 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/Border.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/Border.java
@@ -13,9 +13,11 @@
package org.apache.tapestry5.integration.app1.components;
import org.apache.tapestry5.ComponentResources;
+import org.apache.tapestry5.annotations.BeginRender;
import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.http.services.Request;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.services.pageload.PageClassLoaderContextManager;
@@ -25,7 +27,7 @@ import java.util.Calendar;
* Here's a component with a template, including a t:body element. Really should rename this to "Layout" as that's the
* T5 naming.
*/
-@Import(stylesheet = "context:css/app.css", module = {"bootstrap/collapse", "app/test-support"})
+@Import(stylesheet = "context:css/app.css")
public class Border
{
@Inject
@@ -37,6 +39,9 @@ public class Border
@Inject @Property
private PageClassLoaderContextManager pccm;
+
+ @Inject
+ private RequireJsModeHelper requireJsModeHelper;
public static final int year;
@@ -67,4 +72,11 @@ public class Border
return version + " from " + System.getProperty("java.vendor");
}
+ @BeginRender
+ void beginRender()
+ {
+ requireJsModeHelper.importModule("bootstrap/collapse");
+ requireJsModeHelper.importModule("app/test-support");
+ }
+
}
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ClientConsoleDemo.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ClientConsoleDemo.java
index a319dd580..9b19a5b4f 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ClientConsoleDemo.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ClientConsoleDemo.java
@@ -14,11 +14,19 @@
package org.apache.tapestry5.integration.app1.pages;
-import org.apache.tapestry5.annotations.Import;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
+import org.apache.tapestry5.ioc.annotations.Inject;
/**
* @since 5.3
*/
-@Import(module = "client-console-demo")
public class ClientConsoleDemo {
+
+ @Inject
+ private RequireJsModeHelper requireJsModeHelper;
+
+ void beginRender()
+ {
+ requireJsModeHelper.importModule("client-console-demo");
+ }
}
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/EsModuleDemo.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/EsModuleDemo.java
index de17500ba..f58e2c674 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/EsModuleDemo.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/EsModuleDemo.java
@@ -69,7 +69,7 @@ public class EsModuleDemo
.with();
javaScriptSupport.importEsModule("parameter-type-default-export")
- .with(null, true, false, Math.PI * Math.E, "string", "jsonLiteral",
+ .with(JSONObject.NULL, true, false, Math.PI * Math.E, "string", "jsonLiteral",
new JSONObject("key", "value"), new JSONArray(1, "2"));
if (overrideEsModuleImportAgain != null && overrideEsModuleImportAgain)
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ModuleConfigurationCallbackDemo.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ModuleConfigurationCallbackDemo.java
index 09deb7cfe..2342053d7 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ModuleConfigurationCallbackDemo.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ModuleConfigurationCallbackDemo.java
@@ -13,6 +13,7 @@
// limitations under the License.
package org.apache.tapestry5.integration.app1.pages;
+import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.json.JSONObject;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;
@@ -23,6 +24,7 @@ import org.apache.tapestry5.services.javascript.ModuleConfigurationCallback;
* {@link JavaScriptSupport#addModuleConfigurationCallback(ModuleConfigurationCallback)}.
* Based on http://www.requirejs.org/jqueryui-amd/example/webapp/app.html.
*/
+@Import(module = "validate-in-error")
public class ModuleConfigurationCallbackDemo
{
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ModuleInitDemo.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ModuleInitDemo.java
index 7c20afe1c..c39959ed7 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ModuleInitDemo.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ModuleInitDemo.java
@@ -1,16 +1,16 @@
package org.apache.tapestry5.integration.app1.pages;
-import org.apache.tapestry5.annotations.Environmental;
-import org.apache.tapestry5.services.javascript.JavaScriptSupport;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
+import org.apache.tapestry5.ioc.annotations.Inject;
public class ModuleInitDemo
{
- @Environmental
- private JavaScriptSupport javaScriptSupport;
+ @Inject
+ private RequireJsModeHelper requireJsModeHelper;
void afterRender()
{
- javaScriptSupport.require("app/alert").invoke("alert").with("Module Initialization Demo");
+ requireJsModeHelper.importModule("app/alert").invoke("alert").with("Module Initialization Demo");
}
}
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/MultiZoneUpdateDemo.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/MultiZoneUpdateDemo.java
index 7af7bcc61..898dcccf5 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/MultiZoneUpdateDemo.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/MultiZoneUpdateDemo.java
@@ -15,6 +15,7 @@
package org.apache.tapestry5.integration.app1.pages;
import org.apache.tapestry5.Block;
+import org.apache.tapestry5.SymbolConstants;
import org.apache.tapestry5.ValueEncoder;
import org.apache.tapestry5.ajax.MultiZoneUpdate;
import org.apache.tapestry5.annotations.InjectComponent;
@@ -24,6 +25,8 @@ import org.apache.tapestry5.internal.services.StringValueEncoder;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.services.ajax.AjaxResponseRenderer;
import org.apache.tapestry5.services.ajax.JavaScriptCallback;
+import org.apache.tapestry5.services.javascript.AbstractInitialization;
+import org.apache.tapestry5.services.javascript.Initialization;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;
import java.util.Date;
@@ -46,7 +49,7 @@ public class MultiZoneUpdateDemo
{
return new Date();
}
-
+
Object onActionFromUpdate()
{
wilmaMessage = "His Wife, Wilma.";
@@ -58,7 +61,12 @@ public class MultiZoneUpdateDemo
{
public void run(JavaScriptSupport javascriptSupport)
{
- javascriptSupport.require("app/multi-zone-update").with("message", "Updated");
+ final String moduleName = "app/multi-zone-update";
+ final AbstractInitialization<?> initialization =
+ javascriptSupport.isRequireJsEnabled() ?
+ javascriptSupport.require(moduleName) :
+ javascriptSupport.importEsModule(moduleName);
+ initialization.with("message", "Updated");
}
});
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PaletteDemo.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PaletteDemo.java
index 3694f8ccc..cfe7c92d8 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PaletteDemo.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PaletteDemo.java
@@ -30,12 +30,12 @@ import org.apache.tapestry5.commons.services.TypeCoercer;
import org.apache.tapestry5.integration.app1.data.ProgrammingLanguage;
import org.apache.tapestry5.internal.OptionGroupModelImpl;
import org.apache.tapestry5.internal.OptionModelImpl;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.util.AbstractSelectModel;
import org.apache.tapestry5.util.EnumSelectModel;
import org.apache.tapestry5.util.EnumValueEncoder;
-@Import(module="palette-demo")
public class PaletteDemo
{
@Inject
@@ -52,6 +52,13 @@ public class PaletteDemo
@Inject
private TypeCoercer typeCoercer;
+ @Inject
+ private RequireJsModeHelper requireJsModeHelper;
+
+ void beginRender()
+ {
+ requireJsModeHelper.importModule("palette-demo");
+ }
void onPrepareFromDemo()
{
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PaletteGroupedDemo.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PaletteGroupedDemo.java
index 0fe130ba7..efd65a18c 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PaletteGroupedDemo.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PaletteGroupedDemo.java
@@ -30,20 +30,22 @@ import org.apache.tapestry5.commons.services.TypeCoercer;
import org.apache.tapestry5.integration.app1.data.ProgrammingLanguage;
import org.apache.tapestry5.internal.OptionGroupModelImpl;
import org.apache.tapestry5.internal.OptionModelImpl;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.util.AbstractSelectModel;
import org.apache.tapestry5.util.EnumValueEncoder;
-@Import(module="palette-demo")
public class PaletteGroupedDemo
{
@Inject
private ComponentResources resources;
+
+ @Inject private RequireJsModeHelper requireJsModeHelper;
@Persist
@Property
private List<ProgrammingLanguage> languages;
-
+
@Persist
@Property
private boolean reorder;
@@ -55,6 +57,11 @@ public class PaletteGroupedDemo
ProgrammingLanguage.ERLANG, ProgrammingLanguage.HASKELL, ProgrammingLanguage.LISP);
private static final Iterable<ProgrammingLanguage> OO = Arrays.asList(ProgrammingLanguage.JAVA,
ProgrammingLanguage.RUBY);
+
+ void beginRender()
+ {
+ requireJsModeHelper.importModule("palette-demo");
+ }
void onPrepareFromDemo()
{
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PublishEventDemo.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PublishEventDemo.java
index 9400d49aa..aa8e8dac8 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PublishEventDemo.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PublishEventDemo.java
@@ -1,4 +1,4 @@
-// Copyright 2016 The Apache Software Foundation
+// Copyright 2017, 2025 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -25,15 +25,44 @@
// limitations under the License.
package org.apache.tapestry5.integration.app1.pages;
+import org.apache.tapestry5.Asset;
+import org.apache.tapestry5.SymbolConstants;
import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.annotations.OnEvent;
+import org.apache.tapestry5.annotations.Path;
import org.apache.tapestry5.annotations.PublishEvent;
+import org.apache.tapestry5.ioc.annotations.Inject;
+import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.json.JSONObject;
+import org.apache.tapestry5.services.javascript.JavaScriptSupport;
-@Import(stack = "core", library = "PublishEventDemo.js")
public class PublishEventDemo
{
+ @Inject
+ private JavaScriptSupport javaScriptSupport;
+
+ @Inject
+ @Symbol(SymbolConstants.REQUIRE_JS_ENABLED)
+ private boolean requireJsEnabled;
+
+ @Inject
+ @Path("PublishEventDemo.js")
+ private Asset publishEventDemoAmdAsset;
+
+ void beginRender()
+ {
+ if (requireJsEnabled)
+ {
+ javaScriptSupport.importStack("core");
+ javaScriptSupport.importJavaScriptLibrary(publishEventDemoAmdAsset);
+ }
+ else
+ {
+ javaScriptSupport.importEsModule("publish-event-demo");
+ }
+ }
+
@PublishEvent
JSONObject onAction()
{
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ValidateInErrorEvent.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ValidateInErrorEvent.java
index 645703abb..e70308884 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ValidateInErrorEvent.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/ValidateInErrorEvent.java
@@ -1,10 +1,18 @@
package org.apache.tapestry5.integration.app1.pages;
-import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.annotations.Property;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
+import org.apache.tapestry5.ioc.annotations.Inject;
-@Import(module = {"validate-in-error"})
public class ValidateInErrorEvent {
@Property
private String value;
+
+ @Inject
+ private RequireJsModeHelper requireJsModeHelper;
+
+ void beginRender() {
+ requireJsModeHelper.importModule("validate-in-error");
+ }
+
}
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/services/AppModule.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/services/AppModule.java
index d067f8cac..173707245 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/services/AppModule.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/services/AppModule.java
@@ -187,10 +187,15 @@ public class AppModule
// This is the emphasis of testing at this point.
configuration.add(SymbolConstants.JAVASCRIPT_INFRASTRUCTURE_PROVIDER, "jquery");
- configuration.add(D3_URL_SYMBOL, "cdnjs.cloudflare.com/ajax/libs/d3/3.0.0/d3.js");
+ configuration.add(D3_URL_SYMBOL, "cdnjs.cloudflare.com/ajax/libs/d3/7.9.0/d3.js");
configuration.add(SymbolConstants.PRELOADER_MODE, PreloaderMode.ALWAYS);
configuration.add(SymbolConstants.OPENAPI_APPLICATION_VERSION, "1.2.3.4");
configuration.add(SymbolConstants.OPENAPI_BASE_PATH, "/rest/");
+
+ configuration.add(SymbolConstants.CORS_ENABLED, "true");
+ configuration.add(SymbolConstants.CORS_ALLOWED_ORIGINS, "https://cdnjs.cloudflare.com");
+ configuration.add(SymbolConstants.CORS_MAX_AGE, "60");
+
// configuration.add(SymbolConstants.ERROR_CSS_CLASS, "yyyy");
// configuration.add(SymbolConstants.DEFAULT_STYLESHEET, "classpath:/org/apache/tapestry5/integration/app1/app1.css");
// configuration.add(SymbolConstants.CORS_ENABLED, true);
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/javascript/EsModuleManagerImplTest.java b/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/javascript/EsModuleManagerImplTest.java
index 0e41bc12e..055dcac92 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/javascript/EsModuleManagerImplTest.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/javascript/EsModuleManagerImplTest.java
@@ -32,42 +32,42 @@ public class EsModuleManagerImplTest
@Test
public void test_null_arguments()
{
- assertEquals(convert(null, true), "");
- assertEquals(convert(null, false), "");
+ assertEquals(convert(JSONObject.NULL, true), "null");
+ assertEquals(convert(JSONObject.NULL, false), "null");
}
@Test
public void test_empty_arguments()
{
- assertEquals(convert(new Object[0], true), "");
- assertEquals(convert(new Object[0], false), "");
+ assertEquals(convert(new JSONArray(), true), "");
+ assertEquals(convert(new JSONArray(), false), "");
}
@Test
public void test_one_argument()
{
- assertEquals(convert(new Object[] {null}, false), null);
+ assertEquals(convert(new JSONArray(JSONObject.NULL), false), "null");
- assertEquals(convert(new Object[] {STRING}, false), quote(STRING));
+ assertEquals(convert(new JSONArray().put(STRING), false), quote(STRING));
- assertEquals(convert(new Object[] {NUMBER}, false), NUMBER.toString());
- assertEquals(convert(new Object[] {Boolean.TRUE}, false), Boolean.TRUE.toString());
- assertEquals(convert(new Object[] {Boolean.FALSE}, false), Boolean.FALSE.toString());
+ assertEquals(convert(new JSONArray(NUMBER), false), NUMBER.toString());
+ assertEquals(convert(new JSONArray(Boolean.TRUE), false), Boolean.TRUE.toString());
+ assertEquals(convert(new JSONArray(Boolean.FALSE), false), Boolean.FALSE.toString());
- assertEquals(convert(new Object[] {JSON_LITERAL}, false), quote(JSON_LITERAL.toString()));
+ assertEquals(convert(new JSONArray(JSON_LITERAL), false), quote(JSON_LITERAL.toString()));
- assertEquals(convert(new Object[] {JSON_ARRAY}, false), JSON_ARRAY.toString(false));
- assertEquals(convert(new Object[] {JSON_ARRAY}, true), JSON_ARRAY.toString(true));
+ assertEquals(convert(new JSONArray(JSON_ARRAY), false), JSON_ARRAY.toString(false));
+ assertEquals(convert(new JSONArray(JSON_ARRAY), true), JSON_ARRAY.toString(true));
- assertEquals(convert(new Object[] {JSON_OBJECT}, false), JSON_OBJECT.toString(false));
- assertEquals(convert(new Object[] {JSON_OBJECT}, true), JSON_OBJECT.toString(true));
+ assertEquals(convert(new JSONArray(JSON_OBJECT), false), JSON_OBJECT.toString(false));
+ assertEquals(convert(new JSONArray(JSON_OBJECT), true), JSON_OBJECT.toString(true));
}
@Test
public void test_multiple_arguments()
{
- Object[] arguments = new Object[] { null, STRING, JSON_LITERAL, JSON_ARRAY, JSON_OBJECT };
+ JSONArray arguments = new JSONArray(JSONObject.NULL, STRING, JSON_LITERAL, JSON_ARRAY, JSON_OBJECT);
final String format = "null, '%s', '%s', %s, %s";
assertEquals(convert(arguments, false),
@@ -84,10 +84,15 @@ public class EsModuleManagerImplTest
{
return "'" + string + "'";
}
+
+ private String convert(Object object, boolean compactJSON)
+ {
+ return convert(new JSONArray(object), compactJSON);
+ }
- private String convert(Object[] blah, boolean compactJSON)
+ private String convert(JSONArray array, boolean compactJSON)
{
- return EsModuleManagerImpl.convertToJsFunctionParameters(blah, compactJSON);
+ return EsModuleManagerImpl.convertToJsFunctionParameters(array, compactJSON);
}
}
diff --git a/tapestry-core/src/test/resources/META-INF/assets/ExpressionInJsFunction.js b/tapestry-core/src/test/resources/META-INF/assets/ExpressionInJsFunction.js
index 3cd15539d..20df3d163 100644
--- a/tapestry-core/src/test/resources/META-INF/assets/ExpressionInJsFunction.js
+++ b/tapestry-core/src/test/resources/META-INF/assets/ExpressionInJsFunction.js
@@ -1,4 +1,4 @@
-require(["t5/core/dom"], function (dom) {
+function runTest(dom) {
dom = dom.default;
@@ -9,5 +9,12 @@ require(["t5/core/dom"], function (dom) {
window.test_func_with_map = function () {
dom('target').value("{key=test2}");
};
-});
+}
+const requireJsEnabled = "true" == document.querySelector("html")?.dataset['requireJsEnabled'];
+if (requireJsEnabled) {
+ require(["t5/core/dom"], runTest);
+}
+else {
+ import("t5/core/dom").then(runTest);
+}
diff --git a/tapestry-core/src/test/resources/META-INF/assets/es-modules/app/multi-zone-update.js b/tapestry-core/src/test/resources/META-INF/assets/es-modules/app/multi-zone-update.js
new file mode 100644
index 000000000..411363128
--- /dev/null
+++ b/tapestry-core/src/test/resources/META-INF/assets/es-modules/app/multi-zone-update.js
@@ -0,0 +1,5 @@
+import dom from "t5/core/dom";
+
+export default function (id, message) {
+ dom(id).update(message);
+};
\ No newline at end of file
diff --git a/tapestry-core/src/test/resources/META-INF/assets/es-modules/app/test-support.js b/tapestry-core/src/test/resources/META-INF/assets/es-modules/app/test-support.js
new file mode 100644
index 000000000..7728ef0c1
--- /dev/null
+++ b/tapestry-core/src/test/resources/META-INF/assets/es-modules/app/test-support.js
@@ -0,0 +1,14 @@
+// Provide test support functions that can be addressed via Selenium.
+
+// TODO: Maybe move this to main, for external re-use?
+
+import dom from "t5/core/dom";
+
+const exports = {
+ findCSSMatchCount(selector) { return dom.body.find(selector).length; },
+ doesNotExist(elementId) { return (dom(elementId)) === null; }
+};
+
+window.testSupport = exports;
+
+export default exports;
diff --git a/tapestry-core/src/test/resources/META-INF/assets/es-modules/client-console-demo.js b/tapestry-core/src/test/resources/META-INF/assets/es-modules/client-console-demo.js
new file mode 100644
index 000000000..33df7e83a
--- /dev/null
+++ b/tapestry-core/src/test/resources/META-INF/assets/es-modules/client-console-demo.js
@@ -0,0 +1,6 @@
+import dom from "t5/core/dom";
+import console from "t5/core/console";
+
+for (var name of ["debug", "info", "warn", "error"]) {
+ ((name => (dom(name)).on("change", function() { return console[name](this.value()); })))(name);
+}
diff --git a/tapestry-core/src/test/resources/META-INF/assets/es-modules/palette-demo.js b/tapestry-core/src/test/resources/META-INF/assets/es-modules/palette-demo.js
new file mode 100644
index 000000000..5943f74b6
--- /dev/null
+++ b/tapestry-core/src/test/resources/META-INF/assets/es-modules/palette-demo.js
@@ -0,0 +1,14 @@
+import dom from "t5/core/dom"
+import events from "t5/core/events";
+import _ from "underscore"
+import console from "t5/core/console";
+
+dom.onDocument(events.palette.willChange, function(event, memo) {
+
+ console.info("palette-demo, palette willChange");
+
+ const values = _.map(memo.selectedOptions, o => o.value);
+
+ (dom("event-selection")).update(JSON.stringify(values));
+ return (dom("event-reorder")).update(memo.reorder.toString());
+});
diff --git a/tapestry-core/src/test/resources/META-INF/assets/es-modules/publish-event-demo.js b/tapestry-core/src/test/resources/META-INF/assets/es-modules/publish-event-demo.js
new file mode 100644
index 000000000..7be8d6c5c
--- /dev/null
+++ b/tapestry-core/src/test/resources/META-INF/assets/es-modules/publish-event-demo.js
@@ -0,0 +1,23 @@
+import dom from "t5/core/dom";
+import ajax from "t5/core/ajax";
+import jQuery from "jquery";
+
+function makeAjaxCall(eventName, eventElement, outputElement) {
+ ajax(eventName, {
+ element: eventElement,
+ success: function(response) {
+ outputElement.innerHTML = response.json.origin;
+ }
+ });
+}
+
+jQuery('tbody tr').each(function() {
+ var td = jQuery(this).find('td');
+ var eventName = td[1].innerHTML;
+ var elementId = td[0].innerHTML;
+ var eventElement = null;
+ if (elementId != '(no element)') {
+ eventElement = jQuery('#' + elementId);
+ }
+ makeAjaxCall(eventName, eventElement, td[3]);
+});
diff --git a/tapestry-core/src/test/resources/META-INF/assets/es-modules/validate-in-error.js b/tapestry-core/src/test/resources/META-INF/assets/es-modules/validate-in-error.js
new file mode 100644
index 000000000..55f4777fe
--- /dev/null
+++ b/tapestry-core/src/test/resources/META-INF/assets/es-modules/validate-in-error.js
@@ -0,0 +1,8 @@
+import dom from 't5/core/dom';
+import events from 't5/core/events';
+
+dom.onDocument(events.form.validateInError, 'form', function() {
+ const attributes =
+ {id: 'validate-in-error'};
+ this.prepend(dom.create('div', attributes, 'Validate in error'));
+});
diff --git a/tapestry-core/src/test/resources/META-INF/assets/zonedemo.js b/tapestry-core/src/test/resources/META-INF/assets/zonedemo.js
index 9ab069ff9..015dfe198 100644
--- a/tapestry-core/src/test/resources/META-INF/assets/zonedemo.js
+++ b/tapestry-core/src/test/resources/META-INF/assets/zonedemo.js
@@ -3,5 +3,23 @@
* DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
*/
-require(["t5/core/dom", "t5/core/events"],
- (dom, events) => dom.default.onDocument(events.default.zone.didUpdate, () => (dom.default("zone-update-message")).update("Zone updated.")));
+
+function execute(dom, events) {
+ dom.default.onDocument(events.default.zone.didUpdate, function() {
+ dom.default("zone-update-message").update("Zone updated.");
+ });
+}
+
+if (typeof require !== 'undefined') {
+ require(["t5/core/dom", "t5/core/events"], function(dom, events) {
+ execute(dom, events);
+ });
+
+}
+else {
+ import("t5/core/dom").then((dom) => {
+ import("t5/core/events").then((events) => {
+ execute(dom, events);
+ });
+ });
+}
\ No newline at end of file
diff --git a/tapestry-core/src/test/resources/META-INF/modules/client-console-demo.js b/tapestry-core/src/test/resources/META-INF/modules/client-console-demo.js
index ebca6c142..56f5c9478 100644
--- a/tapestry-core/src/test/resources/META-INF/modules/client-console-demo.js
+++ b/tapestry-core/src/test/resources/META-INF/modules/client-console-demo.js
@@ -1,11 +1,9 @@
-/*
- * decaffeinate suggestions:
- * DS102: Remove unnecessary code created because of implicit returns
- * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
- */
define(["t5/core/dom", "t5/core/console"],
function(dom, console) {
+ dom = dom.default;
+ console = console.default;
+
for (var name of ["debug", "info", "warn", "error"]) {
((name => (dom(name)).on("change", function() { return console[name](this.value()); })))(name);
}
diff --git a/tapestry-core/src/test/resources/META-INF/modules/palette-demo.js b/tapestry-core/src/test/resources/META-INF/modules/palette-demo.js
index 5e0f73f6e..ceb4b39e7 100644
--- a/tapestry-core/src/test/resources/META-INF/modules/palette-demo.js
+++ b/tapestry-core/src/test/resources/META-INF/modules/palette-demo.js
@@ -1,8 +1,3 @@
-/*
- * decaffeinate suggestions:
- * DS102: Remove unnecessary code created because of implicit returns
- * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
- */
define(["t5/core/dom", "t5/core/events", "underscore", "t5/core/console"],
(dom, events, _, console) => {
dom = dom.default;
diff --git a/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/nested/AssetDemo.js b/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/nested/AssetDemo.js
index 5b6a4cb05..2eb6c0421 100644
--- a/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/nested/AssetDemo.js
+++ b/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/nested/AssetDemo.js
@@ -1,4 +1,5 @@
-var sampleSVG = d3.select("#viz")
+function run(d3) {
+ var sampleSVG = d3.select("#viz")
.append("svg")
.attr("width", 100)
.attr("height", 100);
@@ -10,4 +11,15 @@ var sampleSVG = d3.select("#viz")
.attr("cx", 50)
.attr("cy", 50)
.on("mouseover", function(){d3.select(this).style("fill", "aliceblue");})
- .on("mouseout", function(){d3.select(this).style("fill", "white");});
\ No newline at end of file
+ .on("mouseout", function(){d3.select(this).style("fill", "white");});
+
+}
+
+if (typeof require !== 'undefined') {
+ require(["http://cdnjs.cloudflare.com/ajax/libs/d3/7.9.0/d3.js"], function(d3) {
+ run(d3);
+ })
+}
+else {
+ import("http://cdnjs.cloudflare.com/ajax/libs/d3/7.9.0/d3.js").then(ignored => run(d3));
+}
\ No newline at end of file
diff --git a/tapestry-upload/src/main/java/org/apache/tapestry5/upload/components/Upload.java b/tapestry-upload/src/main/java/org/apache/tapestry5/upload/components/Upload.java
index 6481bc3d2..42b2fb423 100755
--- a/tapestry-upload/src/main/java/org/apache/tapestry5/upload/components/Upload.java
+++ b/tapestry-upload/src/main/java/org/apache/tapestry5/upload/components/Upload.java
@@ -23,6 +23,7 @@ import org.apache.tapestry5.corelib.base.AbstractField;
import org.apache.tapestry5.corelib.mixins.RenderDisabled;
import org.apache.tapestry5.http.services.Request;
import org.apache.tapestry5.ioc.annotations.Inject;
+import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.services.FieldValidatorDefaultSource;
import org.apache.tapestry5.services.FormSupport;
import org.apache.tapestry5.upload.services.MultipartDecoder;
@@ -59,6 +60,10 @@ public class Upload extends AbstractField
@Inject
private Locale locale;
+
+ @Inject
+ @Symbol(SymbolConstants.REQUIRE_JS_ENABLED)
+ private boolean requireJsEnabled;
@SuppressWarnings("unused")
@Mixin
@@ -123,7 +128,8 @@ public class Upload extends AbstractField
{
formSupport.setEncodingType(MULTIPART_ENCTYPE);
- writer.element("input", "type", "file", "name", getControlName(), "id", getClientId(), "class", cssClass);
+ final String clientId = getClientId();
+ writer.element("input", "type", "file", "name", getControlName(), "id", clientId, "class", cssClass);
validate.render(writer);
@@ -134,7 +140,15 @@ public class Upload extends AbstractField
// TAPESTRY-2453
if (request.isXHR())
{
- javaScriptSupport.require("t5/core/injected-upload").with(getClientId());
+ final String moduleName = "t5/core/injected-upload";
+ if (requireJsEnabled)
+ {
+ javaScriptSupport.require(moduleName).with(clientId);
+ }
+ else
+ {
+ javaScriptSupport.importEsModule(moduleName).with(clientId);
+ }
}
}