Repository: tapestry-5 Updated Branches: refs/heads/5.4.x b10fa77d2 -> d8a7dbf9d
TAP5-2225 Create client-side API to call a component's event handler methods Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/19fe6853 Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/19fe6853 Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/19fe6853 Branch: refs/heads/5.4.x Commit: 19fe685300d7eb12c6837fdfe165bc081415209d Parents: b10fa77 Author: Thiago H. de Paula Figueiredo <[email protected]> Authored: Sun Mar 19 13:07:00 2017 -0300 Committer: Thiago H. de Paula Figueiredo <[email protected]> Committed: Sun Mar 19 16:15:04 2017 -0300 ---------------------------------------------------------------------- .../org/apache/tapestry5/TapestryConstants.java | 11 ++ .../tapestry5/annotations/PublishEvent.java | 50 ++++++ .../corelib/mixins/PublishServerSideEvents.java | 151 +++++++++++++++++++ .../tapestry5/internal/InternalConstants.java | 17 +++ .../internal/transform/OnEventWorker.java | 54 ++++++- .../org/apache/tapestry5/t5-core-dom.coffee | 56 +++++++ .../src/test/app1/PublishEventDemo.tml | 7 + .../components/PublishEventDemoComponent.java | 32 ++++ .../components/PublishEventDemoComponent2.java | 32 ++++ .../tapestry5/integration/app1/pages/Index.java | 21 +-- .../app1/pages/PublishEventDemo.java | 49 ++++++ .../META-INF/assets/PublishEventDemo.js | 11 ++ .../components/PublishEventDemoComponent.tml | 3 + .../components/PublishEventDemoComponent2.tml | 4 + 14 files changed, 482 insertions(+), 16 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/19fe6853/tapestry-core/src/main/java/org/apache/tapestry5/TapestryConstants.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/TapestryConstants.java b/tapestry-core/src/main/java/org/apache/tapestry5/TapestryConstants.java index ad1495a..cab8c46 100644 --- a/tapestry-core/src/main/java/org/apache/tapestry5/TapestryConstants.java +++ b/tapestry-core/src/main/java/org/apache/tapestry5/TapestryConstants.java @@ -12,6 +12,7 @@ package org.apache.tapestry5; +import org.apache.tapestry5.annotations.PublishEvent; import org.apache.tapestry5.internal.structure.PageResetListener; import org.apache.tapestry5.services.ComponentEventLinkEncoder; @@ -68,4 +69,14 @@ public class TapestryConstants */ public static final String DISABLE_JAVASCRIPT_MINIMIZATION = "tapestry.disable-javascript-minimization"; + /** + * Name of the HTML data attribute which contains information about component events + * published by using the {@linkplain PublishEvent} annotation + * in a component event handler method. + * + * @see PublishEvent + * @since 5.4.2 + */ + public static final String COMPONENT_EVENTS_ATTRIBUTE_NAME = "data-component-events"; + } http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/19fe6853/tapestry-core/src/main/java/org/apache/tapestry5/annotations/PublishEvent.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/annotations/PublishEvent.java b/tapestry-core/src/main/java/org/apache/tapestry5/annotations/PublishEvent.java new file mode 100644 index 0000000..18239d4 --- /dev/null +++ b/tapestry-core/src/main/java/org/apache/tapestry5/annotations/PublishEvent.java @@ -0,0 +1,50 @@ +// 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.annotations; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import static org.apache.tapestry5.ioc.annotations.AnnotationUseContext.COMPONENT; +import static org.apache.tapestry5.ioc.annotations.AnnotationUseContext.PAGE; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import org.apache.tapestry5.ioc.annotations.UseWith; + +/** + * Marks an event handler method to be published as an event to be called in JavaScript + * through the <code>t5/core/triggerServerEvent</code> function. + * + * The event information is stored in JSON format inside the + * {@value org.apache.tapestry5.TapestryConstants#COMPONENT_EVENTS_ATTRIBUTE_NAME} attribute. + * + * When used in a component method, the component must render at least one element, + * and that's what get the + * {@value org.apache.tapestry5.TapestryConstants#COMPONENT_EVENTS_ATTRIBUTE_NAME} attribute above. + * If it doesn't, an exception will be thrown. + * + * When used in a page method, the page must render an <body> element, + * {@value org.apache.tapestry5.TapestryConstants#COMPONENT_EVENTS_ATTRIBUTE_NAME}. If it doesn't, + * an exception will be thrown. + * + * @since 5.4.2 + */ +@Target(ElementType.METHOD) +@Retention(RUNTIME) +@Documented +@UseWith({ COMPONENT, PAGE }) +public @interface PublishEvent +{ +} http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/19fe6853/tapestry-core/src/main/java/org/apache/tapestry5/corelib/mixins/PublishServerSideEvents.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/mixins/PublishServerSideEvents.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/mixins/PublishServerSideEvents.java new file mode 100644 index 0000000..3d73746 --- /dev/null +++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/mixins/PublishServerSideEvents.java @@ -0,0 +1,151 @@ +// 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.corelib.mixins; + +import org.apache.tapestry5.ComponentResources; +import org.apache.tapestry5.MarkupWriter; +import org.apache.tapestry5.MarkupWriterListener; +import org.apache.tapestry5.TapestryConstants; +import org.apache.tapestry5.annotations.PublishEvent; +import org.apache.tapestry5.dom.Element; +import org.apache.tapestry5.internal.InternalConstants; +import org.apache.tapestry5.ioc.annotations.Inject; +import org.apache.tapestry5.json.JSONArray; +import org.apache.tapestry5.json.JSONObject; +import org.apache.tapestry5.model.ComponentModel; + +/** + * Tapestry internal mixin used to implement the {@link PublishEvent} event logic. Don't use directly. + */ +public class PublishServerSideEvents +{ + + private static final String PUBLISH_COMPONENT_EVENTS_URL_PROPERTY = InternalConstants.PUBLISH_COMPONENT_EVENTS_URL_PROPERTY; + private static final String COMPONENT_EVENTS_ATTRIBUTE_NAME = TapestryConstants.COMPONENT_EVENTS_ATTRIBUTE_NAME; + + @Inject + private ComponentResources resources; + + void beginRender(final MarkupWriter writer) { + + final Element element = writer.getElement(); + + // When the component is actually a page, nothing was rendered yet. + // The listener we add here will add the events attribute to the <body> element + // later + if (element == null) { + writer.addListener(new BodyElementListener(writer)); + } + else { + writer.addListener(new DelayedListener(writer)); + } + + } + + private void addEventsAttribute(final Element element) + { + + if (element == null) + { + throw new IllegalStateException("@PublishEvent used inside a page which didn't generate a <body> element"); + } + + final ComponentResources containerResources = resources.getContainerResources(); + final ComponentModel componentModel = containerResources.getComponentModel(); + final String metaValue = componentModel.getMeta(InternalConstants.PUBLISH_COMPONENT_EVENTS_META); + final JSONArray componentEvents = new JSONArray(metaValue); + final JSONObject events = new JSONObject(); + final String existingValue = element.getAttribute(COMPONENT_EVENTS_ATTRIBUTE_NAME); + + if (existingValue != null) + { + final JSONObject existing = new JSONObject(existingValue); + for (String key : existing.keys()) { + events.put(key, existing.get(key)); + } + } + + for (int i = 0; i < componentEvents.length(); i++) + { + final String eventName = componentEvents.getString(i); + JSONObject event = new JSONObject(); + event.put(PUBLISH_COMPONENT_EVENTS_URL_PROPERTY, containerResources.createEventLink(eventName).toString()); + events.put(eventName, event); + } + + element.forceAttributes(TapestryConstants.COMPONENT_EVENTS_ATTRIBUTE_NAME, events.toString()); + } + + final private class DelayedListener implements MarkupWriterListener { + + private MarkupWriter writer; + + private Element element; + + public DelayedListener(MarkupWriter writer) + { + super(); + this.writer = writer; + } + + @Override + public void elementDidStart(Element element) + { + // Store first element generated by rendering the component + if (this.element == null) + { + this.element = element; + } + } + + @Override + public void elementDidEnd(Element element) + { + if (this.element == null) + { + throw new IllegalStateException("@PublishEvent used inside a component which didn't generate any HTML elements"); + } + addEventsAttribute(this.element); + writer.removeListener(this); + } + + } + + final private class BodyElementListener implements MarkupWriterListener { + + private MarkupWriter writer; + + public BodyElementListener(MarkupWriter writer) + { + super(); + this.writer = writer; + } + + @Override + public void elementDidStart(Element element) + { + if (element.getName().equals("body")) + { + addEventsAttribute(element); + writer.removeListener(this); + } + } + + @Override + public void elementDidEnd(Element element) + { + } + + } + +} http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/19fe6853/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalConstants.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalConstants.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalConstants.java index 32b80a6..8370ae0 100644 --- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalConstants.java +++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalConstants.java @@ -13,8 +13,10 @@ package org.apache.tapestry5.internal; import org.apache.tapestry5.ContentType; +import org.apache.tapestry5.annotations.PublishEvent; import org.apache.tapestry5.dom.MarkupModel; import org.apache.tapestry5.ioc.util.TimeInterval; +import org.apache.tapestry5.model.ComponentModel; import org.apache.tapestry5.services.javascript.JavaScriptStack; public final class InternalConstants @@ -213,4 +215,19 @@ public final class InternalConstants * @since 5.4 */ public static final ContentType JAVASCRIPT_CONTENT_TYPE = new ContentType("text/javascript"); + + /** + * Name of the {@linkplain ComponentModel} metadata key whiche stores the {@linkplain PublishEvent} + * data. + * @since 5.4.2 + */ + public static final String PUBLISH_COMPONENT_EVENTS_META = "meta.publish-component-events"; + + /** + * Name of the JSONObject key name which holds the name of the event to be published. + * + * @since 5.4.2 + */ + public static final String PUBLISH_COMPONENT_EVENTS_URL_PROPERTY = "url"; + } http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/19fe6853/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/OnEventWorker.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/OnEventWorker.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/OnEventWorker.java index fb4502b..fdb2dc9 100644 --- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/OnEventWorker.java +++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/OnEventWorker.java @@ -12,15 +12,23 @@ package org.apache.tapestry5.internal.transform; +import java.lang.reflect.Array; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + import org.apache.tapestry5.ComponentResources; import org.apache.tapestry5.EventContext; import org.apache.tapestry5.ValueEncoder; import org.apache.tapestry5.annotations.OnEvent; +import org.apache.tapestry5.annotations.PublishEvent; import org.apache.tapestry5.annotations.RequestParameter; +import org.apache.tapestry5.corelib.mixins.PublishServerSideEvents; import org.apache.tapestry5.func.F; import org.apache.tapestry5.func.Flow; import org.apache.tapestry5.func.Mapper; import org.apache.tapestry5.func.Predicate; +import org.apache.tapestry5.internal.InternalConstants; import org.apache.tapestry5.internal.services.ComponentClassCache; import org.apache.tapestry5.ioc.OperationTracker; import org.apache.tapestry5.ioc.internal.util.CollectionFactory; @@ -28,8 +36,19 @@ import org.apache.tapestry5.ioc.internal.util.InternalUtils; import org.apache.tapestry5.ioc.internal.util.TapestryException; import org.apache.tapestry5.ioc.util.ExceptionUtils; import org.apache.tapestry5.ioc.util.UnknownValueException; +import org.apache.tapestry5.json.JSONArray; import org.apache.tapestry5.model.MutableComponentModel; -import org.apache.tapestry5.plastic.*; +import org.apache.tapestry5.plastic.Condition; +import org.apache.tapestry5.plastic.InstructionBuilder; +import org.apache.tapestry5.plastic.InstructionBuilderCallback; +import org.apache.tapestry5.plastic.LocalVariable; +import org.apache.tapestry5.plastic.LocalVariableCallback; +import org.apache.tapestry5.plastic.MethodAdvice; +import org.apache.tapestry5.plastic.MethodDescription; +import org.apache.tapestry5.plastic.MethodInvocation; +import org.apache.tapestry5.plastic.PlasticClass; +import org.apache.tapestry5.plastic.PlasticField; +import org.apache.tapestry5.plastic.PlasticMethod; import org.apache.tapestry5.runtime.ComponentEvent; import org.apache.tapestry5.runtime.Event; import org.apache.tapestry5.runtime.PageLifecycleListener; @@ -39,11 +58,6 @@ import org.apache.tapestry5.services.ValueEncoderSource; import org.apache.tapestry5.services.transform.ComponentClassTransformWorker2; import org.apache.tapestry5.services.transform.TransformationSupport; -import java.lang.reflect.Array; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - /** * Provides implementations of the * {@link org.apache.tapestry5.runtime.Component#dispatchComponentEvent(org.apache.tapestry5.runtime.ComponentEvent)} @@ -151,6 +165,8 @@ public class OnEventWorker implements ComponentClassTransformWorker2 int minContextValues = 0; boolean handleActivationEventContext = false; + + final PublishEvent publishEvent; EventHandlerMethod(PlasticMethod method) { @@ -165,6 +181,8 @@ public class OnEventWorker implements ComponentClassTransformWorker2 eventType = extractEventType(methodName, onEvent); componentId = extractComponentId(methodName, onEvent); + + publishEvent = method.getAnnotation(PublishEvent.class); } void buildMatchAndInvocation(InstructionBuilder builder, final LocalVariable resultVariable) @@ -343,9 +361,31 @@ public class OnEventWorker implements ComponentClassTransformWorker2 implementDispatchMethod(plasticClass, isRoot, model, eventHandlerMethods); addComponentIdValidationLogicOnPageLoad(plasticClass, eventHandlerMethods); + + addPublishEventInfo(eventHandlerMethods, model); + } + + private void addPublishEventInfo(Flow<EventHandlerMethod> eventHandlerMethods, + MutableComponentModel model) + { + JSONArray publishEvents = new JSONArray(); + for (EventHandlerMethod eventHandlerMethod : eventHandlerMethods) + { + if (eventHandlerMethod.publishEvent != null) + { + publishEvents.put(eventHandlerMethod.eventType.toLowerCase()); + } + } + + // If we do have events to publish, we apply the mixin and pass + // event information to it. + if (publishEvents.length() > 0) { + model.addMixinClassName(PublishServerSideEvents.class.getName(), "after:*"); + model.setMeta(InternalConstants.PUBLISH_COMPONENT_EVENTS_META, publishEvents.toString()); + } } - private void addComponentIdValidationLogicOnPageLoad(PlasticClass plasticClass, Flow<EventHandlerMethod> eventHandlerMethods) + private void addComponentIdValidationLogicOnPageLoad(PlasticClass plasticClass, Flow<EventHandlerMethod> eventHandlerMethods) { ComponentIdValidator[] validators = extractComponentIdValidators(eventHandlerMethods); http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/19fe6853/tapestry-core/src/main/preprocessed-coffeescript/org/apache/tapestry5/t5-core-dom.coffee ---------------------------------------------------------------------- diff --git a/tapestry-core/src/main/preprocessed-coffeescript/org/apache/tapestry5/t5-core-dom.coffee b/tapestry-core/src/main/preprocessed-coffeescript/org/apache/tapestry5/t5-core-dom.coffee index 9d419bc..9b975d4 100644 --- a/tapestry-core/src/main/preprocessed-coffeescript/org/apache/tapestry5/t5-core-dom.coffee +++ b/tapestry-core/src/main/preprocessed-coffeescript/org/apache/tapestry5/t5-core-dom.coffee @@ -906,6 +906,60 @@ define ["underscore", "./utils", "./events", "jquery"], events = utils.split events #endif onevent elements, events, match, handler + + # Returns the URL of a component event based on its name and an optional element + # or null if the event information is not found. When the element isn't passed + # or it's null, the event data is taken from the <body> element. + # + # * eventName - (string) name of the component event + # * element - (object) HTML DOM element to be used as the begining of the event data search. Optional. + getEventUrl = (eventName, element) -> + + if not (eventName?) + throw 'dom.getEventUrl: the eventName parameter cannot be null' + + if not _.isString eventName + throw 'dom.getEventUrl: the eventName parameter should be a string' + + eventName = eventName.toLowerCase() + + if element is null + element = document.getElementsByTagName('body')[0] + + # Look for event data in itself first, then in the preceding siblings + # if not found + url = null + + while not url? and element.previousElementSibling? + data = getDataAttributeAsObject(element, 'component-events') + url = data?[eventName]?.url + element = element.previousElementSibling + + if not url? + + # Look at parent elements recursively + while not url? and element.parentElement? + data = getDataAttributeAsObject(element, 'component-events') + url = data?[eventName]?.url + element = element.parentElement; + + return url; + + # Returns the value of a given data attribute as an object. + # The "data-" prefix is added automatically. + # element - (object) HTML dom element + # attribute - (string) name of the data attribute without the "data-" prefix. + getDataAttributeAsObject = (element, attribute) -> + +#if jquery + value = $(element).data(attribute) +#elseif prototype + value = JSON.parse($(element).readAttribute('data-' + attribute)) + if value isnt null + value = JSON.parse(value) + else + value = {} +#endif # onDocument() is used to add an event handler to the document object; this is used # for global (or default) handlers. @@ -919,5 +973,7 @@ define ["underscore", "./utils", "./events", "jquery"], body: wrapElement document.body scanner: scanner + + getEventUrl : getEventUrl return exports http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/19fe6853/tapestry-core/src/test/app1/PublishEventDemo.tml ---------------------------------------------------------------------- diff --git a/tapestry-core/src/test/app1/PublishEventDemo.tml b/tapestry-core/src/test/app1/PublishEventDemo.tml new file mode 100644 index 0000000..43c2bd7 --- /dev/null +++ b/tapestry-core/src/test/app1/PublishEventDemo.tml @@ -0,0 +1,7 @@ +<t:border xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd" + xmlns:p="tapestry:parameter"> + <div id="page"> + <t:PublishEventDemoComponent/> + <t:PublishEventDemoComponent2/> + </div> +</t:border> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/19fe6853/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/PublishEventDemoComponent.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/PublishEventDemoComponent.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/PublishEventDemoComponent.java new file mode 100644 index 0000000..b8054f9 --- /dev/null +++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/PublishEventDemoComponent.java @@ -0,0 +1,32 @@ +// 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.integration.app1.components; + +import org.apache.tapestry5.annotations.OnEvent; +import org.apache.tapestry5.annotations.PublishEvent; +import org.apache.tapestry5.json.JSONObject; + +public class PublishEventDemoComponent +{ + @OnEvent("answer") + @PublishEvent + JSONObject answer() { + return new JSONObject("origin", "component"); + } + + @PublishEvent + JSONObject onAction() + { + return new JSONObject("origin", "component"); + } + +} http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/19fe6853/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/PublishEventDemoComponent2.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/PublishEventDemoComponent2.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/PublishEventDemoComponent2.java new file mode 100644 index 0000000..7771557 --- /dev/null +++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/PublishEventDemoComponent2.java @@ -0,0 +1,32 @@ +// 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.integration.app1.components; + +import org.apache.tapestry5.annotations.OnEvent; +import org.apache.tapestry5.annotations.PublishEvent; +import org.apache.tapestry5.json.JSONObject; + +public class PublishEventDemoComponent2 +{ + @PublishEvent + JSONObject onAction() + { + return new JSONObject("origin", "component"); + } + + @OnEvent("answer") + @PublishEvent + JSONObject answer() { + return new JSONObject("origin", "component"); + } + +} http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/19fe6853/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java index d7d76d6..e78a874 100644 --- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java +++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java @@ -57,32 +57,35 @@ public class Index private static final List<Item> ITEMS = CollectionFactory .newList( - new Item("ZoneFormDemo", "Zone Form Decoration", "Fields inside an Ajax-updatd Form are still decorated properly."), + + new Item("PublishEventDemo", "@PublishEvent Demo", "Publishing server-side events to client-side code (JavaScript)"), + +// new Item("ZoneFormDemo", "Zone Form Decoration", "Fields inside an Ajax-updatd Form are still decorated properly."), - new Item("AjaxValidationDemo", "Ajax Validation", "Demonstrated proper integration of server-side validation and client-side field decoration."), +// new Item("AjaxValidationDemo", "Ajax Validation", "Demonstrated proper integration of server-side validation and client-side field decoration."), new Item("OverrideEventHandlerDemo", "Event Handler Override Demo", "Event Handler methods overridden by sub-classes invoke base-class correctly."), - new Item("LogoSubclass", "Base class Assets in sub-classes", "Assets are resolved for the parent class if that's where the annotations are."), +// new Item("LogoSubclass", "Base class Assets in sub-classes", "Assets are resolved for the parent class if that's where the annotations are."), new Item("MissingRequiredARP", "Missing Query Parameter for @ActivationRequestParameter", "Activating a page with a required @ActivationRequestParameter, but no matching query parameter, is an error."), - new Item("DateFieldValidationDemo", "DateField Validation Demo", - "Use of DateField component when client validation is disabled."), +// new Item("DateFieldValidationDemo", "DateField Validation Demo", +// "Use of DateField component when client validation is disabled."), new Item("MixinParameters54", "Strict Mixin Parameters", "In the 5.4 DTD, Parameter Mixins must be qualified with the mixin id."), - new Item("AsyncDemo", "Async Links and Forms Demo", "Async (XHR) Updates without a containing Zone."), +// new Item("AsyncDemo", "Async Links and Forms Demo", "Async (XHR) Updates without a containing Zone."), new Item("FormCancelActionDemo", "Form Cancel Action Demo", "FormSupport.addCancel() support"), new Item("AjaxRadioDemo", "Ajax Radio Demo", "Radio components inside an Ajax form"), - new Item("TimeIntervalDemo", "TimeInterval Demo", "Interval component, based on Moment.js"), +// new Item("TimeIntervalDemo", "TimeInterval Demo", "Interval component, based on Moment.js"), - new Item("LocalDateDemo", "LocalDate Demo", "LocalDate component, based on Moment.js"), +// new Item("LocalDateDemo", "LocalDate Demo", "LocalDate component, based on Moment.js"), - new Item("EmptyIfDemo", "Empty If Demo", "Ensure an empty If can still render."), +// new Item("EmptyIfDemo", "Empty If Demo", "Ensure an empty If can still render."), new Item("MissingAssetDemo", "Missing Asset Demo", "Error when injecting an asset that does not exist."), http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/19fe6853/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PublishEventDemo.java ---------------------------------------------------------------------- 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 new file mode 100644 index 0000000..1876de5 --- /dev/null +++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PublishEventDemo.java @@ -0,0 +1,49 @@ +// Copyright 2016 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. + +// 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.integration.app1.pages; + +import org.apache.tapestry5.annotations.Import; +import org.apache.tapestry5.annotations.OnEvent; +import org.apache.tapestry5.annotations.PublishEvent; +import org.apache.tapestry5.json.JSONObject; + +@Import(stack = "core", library = "PublishEventDemo.js") +public class PublishEventDemo +{ + + @PublishEvent + JSONObject onAction() + { + return new JSONObject("origin", "page"); + } + + @OnEvent("answer") + @PublishEvent + JSONObject answer() { + return new JSONObject("origin", "page"); + } + +} http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/19fe6853/tapestry-core/src/test/resources/META-INF/assets/PublishEventDemo.js ---------------------------------------------------------------------- diff --git a/tapestry-core/src/test/resources/META-INF/assets/PublishEventDemo.js b/tapestry-core/src/test/resources/META-INF/assets/PublishEventDemo.js new file mode 100644 index 0000000..20c0406 --- /dev/null +++ b/tapestry-core/src/test/resources/META-INF/assets/PublishEventDemo.js @@ -0,0 +1,11 @@ +require(["t5/core/dom", "t5/core/ajax", "jquery"], function (dom, ajax, $) { + + $(document).ready(function() { + console.log('dom.getEventURL() : ' + dom.getEventUrl('answer', document.getElementById("page"))); + console.log('dom.getEventURL() 1 : ' + dom.getEventUrl('answer', document.getElementById("componentParagraph"))); + console.log('dom.getEventURL() 2 : ' + dom.getEventUrl('answer', document.getElementById("componentParagraph2"))); + console.log('dom.getEventURL() 3 : ' + dom.getEventUrl('answer', document.getElementById("componentParagraph3"))); + }); + +}); + http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/19fe6853/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/components/PublishEventDemoComponent.tml ---------------------------------------------------------------------- diff --git a/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/components/PublishEventDemoComponent.tml b/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/components/PublishEventDemoComponent.tml new file mode 100644 index 0000000..2d2b5f1 --- /dev/null +++ b/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/components/PublishEventDemoComponent.tml @@ -0,0 +1,3 @@ +<div id="component" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd"> + <p id="componentParagraph">I'm a component</p> +</div> http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/19fe6853/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/components/PublishEventDemoComponent2.tml ---------------------------------------------------------------------- diff --git a/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/components/PublishEventDemoComponent2.tml b/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/components/PublishEventDemoComponent2.tml new file mode 100644 index 0000000..b10d020 --- /dev/null +++ b/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/components/PublishEventDemoComponent2.tml @@ -0,0 +1,4 @@ +<t:container xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd"> + <p id="componentParagraph2">I'm another component</p> + <p id="componentParagraph3">I'm another component</p> +</t:container>
