Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Removed broken footnotes (moved them in-line)

Table of Contents

Tapestry and JavaScript

Tapestry 5 has had a interesting mix of characteristics.

...

Many users are perplexed by how Tapestry performs initialization: in a typical bespoke

Wiki Markup
{footnote}By "bespoke", we mean a non-component-based, manually created page; a standalone static HTML page.{footnote}

application, the developer will . In typical web page construction, the developer would create a <script> block at the bottom of the page, and do initializations there. In Tapestry, it can be much more complex:

  • A JavaScript library, containing one or more initialization functions, is created
  • The initialization functions must be monkey patched into the T5.initializers namespace

    Wiki Markup{footnote}Prior to 5.3, it was the {{(or older Tapestry.Initializers}} namespace; both names reference the same object, for backwards compatibility.{footnote}) namespace.

  • The JavaScriptSupport environmental must be used to invoke the function, by name, passing it a JSONObject to configure itself (the "specification")
  • The affected element must have a unique id attribute, used to coordinate the initialization in the client web browser

    Wiki Markup{footnote}Tapestry assists with unique id allocation, but it would be much better if unique ids were not necessary.{footnote}. (Tapestry assists with unique id allocation, but it would be much better if unique ids were not necessary.)

This often feels like overkill, but it is necessary for a number of desirable characteristics:

...

  • A module may be overriden (for instance, to work around a bug), in which case a specific asset may be used for the module, rather than the default
  • A module may need to be converted from one language to another: specifically, a module may be written in CoffeeScript, and need to be compiled down to JavaScript
  • A module's content may be aggregated with other related modules (much like a Tapestry 5.3 stack), especially in production

    Wiki Markup{footnote}A request for any module should provide the aggregated set of modules; RequireJS will not need to send additional requests for the other modules{footnote}. (A request for any module should provide the aggregated set of modules; RequireJS will not need to send additional requests for the other modules.)

  • Module content (aggregated or not) should be minimized

In addition, it may be reasonable to have Tapestry automatically (or via some configuration) wrap CommonJS modules as AMD modules Wiki Markup{footnote}. (Traditionally, Tapestry has configured this kind of behavior via service contributions, but there is ample evidence that this could be done using external configuration, perhaps using a JSON file in the module package, to control aggregation, wrapping, and other aspects the process. This would be more agile, as it would not require restarts when the configuration changes.{footnote})

Modules will be stored on the classpath, in a modulejs package below each library's root package. Modules within that package are referenced by their name relative to the package

Wiki Markup
{footnote}A rarely used feature of Tapestry is that a component library name may be mapped to multiple packages; resolving a module name may require a search among the packages. There is the expectation that the developer will ensure that there are no duplications that would lead to ambiguities.{footnote}

. . (A rarely used feature of Tapestry is that a component library name may be mapped to multiple packages; resolving a module name may require a search among the packages. There is the expectation that the developer will ensure that there are no duplications that would lead to ambiguities.)

Under this system, module core/pubsub would be the file pubsub.js in the package org.apache.tapestry5.corelib.modulejs, since Tapestry's component library 'core' is mapped to package org.apache.tapestry5.corelib.

...

  • require one or more modules
  • require a module (that exports a single function) and invoke the function, passing zero or more values

    Wiki Markup{footnote}Values passed to module functions may be limited to String and [JSONObject|http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/json/JSONObject.html].{footnote}. (Values passed to module functions may be limited to String and JSONObject.)

  • require a module and a function name and invoke named function exported by the module, passing zero or more values

...

Tapestry currently maintains two global message catalogs; a global server-side catalog (usually named WEB-INF/app.properties Wiki Markup{footnote}{{) and a client-side catalog. (app.properties }} provides application-specific messages, and overrides of other messages provided by Tapestry and other third-party libraries. The global message catalog is actually a composite of all of these sources.{footnote}) and a client-side catalog. The client-side catalog is smaller, more limited, and less extensible.

...

  • Redirect the entire page to a new URL (on the server, or elsewhere)
  • A server-side error to be presented to the user

    Wiki Markup{footnote}This was greatly enhanced in . (This was greatly enhanced in 5.3 to present the full exception report in a pop-up iframe.{footnote})

  • Update the content of an implicit (originating) element; typically the element for the Zone that triggered the request
  • Update the content of any number of other elements (identified by their client-side id)
  • Inject new JavaScript libraries into the page
  • Inject new CSS links into the page
  • Peform initializations (using T5.initializers) ... but only after all content updates have occurred

The injected JavaScript libraries and CSS links will often duplicate libraries and CSS links already present on the page; when the page is partially rendered, the server has no way to know what full or partial page renders have already occured

Wiki Markup
{footnote}It might be possible for the request to include a list of what's already loaded in the browser, so that the server can filter what it sends back; however, given factors such as content compression and typical upload vs. download bandwidth, it is almost certainly more effective for the browser to send too much, and let the client filter out duplicates.{footnote}

.

occurred. (It might be possible for the request to include a list of what's already loaded in the browser, so that the server can filter what it sends back; however, given factors such as content compression and typical upload vs. download bandwidth, it is almost certainly more effective for the browser to send too much, and let the client filter out duplicates.)

Tapestry 5.3 first loads any additional JavaScript (usually by adding new <script> tags to the page). Once JavaScript libraries and CSS links have been added, and JavaScript libraries have been loaded, the DOM is updated with the new content. Lastly, any initializations are processed.

...

  • Tapestry 5.3 style initializations will be a specific application of 5.4 style module requirement and invocation
  • IMMEDIATE may occur before DOM changes
  • Module requirement/invocation will occur in initialization priority order; for any single priority, initialization will occur in render order

    Wiki Markup
    {footnote}Technically, in the order of invocations on JavaScriptSupport.{footnote}

    .occur in render order. (Technically, in the order of invocations on JavaScriptSupport.)
  • The response will be embeddable inside other JSONObject responses.

...

Determining what assets are available is somewhat problematic as Tapestry mixes server-side only resources (.class files, .tml files, etc.) freely with assets that might be exposed to the browser Wiki Markup{footnote}This should never have been the case, but . (This should never have been the case, but that's hindsight.{footnote}. ) Some of those server-side resource may expose details, such as other server hosts and potentially user names and passwords, that should never be exposed to the client.

...

This is a big undertaking; this document is not a contract, and is certainly not complete, but is only starting point for discussions about what will be forthcoming in Tapestry 5.4. Wiki Markup{display-footnotes}