Tapestry 5
  1. Tapestry 5
  2. TAP5-1861

Wrap javascript call rendering apis for interoperability and convenience

    Details

    • Type: Improvement Improvement
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: 5.3.2
    • Fix Version/s: None
    • Component/s: tapestry-core
    • Labels:

      Description

      Vast improvements to the ajax and javascript rendering API's have made things much easier to use in tapestry 5.2+, however I still think there is room for improvement. I find I can't work without this 'helper' service I designed to standardise script call rendering between xhr and non-xhr requests. The main motivation/benefit is that a set of functionality can now be called in either (xhr/non-xhr) context and still work. It also has the benefit of building the necessary JavaScriptCallback in the xhr context. In my opinion, this makes user code much tidier:

      public class JavascriptHelperImpl implements JavascriptHelper
      {
      @Inject
      private AjaxResponseRenderer ajaxResponseRenderer;
      @Inject
      private Request request;
      @Inject
      private JavaScriptSupport jsSupport;

      @Override
      public void addScript(final String format, final Object... args)
      {
      if (!request.isXHR())

      { jsSupport.addScript(format, args); return; }

      ajaxResponseRenderer.addCallback(new JavaScriptCallback()
      {
      @Override
      public void run(JavaScriptSupport javascriptSupport)

      { javascriptSupport.addScript(format, args); }

      });
      }
      }

      There may or may not be additional opportunity with the other methods such as 'addInitializerCall' but I haven't needed to.

      This code is free for anyone (including apache/tapestry) to use.

        Issue Links

          Activity

          Paul Stanton created issue -
          Paul Stanton made changes -
          Field Original Value New Value
          Description Vast improvements to the ajax and javascript rendering API's have made things much easier to use in tapestry 5.2+, however I still think there is room for improvement. I find I can't work without this 'helper' service I designed to standardise script call rendering between xhr and non-xhr requests. The main motivation/benefit is that a set of functionality can now be called in either (xhr/non-xhr) context and still work. It also has the benefit of building the necessary JavaScriptCallback in the xhr context. In my opinion, this makes user code much tidier:

          public class JavascriptHelperImpl implements JavascriptHelper
          {
          @Inject
          private AjaxResponseRenderer ajaxResponseRenderer;
          @Inject
          private Request request;
          @Inject
          private JavaScriptSupport jsSupport;

          @Override
          public void addScript(final String format, final Object... args)
          {
          if (!request.isXHR())
          {
          jsSupport.addScript(format, args);
          return;
          }

          ajaxResponseRenderer.addCallback(new JavaScriptCallback()
          {
          @Override
          public void run(JavaScriptSupport javascriptSupport)
          {
          javascriptSupport.addScript(format, args);
          }
          });
          }
          }

          There may or may not be additional opportunity with the other methods such as 'addInitializerCall' but I haven't needed to.
          Vast improvements to the ajax and javascript rendering API's have made things much easier to use in tapestry 5.2+, however I still think there is room for improvement. I find I can't work without this 'helper' service I designed to standardise script call rendering between xhr and non-xhr requests. The main motivation/benefit is that a set of functionality can now be called in either (xhr/non-xhr) context and still work. It also has the benefit of building the necessary JavaScriptCallback in the xhr context. In my opinion, this makes user code much tidier:

          public class JavascriptHelperImpl implements JavascriptHelper
          {
              @Inject
              private AjaxResponseRenderer ajaxResponseRenderer;
              @Inject
              private Request request;
              @Inject
              private JavaScriptSupport jsSupport;

              @Override
              public void addScript(final String format, final Object... args)
              {
                  if (!request.isXHR())
                  {
                      jsSupport.addScript(format, args);
                      return;
                  }

                  ajaxResponseRenderer.addCallback(new JavaScriptCallback()
                  {
                      @Override
                      public void run(JavaScriptSupport javascriptSupport)
                      {
                          javascriptSupport.addScript(format, args);
                      }
                  });
              }
          }

          There may or may not be additional opportunity with the other methods such as 'addInitializerCall' but I haven't needed to.

          This code is free for anyone (including apache/tapestry) to use.
          Hide
          Paul Stanton added a comment -

          usage:

          private void doSomethingOnServer()

          { ... jsHelper.addScript("MyObject.doSomethingOnClient();"); ... }

          void setupRender()

          { ... doSomethingOnServer(); ... }

          void onSomeAjaxEvent(){ ... doSomethingOnServer(); ... }
          Show
          Paul Stanton added a comment - usage: private void doSomethingOnServer() { ... jsHelper.addScript("MyObject.doSomethingOnClient();"); ... } void setupRender() { ... doSomethingOnServer(); ... } void onSomeAjaxEvent(){ ... doSomethingOnServer(); ... }
          Hide
          Howard M. Lewis Ship added a comment -

          Not a bad idea; I think the implementation is not quite ideal; basically, we could put different implementations of JavaScriptSupport into the Environment at different times to accomplish the "Right Thing" for invoking the methods in a way compatible with the overall request cycle.

          Show
          Howard M. Lewis Ship added a comment - Not a bad idea; I think the implementation is not quite ideal; basically, we could put different implementations of JavaScriptSupport into the Environment at different times to accomplish the "Right Thing" for invoking the methods in a way compatible with the overall request cycle.
          Hide
          Paul Stanton added a comment -

          that would be better!

          Show
          Paul Stanton added a comment - that would be better!
          Paul Stanton made changes -
          Link This issue relates to TAP5-1870 [ TAP5-1870 ]
          Hide
          Paul Stanton added a comment -

          Howard, is it your view that this is no longer an issue and that JavascriptSupport.addScript should be used instead of AjaxResponseRenderer.addCallback in both XHR and non-XHR requests?

          Show
          Paul Stanton added a comment - Howard, is it your view that this is no longer an issue and that JavascriptSupport.addScript should be used instead of AjaxResponseRenderer.addCallback in both XHR and non-XHR requests?
          Hide
          Howard M. Lewis Ship added a comment -

          No, we still have this issue.

          I can definitely see the need for a facade to handle this situation. Probably, the JavaScriptSupport interface could be used; most methods would throw an IllegalStateException, a few, such as require(), would capture results and add them to AjaxResponseRenderer.

          Show
          Howard M. Lewis Ship added a comment - No, we still have this issue. I can definitely see the need for a facade to handle this situation. Probably, the JavaScriptSupport interface could be used; most methods would throw an IllegalStateException, a few, such as require(), would capture results and add them to AjaxResponseRenderer.
          Howard M. Lewis Ship made changes -
          Assignee Howard M. Lewis Ship [ hlship ]
          Hide
          Paul Stanton added a comment -

          Hi Howard,

          I've made some discoveries which make the implementation posted here out of date; i'm sure you are aware of the following:

          1. if in the render or event handling phase of a normal request, JavaScriptSupport must be used over AjaxResponseRenderer
          2. if in the event handling phase of an ajax request AjaxResponseRenderer must be used over JavaScriptSupport
          however this was news to me:
          3. if in the 'render phase' of an ajax request, JavaScriptSupport must be used over AjaxResponseRenderer

          .. and in this third case, the 'isXHR' test is not sufficient; the only way to determine this case is to 'peek' for JavaScriptSupport.

          therefore, my current implementation of the previously posted utility looks like this:

          public void addScript(final InitializationPriority priority, final String format, final Object... args)
          {
          if (!request.isXHR()

          env.peek(JavaScriptSupport.class) != null) { jsSupport.addScript(priority, format, args); return; }

          ajaxResponseRenderer.addCallback(new JavaScriptCallback()
          {
          @Override
          public void run(JavaScriptSupport javascriptSupport)

          { javascriptSupport.addScript(priority, format, args); }

          });
          }

          I hope this helps design whatever solution you come up with.

          Regards, Paul.

          Show
          Paul Stanton added a comment - Hi Howard, I've made some discoveries which make the implementation posted here out of date; i'm sure you are aware of the following: 1. if in the render or event handling phase of a normal request, JavaScriptSupport must be used over AjaxResponseRenderer 2. if in the event handling phase of an ajax request AjaxResponseRenderer must be used over JavaScriptSupport however this was news to me: 3. if in the 'render phase' of an ajax request, JavaScriptSupport must be used over AjaxResponseRenderer .. and in this third case, the 'isXHR' test is not sufficient; the only way to determine this case is to 'peek' for JavaScriptSupport. therefore, my current implementation of the previously posted utility looks like this: public void addScript(final InitializationPriority priority, final String format, final Object... args) { if (!request.isXHR() env.peek(JavaScriptSupport.class) != null) { jsSupport.addScript(priority, format, args); return; } ajaxResponseRenderer.addCallback(new JavaScriptCallback() { @Override public void run(JavaScriptSupport javascriptSupport) { javascriptSupport.addScript(priority, format, args); } }); } I hope this helps design whatever solution you come up with. Regards, Paul.

            People

            • Assignee:
              Howard M. Lewis Ship
              Reporter:
              Paul Stanton
            • Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated:

                Development