You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2011/07/19 03:32:26 UTC

svn commit: r1148123 - in /tapestry/tapestry5/trunk/tapestry-core/src: main/resources/org/apache/tapestry5/ test/resources/org/apache/tapestry5/integration/app1/pages/

Author: hlship
Date: Tue Jul 19 01:32:26 2011
New Revision: 1148123

URL: http://svn.apache.org/viewvc?rev=1148123&view=rev
Log:
TAP5-999: Pass the actual element on which a topic is published to listener functions

Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/t5-pubsub.js
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/JavaScriptTests.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/js-testing.js

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/t5-pubsub.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/t5-pubsub.js?rev=1148123&r1=1148122&r2=1148123&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/t5-pubsub.js (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/t5-pubsub.js Tue Jul 19 01:32:26 2011
@@ -1,226 +1,252 @@
-T5.define("pubsub", function() {
+T5.define("pubsub", function()
+{
 
-	var arrays = T5.arrays;
-	var first = arrays.first;
-	var without = arrays.without;
-	var filter = arrays.filter;
-	var remove = arrays.remove;
-	var map = arrays.map;
-	var each = arrays.each;
-
-	// Element keys: topic, element, listenerfn
-	// May be multiple elements with some topic/element pair
-	// element property may be undefined
-	var subscribers = [];
-
-	// Element keys: topic, element, publisherfn
-	var publishers = [];
-
-	// Necessary since T5.dom depends on T5.pubsub
-	function $(element) {
-		return T5.$(element);
-	}
-
-	function purgePublisherCache(topic) {
-		each(function(publisher) {
-			if (publisher.topic === topic) {
-				publisher.listeners = undefined;
-			}
-		}, publishers);
-	}
-
-	function findListeners(topic, element) {
-		var gross = filter(function(subscriber) {
-			return subscriber.topic === topic;
-		}, subscribers);
-
-		var primary = filter(function(subscriber) {
-			return subscriber.element === element;
-		}, gross);
-
-		var secondary = filter(function(subscriber) {
-			// Match where the element is null or undefined
-			return !subscriber.element;
-		}, gross);
-
-		// Return the listenerfn property from each match.
-		return map(arrays.extractProperty("listenerfn"), primary
-				.concat(secondary));
-	}
-
-	/**
-	 * Subscribes a listener function to the selector. The listener function
-	 * will be invoked when a message for the given topic is published. If an
-	 * element is specified, then the listener will only be invoked when the
-	 * subscribed element matches the published element.
-	 * 
-	 * @param topic
-	 *            a topic name, which must not be blank
-	 * @param element
-	 *            a DOM element, which may be null to subscribe to all messages
-	 *            for the topic. If a string, then T5.$() is used to locate the
-	 *            DOM element with the matching client id.
-	 * @param listenerfn
-	 *            function invoked when a message for the topic is published.
-	 *            The function is invoked only if the supplied selector element
-	 *            is undefined OR exactly matches the source element node. The
-	 *            return value of the listenerfn will be accumulated in an array
-	 *            and returned to the publisher.
-	 * @return a function of no arguments used to unsubscribe the listener
-	 */
-	function subscribe(topic, element, listenerfn) {
-
-		var subscriber = {
-			topic : topic,
-			element : $(element),
-			listenerfn : listenerfn
-		};
-
-		subscribers.push(subscriber);
-		purgePublisherCache(subscriber.topic);
-
-		// To prevent memory leaks via closure:
-
-		topic = null;
-		element = null;
-		listenerfn = null;
-
-		// Return a function to unsubscribe
-		return function() {
-			subscribers = without(subscriber, subscribers);
-			purgePublisherCache(subscriber.topic);
-		}
-	}
-
-	/**
-	 * Creates a publish function for the indicated topic name and DOM element.
-	 * 
-	 * <p>
-	 * The returned function is used to publish a message. Messages are
-	 * published synchronously. The publish function will invoke listener
-	 * functions for matching subscribers (subscribers to the same topic). Exact
-	 * subscribers (matching the specific element) are invoked first, then
-	 * general subscribers (not matching any specific element). The return value
-	 * for the publish function is an array of all the return values from all
-	 * invoked listener functions.
-	 * 
-	 * <p>
-	 * There is not currently a way to explicitly remove a publisher; however,
-	 * when the DOM element is removed properly, all publishers and subscribers
-	 * for the specific element will be removed as well.
-	 * 
-	 * <p>
-	 * Publish functions are cached, repeated calls with the same topic and
-	 * element return the same publish function.
-	 * 
-	 * @param topic
-	 *            used to select listeners
-	 * @param element
-	 *            the DOM element used as the source of the published message
-	 *            (also used to select listeners). Passed through T5.$(), the
-	 *            result must not be null.
-	 * @return publisher function used to publish a message
-	 */
-	function createPublisher(topic, element) {
-
-		element = $(element);
-
-		if (element == null) {
-			throw "Element may not be null when creating a publisher.";
-		}
-
-		var existing = first(function(publisher) {
-			return publisher.topic === topic && publisher.element === element;
-		}, publishers);
-
-		if (existing) {
-			return existing.publisherfn;
-		}
-
-		var publisher = {
-			topic : topic,
-			element : element,
-			publisherfn : function(message) {
-
-				if (publisher.listeners == undefined) {
-					publisher.listeners = findListeners(publisher.topic,
-							publisher.element);
-				}
-
-				// TODO: pass a second object to each function to allow for
-				// control over message propagation, supply listener with access
-				// to source element.
-
-				return map(function(listenerfn) {
-					return listenerfn(message);
-				}, publisher.listeners);
-			}
-		};
-
-		publishers.push(publisher);
-
-		// If only there was an event or something that would inform us when the
-		// element was removed. Certainly, IE doesn't support that! Have to rely
-		// on T5.dom.remove() to inform us.
-
-		// Mark the element to indicate it requires cleanup once removed from
-		// the DOM.
-
-		element.t5pubsub = true;
-
-		// Don't want to hold a reference via closure:
-
-		topic = null;
-		element = null;
-
-		return publisher.publisherfn;
-	}
-
-	/**
-	 * Creates a publisher and immediately publishes the message, return the
-	 * array of results.
-	 */
-	function publish(topic, element, message) {
-		return createPublisher(topic, element)(message);
-	}
-
-	/**
-	 * Invoked whenever an element is about to be removed from the DOM to remove
-	 * any publishers or subscribers for the element.
-	 */
-	function cleanup(element) {
-		subscribers = remove(function(subscriber) {
-			return subscriber.element === element
-		}, subscribers);
-
-		// A little evil to modify the publisher object at the same time it is
-		// being removed.
-
-		publishers = remove(function(publisher) {
-			var match = publisher.element === element;
-
-			if (match) {
-				publisher.listeners = undefined;
-				publisher.element = undefined;
-			}
-
-			return match;
-		});
-	}
-
-	return {
-		createPublisher : createPublisher,
-		subscribe : subscribe,
-		publish : publish,
-		cleanupRemovedElement : cleanup
-	};
+    var arrays = T5.arrays;
+    var first = arrays.first;
+    var without = arrays.without;
+    var filter = arrays.filter;
+    var remove = arrays.remove;
+    var map = arrays.map;
+    var each = arrays.each;
+
+    // Element keys: topic, element, listenerfn
+    // May be multiple elements with some topic/element pair
+    // element property may be undefined
+    var subscribers = [];
+
+    // Element keys: topic, element, publisherfn
+    var publishers = [];
+
+    // Necessary since T5.dom depends on T5.pubsub
+    function $(element)
+    {
+        return T5.$(element);
+    }
+
+    function purgePublisherCache(topic)
+    {
+        each(function(publisher)
+        {
+            if (publisher.topic === topic)
+            {
+                publisher.listeners = undefined;
+            }
+        }, publishers);
+    }
+
+    function findListeners(topic, element)
+    {
+        var gross = filter(function(subscriber)
+        {
+            return subscriber.topic === topic;
+        }, subscribers);
+
+        var primary = filter(function(subscriber)
+        {
+            return subscriber.element === element;
+        }, gross);
+
+        var secondary = filter(function(subscriber)
+        {
+            // Match where the element is null or undefined
+            return !subscriber.element;
+        }, gross);
+
+        // Return the listenerfn property from each match.
+        return map(arrays.extractProperty("listenerfn"), primary
+            .concat(secondary));
+    }
+
+    /**
+     * Subscribes a listener function to the selector. The listener function
+     * will be invoked when a message for the given topic is published. If an
+     * element is specified, then the listener will only be invoked when the
+     * subscribed element matches the published element.
+     *
+     * @param topic
+     *            a topic name, which must not be blank
+     * @param element
+     *            a DOM element, which may be null to subscribe to all messages
+     *            for the topic. If a string, then T5.$() is used to locate the
+     *            DOM element with the matching client id.
+     * @param listenerfn
+     *            function invoked when a message for the topic is published.
+     *            The function is invoked only if the supplied selector element
+     *            is undefined OR exactly matches the source element node. The
+     *            return value of the listenerfn will be accumulated in an array
+     *            and returned to the publisher.
+     *
+     *            The listener function is passed a message object as the first parameter; this is provided
+     *            on each call to the topic's publish function. The second parameter is the element
+     *            defined by the publisher (this is useful when subscribed to all elements). For truly global
+     *            events, the document object is used as the element.
+     * @return a function of no arguments used to unsubscribe the listener
+     */
+    function subscribe(topic, element, listenerfn)
+    {
+
+        var subscriber = {
+            topic : topic,
+            element : $(element),
+            listenerfn : listenerfn
+        };
+
+        subscribers.push(subscriber);
+        purgePublisherCache(subscriber.topic);
+
+        // To prevent memory leaks via closure:
+
+        topic = null;
+        element = null;
+        listenerfn = null;
+
+        // Return a function to unsubscribe
+        return function()
+        {
+            subscribers = without(subscriber, subscribers);
+            purgePublisherCache(subscriber.topic);
+        }
+    }
+
+    /**
+     * Creates a publish function for the indicated topic name and DOM element. For global
+     * events, the convention is to use the document object.
+     *
+     * <p>
+     * The returned function is used to publish a message. Messages are
+     * published synchronously. The publish function will invoke listener
+     * functions for matching subscribers (subscribers to the same topic). Exact
+     * subscribers (matching the specific element) are invoked first, then
+     * general subscribers (not matching any specific element). The return value
+     * for the publish function is an array of all the return values from all
+     * invoked listener functions.
+     *
+     * <p>
+     * There is not currently a way to explicitly remove a publisher; however,
+     * when the DOM element is removed properly, all publishers and subscribers
+     * for the specific element will be removed as well.
+     *
+     * <p>
+     * Publish functions are cached, repeated calls with the same topic and
+     * element return the same publish function.
+     *
+     * @param topic
+     *            used to select listeners
+     * @param element
+     *            the DOM element used as the source of the published message
+     *            (also used to select listeners). Passed through T5.$(), the
+     *            result must not be null.   The element will be passed to listener function as
+     *            the second parameter.
+     * @return publisher function used to publish a message
+     */
+    function createPublisher(topic, element)
+    {
+
+        element = $(element);
+
+        if (element == null)
+        {
+            throw "Element may not be null when creating a publisher.";
+        }
+
+        var existing = first(function(publisher)
+        {
+            return publisher.topic === topic && publisher.element === element;
+        }, publishers);
+
+        if (existing)
+        {
+            return existing.publisherfn;
+        }
+
+        var publisher = {
+            topic : topic,
+            element : element,
+            publisherfn : function(message)
+            {
+
+                if (publisher.listeners == undefined)
+                {
+                    publisher.listeners = findListeners(publisher.topic,
+                        publisher.element);
+                }
+
+                return map(function(listenerfn)
+                {
+                    return listenerfn(message, publisher.element);
+                }, publisher.listeners);
+            }
+        };
+
+        publishers.push(publisher);
+
+        // If only there was an event or something that would inform us when the
+        // element was removed. Certainly, IE doesn't support that! Have to rely
+        // on T5.dom.remove() to inform us.
+
+        // Mark the element to indicate it requires cleanup once removed from
+        // the DOM.
+
+        element.t5pubsub = true;
+
+        // Don't want to hold a reference via closure:
+
+        topic = null;
+        element = null;
+
+        return publisher.publisherfn;
+    }
+
+    /**
+     * Creates a publisher and immediately publishes the message, return the
+     * array of results.
+     */
+    function publish(topic, element, message)
+    {
+        return createPublisher(topic, element)(message);
+    }
+
+    /**
+     * Invoked whenever an element is about to be removed from the DOM to remove
+     * any publishers or subscribers for the element.
+     */
+    function cleanup(element)
+    {
+        subscribers = remove(function(subscriber)
+        {
+            return subscriber.element === element
+        }, subscribers);
+
+        // A little evil to modify the publisher object at the same time it is
+        // being removed.
+
+        publishers = remove(function(publisher)
+        {
+            var match = publisher.element === element;
+
+            if (match)
+            {
+                publisher.listeners = undefined;
+                publisher.element = undefined;
+            }
+
+            return match;
+        });
+    }
+
+    return {
+        createPublisher : createPublisher,
+        subscribe : subscribe,
+        publish : publish,
+        cleanupRemovedElement : cleanup
+    };
 });
 
 /**
- * Create aliases on T5 directly: pub -&gt; pubsub.publish and sub -&gt;
- * pubsub.subscribe.
+ * Create aliases on T5 directly: pub -&gt; T5.pubsub.publish and sub -&gt;
+ * T5.pubsub.subscribe.
  */
 T5.extend(T5, {
-	pub : T5.pubsub.publish,
-	sub : T5.pubsub.subscribe
+    pub : T5.pubsub.publish,
+    sub : T5.pubsub.subscribe
 });
\ No newline at end of file

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/JavaScriptTests.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/JavaScriptTests.tml?rev=1148123&r1=1148122&r2=1148123&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/JavaScriptTests.tml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/JavaScriptTests.tml Tue Jul 19 01:32:26 2011
@@ -1,18 +1,18 @@
 <html t:type="Border" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
 
-  <h1>JavaScript Tests</h1>
+<h1>JavaScript Tests</h1>
 
-  <p>
+<p>
     This page executes a number of JavaScript tests.
-  </p>
+</p>
 
-  <div id="tests">
+<div id="tests">
 
-    <h2>Arrays</h2>
+<h2>Arrays</h2>
 
-    <div>
-      <p> Checks for T5.arrays.isEmpty()
-        </p>
+<div>
+    <p> Checks for T5.arrays.isEmpty()
+    </p>
       <pre>
         assertEqual(isEmpty(null), true)
         assertEqual(isEmpty(undefined), true)
@@ -20,10 +20,10 @@
         assertEqual(isEmpty([1]), false)
     </pre>
 
-    </div>
-    <div>
-      <p> Checks for T5.arrays.isNonEmpty()
-        </p>
+</div>
+<div>
+    <p> Checks for T5.arrays.isNonEmpty()
+    </p>
       <pre>
         assertEqual(isNonEmpty(null), false)
         assertEqual(isNonEmpty(undefined), false)
@@ -31,59 +31,59 @@
         false)
         assertEqual(isNonEmpty([1]), true)
     </pre>
-    </div>
-    <div>
-      <p> Map() on null returns an empty array        
-        </p>
+</div>
+<div>
+    <p> Map() on null returns an empty array
+    </p>
       <pre>
         assertEqual(map(null, null), [])
         </pre>
-    </div>
+</div>
 
-    <div>
-      <p> Map() on undefined returns an empty array    
+<div>
+    <p> Map() on undefined returns an empty array
     </p>
       <pre>
         assertEqual(map(null, undefined), [])    
     </pre>
-    </div>
+</div>
 
-    <div>
-      <p>Map() on empty array returns an empty array</p>
+<div>
+    <p>Map() on empty array returns an empty array</p>
       <pre>
         assertEqual(map(null, []), [])
       </pre>
-    </div>
+</div>
 
 
-    <div>
-      <p> The normal use of map().
+<div>
+    <p> The normal use of map().
     </p>
       <pre>
         assertEqual(map(function(e) { return e + 100; }, [1, 2, 3]), [101, 102, 103])   
     </pre>
-    </div>
+</div>
 
-    <div>
-      <p> Optional second parameter to map() is an index number.    </p>
+<div>
+    <p> Optional second parameter to map() is an index number. </p>
       <pre>
         assertEqual(map(function(e, index) { return (e + 100) + "@" + index; }, [1, 2, 3]),
         ["101@0", "102@1",
         "103@2"])                
     </pre>
-    </div>
+</div>
 
-    <div>
-      <p> The initial value is returned, as is, when no reducing occurs due to empty/null/undefined list.
+<div>
+    <p> The initial value is returned, as is, when no reducing occurs due to empty/null/undefined list.
     </p>
       <pre>
         var initial = { };
         assertSame(reduce(function() { }, initial, []), initial);   
     </pre>
-    </div>
+</div>
 
-    <div>
-      <p> Show that the index of each element is passed to the reducer function.</p>
+<div>
+    <p> Show that the index of each element is passed to the reducer function.</p>
       <pre>
         assertEqual(reduce(function(o, value, index) {
         o[value] = index; return o;
@@ -92,44 +92,44 @@
         { fred: 0, barney: 1, wilma: 2 })
         </pre>
 
-    </div>
+</div>
 
-    <div>
-      <p> Removing a value that does not exist in the array returns the array unchanged.
+<div>
+    <p> Removing a value that does not exist in the array returns the array unchanged.
     </p>
       <pre>
         var initial = [1, 2, 3]
         assertSame(without(9, initial), initial)
         </pre>
-    </div>
+</div>
 
-    <div>
-      <p> Multiple matches should all be removed.</p>
+<div>
+    <p> Multiple matches should all be removed.</p>
       <pre>
         assertEqual(without(2, [1, 2, 2, 3, 4, 2, 5]), [1, 3, 4, 5])
 </pre>
-    </div>
+</div>
 
-    <div>
-      <p> The array should not be changed even if values are removed from the result.
-</p>
+<div>
+    <p> The array should not be changed even if values are removed from the result.
+    </p>
       <pre>
         var initial = [1, 2, 3]
         without(2, initial)
         assertEqual(initial, [1, 2, 3])
 </pre>
-    </div>
+</div>
 
-    <div>
-      <p>mapcat() on empty/null/undefined returns empty list.
+<div>
+    <p>mapcat() on empty/null/undefined returns empty list.
     </p>
       <pre>
         assertEqual(mapcat(null,null), [])</pre>
-    </div>
+</div>
 
-    <div>
-      <p> Basic execution of mapcat().
-  </p>
+<div>
+    <p> Basic execution of mapcat().
+    </p>
       <pre>
         assertEqual(mapcat(function (value) {
         var out = []
@@ -138,19 +138,19 @@
         }, [1, 3, 5]),
         [1, 3, 3, 3, 5, 5, 5, 5, 5])            
   </pre>
-    </div>
+</div>
 
-    <div>
-      <p>filter() a list.</p>
+<div>
+    <p>filter() a list.</p>
       <pre>
         assertEqual(filter(function(value) {
         return value % 2 === 0;
         }, [1, 2, 3, 4, 5, 6, 7, 8, 9]), [2, 4, 6, 8])
     </pre>
-    </div>
+</div>
 
-    <div>
-      <p>
+<div>
+    <p>
         Check that filter passes an optional index argument.
     </p>
       <pre>
@@ -160,10 +160,10 @@
         8, 9]),
         [1, 2, 4, 6, 7, 8])
     </pre>
-    </div>
+</div>
 
-    <div>
-      <p>remove() elements from a list.</p>
+<div>
+    <p>remove() elements from a list.</p>
       <pre>
         assertEqual(remove(function(value, index) {
         return value % 2 !== 0 &amp;&amp; index % 3 !== 0;
@@ -172,56 +172,56 @@
         5, 6, 7, 8, 9]),
         [1, 2, 4, 6, 7, 8])
         </pre>
-    </div>
+</div>
 
-    <div>
-      <p>first() on empty list returns null.</p>
+<div>
+    <p>first() on empty list returns null.</p>
       <pre>
         assertEqual(first(null, null), null)
     </pre>
-    </div>
+</div>
 
-    <div>
-      <p>first() match</p>
+<div>
+    <p>first() match</p>
 
       <pre>
         assertEqual(first(function(value) { return value &gt; 3; }, [1, 2, 3, 4, 5]), 4)
 </pre>
-    </div>
+</div>
 
-    <div>
-      <p>first() passes the index as the second value.</p>
+<div>
+    <p>first() passes the index as the second value.</p>
 
       <pre>
         assertEqual(first(function(value, index) { return index &gt; 2 }, [1, 2, 3, 4, 5]), 4)
 </pre>
 
-      <div>
+    <div>
         <p>extractProperty() returns a function to extract a named property.</p>
         <pre>
           var fn = T5.arrays.extractProperty('name')
 
           assertEqual(fn({name: 'Tapestry', id: 5}), 'Tapestry')
     </pre>
-      </div>
+    </div>
 
-      <div>
+    <div>
         <p>
-          Extract a property from an array.
-</p>
+            Extract a property from an array.
+        </p>
 
         <pre>
           assertEqual(extract('id', [ { id: 7, name: "Fred" }, { id: 22, name: "Barney" }]), [7, 22])    
     </pre>
-      </div>
-
     </div>
 
-    <h2>Publish / Subscribe</h2>
+</div>
 
+<h2>Publish / Subscribe</h2>
 
-    <div>
-      <p> Ensure that the message object passed to pub() is delivered to the listener.</p>
+
+<div>
+    <p> Ensure that the message object passed to pub() is delivered to the listener.</p>
       <pre>
         var message = { }
         var rcvd;
@@ -232,10 +232,21 @@
 
         assertSame(rcvd, message)        
         </pre>
-    </div>
+</div>
 
-    <div>
-      <p>Check that the function returned from sub() can be used to cancel message reciept.</p>
+<div>
+    <p> Ensure that the second object to a listener is the source object.</p>
+      <pre>
+        var unsub = sub("foo", null, function(message, element) { assertSame(element, document); })
+
+        pub("foo", document, null)
+
+        unsub()
+        </pre>
+</div>
+
+<div>
+    <p>Check that the function returned from sub() can be used to cancel message receipt.</p>
       <pre>
         var count = 0;
 
@@ -257,11 +268,11 @@
         pub("foo", document);
         assertEqual(count, 2)
           </pre>
-    </div>
+</div>
 
-    <div>
-      <p> Ensure that messages are delivered to specific listeners before general listeners. 
-      </p>
+<div>
+    <p> Ensure that messages are delivered to specific listeners before general listeners.
+    </p>
       <pre>
         var pubs = []
 
@@ -283,10 +294,10 @@
         "general1",
         "general2"])                
         </pre>
-    </div>
+</div>
 
-    <div>
-      <p>Removing an element also removes publishers and subscribers for the element.</p>
+<div>
+    <p>Removing an element also removes publishers and subscribers for the element.</p>
       <pre>
         var pubs = []
 
@@ -317,10 +328,10 @@
 
         assertEqual(pubs, ["general"])
       </pre>
-    </div>
+</div>
 
-    <div>
-      <p>Publish/subscribe via client id rather than element.</p>
+<div>
+    <p>Publish/subscribe via client id rather than element.</p>
 
       <pre>
         var element = new Element("span",{ id: "zaphod" }).update("Published Message Source Zaphod")
@@ -341,12 +352,12 @@
 
         T5.dom.remove(element)  
     </pre>
-    </div>
+</div>
 
-  </div>
+</div>
 
-  <script>
-<![CDATA[
+<script>
+    <![CDATA[
     isEmpty = T5.arrays.isEmpty
     isNonEmpty = T5.arrays.isNonEmpty
     map = T5.arrays.map
@@ -367,6 +378,6 @@
 
     JST.runTestSuite("tests");
     ]]>
-  </script>
+</script>
 </html>
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/js-testing.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/js-testing.js?rev=1148123&r1=1148122&r2=1148123&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/js-testing.js (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/js-testing.js Tue Jul 19 01:32:26 2011
@@ -106,6 +106,9 @@ var JST = (function() {
 						test.addClassName("pass");
 
 					} catch (e) {
+
+                        Tapestry.error(e)
+
 						failCount++;
 
 						if (e !== $fail) {