Cool and long awaited feature.

On Sun, Mar 19, 2017 at 5:08 PM,  <thiag...@apache.org> wrote:
> Repository: tapestry-5
> Updated Branches:
>   refs/heads/master aaa0d550a -> 6b4ca30b8
>
>
> 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/6b4ca30b
> Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/6b4ca30b
> Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/6b4ca30b
>
> Branch: refs/heads/master
> Commit: 6b4ca30b83bed396006107f5008a3781eee1db86
> Parents: aaa0d55
> Author: Thiago H. de Paula Figueiredo <thi...@arsmachina.com.br>
> Authored: Sun Mar 19 13:07:00 2017 -0300
> Committer: Thiago H. de Paula Figueiredo <thi...@arsmachina.com.br>
> Committed: Sun Mar 19 13:07:00 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/6b4ca30b/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/6b4ca30b/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 &lt;body&gt; 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/6b4ca30b/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/6b4ca30b/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/6b4ca30b/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/6b4ca30b/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/6b4ca30b/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/6b4ca30b/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/6b4ca30b/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/6b4ca30b/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/6b4ca30b/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/6b4ca30b/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/6b4ca30b/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/6b4ca30b/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>
>



-- 
Massimo Lusetti


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tapestry.apache.org
For additional commands, e-mail: dev-h...@tapestry.apache.org

Reply via email to