Modified: websites/production/tapestry/content/class-reloading.html
==============================================================================
--- websites/production/tapestry/content/class-reloading.html (original)
+++ websites/production/tapestry/content/class-reloading.html Wed Sep 20 
12:29:16 2017
@@ -27,6 +27,16 @@
       </title>
   <link type="text/css" rel="stylesheet" href="/resources/space.css" />
 
+          <link href='/resources/highlighter/styles/shCoreCXF.css' 
rel='stylesheet' type='text/css' />
+    <link href='/resources/highlighter/styles/shThemeCXF.css' rel='stylesheet' 
type='text/css' />
+    <script src='/resources/highlighter/scripts/shCore.js' 
type='text/javascript'></script>
+          <script src='/resources/highlighter/scripts/shBrushJava.js' 
type='text/javascript'></script>
+          <script src='/resources/highlighter/scripts/shBrushXml.js' 
type='text/javascript'></script>
+          <script src='/resources/highlighter/scripts/shBrushPlain.js' 
type='text/javascript'></script>
+        <script>
+      SyntaxHighlighter.defaults['toolbar'] = false;
+      SyntaxHighlighter.all();
+    </script>
   
   <link href="/styles/style.css" rel="stylesheet" type="text/css"/>
 
@@ -67,13 +77,47 @@
       </div>
 
       <div id="content">
-                <div id="ConfluenceContent"><h1 
id="ClassReloading-LiveClassandTemplateReloading">Live Class and Template 
Reloading</h1><parameter ac:name="style">float:right</parameter><parameter 
ac:name="title">Related Articles</parameter><parameter 
ac:name="class">aui-label</parameter><rich-text-body><parameter 
ac:name="showLabels">false</parameter><parameter 
ac:name="showSpace">false</parameter><parameter ac:name="title">Related 
Articles</parameter><parameter ac:name="cql">label = "class-reloading" and 
space = currentSpace()</parameter></rich-text-body><p>One of the best features 
of Tapestry is automatic reloading of changed classes and templates. <em>Page 
and component</em> classes will automatically reload when changed. Likewise, 
changes to component templates and other related resources will also be picked 
up immediately. In addition, starting in version 5.2, your service classes will 
also be reloaded automatically after changes (if you're using <a  
href="ioc.html">Tapestry I
 oC</a>).</p><h2 id="ClassReloading-TemplateReloading">Template 
Reloading</h2><p>When a template changes, all page instances (as well as the 
hierarchy of components below them) are discarded and reconstructed with the 
new template. However, classes are not reloaded in this case.</p><h2 
id="ClassReloading-ClassReloading">Class Reloading</h2><p>On a change to 
<em>any</em> loaded class from inside a controlled package (or any sub-package 
of a controlled package), Tapestry will discard all page instances, and discard 
the class loader.</p><p><a  href="persistent-page-data.html">Persistent field 
data</a> on the pages will usually not be affected (as it is stored separately, 
usually in the session). This allows you to make fairly significant changes to 
a component class even while the application continues to run.</p><h2 
id="ClassReloading-PackagesScanned">Packages Scanned</h2><p>Only certain 
classes are subject to reload. Reloading is based on package name; the packages 
that are reloaded a
 re derived from the <a  href="configuration.html">application 
configuration</a>.</p><p>If your root package is 
<code>org.example.myapp</code>, then only classes in the following packages 
(and their sub-packages) will be scanned for automatic 
reloads:</p><ul><li>org.example.myapp.pages</li><li>org.example.myapp.components</li><li>org.example.myapp.mixins</li><li>org.example.myapp.base</li><li>org.example.myapp.services
 (Tapestry 5.2 and later, with restrictions)</li></ul><p>
+                <div id="ConfluenceContent"><h1 
id="ClassReloading-LiveClassandTemplateReloading">Live Class and Template 
Reloading</h1><div class="aui-label" style="float:right" title="Related 
Articles">
+
+
+
+
+
+
+
+
+<h3>Related Articles</h3>
+
+<ul class="content-by-label"><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  
href="service-implementation-reloading.html">Service Implementation 
Reloading</a>
+                
+                        
+                    </div>
+    </li><li>
+        <div>
+                <span class="icon aui-icon aui-icon-small 
aui-iconfont-page-default" title="Page">Page:</span>        </div>
+
+        <div class="details">
+                        <a  href="class-reloading.html">Class Reloading</a>
+                
+                        
+                    </div>
+    </li></ul>
+</div>
+
+
+<p>One of the best features of Tapestry is automatic reloading of changed 
classes and templates. <em>Page and component</em> classes will automatically 
reload when changed. Likewise, changes to component templates and other related 
resources will also be picked up immediately. In addition, starting in version 
5.2, your service classes will also be reloaded automatically after changes (if 
you're using <a  href="ioc.html">Tapestry IoC</a>).</p><h2 
id="ClassReloading-TemplateReloading">Template Reloading</h2><p>When a template 
changes, all page instances (as well as the hierarchy of components below them) 
are discarded and reconstructed with the new template. However, classes are not 
reloaded in this case.</p><h2 id="ClassReloading-ClassReloading">Class 
Reloading</h2><p>On a change to <em>any</em> loaded class from inside a 
controlled package (or any sub-package of a controlled package), Tapestry will 
discard all page instances, and discard the class loader.</p><p><a  
href="persistent-
 page-data.html">Persistent field data</a> on the pages will usually not be 
affected (as it is stored separately, usually in the session). This allows you 
to make fairly significant changes to a component class even while the 
application continues to run.</p><h2 
id="ClassReloading-PackagesScanned">Packages Scanned</h2><p>Only certain 
classes are subject to reload. Reloading is based on package name; the packages 
that are reloaded are derived from the <a  
href="configuration.html">application configuration</a>.</p><p>If your root 
package is <code>org.example.myapp</code>, then only classes in the following 
packages (and their sub-packages) will be scanned for automatic 
reloads:</p><ul><li>org.example.myapp.pages</li><li>org.example.myapp.components</li><li>org.example.myapp.mixins</li><li>org.example.myapp.base</li><li>org.example.myapp.services
 (Tapestry 5.2 and later, with restrictions)</li></ul><p>
 
 </p><div class="confluence-information-macro 
confluence-information-macro-information"><p class="title">Added in 
5.2</p><span class="aui-icon aui-icon-small aui-iconfont-info 
confluence-information-macro-icon"></span><div 
class="confluence-information-macro-body">
 </div></div>
 <div class="error"><span class="error">Unknown macro: {div}</span> 
 <p>Starting in Tapestry 5.2, live class reloading includes service 
implementation classes. There are some limitations to this. See <a  
href="service-implementation-reloading.html" title="Service Implementation 
Reloading">Service Implementation Reloading</a> for more details.</p>
-</div><h2 id="ClassReloading-FileSystemOnly">File System Only</h2><p>Reloading 
of classes and other files applies only to files that are actually on the file 
system, and not files obtained from JAR files. This is perfect during 
development, where the files in question are in your local workspace. In a 
deployed application, you are somewhat subject to the implementation of your 
servlet container or application server.</p><h2 
id="ClassReloading-ClassLoaderIssues">Class Loader Issues</h2><p>Tapestry uses 
an extra class loader to load page and component classes.</p><p>When a change 
to an underlying Java class file is detected, Tapestry discards the class 
loader and any pooled page instances.</p><p>You should be careful to not hold 
any references to Tapestry pages or components in other code, such as Tapestry 
IoC services. Holding such references can cause significant memory leaks, as 
they can prevent the class loader from being reclaimed by the garbage 
collector.</p><h2 id="ClassReloadi
 ng-ClassCastExceptions">ClassCastExceptions</h2><p>Tapestry's class loader 
architecture can cause minor headaches when you make use of a services layer, 
or any time that you pass component instances to objects that are not 
themselves components.</p><p>In such cases you may see ClassCastException 
errors. This is because the same class name, say org.example.myapp.pages.Start, 
exists as two different class instances. One class instance is loaded by the 
web application's default class loader. A second class instance has been loaded 
<em>and transformed</em> by Tapestry's reloading class loader.</p><p>Ordinary 
classes, such as Tapestry IoC Services, will be loaded by the default class 
loader and expect instances to be loaded by the same class loader (or a 
parent).</p><p>The solution to this problem is to introduce an interface; the 
component class should implement the interface, and the service should expect 
an instance of the interface, rather than a specific type.</p><p>It is 
important 
 that the interface be loaded by the default class loader. It should not be in 
the pages or components package, but instead be in another package, such as 
services.</p><h2 id="ClassReloading-HandlingReloadsinyourCode">Handling Reloads 
in your Code</h2><p>On occasion, you may need to know when invalidations occur, 
to clear your own cache. For example, if you have a binding that creates new 
classes, the way <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/PropertyConduitSource.html";>PropertyConduitSource</a>
 does, you need to discard any cached classes or instances when a change is 
detected in component classes.</p><p>You do this by registering a listener with 
the correct <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tpaestry5/services/InvalidationEventHub.html";>InvalidationEventHub</a>
 service.</p><p>For example, your service may be in the business of creating 
new classes based on component
  classes, and keep a cache of those classes:</p><parameter 
ac:name="">java</parameter><plain-text-body>public class MyServiceImpl 
implements MyService, InvalidationEventListener
+</div><h2 id="ClassReloading-FileSystemOnly">File System Only</h2><p>Reloading 
of classes and other files applies only to files that are actually on the file 
system, and not files obtained from JAR files. This is perfect during 
development, where the files in question are in your local workspace. In a 
deployed application, you are somewhat subject to the implementation of your 
servlet container or application server.</p><h2 
id="ClassReloading-ClassLoaderIssues">Class Loader Issues</h2><p>Tapestry uses 
an extra class loader to load page and component classes.</p><p>When a change 
to an underlying Java class file is detected, Tapestry discards the class 
loader and any pooled page instances.</p><p>You should be careful to not hold 
any references to Tapestry pages or components in other code, such as Tapestry 
IoC services. Holding such references can cause significant memory leaks, as 
they can prevent the class loader from being reclaimed by the garbage 
collector.</p><h2 id="ClassReloadi
 ng-ClassCastExceptions">ClassCastExceptions</h2><p>Tapestry's class loader 
architecture can cause minor headaches when you make use of a services layer, 
or any time that you pass component instances to objects that are not 
themselves components.</p><p>In such cases you may see ClassCastException 
errors. This is because the same class name, say org.example.myapp.pages.Start, 
exists as two different class instances. One class instance is loaded by the 
web application's default class loader. A second class instance has been loaded 
<em>and transformed</em> by Tapestry's reloading class loader.</p><p>Ordinary 
classes, such as Tapestry IoC Services, will be loaded by the default class 
loader and expect instances to be loaded by the same class loader (or a 
parent).</p><p>The solution to this problem is to introduce an interface; the 
component class should implement the interface, and the service should expect 
an instance of the interface, rather than a specific type.</p><p>It is 
important 
 that the interface be loaded by the default class loader. It should not be in 
the pages or components package, but instead be in another package, such as 
services.</p><h2 id="ClassReloading-HandlingReloadsinyourCode">Handling Reloads 
in your Code</h2><p>On occasion, you may need to know when invalidations occur, 
to clear your own cache. For example, if you have a binding that creates new 
classes, the way <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/PropertyConduitSource.html";>PropertyConduitSource</a>
 does, you need to discard any cached classes or instances when a change is 
detected in component classes.</p><p>You do this by registering a listener with 
the correct <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tpaestry5/services/InvalidationEventHub.html";>InvalidationEventHub</a>
 service.</p><p>For example, your service may be in the business of creating 
new classes based on component
  classes, and keep a cache of those classes:</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">public class MyServiceImpl implements MyService, 
InvalidationEventListener
 {
   public final Map&lt;String,Class&gt; cache = new 
ConcurrentHashMap&lt;String,Class&gt;();
 
@@ -81,14 +125,19 @@
 
   public void objectWasInvalidated() { cache.clear(); }
 }
-</plain-text-body><p>Here, the service implementation implements the 
InvalidationEventListener interface, as well as its service interface. The 
question is: how does it register for notifications?</p><p>In your module, you 
will want to use a service builder method, such as:</p><parameter 
ac:name="">java</parameter><plain-text-body>public static MyService 
buildMyService(@Autobuild MyServiceImpl service, @ComponentClasses 
InvalidationEventHub hub)
+</pre>
+</div></div><p>Here, the service implementation implements the 
InvalidationEventListener interface, as well as its service interface. The 
question is: how does it register for notifications?</p><p>In your module, you 
will want to use a service builder method, such as:</p><div class="code panel 
pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">public static MyService buildMyService(@Autobuild 
MyServiceImpl service, @ComponentClasses InvalidationEventHub hub)
 {
   hub.addInvalidationListener(service);
 
   return service;
 }
-</plain-text-body><p>This is the intent of service builder methods; to do more 
than just injecting dependencies.</p><h2 
id="ClassReloading-CheckingForUpdates">Checking For Updates</h2><p>The built in 
InvalidationEventHub services provide notifications of changes to component 
classes, to component templates, and to component message catalogs. If you wish 
to check some other resources (for example, files in a directory of the file 
system or rows in a database table), you should register as an <a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/UpdateListener.html";>UpdateListener</a>
 with the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/UpdateListenerHub.html";>UpdateListenerHub</a>
 service.</p><p>Periodically (the frequency is configurable), UpdateListeners 
are notified that they should check for updates. Typically, UpdateListeners are 
also InvalidationEventHubs (or provide 
 InvalidationEventHubs), so that other interested parties can be alerted when 
underlying data changes.</p><h2 
id="ClassReloading-TroubleshootingLiveClassReloading">Troubleshooting Live 
Class Reloading</h2><h3 id="ClassReloading-QuickChecklist">Quick 
Checklist</h3><ul><li>"Production Mode" must be false (in Tapestry 5.3 and 
later)</li><li>The class must be one that Tapestry instantiates (a page, 
component, or mixin class, or a Tapestry IOC service implementation that 
implements an interface)</li><li>Turn on "Build Automatically" in your IDE, or 
remember to build manually.</li><li>Turn <em>off</em> JVM hot code swapping, if 
your servlet container supports it.</li><li>Eclipse: Uncheck the "derived" 
checkbox for the Target dir (in the Project Explorer view, right click on 
"target", select properties, uncheck "derived" on the Resource 
tab)</li></ul><p>Some of these issues are described in more detail 
below.</p><h3 id="ClassReloading-IfLiveClassReloadingdoesn'twork">If Live Class 
Reloading
  doesn't work</h3><h4 id="ClassReloading-ProductionMode">Production 
Mode</h4><p>Starting with Tapestry 5.3, Live Class Reloading only works when 
not in "Production Mode". Check your application module (usually 
AppModule.java) to be sure you have:</p><parameter 
ac:name="lang">java</parameter><plain-text-body>configuration.add(SymbolConstants.PRODUCTION_MODE,
 "false");
-</plain-text-body><p>and that this isn't being overridden to "true" on your 
application's startup command line.</p><h4 
id="ClassReloading-BuildPathIssues">Build Path Issues</h4><p>Live Class 
Reloading can fail if your build path isn't set correctly, and the exact 
configuration may differ between Maven plugin versions and Eclipse versions. 
The build process must be set to create classes in a folder which is in the 
servlet container's classpath.</p><p>Live Class Reloading won't work correctly 
with vanilla Tomcat without some tweaks (see below).</p><p>Non-Tapestry filters 
can interfere with LCR. Try disabling other filters in your web.xml file to see 
if that helps.</p><h4 id="ClassReloading-BuildingAutomatically">Building 
Automatically</h4><p>Although LCR allows you to see changes without restarting 
your app, you still need to "build" your project (to compile the Java source 
into byte code). Your IDE can be set to do this automatically every time you 
save a file. (In Eclipse, this is d
 one using <code>Project &gt; Build Automatically</code>.) Alternatively, you 
can manually trigger a build after you save a file. (In Eclipse, this is done 
using <code>Project &gt; Build</code>, or by pressing 
<code>Control-B</code>.)</p><h4 
id="ClassReloading-TurnoffJVMhotcodeswapping&amp;automaticrestarts">Turn off 
JVM hot code swapping &amp; automatic restarts</h4><p>Many servlet containers, 
including Tomcat and Jetty, support various forms of hot code swapping and/or 
automatic restarts when file changes are detected. These are generally 
<strong>much slower</strong> than LCR and usually should be turned off with 
Tapestry applications. If you're using RunJettyRun plugin for Eclipse, for 
example, edit your Run Configuration, and on the Jetty tab, click Show Advanced 
Options and uncheck the Enable Scanner checkbox.</p><h3 
id="ClassReloading-TomcatSpecifics">Tomcat Specifics</h3><p>See <a  
class="external-link" 
href="http://docs.codehaus.org/display/TYNAMO/Developing+with+Tomcat+and+E
 clipse" rel="nofollow">these Tomcat-specific hints</a></p><h3 
id="ClassReloading-IfLiveClassReloadingworksbutisslow">If Live Class Reloading 
works but is slow</h3><p>If LCR works for you but is slow (more than a second 
or two), consider the following.</p><ul><li>Be sure your project source files 
(your workspace in Eclipse, for example), are on a local drive, NOT a network 
location. Network drives are always slower, and the file system scanning needed 
for LCR can add a noticable lag if I/O is slow. If you use Maven, be sure to 
put your local repository (e.g. ~/.m2/repository) on a local drive for similar 
reasons.</li><li>Since LCR adds classes to your PermGen space, you may be 
running low on PermGen memory (and may eventually get a 
"java.lang.OutOfMemoryError: PermGen space" error). Try increasing PermGen size 
with a JVM argument of something like 
<code>-XX:MaxPermSize=400m</code></li></ul><p><plain-text-body>{scrollbar}</plain-text-body></p></div>
+</pre>
+</div></div><p>This is the intent of service builder methods; to do more than 
just injecting dependencies.</p><h2 
id="ClassReloading-CheckingForUpdates">Checking For Updates</h2><p>The built in 
InvalidationEventHub services provide notifications of changes to component 
classes, to component templates, and to component message catalogs. If you wish 
to check some other resources (for example, files in a directory of the file 
system or rows in a database table), you should register as an <a  
class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/UpdateListener.html";>UpdateListener</a>
 with the <a  class="external-link" 
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/UpdateListenerHub.html";>UpdateListenerHub</a>
 service.</p><p>Periodically (the frequency is configurable), UpdateListeners 
are notified that they should check for updates. Typically, UpdateListeners are 
also InvalidationEventHubs (or provide Invali
 dationEventHubs), so that other interested parties can be alerted when 
underlying data changes.</p><h2 
id="ClassReloading-TroubleshootingLiveClassReloading">Troubleshooting Live 
Class Reloading</h2><h3 id="ClassReloading-QuickChecklist">Quick 
Checklist</h3><ul><li>"Production Mode" must be false (in Tapestry 5.3 and 
later)</li><li>The class must be one that Tapestry instantiates (a page, 
component, or mixin class, or a Tapestry IOC service implementation that 
implements an interface)</li><li>Turn on "Build Automatically" in your IDE, or 
remember to build manually.</li><li>Turn <em>off</em> JVM hot code swapping, if 
your servlet container supports it.</li><li>Eclipse: Uncheck the "derived" 
checkbox for the Target dir (in the Project Explorer view, right click on 
"target", select properties, uncheck "derived" on the Resource 
tab)</li></ul><p>Some of these issues are described in more detail 
below.</p><h3 id="ClassReloading-IfLiveClassReloadingdoesn'twork">If Live Class 
Reloading doesn
 't work</h3><h4 id="ClassReloading-ProductionMode">Production 
Mode</h4><p>Starting with Tapestry 5.3, Live Class Reloading only works when 
not in "Production Mode". Check your application module (usually 
AppModule.java) to be sure you have:</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">configuration.add(SymbolConstants.PRODUCTION_MODE, 
"false");
+</pre>
+</div></div><p>and that this isn't being overridden to "true" on your 
application's startup command line.</p><h4 
id="ClassReloading-BuildPathIssues">Build Path Issues</h4><p>Live Class 
Reloading can fail if your build path isn't set correctly, and the exact 
configuration may differ between Maven plugin versions and Eclipse versions. 
The build process must be set to create classes in a folder which is in the 
servlet container's classpath.</p><p>Live Class Reloading won't work correctly 
with vanilla Tomcat without some tweaks (see below).</p><p>Non-Tapestry filters 
can interfere with LCR. Try disabling other filters in your web.xml file to see 
if that helps.</p><h4 id="ClassReloading-BuildingAutomatically">Building 
Automatically</h4><p>Although LCR allows you to see changes without restarting 
your app, you still need to "build" your project (to compile the Java source 
into byte code). Your IDE can be set to do this automatically every time you 
save a file. (In Eclipse, this is done us
 ing <code>Project &gt; Build Automatically</code>.) Alternatively, you can 
manually trigger a build after you save a file. (In Eclipse, this is done using 
<code>Project &gt; Build</code>, or by pressing <code>Control-B</code>.)</p><h4 
id="ClassReloading-TurnoffJVMhotcodeswapping&amp;automaticrestarts">Turn off 
JVM hot code swapping &amp; automatic restarts</h4><p>Many servlet containers, 
including Tomcat and Jetty, support various forms of hot code swapping and/or 
automatic restarts when file changes are detected. These are generally 
<strong>much slower</strong> than LCR and usually should be turned off with 
Tapestry applications. If you're using RunJettyRun plugin for Eclipse, for 
example, edit your Run Configuration, and on the Jetty tab, click Show Advanced 
Options and uncheck the Enable Scanner checkbox.</p><h3 
id="ClassReloading-TomcatSpecifics">Tomcat Specifics</h3><p>See <a  
class="external-link" 
href="http://docs.codehaus.org/display/TYNAMO/Developing+with+Tomcat+and+Eclipse
 " rel="nofollow">these Tomcat-specific hints</a></p><h3 
id="ClassReloading-IfLiveClassReloadingworksbutisslow">If Live Class Reloading 
works but is slow</h3><p>If LCR works for you but is slow (more than a second 
or two), consider the following.</p><ul><li>Be sure your project source files 
(your workspace in Eclipse, for example), are on a local drive, NOT a network 
location. Network drives are always slower, and the file system scanning needed 
for LCR can add a noticable lag if I/O is slow. If you use Maven, be sure to 
put your local repository (e.g. ~/.m2/repository) on a local drive for similar 
reasons.</li><li>Since LCR adds classes to your PermGen space, you may be 
running low on PermGen memory (and may eventually get a 
"java.lang.OutOfMemoryError: PermGen space" error). Try increasing PermGen size 
with a JVM argument of something like 
<code>-XX:MaxPermSize=400m</code></li></ul><p></p></div>
       </div>
 
       <div class="clearer"></div>

Modified: websites/production/tapestry/content/client-side-javascript.html
==============================================================================
--- websites/production/tapestry/content/client-side-javascript.html (original)
+++ websites/production/tapestry/content/client-side-javascript.html Wed Sep 20 
12:29:16 2017
@@ -27,6 +27,14 @@
       </title>
   <link type="text/css" rel="stylesheet" href="/resources/space.css" />
 
+          <link href='/resources/highlighter/styles/shCoreCXF.css' 
rel='stylesheet' type='text/css' />
+    <link href='/resources/highlighter/styles/shThemeCXF.css' rel='stylesheet' 
type='text/css' />
+    <script src='/resources/highlighter/scripts/shCore.js' 
type='text/javascript'></script>
+          <script src='/resources/highlighter/scripts/shBrushJava.js' 
type='text/javascript'></script>
+        <script>
+      SyntaxHighlighter.defaults['toolbar'] = false;
+      SyntaxHighlighter.all();
+    </script>
   
   <link href="/styles/style.css" rel="stylesheet" type="text/css"/>
 
@@ -36,26 +44,13 @@
 
   <div class="wrapper bs">
 
-        <div id="navigation"><div class="nav"><ul class="alternate"><li><a  
href="index.html">Home</a></li><li><a  href="getting-started.html">Getting 
Started</a></li><li><a  href="documentation.html">Documentation</a></li><li><a  
href="download.html">Download</a></li><li><a  
href="about.html">About</a></li><li><a  class="external-link" 
href="http://www.apache.org/licenses/LICENSE-2.0";>License</a></li><li><a  
href="community.html">Community</a></li><li><a  class="external-link" 
href="http://www.apache.org/security/";>Security</a></li><li><a  
class="external-link" href="http://www.apache.org/";>Apache</a></li><li><a  
class="external-link" 
href="http://www.apache.org/foundation/sponsorship.html";>Sponsorship</a></li><li><a
  class="external-link" 
href="http://www.apache.org/foundation/thanks.html";>Thanks</a></li></ul></div>
-
-</div>
+        <div id="navigation"><div class="nav"><ul class="alternate"><li><a  
href="index.html">Home</a></li><li><a  href="getting-started.html">Getting 
Started</a></li><li><a  href="documentation.html">Documentation</a></li><li><a  
href="download.html">Download</a></li><li><a  
href="about.html">About</a></li><li><a  class="external-link" 
href="http://www.apache.org/licenses/LICENSE-2.0";>License</a></li><li><a  
href="community.html">Community</a></li><li><a  class="external-link" 
href="http://www.apache.org/security/";>Security</a></li><li><a  
class="external-link" href="http://www.apache.org/";>Apache</a></li><li><a  
class="external-link" 
href="http://www.apache.org/foundation/sponsorship.html";>Sponsorship</a></li><li><a
  class="external-link" 
href="http://www.apache.org/foundation/thanks.html";>Thanks</a></li></ul></div></div>
 
           <div id="top">
-            <div id="smallbanner"><div class="searchbox" 
style="float:right;margin: .3em 1em .1em 1em"><span style="color: #999; 
font-size: 90%">Tapestry docs, issues, wikis &amp; blogs:</span>
-<form enctype="application/x-www-form-urlencoded" method="get" 
action="http://tapestry.apache.org/search.html";>
-  <input type="text" name="q">
-  <input type="submit" value="Search">
-</form>
-
-</div>
-
-
-<div class="emblem" style="float:left"><p><a  href="index.html"><span 
class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image 
confluence-external-resource" 
src="http://tapestry.apache.org/images/tapestry_small.png"; 
data-image-src="http://tapestry.apache.org/images/tapestry_small.png";></span></a></p></div>
-
-
-<div class="title" style="float:left; margin: 0 0 0 3em"><h1 
id="SmallBanner-PageTitle">Client-Side JavaScript</h1></div>
-
-</div>
+            <div id="smallbanner"><div class="searchbox" 
style="float:right;margin: .3em 1em .1em 1em"><span style="color: #999; 
font-size: 90%">Tapestry docs, issues, wikis &amp; blogs:</span><form 
enctype="application/x-www-form-urlencoded" method="get" 
action="http://tapestry.apache.org/search.html";> 
+ <input type="text" name="q"> 
+ <input type="submit" value="Search"> 
+</form></div><div class="emblem" style="float:left"><p><a  
href="index.html"><span class="confluence-embedded-file-wrapper"><img 
class="confluence-embedded-image confluence-external-resource" 
src="http://tapestry.apache.org/images/tapestry_small.png"; 
data-image-src="http://tapestry.apache.org/images/tapestry_small.png";></span></a></p></div><div
 class="title" style="float:left; margin: 0 0 0 3em"><h1 
id="SmallBanner-PageTitle">Client-Side JavaScript</h1></div></div>
       <div class="clearer"></div>
       </div>
 
@@ -67,7 +62,62 @@
       </div>
 
       <div id="content">
-                <div id="ConfluenceContent"><p>Perhaps nothing in Tapestry has 
changed over the years so much as the way client-side JavaScript is supported. 
From the get go, the goal was to make JavaScript a first-class citizen in the 
Tapestry world, and make it easy to encapsulate JavaScript within 
components.</p><parameter ac:name="style">float:right</parameter><parameter 
ac:name="title">Related Articles</parameter><parameter 
ac:name="class">aui-label</parameter><rich-text-body><parameter 
ac:name="showLabels">false</parameter><parameter 
ac:name="showSpace">false</parameter><parameter ac:name="title">Related 
Articles</parameter><parameter ac:name="cql">label in ("javascript","ajax") and 
space = currentSpace()</parameter></rich-text-body><p>The <a  
href="legacy-javascript.html">legacy JavaScript</a> page discusses the earlier 
approaches; the main feature of Tapestry 5.4 is a total rewrite of all things 
client-side, with the following goals:</p><ul><li>Break the hard linkage of Tape
 stry to <a  class="external-link" href="http://prototypejs.org/"; 
rel="nofollow">Prototype</a> and <a  class="external-link" 
href="http://script.aculo.us/"; rel="nofollow">Scriptaculous</a>, by introducing 
an abstraction layer</li><li>Remove the clumsy <code>Tapestry</code> and 
<code>T5</code> "namespaces"</li><li>Reduce the amount of page-specific 
JavaScript initialization</li><li>Make it easier to override behavior 
associated with client elements</li><li>Support CoffeeScript and (potentially) 
other languages that target JavaScript</li><li>Organize client-side JavaScript 
using <a  href="javascript-modules.html">modules</a></li><li>Make pages load 
faster</li><li>Integrate <a  class="external-link" 
href="http://getbootstrap.com/"; rel="nofollow">Bootstrap</a></li><li>Make it 
easier for rich client libraries such as&#160;<a  class="external-link" 
href="http://backbonejs.org/"; rel="nofollow">Backbone</a> or&#160;<a  
class="external-link" href="https://angularjs.org/"; rel="nofollow">Angula
 rJS</a> to operate within a page</li><li>Properly document Tapestry's client 
support</li></ul><h3 id="Client-SideJavaScript-TheOverallVision">The Overall 
Vision</h3><p>The overall vision for the client-side in Tapestry is 
encapsulation, at several different levels.</p><p>On the server-side, a 
Tapestry component (or mixin) exposes configurable parameters. The component 
writes DOM elements or attributes, as well as some amount of JavaScript 
initialization. The encapsulation here allows developers with little or no 
knowledge of client-side JavaScript to enjoy the benefits (as consumers of 
components created by developers who are versed in client-side coding and 
Tapestry components).</p><p>On the client-side, the JavaScript combines with 
the special markup to produce the behaviors that are desired ... anything from 
controlling the initial focus field, to performing client-side input field 
validation, to running complex Ajax workflows.</p><p>Where possible, all of 
this behavior is driven
  by <code>data-</code> attributes on the elements, combined with top-level 
event handlers. On the client side, events are used not only to respond 
directly to user actions (with "click", "mouseOver", "submit", or other event 
listeners) but also to allow elements to collaborate in various ways. &#160;For 
example, input validation is based on triggering a specific custom event on 
each form control element, and top-level event handlers can then manage the 
validation for any number of fields.</p><h3 
id="Client-SideJavaScript-Prototypevs.jQuery">Prototype vs. jQuery</h3><p>For 
several years, it has been obvious that Tapestry "backed the wrong horse" with 
respect to Prototype and jQuery. When the first code was being laid down in 
2007 or 2008, it wasn't so clear that jQuery with its odd abstractions and 
unfamiliar approach, would go on to conquer the world. Meanwhile, Prototype was 
very strongly integrated into Ruby on Rails and had first class documentation 
and books.</p><p>That being sa
 id, jQuery is not the be-all and end-all either. Tapestry 5.4 introduces an 
abstraction layer, that allows many components to write code that doesn't care 
whether the foundation framework is Prototype or jQuery or something else. 
If<span style="font-size: 14.0px;">&#160;you like jQuery then there's no 
problem: write your application using just jQuery and you can ignore a lot of 
the features in the abstraction layer. Your code will likely be just a bit more 
efficient.</span></p><p>If you are building a reusable component or library, 
writing to the abstraction layer may be worth the effort; it is entirely 
possible that someone may write a replacement for the abstraction layer that 
targets your favorite foundation framework, such as ExtJS, MooTools, or 
something not even known of today.</p><h3 
id="Client-SideJavaScript-Heavyvs.Light">Heavy vs. Light</h3><p>Earlier 
Tapestry JavaScript was&#160;<em>heavy</em>. Essentially, each component would 
write some very specific JavaScript initiali
 zation that would include the component's DOM id and many other details. This 
initialization would reference a function on the <code>T5.inits</code> 
namespace.</p><p>The function there would typically locate the specific element 
by its client DOM id, then attach event handlers to the one element. It might 
also create some form of client-side controller object. There were issues due 
to this: for complex pages (or perhaps even typical pages), the "blob" of 
JavaScript initialization at the bottom of the page could be quite 
large.</p><p>The use of individual event handlers meant that Tapestry 
applications would use more client-side objects that a bespoke jQuery solution 
... because the normal approach in jQuery is to attach a single event handler 
to the document or body that handles any events that bubble up to the 
top&#160;<em>and</em> match a CSS selector.</p><p>In Tapestry 5.4, the goal is 
to make things&#160;<em>light</em>. In most cases, there isn't a specific 
initialization functi
 on; instead a <a  href="javascript-modules.html">JavaScript module</a>&#160;is 
loaded, and it installs one or more top-level event handlers; the elements has 
data-<a  class="external-link" 
href="https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Using_data_attributes";
 rel="nofollow">&#160;attributes</a> that are used by those top level handlers 
to recognize which elements they are responsible for.</p><p>This is more of a 
full lifecycle approach; adding or removing page content (such as with 
a&#160;<a  href="ajax-and-zones.html">Zone</a> component) is both cheaper and 
less error prone using top-level event handlers than per-element event 
handlers; there's also less of a chance of memory leaks under Internet 
Explorer.</p><rich-text-body><p>Internet Explorer is pretty well known for 
memory leaks; its DOM and JavaScript run in different kinds of memory, which 
are garbage collected individually. This means that a reference from JavaScript 
to a DOM element will keep the DOM element l
 ive, even if that's the only reference to the DOM element anywhere. Meanwhile, 
event handler JavaScript functions are kept live from the DOM element, making a 
cycle that can't be broken. Libraries like Prototype and jQuery have to expend 
some effort to break this link by unregistering event handlers from DOM 
elements when removing them from the DOM.</p></rich-text-body><p>A specific 
example of this approach is how client-side validation now works; in the past, 
there was a complex system of classes and event listeners that were specific to 
each individual field. Field controllers had to register with Form controllers. 
Validators had to register with Field controllers.</p><p>Under 5.4, there are a 
number of&#160;<code>data-</code> attributes that can be attached to any DOM 
element. A form searches for elements with a non-blank value 
for&#160;<code>data-validation</code>; each such element has a series of custom 
events triggered on it. The top-level handlers for those events receive no
 tifications for elements throughout the document.</p><parameter 
ac:name="title">t5/core/validation.coffee 
(partial)</parameter><plain-text-body>define ["underscore", "./dom", 
"./events", "./utils", "./messages", "./fields"],
+                <div id="ConfluenceContent"><p>Perhaps nothing in Tapestry has 
changed over the years so much as the way client-side JavaScript is supported. 
From the get go, the goal was to make JavaScript a first-class citizen in the 
Tapestry world, and make it easy to encapsulate JavaScript within 
components.</p><div class="aui-label" style="float:right" title="Related 
Articles"><h3>Related Articles</h3><ul class="content-by-label"><li> 
+  <div> 
+   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
+  </div> 
+  <div class="details"> 
+   <a  href="ajax-and-zones.html">Ajax and Zones</a> 
+  </div> </li><li> 
+  <div> 
+   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
+  </div> 
+  <div class="details"> 
+   <a  href="legacy-javascript.html">Legacy JavaScript</a> 
+  </div> </li><li> 
+  <div> 
+   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
+  </div> 
+  <div class="details"> 
+   <a  href="coffeescript.html">CoffeeScript</a> 
+  </div> </li><li> 
+  <div> 
+   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
+  </div> 
+  <div class="details"> 
+   <a  href="client-side-javascript.html">Client-Side JavaScript</a> 
+  </div> </li><li> 
+  <div> 
+   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
+  </div> 
+  <div class="details"> 
+   <a  href="javascript-modules.html">JavaScript Modules</a> 
+  </div> </li><li> 
+  <div> 
+   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
+  </div> 
+  <div class="details"> 
+   <a  href="javascript-faq.html">JavaScript FAQ</a> 
+  </div> </li><li> 
+  <div> 
+   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
+  </div> 
+  <div class="details"> 
+   <a  href="ajax-components-faq.html">Ajax Components FAQ</a> 
+  </div> </li><li> 
+  <div> 
+   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
+  </div> 
+  <div class="details"> 
+   <a  href="component-cheat-sheet.html">Component Cheat Sheet</a> 
+  </div> </li><li> 
+  <div> 
+   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
+  </div> 
+  <div class="details"> 
+   <a  href="assets.html">Assets</a> 
+  </div> </li></ul></div><p>The <a  href="legacy-javascript.html">legacy 
JavaScript</a> page discusses the earlier approaches; the main feature of 
Tapestry 5.4 is a total rewrite of all things client-side, with the following 
goals:</p><ul><li>Break the hard linkage of Tapestry to <a  
class="external-link" href="http://prototypejs.org/"; 
rel="nofollow">Prototype</a> and <a  class="external-link" 
href="http://script.aculo.us/"; rel="nofollow">Scriptaculous</a>, by introducing 
an abstraction layer</li><li>Remove the clumsy <code>Tapestry</code> and 
<code>T5</code> "namespaces"</li><li>Reduce the amount of page-specific 
JavaScript initialization</li><li>Make it easier to override behavior 
associated with client elements</li><li>Support CoffeeScript and (potentially) 
other languages that target JavaScript</li><li>Organize client-side JavaScript 
using <a  href="javascript-modules.html">modules</a></li><li>Make pages load 
faster</li><li>Integrate <a  class="external-link" href="http://getboo
 tstrap.com/" rel="nofollow">Bootstrap</a></li><li>Make it easier for rich 
client libraries such as&#160;<a  class="external-link" 
href="http://backbonejs.org/"; rel="nofollow">Backbone</a> or&#160;<a  
class="external-link" href="https://angularjs.org/"; 
rel="nofollow">AngularJS</a> to operate within a page</li><li>Properly document 
Tapestry's client support</li></ul><h3 
id="Client-SideJavaScript-TheOverallVision">The Overall Vision</h3><p>The 
overall vision for the client-side in Tapestry is encapsulation, at several 
different levels.</p><p>On the server-side, a Tapestry component (or mixin) 
exposes configurable parameters. The component writes DOM elements or 
attributes, as well as some amount of JavaScript initialization. The 
encapsulation here allows developers with little or no knowledge of client-side 
JavaScript to enjoy the benefits (as consumers of components created by 
developers who are versed in client-side coding and Tapestry 
components).</p><p>On the client-side, the JavaS
 cript combines with the special markup to produce the behaviors that are 
desired ... anything from controlling the initial focus field, to performing 
client-side input field validation, to running complex Ajax 
workflows.</p><p>Where possible, all of this behavior is driven by 
<code>data-</code> attributes on the elements, combined with top-level event 
handlers. On the client side, events are used not only to respond directly to 
user actions (with "click", "mouseOver", "submit", or other event listeners) 
but also to allow elements to collaborate in various ways. &#160;For example, 
input validation is based on triggering a specific custom event on each form 
control element, and top-level event handlers can then manage the validation 
for any number of fields.</p><h3 
id="Client-SideJavaScript-Prototypevs.jQuery">Prototype vs. jQuery</h3><p>For 
several years, it has been obvious that Tapestry "backed the wrong horse" with 
respect to Prototype and jQuery. When the first code was being lai
 d down in 2007 or 2008, it wasn't so clear that jQuery with its odd 
abstractions and unfamiliar approach, would go on to conquer the world. 
Meanwhile, Prototype was very strongly integrated into Ruby on Rails and had 
first class documentation and books.</p><p>That being said, jQuery is not the 
be-all and end-all either. Tapestry 5.4 introduces an abstraction layer, that 
allows many components to write code that doesn't care whether the foundation 
framework is Prototype or jQuery or something else. If<span style="font-size: 
14.0px;">&#160;you like jQuery then there's no problem: write your application 
using just jQuery and you can ignore a lot of the features in the abstraction 
layer. Your code will likely be just a bit more efficient.</span></p><p>If you 
are building a reusable component or library, writing to the abstraction layer 
may be worth the effort; it is entirely possible that someone may write a 
replacement for the abstraction layer that targets your favorite foundation fra
 mework, such as ExtJS, MooTools, or something not even known of today.</p><h3 
id="Client-SideJavaScript-Heavyvs.Light">Heavy vs. Light</h3><p>Earlier 
Tapestry JavaScript was&#160;<em>heavy</em>. Essentially, each component would 
write some very specific JavaScript initialization that would include the 
component's DOM id and many other details. This initialization would reference 
a function on the <code>T5.inits</code> namespace.</p><p>The function there 
would typically locate the specific element by its client DOM id, then attach 
event handlers to the one element. It might also create some form of 
client-side controller object. There were issues due to this: for complex pages 
(or perhaps even typical pages), the "blob" of JavaScript initialization at the 
bottom of the page could be quite large.</p><p>The use of individual event 
handlers meant that Tapestry applications would use more client-side objects 
that a bespoke jQuery solution ... because the normal approach in jQuery is to a
 ttach a single event handler to the document or body that handles any events 
that bubble up to the top&#160;<em>and</em> match a CSS selector.</p><p>In 
Tapestry 5.4, the goal is to make things&#160;<em>light</em>. In most cases, 
there isn't a specific initialization function; instead a <a  
href="javascript-modules.html">JavaScript module</a>&#160;is loaded, and it 
installs one or more top-level event handlers; the elements has data-<a  
class="external-link" 
href="https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Using_data_attributes";
 rel="nofollow">&#160;attributes</a> that are used by those top level handlers 
to recognize which elements they are responsible for.</p><p>This is more of a 
full lifecycle approach; adding or removing page content (such as with 
a&#160;<a  href="ajax-and-zones.html">Zone</a> component) is both cheaper and 
less error prone using top-level event handlers than per-element event 
handlers; there's also less of a chance of memory leaks under Internet Exp
 lorer.</p><div class="confluence-information-macro 
confluence-information-macro-note"><span class="aui-icon aui-icon-small 
aui-iconfont-warning confluence-information-macro-icon"></span><div 
class="confluence-information-macro-body"><p>Internet Explorer is pretty well 
known for memory leaks; its DOM and JavaScript run in different kinds of 
memory, which are garbage collected individually. This means that a reference 
from JavaScript to a DOM element will keep the DOM element live, even if that's 
the only reference to the DOM element anywhere. Meanwhile, event handler 
JavaScript functions are kept live from the DOM element, making a cycle that 
can't be broken. Libraries like Prototype and jQuery have to expend some effort 
to break this link by unregistering event handlers from DOM elements when 
removing them from the DOM.</p></div></div><p>A specific example of this 
approach is how client-side validation now works; in the past, there was a 
complex system of classes and event listeners
  that were specific to each individual field. Field controllers had to 
register with Form controllers. Validators had to register with Field 
controllers.</p><p>Under 5.4, there are a number of&#160;<code>data-</code> 
attributes that can be attached to any DOM element. A form searches for 
elements with a non-blank value for&#160;<code>data-validation</code>; each 
such element has a series of custom events triggered on it. The top-level 
handlers for those events receive notifications for elements throughout the 
document.</p><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeHeader panelHeader pdl" style="border-bottom-width: 
1px;"><b>t5/core/validation.coffee (partial)</b></div><div class="codeContent 
panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">define ["underscore", "./dom", "./events", "./utils", 
"./messages", "./fields"],
   (_, dom, events, utils, messages) -&gt;
 
 
@@ -84,7 +134,8 @@
       min = parseInt @attr "data-validate-min-length"
       if memo.translated.length &lt; min
         memo.error = (@attr "data-min-length-message") or "TOO SHORT"
-        return false</plain-text-body><p>The&#160;<code>t5/core/events</code> 
module defines constants for different custom event name, it's also a handy 
place to <a  class="external-link" 
href="http://tapestry.apache.org/5.4/coffeescript/events.html";>hang 
documentation</a> about those events.</p><p>The&#160;<code>t5/core/dom</code> 
namespace is the abstraction layer. &#160;<code>onDocument</code> is a handy 
way to attach a top-level event handler.</p><p>Fields that are required have 
the attribute&#160;<code>data-optionality=required</code>; the event handler is 
passed a&#160;<em>memo</em> object that includes a&#160;<code>value</code> 
property, the value from the field. This makes it easier to generate an error 
if the value is blank. &#160;Because the exact error message may be customized 
or localized, it is provided in the element as well, as 
the&#160;<code>data-required-message</code> attribute. 
Setting&#160;<code>memo.error</code> to a validation error string causes the 
field to
  be decorated with the error message and indicates that the form itself is in 
error and not ready for submission.</p><p>A different event is triggered after 
the optionality check; The&#160;<code>memo.translated</code> property is the 
value translated before validation (for a numeric field, it would be translated 
from a string to a number, for example). Again, the&#160;<code>error</code> 
property is set, and the&#160;<code>return false</code> ensures that the event 
will stop bubbling to containing elements or event handlers.</p><p>What's very 
useful in this overall approach is that it no longer matters whether the fields 
were rendered by Tapestry on the server, or rendered locally (perhaps using 
Backbone or AngularJS) on the client. As long as they have the 
correct&#160;<code>data-</code> attributes, then they can participate in 
Tapestry's overall form validation and submission cycle, and even leverage the 
default validation decoration behavior.</p><h3 id="Client-SideJavaScript-TheAb
 stractionLayer">The Abstraction Layer</h3><p>The abstraction layer is defined 
by the&#160;<code>t5/core/dom</code> module. This module currently has two 
different implementations - one is a wrapper around Prototype, and the other is 
a wrapper around jQuery.</p><p>The resulting abstraction layer is a bit of a 
hybrid; it mostly looks like jQuery, but events look a bit more like Prototype. 
It also doesn't have jQuery's concept of operating on a matched set of 
elements.</p><p>The abstraction is both transitional and permanent. It is 
transitional in that it is about allowing existing sites with a heavy 
investment in Prototype to continue to operate with Prototype in the mix. It is 
permanent &#160;in that it is desirable for third party library developers to 
keep an abstraction layer between Tapestry's client-side code and any 
underlying framework, so that particular applications can provide their own 
abstraction layer and operate without breaking built-in components.</p><p>Most 
applicati
 ons should transition to jQuery and feel free to use jQuery directly. &#160;It 
is still best to inject module <span style="font-family: 
monospace;">jquery</span>&#160;into your own modules (usually as 
parameter&#160;<code>$</code>).&#160;</p><p>If you are writing a third-party 
application and want to maximize re-use, then use the abstraction 
layer.</p><p>It is often easier to use the abstraction layer to respond 
correctly to custom Tapestry events.</p></div>
+        return false</pre>
+</div></div><p>The&#160;<code>t5/core/events</code> module defines constants 
for different custom event name, it's also a handy place to <a  
class="external-link" 
href="http://tapestry.apache.org/5.4/coffeescript/events.html";>hang 
documentation</a> about those events.</p><p>The&#160;<code>t5/core/dom</code> 
namespace is the abstraction layer. &#160;<code>onDocument</code> is a handy 
way to attach a top-level event handler.</p><p>Fields that are required have 
the attribute&#160;<code>data-optionality=required</code>; the event handler is 
passed a&#160;<em>memo</em> object that includes a&#160;<code>value</code> 
property, the value from the field. This makes it easier to generate an error 
if the value is blank. &#160;Because the exact error message may be customized 
or localized, it is provided in the element as well, as 
the&#160;<code>data-required-message</code> attribute. 
Setting&#160;<code>memo.error</code> to a validation error string causes the 
field to be decorated with the err
 or message and indicates that the form itself is in error and not ready for 
submission.</p><p>A different event is triggered after the optionality check; 
The&#160;<code>memo.translated</code> property is the value translated before 
validation (for a numeric field, it would be translated from a string to a 
number, for example). Again, the&#160;<code>error</code> property is set, and 
the&#160;<code>return false</code> ensures that the event will stop bubbling to 
containing elements or event handlers.</p><p>What's very useful in this overall 
approach is that it no longer matters whether the fields were rendered by 
Tapestry on the server, or rendered locally (perhaps using Backbone or 
AngularJS) on the client. As long as they have the 
correct&#160;<code>data-</code> attributes, then they can participate in 
Tapestry's overall form validation and submission cycle, and even leverage the 
default validation decoration behavior.</p><h3 
id="Client-SideJavaScript-TheAbstractionLayer">The Abstra
 ction Layer</h3><p>The abstraction layer is defined by 
the&#160;<code>t5/core/dom</code> module. This module currently has two 
different implementations - one is a wrapper around Prototype, and the other is 
a wrapper around jQuery.</p><p>The resulting abstraction layer is a bit of a 
hybrid; it mostly looks like jQuery, but events look a bit more like Prototype. 
It also doesn't have jQuery's concept of operating on a matched set of 
elements.</p><p>The abstraction is both transitional and permanent. It is 
transitional in that it is about allowing existing sites with a heavy 
investment in Prototype to continue to operate with Prototype in the mix. It is 
permanent &#160;in that it is desirable for third party library developers to 
keep an abstraction layer between Tapestry's client-side code and any 
underlying framework, so that particular applications can provide their own 
abstraction layer and operate without breaking built-in components.</p><p>Most 
applications should transition to j
 Query and feel free to use jQuery directly. &#160;It is still best to inject 
module <span style="font-family: monospace;">jquery</span>&#160;into your own 
modules (usually as parameter&#160;<code>$</code>).&#160;</p><p>If you are 
writing a third-party application and want to maximize re-use, then use the 
abstraction layer.</p><p>It is often easier to use the abstraction layer to 
respond correctly to custom Tapestry events.</p></div>
       </div>
 
       <div class="clearer"></div>

Modified: websites/production/tapestry/content/coffeescript.html
==============================================================================
--- websites/production/tapestry/content/coffeescript.html (original)
+++ websites/production/tapestry/content/coffeescript.html Wed Sep 20 12:29:16 
2017
@@ -27,6 +27,14 @@
       </title>
   <link type="text/css" rel="stylesheet" href="/resources/space.css" />
 
+          <link href='/resources/highlighter/styles/shCoreCXF.css' 
rel='stylesheet' type='text/css' />
+    <link href='/resources/highlighter/styles/shThemeCXF.css' rel='stylesheet' 
type='text/css' />
+    <script src='/resources/highlighter/scripts/shCore.js' 
type='text/javascript'></script>
+          <script src='/resources/highlighter/scripts/shBrushXml.js' 
type='text/javascript'></script>
+        <script>
+      SyntaxHighlighter.defaults['toolbar'] = false;
+      SyntaxHighlighter.all();
+    </script>
   
   <link href="/styles/style.css" rel="stylesheet" type="text/css"/>
 
@@ -36,26 +44,13 @@
 
   <div class="wrapper bs">
 
-        <div id="navigation"><div class="nav"><ul class="alternate"><li><a  
href="index.html">Home</a></li><li><a  href="getting-started.html">Getting 
Started</a></li><li><a  href="documentation.html">Documentation</a></li><li><a  
href="download.html">Download</a></li><li><a  
href="about.html">About</a></li><li><a  class="external-link" 
href="http://www.apache.org/licenses/LICENSE-2.0";>License</a></li><li><a  
href="community.html">Community</a></li><li><a  class="external-link" 
href="http://www.apache.org/security/";>Security</a></li><li><a  
class="external-link" href="http://www.apache.org/";>Apache</a></li><li><a  
class="external-link" 
href="http://www.apache.org/foundation/sponsorship.html";>Sponsorship</a></li><li><a
  class="external-link" 
href="http://www.apache.org/foundation/thanks.html";>Thanks</a></li></ul></div>
-
-</div>
+        <div id="navigation"><div class="nav"><ul class="alternate"><li><a  
href="index.html">Home</a></li><li><a  href="getting-started.html">Getting 
Started</a></li><li><a  href="documentation.html">Documentation</a></li><li><a  
href="download.html">Download</a></li><li><a  
href="about.html">About</a></li><li><a  class="external-link" 
href="http://www.apache.org/licenses/LICENSE-2.0";>License</a></li><li><a  
href="community.html">Community</a></li><li><a  class="external-link" 
href="http://www.apache.org/security/";>Security</a></li><li><a  
class="external-link" href="http://www.apache.org/";>Apache</a></li><li><a  
class="external-link" 
href="http://www.apache.org/foundation/sponsorship.html";>Sponsorship</a></li><li><a
  class="external-link" 
href="http://www.apache.org/foundation/thanks.html";>Thanks</a></li></ul></div></div>
 
           <div id="top">
-            <div id="smallbanner"><div class="searchbox" 
style="float:right;margin: .3em 1em .1em 1em"><span style="color: #999; 
font-size: 90%">Tapestry docs, issues, wikis &amp; blogs:</span>
-<form enctype="application/x-www-form-urlencoded" method="get" 
action="http://tapestry.apache.org/search.html";>
-  <input type="text" name="q">
-  <input type="submit" value="Search">
-</form>
-
-</div>
-
-
-<div class="emblem" style="float:left"><p><a  href="index.html"><span 
class="confluence-embedded-file-wrapper"><img class="confluence-embedded-image 
confluence-external-resource" 
src="http://tapestry.apache.org/images/tapestry_small.png"; 
data-image-src="http://tapestry.apache.org/images/tapestry_small.png";></span></a></p></div>
-
-
-<div class="title" style="float:left; margin: 0 0 0 3em"><h1 
id="SmallBanner-PageTitle">CoffeeScript</h1></div>
-
-</div>
+            <div id="smallbanner"><div class="searchbox" 
style="float:right;margin: .3em 1em .1em 1em"><span style="color: #999; 
font-size: 90%">Tapestry docs, issues, wikis &amp; blogs:</span><form 
enctype="application/x-www-form-urlencoded" method="get" 
action="http://tapestry.apache.org/search.html";> 
+ <input type="text" name="q"> 
+ <input type="submit" value="Search"> 
+</form></div><div class="emblem" style="float:left"><p><a  
href="index.html"><span class="confluence-embedded-file-wrapper"><img 
class="confluence-embedded-image confluence-external-resource" 
src="http://tapestry.apache.org/images/tapestry_small.png"; 
data-image-src="http://tapestry.apache.org/images/tapestry_small.png";></span></a></p></div><div
 class="title" style="float:left; margin: 0 0 0 3em"><h1 
id="SmallBanner-PageTitle">CoffeeScript</h1></div></div>
       <div class="clearer"></div>
       </div>
 
@@ -67,11 +62,61 @@
       </div>
 
       <div id="content">
-                <div id="ConfluenceContent"><p><strong>CoffeeScript</strong> 
(<a  class="external-link" href="http://coffeescript.org"; 
rel="nofollow">http://coffeescript.org</a>) is a language that compiles down to 
JavaScript.</p><parameter ac:name="style">float:right</parameter><parameter 
ac:name="title">Related Articles</parameter><parameter 
ac:name="class">aui-label</parameter><rich-text-body><parameter 
ac:name="showLabels">false</parameter><parameter 
ac:name="showSpace">false</parameter><parameter ac:name="title">Related 
Articles</parameter><parameter ac:name="cql">label = "javascript" and space = 
currentSpace()</parameter></rich-text-body><p><em>Starting with version 
5.4,</em> Tapestry can automatically compile your CoffeeScript code into 
JavaScript on the fly. This is done with the optional tapestry-webresources 
module. It is highly recommended for anyone who wants to use CoffeeScript in 
their application ... just let Tapestry do the compilation at runtime (with 
access to Tape
 stry's full exception reporting capabilities).</p><p>To use the 
tapestry-webresources module, just add the JAR to your project. For example, if 
you're using Maven:</p><parameter ac:name="language">xml</parameter><parameter 
ac:name="title">pom.xml (partial)</parameter><plain-text-body>&lt;dependency&gt;
+                <div id="ConfluenceContent"><p><strong>CoffeeScript</strong> 
(<a  class="external-link" href="http://coffeescript.org"; 
rel="nofollow">http://coffeescript.org</a>) is a language that compiles down to 
JavaScript.</p><div class="aui-label" style="float:right" title="Related 
Articles"><h3>Related Articles</h3><ul class="content-by-label"><li> 
+  <div> 
+   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
+  </div> 
+  <div class="details"> 
+   <a  href="coffeescript.html">CoffeeScript</a> 
+  </div> </li><li> 
+  <div> 
+   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
+  </div> 
+  <div class="details"> 
+   <a  href="client-side-javascript.html">Client-Side JavaScript</a> 
+  </div> </li><li> 
+  <div> 
+   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
+  </div> 
+  <div class="details"> 
+   <a  href="javascript-modules.html">JavaScript Modules</a> 
+  </div> </li><li> 
+  <div> 
+   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
+  </div> 
+  <div class="details"> 
+   <a  href="javascript-faq.html">JavaScript FAQ</a> 
+  </div> </li><li> 
+  <div> 
+   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
+  </div> 
+  <div class="details"> 
+   <a  href="ajax-and-zones.html">Ajax and Zones</a> 
+  </div> </li><li> 
+  <div> 
+   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
+  </div> 
+  <div class="details"> 
+   <a  href="component-cheat-sheet.html">Component Cheat Sheet</a> 
+  </div> </li><li> 
+  <div> 
+   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
+  </div> 
+  <div class="details"> 
+   <a  href="legacy-javascript.html">Legacy JavaScript</a> 
+  </div> </li><li> 
+  <div> 
+   <span class="icon aui-icon aui-icon-small aui-iconfont-page-default" 
title="Page">Page:</span> 
+  </div> 
+  <div class="details"> 
+   <a  href="assets.html">Assets</a> 
+  </div> </li></ul></div><p><em>Starting with version 5.4,</em> Tapestry can 
automatically compile your CoffeeScript code into JavaScript on the fly. This 
is done with the optional tapestry-webresources module. It is highly 
recommended for anyone who wants to use CoffeeScript in their application ... 
just let Tapestry do the compilation at runtime (with access to Tapestry's full 
exception reporting capabilities).</p><p>To use the tapestry-webresources 
module, just add the JAR to your project. For example, if you're using 
Maven:</p><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>pom.xml 
(partial)</b></div><div class="codeContent panelContent pdl">
+<pre class="brush: xml; gutter: false; theme: Default" 
style="font-size:12px;">&lt;dependency&gt;
     &lt;groupId&gt;org.apache.tapestry&lt;/groupId&gt;
     &lt;artifactId&gt;tapestry-webresources&lt;/artifactId&gt;
     &lt;version&gt;${tapestry-release-version}&lt;/version&gt;
-&lt;/dependency&gt;</plain-text-body><p>All of Tapestry's own client-side code 
is written in CoffeeScript and compiled, at <em>build</em> time, to 
JavaScript.</p><rich-text-body><p>You are completely free to use either 
JavaScript or CoffeeScript in your Tapestry 
application.</p></rich-text-body><h2 
id="CoffeeScript-CoffeeScriptversusJavaScript">CoffeeScript versus 
JavaScript</h2><p>CoffeeScript can be quite controversial, but also quite 
effective.</p><p>On the controversial side, it uses significant whitespace to 
denote blocks of code (like Python or Haskell) rather than curl braces (like 
Java, JavaScript, or Ruby). In fact, it draws influences from a wide rage of 
other languages, incorporating many functional programming features, a 
rudimentary class system, string interpolation, destructuring assignment, and 
more.</p><p>However, for all that, it is very close to JavaScript; it simply 
rounds out many of the rough edges of JavaScript (and adds a few of its own). 
As wide ranging as C
 offeeScript syntax can be, there's generally a very close mapping from 
CoffeeScript to JavaScript.</p><p>CoffeeScript code often approaches Python's 
goal of being a "executable psuedo-code"; code that looks like a placeholder 
that will actually run. Some people find it more pleasant to read than 
JavaScript ... more&#160;<em>essence</em> and 
less&#160;<em>ceremony</em>.</p><p>You can still write bad code in 
CoffeeScript. You can write bad code in any language.</p></div>
+&lt;/dependency&gt;</pre>
+</div></div><p>All of Tapestry's own client-side code is written in 
CoffeeScript and compiled, at <em>build</em> time, to JavaScript.</p><div 
class="confluence-information-macro 
confluence-information-macro-information"><span class="aui-icon aui-icon-small 
aui-iconfont-info confluence-information-macro-icon"></span><div 
class="confluence-information-macro-body"><p>You are completely free to use 
either JavaScript or CoffeeScript in your Tapestry 
application.</p></div></div><h2 
id="CoffeeScript-CoffeeScriptversusJavaScript">CoffeeScript versus 
JavaScript</h2><p>CoffeeScript can be quite controversial, but also quite 
effective.</p><p>On the controversial side, it uses significant whitespace to 
denote blocks of code (like Python or Haskell) rather than curl braces (like 
Java, JavaScript, or Ruby). In fact, it draws influences from a wide rage of 
other languages, incorporating many functional programming features, a 
rudimentary class system, string interpolation, destructuring assignment
 , and more.</p><p>However, for all that, it is very close to JavaScript; it 
simply rounds out many of the rough edges of JavaScript (and adds a few of its 
own). As wide ranging as CoffeeScript syntax can be, there's generally a very 
close mapping from CoffeeScript to JavaScript.</p><p>CoffeeScript code often 
approaches Python's goal of being a "executable psuedo-code"; code that looks 
like a placeholder that will actually run. Some people find it more pleasant to 
read than JavaScript ... more&#160;<em>essence</em> and 
less&#160;<em>ceremony</em>.</p><p>You can still write bad code in 
CoffeeScript. You can write bad code in any language.</p></div>
       </div>
 
       <div class="clearer"></div>


Reply via email to