Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: cleaning up old wiki formatting

 

 

Warning
titleFor Older Versions of Tapestry

 

...

Div
stylefloat:right
titleRelated Articles
classaui-label
Content by Label
showLabelsfalse
showSpacefalse
titleRelated Articles
cqllabel in ("javascript","ajax") and space = currentSpace()

In production mode, by default, Tapestry will merge JavaScript libraries, add version numbering, and set a far-future expires header to encourage aggressive browser caching. Starting with version 5.3, Tapestry can also automatically minify (compress) JavaScript libraries when in production mode.

...

Tapestry provides several ways to add a link to a JavaScript library within your page or component. Although you can use direct <script type="text/javascript" src="xxx.js"></script> approach, you should only use it for JavaScript that resides outside of your application. For JavaScript within your app, Tapestry provides much better ways to do the same thing. Most users choose the simplest, the @Import annotation approach.{

Div
stylefloat: right

...

; max-width: 30%
Panel
borderColor#eee
titleBGColor#eee
titleJumpStart Demo

 JavaScript

Approach 1: @Import

Use the @Import annotation (or @IncludeJavaScriptLibrary in Tapestry 5.0 and 5.1) to include links to JavaScript (and CSS) files in your page or component. Tapestry ensures that each such file is only referenced once in your page.

Section
Column
Code Block
languagejava
titleFor Tapestry 5.2 and later
@Import(library={"context:js/jquery.js",
		"context:js/myeffects.js"})
public class MyComponent
{
 . . .

...


}
Column
Code Block
languagejava
titleFor Tapestry

...

5.0 and 5.1
@IncludeJavaScriptLibrary(value={"context:js/jquery.js",
		"context:js/myeffects.js"})
public class MyComponent
{
 . . .
}

@Import may also be applied to individual methods, in which case the import operation only occurs when the method is invoked.

Note: When specifying a file to import, you'll often use the context: binding prefix to indicate that the file is stored in the web application context, and not on the classpath. Relative paths will be on the classpath, relative to the Java class. See See Component Parameters for other binding prefix options.

...

Alternatively, you can use JavaScriptSupport (for Tapestry 5.2 or later) or RenderSupport (for Tapestry 5.0 and 5.1) to include a JavaScript library in your page or component. JavaScriptSupport and RenderSupport are environmental services that include a number of methods that will be used by components, or by services that are called from components. For example:

...

The importJavaScriptLibrary method (or addScriptLink for Tapestry 5.0 and 5.1) adds a link to a JavaScript library. A component can inject such a script and pass one or more of assets to this method:

Section
Column
Code Block
languagejava
titleTapestry 5.2 and later
  @Inject @Path("context:/js/myeffects.js")
  private Asset myEffects;

  @Environmental
  private JavaScriptSupport javaScriptSupport;

  void setupRender()
  {
    javaScriptSupport.importJavaScriptLibrary(myEffects);
  }
Column
Code Block
languagejava
titleTapestry 5.1 and earlier
  @Inject @Path("context:/js/myeffects.js")
  private Asset myEffects;

  @Environmental
  private RenderSupport renderSupport;

  void setupRender()
  {
    renderSupport.addScriptLink(myEffects);
  }

Tapestry will ensure that the necessary <link> elements are added to the top of the document (in the <head> element). With Tapestry 5.3 and later the new elements are inserted at the bottom of the <head> element; in versions before 5.3 they appear at the top of the <head> element).

...

The setupRender method (the name is specifically linked to a render phase) is the correct place to inform the JavaScriptSupport (or RenderSupport) service that the library is needed.{

Div
stylemax-width: 30%; float: right

...

;
Panel
borderColor#eee
titleBGColor#eee
titleJumpStart Demo

 Reusable JavaScript

The addScript method

The addScript method is used when you need to add some JavaScript code directly to the page. This will be inserted at the bottom of the document, and will only be executed when the document has finished loading on the client (i.e., from the window.onload event handler).

Section
Column
Code Block
languagetext
titleTapestry 5.2 and later
void afterRender()
{
    javaScriptSupport.addScript(
        "$('%s').observe('click', hideMe());",
        container.getClientId());
}
Column
Code Block
languagetext
titleTapestry 5.1 and earlier
void afterRender()
{
    javaScriptSupport.addScript(String.format(
        "$('%s').observe('click', hideMe());",
        container.getClientId()));
}

When calling the method, the format string can include standard substitutions (such as '%s') for arguments. This saves you the trouble of calling String.format() yourself. (For Tapestry 5.1 and earlier, you must call String.format() yourself.) In any case, the formatted JavaScript is added to the script block in the rendered output.

...

JavaScriptSupport (like RenderSupport before it) is an environmental object, so you will normally inject it via the @Environmental annotation:

Section
Column
Code Block
languagejava
titleFor Tapestry 5.2 and later
  @Environmental
  private JavaScriptSupport javaScriptSupport;
Column
Code Block
languagejava
titleFor Tapestry 5.0 and 5.1
  @Environmental
  private RenderSupport renderSupport;

The @Environmental annotation only works inside components, but occasionally you may want to inject JavaScriptSupport (or RenderSupport) into a service. Fortunately, a proxy has been set up to allow the use of @Inject instead:

Section
Column
Code Block
languagejava
titleFor Tapestry 5.2 and later
  @Inject
  private JavaScriptSupport javaScriptSupport;

...


Column
Code Block
languagejava
titleFor Tapestry

...

5.0 and 5.1
  @Inject
  private RenderSupport renderSupport;

... or, in a service implementation constructor:

Section
Column
Code Block
languagejava
titleFor Tapestry 5.2 and later
  public MyServiceImpl(JavaScriptSupport support)
  {
    . . .
  }
Column
Code Block
languagejava
titleFor Tapestry 5.0 and 5.1
  public MyServiceImpl(RenderSupport support)
  {
    . . .
  }

Inside a component, you should use @Environmental, to highlight the fact that RenderSupport (like most environmental objects) is only available during rendering, not during action requests.

...

This is a very useful feature, as it reduces the number of requests needed to present a page to the user. It can be disabled, however, by setting the SymbolConstants.COMBINE_SCRIPTS configuration symbol to false in your application's module class (normally AppModule.java). By default it is enabled when in production mode and disabled otherwise.

...

IMPORTANT NOTE: The tapestry-core module only provides the empty infrastructure for supporting minification; the actual logic is supplied in the tapestry-yuicompressor module. To use it, you'll need to update your dependencies to include this module.

Code Block
languagexml
titleMaven pom.xml (partial)
<dependency>
    <groupId>org.apache.tapestry</groupId>
    <artifactId>tapestry-yuicompressor</artifactId>
    <version>${tapestry-release-version}</version>
</dependency>

Gradle would be similar, of course. If you aren't using something like Maven or Gradle, you'll have to download the jar and its dependency (com.yahoo.platform.yui: yuicompressor) yourself.

Minification can be disabled by setting the SymbolConstants.MINIFICATION_ENABLED the tapestry.enable-minification configuration symbol to false in your application's module class (usually AppModule.java). By default it is enabled when in production mode and disabled otherwise.

...

In versions prior to 5.3, Tapestry uses used a modified version of the Blackbird JavaScript console. The Tapestry object includes three functions: debug, warn and error.

Each of these functions take a message and an optional pattern; if the pattern is provided, the message is interpolated on the pattern. The final message is displayed in the Blackbird console, which will make itself visible automatically.

In production mode, debug messages will be filtered out (they will not be visible until the user presses F2 to display the console, and then clicks the grayed out icon for debug messages). In development mode, debug messages are not filtered out.

Example usage:

Code Block
languagejava
 Tapestry.debug("Field id is #{id}, value is #{value}", field);

 Tapestry.error("Server is not available.");

With Tapestry 5.3 and later the Blackbird console has been removed; just use the standard console logging features (e.g. console.log()) built into modern browsers.

...

The client-side function Tapestry.waitForPage() can be used in an element's onclick handler to force a wait for the page to fully load. In this race condition, the screen will dim and a message will appear advising the user to wait a moment; once the page is fully loaded, this modal dialog will be removed.

The correct usage is:

Code Block
languagejava
  <a href="..." onclick="javascript:Tapestry.waitForPage(event);"> ... </a>

The constant MarkupConstants.WAIT_FOR_PAGE contains the part of this snippet inside the quotes.

...

For example, you might store a value for an element in one place:

Code Block
languagejava
  $T(myid).fadeDuration = .5;

Then use it somewhere else:

Code Block
languagejava
  new Effect.Fade($(myId), { duration: $T(myid).fadeDuration });

Ajax Components and Mixins

...

Built-in Libraries

Div
style

...

float: right

...

; max-width

...

: 30%
Panel
borderColor#eee
titleBGColor#eee
titleAlternatives to Prototype

Tapestry 5.4 includes the ability to switch between Prototype and JQuery. For Tapestry 5.3 and earlier, you also have some options::

 

Tapestry 5.4 and earlier come with the Prototype and Scriptaculous libraries ... no extra download is required. Tapestry will automatically link into your pages the prototype.js, scriptaculous.js, and effects.js libraries, as well as the Tapestry library, tapestry.js (which largely consists of support for form input validation). Starting with Tapestry 5.3, Underscore is also included.

Prototype and Scriptaculous Versions

Tapestry included only Prototype and Scriptaculous in versions prior to Tapestry 5.4. See Supported Environments and Versions for a matrix of prototype and scriptaculous versions supported by Tapestry.

In versions before 5.4, Tapestry used

...

Prototype and Scriptaculous Versions

Tapestry 5.3.5

Prototype 1.7.1

Scriptaculous 1.9

Underscore 1.1.7

Tapestry 5.3+

Prototype 1.7

Scriptaculous 1.9

Underscore 1.1.7

Tapestry 5.2.6

Prototype 1.7

Scriptaculous 1.9

Tapestry 5.2

Prototype 1.6.1

Scriptaculous 1.8.2

Tapestry 5.1

Prototype 1.6.0.3

Scriptaculous 1.8.2

Tapestry 5.0

Prototype 1.6.0

Scriptaculous 1.8.0

Tapestry uses a modified version of the main Scriptaculous library, scriptaculous.js, with the library's default autoloading behavior turned off. This lets Tapestry and Tapestry components control which Scriptaculus scripts are loaded, rather than having all of them loaded unnecessarily.

If you need access to other Scriptaculous libraries, you can provide them as follows:

Code Block
languagejava
  @Inject @Path("${tapestry.scriptaculous}/dragdrop.js")
  private Asset dragDropLibrary;

  @Environmental
  private JavaScriptSupport javaScriptSupport;

  void setupRender()
  {
    javaScriptSupport.addScriptLink(dragDropLibrary);
  }

The Asset is injected, using the ${tapestry.scriptaculous} configuration symbol to reference the location of the Scriptaculous library.

...

  • getInitialization : this method makes it possible to call a JavaScript initialization for the stack. Tapestry will automatically add this initialization to the page that imports the stacks.
Code Block
languagejava
titlemyStack.java
public class myStack implements JavaScriptStack {

    private final AssetSource assetSource;

    public myStack (final AssetSource assetSource)
    {
        this.assetSource = assetSource;
    }

    public String getInitialization()
    {
    	return null;
    }



    public List<Asset> getJavaScriptLibraries(

...

)
    {
    	List<Asset> ret = new ArrayList<Asset>();

	ret.add(assetSource.getContextAsset("static/js/jquery.js", null));

        ret.add(assetSource.getContextAsset("static/js/jquery.ui.core.js", null));

        return ret;
    }

    public List<StylesheetLink> getStylesheets()
    {
    	List<StylesheetLink> ret = new ArrayList<StylesheetLink>();

    	ret.add(new StylesheetLink(assetSource.getContextAsset("static/css/style.css", null)));

	return ret;
    }

    public List<String> getStacks()
    {
        return Collections.emptyList();
    }

}

When your new Stack is created, you have to define it in your AppModule.

Code Block
languagejava
titleAppModule.java (partial)
@Contribute(JavaScriptStackSource.class)
public static void addMyStack (MappedConfiguration<String, JavaScriptStack> configuration)
{
        configuration.addInstance("MyNewStack", myStack.class);
}

You can now use it in your pages and components, by using the @Import annotation or the JavaScriptSupport service :

Section
Column
Code Block
languagejava
titleWith @Import
  @Import(stack="MyNewStack")
  public class myPage {
  }
Column
Code Block
languagejava
titleWith JavaScriptSupport
@Inject
private JavaScriptSupport js;

@SetupRender
public void importStack(){
  js.importStack("MyNewStack");
}